행렬 미분 · 야코비와 헤시안
기말 범위 12주차 요약. 입력·출력이 스칼라·벡터·행렬인 함수들의 도함수 표기법과, 그 대표인 야코비 행렬·헤시안, 그리고 자주 쓰는 행렬 미분 항등식을 정리한다.
함수 종류별 도함수의 모양
미분의 대상이 스칼라냐 벡터냐 행렬이냐에 따라 도함수의 모양(스칼라·벡터·행렬)이 달라진다.
스칼라 인수 벡터 함수
- 스칼라를 받아 벡터를 돌려주는 함수
를 벡터값 함수vector-valued function라 한다. 그 예가 매개변수 곡선parametric curve이다.
- 이 함수의 도함수를 접벡터tangent vector라 하며, 각 성분을 미분한 열벡터이다.
벡터 인수 스칼라 함수
- 벡터를 받아 스칼라를 돌려주는 스칼라장
의 도함수는 그래디언트이며, 행렬 미분 표기법에서는 행벡터로 쓴다.
도함수의 모양 정리
- 스칼라 인수 벡터 함수의 도함수는 열벡터(접벡터).
- 벡터 인수 스칼라 함수의 도함수는 행벡터(그래디언트).
- 벡터 인수 벡터 함수
의 도함수는 행렬(야코비 행렬).
벡터 인수 벡터 함수와 행렬 함수
- 벡터 인수 벡터 함수의 도함수는 행렬이며, 각 행이 성분 함수의 그래디언트이다.
- 스칼라를 받아 행렬을 돌려주는 함수
의 도함수(각 성분을 미분)를 접행렬tangent matrix이라 하고, 행렬을 받아 스칼라를 돌려주는 함수 의 도함수를 기울기 행렬gradient matrix이라 한다.
야코비 행렬
야코비 행렬
야코비 행렬Jacobian matrix은 벡터 인수 벡터 함수
기계학습의 역전파에서 쓰이는 손실 함수loss function의 도함수가 바로 이런 벡터 인수 벡터 함수의 도함수이다.
python
import numpy as np
# 유한 차분으로 야코비 행렬 계산: J[i,j] = ∂f_i/∂x_j
def jacobian(f, x, h=1e-6):
x = np.asarray(x, dtype=float)
f0 = np.asarray(f(x), dtype=float)
J = np.zeros((f0.size, x.size))
for j in range(x.size):
e = np.zeros_like(x); e[j] = h
J[:, j] = (f(x + e) - f(x - e)) / (2 * h)
return J
# f(x,y) = [ x^2 * y , 5x + sin(y) ]
f = lambda v: np.array([v[0]**2 * v[1], 5*v[0] + np.sin(v[1])])
p = np.array([2.0, 1.0])
J = jacobian(f, p)
exact = np.array([[2*p[0]*p[1], p[0]**2], # [2xy, x^2]
[5.0, np.cos(p[1])]]) # [5, cos y]
print("점 (2,1)에서 수치 야코비 =")
print(np.round(J, 4))
print("해석 야코비 =")
print(np.round(exact, 4))
print("일치:", np.allclose(J, exact))헤시안 행렬
- 스칼라장
의 그래디언트 는 다시 벡터 인수 벡터 함수이므로, 그 야코비 행렬을 취하면 헤시안 행렬Hessian matrix이 된다. 헤시안은 이계 편미분들을 성분으로 갖는다.
- 혼합 편미분의 순서가 무관하므로(
) 헤시안은 대칭행렬이다. 정류점에서 헤시안이 양의 정부호이면 극소, 음의 정부호이면 극대, 부호가 섞이면 안장점이다.
python
import numpy as np
# 유한 차분 헤시안: H[i,j] = ∂²f / ∂x_i∂x_j
def hessian(f, x, h=1e-4):
x = np.asarray(x, dtype=float); n = x.size
H = np.zeros((n, n))
for i in range(n):
for j in range(n):
ei = np.zeros(n); ei[i] = h
ej = np.zeros(n); ej[j] = h
H[i, j] = (f(x+ei+ej) - f(x+ei-ej) - f(x-ei+ej) + f(x-ei-ej)) / (4*h*h)
return H
# f(x,y) = x^2 + y^2 + 3xy -> H = [[2,3],[3,2]] (상수)
f = lambda v: v[0]**2 + v[1]**2 + 3*v[0]*v[1]
H = hessian(f, np.array([1.0, 1.0]))
print("헤시안 H =")
print(np.round(H, 3))
print("대칭 여부:", np.allclose(H, H.T))
print("고윳값:", np.round(np.linalg.eigvalsh(H), 3),
"-> 부호 혼재이면 안장점")행렬 미분 항등식
, 를 벡터 를 받아 스칼라를 돌려주는 함수, 를 에 무관한 스칼라라 하면 기본 항등식은 다음과 같다.
에 무관한 상수 벡터 에 대해 선형형식의 미분과, 벡터값 함수의 곱셈 항등식이 성립한다.
역전파의 핵심 — 벡터 함수의 연쇄법칙
스칼라 인수 벡터 함수와 벡터 인수 벡터 함수 모두에 대해 상수배·상수행렬배·합·연쇄법칙이 성립한다.
마지막 연쇄법칙(야코비의 곱)이 신경망 역전파의 수학적 뼈대이다.
성분별 연산의 도함수
- 두 벡터의 덧셈
의 야코비는 , 이다. 뺄셈이면 이다. - 성분별 곱셈
의 야코비는 대각행렬이 된다(비대각 성분은 서로 무관하므로 ).