펜로즈 도식 · 텐서 다이어그램
선을 이으면
계산이 된다
Σ와 첨자가 잔뜩 붙은 식 대신, 도형과 선으로 행렬과 텐서를 다루는 방법이 있습니다. 물리학자 로저 펜로즈가 1970년대에 쓰기 시작한 이 그림 표기법은 지금은 양자역학, 머신러닝, 텐서 네트워크에서 널리 쓰입니다.
이 페이지의 그림은 전부 직접 만질 수 있습니다. 다리 끝을 끌어서 다른 다리에 놓으면 선이 이어지고, 바로 아래에 그 그림이 뜻하는 식과 실제 숫자 계산이 나옵니다. 행렬 곱셈을 할 줄 알면 충분합니다.
1텐서 = 다리 달린 도형
숫자를 담는 상자를 도형 하나로 그리고, 인덱스(첨자) 하나마다 다리 하나를 붙입니다.
- 스칼라 s — 숫자 하나. 인덱스가 없으니 다리 0개.
- 벡터 vi — 숫자 한 줄. 인덱스 i 하나 → 다리 1개.
- 행렬 Aij — 숫자 표. 행 i, 열 j → 다리 2개.
- 3차 텐서 Tijk — 표를 여러 장 쌓은 것 → 다리 3개.
다리의 개수를 텐서의 차수(order)라고 합니다. 다리마다 길이(차원)가 있어서, 길이 3인 다리는 그 인덱스가 1, 2, 3 중 하나라는 뜻입니다. 아래에서 차수를 바꿔 보고, 다리 색과 숫자 표의 축 색이 어떻게 맞물리는지 보세요.
이 페이지에서는 다리의 색 = 인덱스 글자입니다. 식에 나오는 빨간 i는 그림의 빨간 다리입니다.
2선 잇기 = 곱해서 더하기
펜로즈 도식의 규칙은 사실상 하나뿐입니다.
벡터 a와 b의 다리를 이어 보세요. ai와 bi가 같은 i를 쓰게 되고, i에 대해 더하면 Σi aibi, 곧 내적입니다.
이은 다음에는 남은 다리가 없습니다. 다리가 없다는 것은 결과가 숫자 하나(스칼라)라는 뜻입니다. 그림만 보고도 결과의 모양을 알 수 있다는 것, 이것이 이 표기법의 첫 번째 힘입니다.
3행렬 × 벡터
행렬 A는 다리가 둘입니다. 왼쪽 다리가 행 인덱스(첫째), 오른쪽 다리가 열 인덱스(둘째)입니다. 벡터 x를 A의 오른쪽 다리에 이으면 열 인덱스로 더하게 되므로 yi = Σj Aijxj, 곧 Ax입니다. 왼쪽 다리가 남으니 결과는 벡터입니다.
두 목표를 모두 해 보세요. x를 A의 왼쪽 다리에 이으면 행 인덱스로 더하게 되어 Σi xiAij, 즉 xTA가 됩니다. 행렬식에서는 전치 기호가 필요했지만 그림에서는 어느 다리에 이었는지만 다릅니다.
결과 표의 칸 위에 마우스를 올리거나 칸을 누르면, 그 칸이 어떤 곱들의 합인지 펼쳐지고 쓰인 숫자들이 강조됩니다. “행과 열을 곱해서 더한다”는 익숙한 그림이 그대로 보입니다.
4행렬 곱과 “남은 선 세기”
행렬 곱 AB는 A의 오른쪽 다리와 B의 왼쪽 다리를 잇는 것입니다: (AB)ij = Σk AikBkj. 세 행렬을 한 줄로 이으면 ABC. 행렬 곱이 왜 결합법칙 (AB)C = A(BC)를 만족하는지도 그림에서는 당연합니다. 괄호를 칠 곳이 없으니까요.
연습해 봅시다. 각 그림의 결과는 무엇일까요?
5잇지 않으면: 외적
선이 없으면 더할 것도 없습니다. 벡터 두 개를 나란히 두기만 하면 다리가 둘 남으니 결과는 행렬이고, 그 성분은 그냥 곱 Rij = aibj입니다. 이것이 외적(outer product) abT입니다.
노드를 끌어 b를 a의 왼쪽으로 옮겨 보세요. 남은 다리를 왼쪽부터 첫째·둘째 인덱스로 읽기로 했으므로, 결과가 baT로 바뀝니다(표가 전치됩니다). 연결이 없는 도식에서는 다리의 자리가 결과 인덱스의 순서를 정합니다.
6고리 = 대각합(trace)
행렬 하나의 두 다리를 서로 이으면? 행 인덱스와 열 인덱스가 같은 글자가 되어 Σi Aii — 대각선을 더한 대각합 tr(A)입니다. 다리가 하나도 남지 않으니 숫자입니다.
이제 세 행렬을 고리로 이은 tr(ABC)를 봅시다. 선형대수 시간에 배우는 순환 성질 tr(ABC) = tr(BCA) = tr(CAB)는 그림에서는 그저 같은 고리를 돌려 본 것입니다. 어디서부터 읽기 시작하느냐만 다를 뿐 그림은 하나입니다.
반대로 tr(ACB)는 선을 다르게 이어야 만들 수 있습니다. 노드를 옮기는 것만으로는 절대 바뀌지 않습니다. 도식에서 중요한 것은 모양이 아니라 무엇과 무엇이 이어졌는가입니다.
7전치 = 뒤집기
행렬의 왼쪽 다리가 첫째 인덱스이므로, 행렬을 좌우로 뒤집으면 두 인덱스의 순서가 바뀝니다. 그것이 전치 AT입니다.
그러면 (AB)T = BTAT도 그림 하나로 끝납니다. AB 전체를 거울에 비추면, 오른쪽에 있던 B가 뒤집힌 채 왼쪽으로 오고 A도 뒤집혀 오른쪽으로 갑니다. 왼쪽부터 읽으면 BTAT입니다.
8검은 점: 복사 텐서
다리가 여럿 달린 검은 점은 특별한 텐서입니다. 이어진 다리의 인덱스가 모두 같을 때만 1, 아니면 0입니다(크로네커 델타 δijk…). 그래서 검은 점은 “여기 모인 선들은 모두 같은 인덱스를 쓴다”는 표시라고 생각하면 됩니다. (어두운 화면 설정에서는 밝은 점으로 보입니다.)
- 다리 2개짜리 점 = 단위행렬 I. 선 중간에 있어도 없는 것과 같습니다.
- 벡터 a를 다리 3개짜리 점에 달면 → a를 대각선에 놓은 대각행렬 diag(a).
- 벡터 둘을 한 점에 달면 → 성분끼리 곱한 아다마르 곱 (a∘b)i = aibi.
아다마르 곱을 직접 만들어 보세요. 일반 행렬식에는 이 연산을 위한 별도 기호(∘)가 필요했지만, 도식에서는 점 하나면 됩니다.
마지막으로 이어진 검은 점들은 하나로 합칠 수 있습니다(“같은 인덱스”의 “같은 인덱스”는 같은 인덱스니까요). 아래 그림은 diag(a)·diag(b)입니다. 두 점 사이 선을 눌러 합치면 diag(a∘b)가 되고, 숫자는 그대로입니다.
9계산 순서와 비용
그림은 하나여도 어느 선부터 계산하느냐에 따라 걸리는 시간이 크게 달라집니다. 선 하나를 계산(축약)하면 양쪽 노드가 하나로 합쳐지고, 그때 드는 곱셈 횟수는 두 노드에 붙은 모든 선 길이의 곱입니다.
아래 A·B·x에서 선을 눌러 하나씩 축약해 보세요. 먼저 A–B를 합치면 (AB)x, 먼저 B–x를 합치면 A(Bx)입니다. 결과는 같지만 곱셈 횟수가 다릅니다.
차원이 n = 1000이라면 (AB)x는 약 10억 번, A(Bx)는 약 200만 번입니다. 딥러닝 라이브러리의 einsum이 축약 순서를 열심히 고르는 이유입니다. (최적 순서를 찾는 일 자체는 일반적으로 어려운 문제입니다.)
10미분 = 노드 빼기
보너스입니다. 선만으로 이루어진 도식은 각 노드에 대해 선형입니다. 그래서 어떤 노드 X로 미분하면 그 노드를 빼고, 비어 버린 다리를 새 인덱스로 남기면 됩니다.
스칼라 aTXb를 X로 미분해 봅시다. X를 누르세요.
같은 노드가 두 번 나오면 곱의 미분법처럼, 하나씩 빼 본 결과를 모두 더합니다. xTBx를 x로 미분해 봅시다. 두 x를 차례로 누르세요.
이 아이디어를 끝까지 밀고 가면 행렬 미분 공식집(Matrix Cookbook)의 공식 대부분을 그림 몇 장으로 다시 얻을 수 있습니다. 그것이 아래 소개하는 The Tensor Cookbook이 하는 일입니다.
11놀이터
자유롭게 만들어 보세요. 노드를 추가하고, 이어 보고, 결과가 어떤 식이 되는지 확인하세요. 노드를 누르면 선택되고, 선택한 노드를 뒤집거나 지울 수 있습니다. 맨 아래 einsum 한 줄은 numpy에 그대로 붙여 넣을 수 있습니다.
12더 읽을거리
- The Tensor Cookbook — Thomas Dybdahl Ahle. 이 페이지가 많이 참고한 책입니다. 행렬 공식집의 내용을 텐서 도식으로 옮겼고, 도함수·기댓값·크로네커 곱·텐서 트레인까지 다룹니다. 이 페이지의 1~10절은 그 책 1–2장 앞부분을 학부 1학년 눈높이로 풀어 쓴 것입니다.
- tensorgrad — 위 책의 저자가 만든, 텐서 도식으로 기호 미분을 하는 파이썬 라이브러리.
- Roger Penrose, “Applications of negative dimensional tensors” (1971) — 이 표기법의 출발점.
- numpy.einsum — 도식을 그대로 코드로 옮기는 함수. 이어진 선 = 겹치는 글자, 남은 다리 = 화살표 뒤 글자.
- tensors.net — 물리(텐서 네트워크) 쪽 입문 자료.
이 페이지는 독립적으로 만든 학습용 자료이며, 위 책과 저자와는 관계가 없습니다.