8.1 다변수 미분

실습 · 연습문제 2개

중앙차분으로 Jacobian 만들기 numerical-jacobian

함수 f:Rn→Rmf: \mathbb{R}^n \to \mathbb{R}^m의 Jacobian Jf(x)\mathbf{J}_f(\mathbf{x})는 (출력 차원 × 입력 차원) 행렬이고, jj번째 열은 입력의 jj번째 성분만 움직였을 때 출력이 변하는 비율이다. 중앙차분으로 이 열을 근사하면

Jf(x):,j≈f(x+εej)−f(x−εej)2ε\mathbf{J}_f(\mathbf{x})_{:,j} \approx \frac{f(\mathbf{x} + \varepsilon \mathbf{e}_j) - f(\mathbf{x} - \varepsilon \mathbf{e}_j)}{2\varepsilon}

이다. 여기서 ej\mathbf{e}_j는 jj번째 성분만 1인 단위벡터다.

함수 jacobian(f, x, eps=1e-6)을 완성한다.

인자 설명
f 1차원 배열 (n,)을 받아 1차원 배열 (m,) 또는 스칼라를 돌려주는 함수
x 미분할 점, shape (n,)
eps 차분 간격

반환값은 shape (m, n)인 NumPy 배열이다. f가 스칼라를 돌려주면 m = 1로 보고 (1, n)을 반환한다. 이 경우 반환값의 전치가 gradient(열벡터)다.

테스트는 선형사상(Jacobian이 행렬 자체), 극좌표 변환(해석적 Jacobian과 비교), 입력·출력 차원이 다른 함수의 shape, 스칼라 함수를 확인한다.

힌트: 열을 하나씩 계산해 np.stack(..., axis=1)로 붙인다. x를 float 배열로 바꿔 두면 정수 입력에서도 안전하다.

chain rule로 2층 신경망의 Jacobian 유도하기 tanh-layer-jacobian

입력 x∈Rn\mathbf{x} \in \mathbb{R}^n을 받는 2층 신경망

g(x)=W2tanh⁡(W1x+b1)+b2g(\mathbf{x}) = \mathbf{W}_2 \tanh(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2

를 세 사상의 합성 x↦a=W1x+b1↦h=tanh⁡(a)↦W2h+b2\mathbf{x} \mapsto \mathbf{a} = \mathbf{W}_1\mathbf{x} + \mathbf{b}_1 \mapsto \mathbf{h} = \tanh(\mathbf{a}) \mapsto \mathbf{W}_2\mathbf{h} + \mathbf{b}_2로 본다. 각 사상의 Jacobian을 구하고 chain rule로 곱해 Jg(x)\mathbf{J}_g(\mathbf{x})를 계산하는 함수 mlp_jacobian(W1, b1, W2, b2, x)를 완성한다.

인자 shape
W1 (k, n)
b1 (k,)
W2 (m, k)
b2 (m,)
x (n,)

반환값은 shape (m, n)이다. 유한차분을 쓰지 말고 해석적으로 계산한다. 테스트는 유한차분 Jacobian과 비교하고, shape과 몇 가지 성질을 확인한다.

힌트: tanh⁡′(a)=1−tanh⁡(a)2\tanh'(a) = 1 - \tanh(a)^2이다. 성분별 함수의 Jacobian은 대각행렬이다. 대각행렬을 만들지 않고 (1 - h**2)[:, None] * W1처럼 행마다 곱해도 같다.