7.7 텐서와 einsum

실습 · 연습문제 2개

batch 공분산을 축 규약대로 batch-covariance

센서 BB개가 각각 NN번 측정한 DD차원 신호를 X, shape (B, N, D)로 받았다. 축의 의미는 batch(센서) · 샘플(측정 시점) · feature(측정 채널)다. 함수 batch_cov(X)를 완성해 센서마다 표본 공분산 행렬을 반환한다.

Σb=1N−1∑n=1N(xbn−μb)(xbn−μb)⊤,μb=1N∑n=1Nxbn\boldsymbol{\Sigma}_b = \frac{1}{N-1} \sum_{n=1}^{N} (\mathbf{x}_{bn} - \boldsymbol{\mu}_b)(\mathbf{x}_{bn} - \boldsymbol{\mu}_b)^\top, \qquad \boldsymbol{\mu}_b = \frac{1}{N} \sum_{n=1}^{N} \mathbf{x}_{bn}

반환값의 shape은 (B, D, D)다.

테스트는 다음을 확인한다.

  • 센서마다 np.cov(X[b], rowvar=False)와 같다.
  • 평균은 센서마다 따로(샘플 축 N으로) 뺀다. 전체 batch의 평균을 빼면 센서마다 기준점이 다른 데이터에서 공분산이 부풀려진다.
  • 결과는 대칭이고 고윳값이 음수가 아니다.

힌트: X.mean(axis=?, keepdims=True)로 중심화한 뒤, 합해서 사라질 축이 무엇인지 생각하며 einsum 문자열을 쓴다. 출력의 두 feature 축에는 서로 다른 글자가 필요하다.

bilinear layer를 einsum 한 줄로 bilinear-einsum

두 입력 x∈RI\mathbf{x} \in \mathbb{R}^I, z∈RJ\mathbf{z} \in \mathbb{R}^J을 받아 KK개의 출력을 내는 bilinear layer는 출력마다 행렬 Wk∈RI×J\mathbf{W}_k \in \mathbb{R}^{I \times J} 하나를 써서

yk=x⊤Wkz+ck=∑i,jxi Wkij zj+cky_k = \mathbf{x}^\top \mathbf{W}_k \mathbf{z} + c_k = \sum_{i,j} x_i \, W_{kij} \, z_j + c_k

를 계산한다. 함수 bilinear(x, W, z, c)를 완성해 batch 전체의 출력을 반환한다.

인자 shape 의미
x (B, I) 첫 번째 입력
W (K, I, J) 출력마다 행렬 하나
z (B, J) 두 번째 입력
c (K,) bias

반환값의 shape은 (B, K)다. 테스트는 이중 loop로 계산한 값과 비교하고, I≠JI \neq J인 경우와 B=1B = 1인 경우도 확인한다.

힌트: 먼저 각 축에 글자를 붙인다(b, i, j, k). 출력에 남는 축과 합해서 사라지는 축을 나누면 einsum 문자열이 정해진다. bias는 broadcasting으로 더한다.