
Gradient (그래디언트), Jacobian (자코비안) 및 Hessian (헤시안)
2019, Feb 06
- 참조 : https://gaussian37.github.io/math-mfml-multivariate_calculus_and_jacobian/
- 참조 : http://t-robotics.blogspot.com/2013/12/jacobian.html#.XGlnkegzaUk
- 참조 : https://suhak.tistory.com/944
- 참조 : https://gaussian37.github.io/math-mfml-multivariate_calculus_and_jacobian/
- 참조 : https://www.khanacademy.org/math/multivariable-calculus/applications-of-multivariable-derivatives/quadratic-approximations/a/quadratic-approximation
목차
-
Gradient, Jacobian 및 Hessian의 비교 요약
-
Gradient의 정의 및 예시
-
Python을 이용한 Gradient 계산
-
Jacobian의 정의 및 예시
-
Python을 이용한 Jacobian 계산
-
Hessian의 정의 및 예시
-
Python을 이용한 Hessian 계산
-
Quadratic approximation
Gradient, Jacobian 및 Hessian의 비교 요약
- 먼저 이번 글에서 다룰 3가지 개념인
Gradient
,Jacobian
, 그리고Hessian
의 내용을 간략하게 표로 정리하면 다음과 같습니다.

- 3가지 모두 Objective Function을 최적화할 때 사용한다는 점에서 다변수에 대한 편미분을 한다는 공통점이 있으나 알고리즘에 따라서 사용하는 값이 다르기 때문에
함수의 갯수
,편미분 차수
에 차이점이 있습니다. - 위 도표에서 보이는 것 처럼
Gradient
는 1개의 함수에 대한 다변수 1차 편미분을 통해 벡터를 출력합니다.Jacobian
은Gradient
를 확장하여 N개의 함수에 대한 다변수 1차 편미분을 통해 행렬을 출력합니다. 마지막으로Hessian
은 1개의 함수에 대한 다변수 2차 편미분을 통하여 행렬을 출력합니다. 2차 편미분을 거치기 때문에 편미분할 변수를 2가지 선택해야 하므로 2차원 행렬을 가지게 됩니다. - 그러면
Gradient
,Jacobian
,Hessian
의 개념과 실제 코드 상으로 어떻게 쉽게 구하는 지 살펴보도록 하겠습니다. - 앞으로 사용할 용어 중 위 도표와 같이 단일 함수는
scalar-valued function
이라고 하며 복수 개의 함수는vector-valued function
이라고 명명하곘습니다.
Gradient의 정의 및 예시
scalar-valued multivariable function
인 f(x,y,...)f(x,y,...) 의Gradient
는 ∇f 로 표기하며 그 의미는 다음과 같습니다.
- ∇f=[∂f∂x∂f∂y⋮]
- 즉, 각 변수인 (x,y,...) 대하여 편미분한 결과를 벡터의 각 성분으로 가지는 것을
Gradient (Vectors)
라고 합니다. 즉, 모든 변수를 고려한 변화량 (derivative
)을 표현한 벡터가 됩니다. 따라서Gradient
는scalar-valued multivariable function
을 이용하여vector-valued multivariable function
을 만드는 연산이라고 말할 수 있습니다. 다음 예제들을 살펴보도록 하겠습니다.
- f(x,y)=x2−xy
- ∇f(x,y)=[∂∂x(x2−xy)∂∂y(x2−xy)]=[2x−y−x]
- 위 식과 같이 구한
Gradient
를vector field
로 나타내 보겠습니다.

- 위
vector field
는 f(x,y) 의 각 (x,y) 에서의gradient
의 크기와 방향을 나타냅니다. 원점을 기준으로 우상향하는 대각선 방향에서의graident
의 크기가 매우 작은 것을 확인할 수 있습니다. 예시를 살펴보면 다음과 같습니다.

- ∇f(1,2)=[2(1)−2−(1)]=[0−1]
- ‖∇f(1,2)‖=√02+(−1)2=1
- ∇f(2,1)=[2(2)−1−(2)]=[3−2]
- ‖∇f(2,1)‖=√32+(−2)2=√13
- 이와 같은 방법으로
Graident
를 구하면 각 위치에서의Gradient
를 이용하여Vector Field
를 생성할 수 있고 각 위치의 변화량 또한 확인할 수 있습니다.
- f(x,y,z)=x−xy+z2
- ∇f(x,y,z)=[∂∂x(x−xy+z2)∂∂y(x−xy+z2)∂∂z(x−xy+z2)]=[1−y−x2z]
- 3개의 변수를 이용하여
gradient
를 구해도 원리는 같습니다. 3개의 변수를 이용하여vector field
를 나타내면 아래와 같이 3차원 공간으로 나타나는 것을 볼 수 있습니다.

gradient
를 구한 결과 z 에 대한 변화량이 가장 큰 것을 알 수 있습니다. 따라서 위vector field
에서도 z 가 커지면 각 벡터의 크기도 가장 영향을 많이 받는 것을 확인할 수 있습니다.
- f(x,y)=−x4+4(x2−y2)−3
- ∇f(x,y)=[∂∂x(−x4+4(x2−y2)−3)∂∂y(−x4+4(x2−y2)−3)]=[−4x3+8x−8y]

- 위 예제에서도 동일하게
Gradient
를 적용하여Vector Field
를 시각화 하였습니다. 위 그림을 통하여Gradient
의 방향 및 크기를 통해optimization
시 수렴할 수 있는Local/Global Minimum
위치 등을 확인할 수 있습니다.

- 확대해서 살펴보면 위 그림과 같습니다.
Python을 이용한 Gradient 계산
- Python의
sympy
를 이용하면Gradient
를 쉽게 구할 수 있습니다.sympy
의diff
함수를 이용하면 원하는 변수의 미분값을 쉽게 구할 수 있기 때문입니다. - 앞에서 살펴본 예제를 실제 파이썬 코드를 통하여 어떻게 구하는 지 한번 살펴보도록 하겠습니다.
from sympy import symbols, diff, Matrix, latex
# Define the variables
variables = symbols('x y')
x, y = variables
# Define the function
f = x**2 - x*y
# Calculate the gradient
gradient = Matrix([diff(f, var) for var in variables])
latex_code = latex(gradient)
# Output the gradient
print("Gradient of f:", gradient)
# Gradient of f: Matrix([[2*x - y], [-x]])
print("LaTex of gradient of f", latex_code)
# \left[\begin{matrix}2 x - y\\- x\end{matrix}\right]

vector field
를 구하는 코드는 다음과 같습니다.
import numpy as np
import matplotlib.pyplot as plt
from sympy import symbols, diff, lambdify
num_variable = 2
if num_variable == 2:
# Step 1: Define the variables and function
x, y = symbols('x y')
f = -x**4 + 4*(x**2 - y**2) - 3
# f = x**2 - x*y
# Step 2: Compute the gradient symbolically
gradient = [diff(f, var) for var in (x, y)]
# Step 3: Create a numerical version of the gradient expressions
grad_f = lambdify((x, y), gradient)
# Step 4: Create a grid of points
X, Y = np.meshgrid(np.linspace(-5, 5, 40), np.linspace(-5, 5, 40))
# Step 5: Evaluate the gradient numerically at each point
U, V = grad_f(X, Y)
# Calculate the magnitude of the vectors
magnitude = np.sqrt(U**2 + V**2)
mean_magnitude = np.mean(magnitude)
# # Step 6: Plot the vector field using quiver
plt.figure(figsize=(8, 6))
quiver = plt.quiver(X, Y, U, V, magnitude, angles='xy', scale_units='xy', scale=mean_magnitude, cmap='viridis')
# Adding a color bar to indicate the magnitude
plt.colorbar(quiver, label='Magnitude')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('Gradient Vector Field of f(x,y,)={}'.format(str(f)))
plt.grid(True)
plt.show()
elif num_variable == 3:
# # Define the variables and function
x, y, z = symbols('x y z')
f = x - x*y + z**2
# # Compute the gradient symbolically
gradient = [diff(f, var) for var in (x, y, z)]
# # Create a numerical version of the gradient expressions
grad_f = lambdify((x, y, z), gradient)
# # Create a grid of points
X, Y, Z = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10), np.linspace(-5, 5, 10))
# # Evaluate the gradient numerically at each point
U, V, W = grad_f(X, Y, Z)
# Calculate the magnitude of the vectors
magnitude = np.sqrt(U**2 + V**2 + W**2)
# Plot the vector field using quiver in 3D, colored by magnitude
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
quiver = ax.quiver(X, Y, Z, U, V, W, length=0.1, cmap='viridis')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_zlabel('Z-axis')
ax.set_title('Gradient Vector Field of f(x,y,z)={}'.format(str(f)))
plt.show()
Jacobian의 정의 및 예시
- 위키피디아의
Jacobian
의 정의를 찾아보면 “The Jacobian matrix is the matrix of all first-order partial derivatives of a vector-valued function” 으로 나옵니다. 즉,Jacobian
은 모든 벡터들의1차 편미분값
으로 구성된 행렬이고 각 행렬의 값은 vector-valued multivariable function일 때의 미분값으로 정의됩니다. 관련 용어 및 내용은 아래 내용을 천천히 읽어보시면 충분히 이해할 수 있도록 설명하였습니다.
Jacobian
은 다양한 문제에서approximation
접근법을 사용할 때 자주 사용 되는 방법입니다.- 예를 들어 비선형 칼만필터를 사용할 때, 비선형 식을 선형으로 근사시켜서 모델링 할 때 사용하는 Extended Kalman Filter가 대표적인 예가 될 수 있습니다. Jacobian은 정말 많이 쓰기 때문에 익혀두면 상당히 좋습니다.
- 먼저
Jacobian
의 형태에 대하여 먼저 살펴보고 그 다음Jacobian
을 어떤 용도로 주로 사용하는 지 확인해 보도록 하겠습니다.
- 앞에서
Gradient
는 다음과 같이 구하였었습니다.
- ∇f(x,y,...)=[∂f∂x∂f∂y⋮]
- 위 식에서 출력 형태는
vector
입니다.Jacobian
은 위 식의 출력 형태에서 부터 편미분을 시작합니다. 따라서Jacobian
은vector-valued multivariable function
을 편미분하는 것이라고 말할 수 있습니다.
- f(x,y,...)=[f1(x,y,...)f2(x,y,...)⋮]
- 위 식에서 각 행의 함수에 대한 편미분의 결과는
Gradient
예제에서 살펴보았듯이 벡터가 됩니다. 따라서vector-valued multivariable function
f 의Jacobian
인 Jf 는 다음과 같은 행렬 결과를 가지게 됩니다.
- Jf(x,y,...)=[∂f1∂x(x,y,...)∂f1∂y(x,y,...)⋯∂f2∂x(x,y,...)∂f2∂y(x,y,...)⋯⋮⋮⋱]
- 정리하면
Jacobian
은 1개의 함수만을 이용하여Gradient
를 구하는 것에서 시작하여 N개 함수의Gradient
를 구하여 행렬로 만드는 것으로 이해할 수 있습니다. 이 때, 각 함수의Gradient
는 행벡터로 나열한 다음에 행방향으로 쌓아 행렬을 만듭니다.
Jacobian
은 다양한 용도로 사용될 수 있으나 가장 기본적으로approximation
을 할 때 주로 사용됩니다.

- 앞에서 말했듯이
Jacobian의 목적
은 복잡하게 얽혀있는 식을 미분을 통하여linear approximation
시킴으로써 간단한근사 선형식
을 만들어 주는 것입니다. 관련 내용은테일러 급수
와 연관되어 있으며 아래 내용에서 참조할 수 있습니다.- 참조 : https://gaussian37.github.io/math-mfml-taylor_series_and_linearisation/
- 참조 : https://gaussian37.github.io/math-mfml-multivariate_calculus_and_jacobian/
- 위 그래프에서 미분 기울기를 통하여 Δx 후의 y값을
선형 근사
하여 예측하는 것과 비슷한 원리 입니다. - 그런데 위 그래프에서 알고 싶은 것은 f′(x1) 에서의 함수 입니다. 위 그래프에서 f′(x1) 이 기울기이기 때문에, f′(x1)×Δx≈y2−y1 으로 근사화할 수 있기 때문입니다.
- 다시 한번
Jacobian
을 행렬로 표현하면 다음과 같습니다.
- J=∂y∂x=∂f(x)∂x=[∂f1∂x1⋯∂f1∂xm⋮⋱⋮∂fn∂x1⋯∂fn∂xm]
- 여기서
J
가 앞의 그래프 예시에 있는 함수 f′(x) 입니다. 따라서 다음과 같이 식을 정리할 수 있습니다.
- yi+1=f(xi+1)≈yi+∂f(xi)∂xiΔx=yi+JΔx
- 또는 함수 f 에서 p 지점에서의
linear approximation
을 나타내기 위해 다음과 같이 수식을 써서 표현하기도 합니다.
- f(x)≈f(p)+Jf(p)(x−p)
Python을 이용한 Jacobian 계산
- Jacobian은 n×m 크기의 행렬이며 n 개의 함수식과 m 개의 변수를 이용하여 다음과 같이 구해짐을 확인하였습니다. 편의상 변수는 xi 로 나타내겠습니다.
- J=[∂f1∂x1∂f1∂x2⋯∂f1∂xm−1∂f1∂xm∂f2∂x1∂f2∂x2⋯∂f2∂xm−1∂f2∂xm⋮⋮⋱⋮⋮∂fn−1∂x1∂fn−1∂x2⋯∂fn−1∂xm−1∂fn−1∂xm∂fn∂x1∂fn∂x2⋯∂fn∂xm−1∂fn∂xm]
- 위 식에서 Jacobian을 구하기 위한 편미분 계산은 파이썬의
sympy
를 이용하면 간단하게 처리할 수 있습니다. (울프람 알파 등을 이용하여도 됩니다.) - 이번 글에서는 Jacobian을
sympy
를 이용하여 구하는 방법에 대하여 알아보도록 하겠습니다.
- 먼저 fi 를 각각 정의해야 하고 편미분할 변수를 정의해야 합니다. 다루어볼 예제는 다음과 같습니다.
- F=[x21+x22+x3sin(x1)+cos(x2)]
- X=[x1x2x3]T
- Jacobian의 정의에 맞게 각 행렬의 성분을 편미분 하면 다음 결과를 얻을 수 있습니다.
- J=[f1x1f1x2f1x3f2x1f2x2f2x3]=[2x12x21cos(x1)−sin(x2)0]
- 위 연산을 다음과 같이 계산할 수 있습니다.
from sympy import symbols, Matrix, sin, cos, lambdify
import numpy as np
# Step 1: Define the symbolic variables
x1, x2, x3 = symbols('x1 x2 x3')
# Step 2: Define the function vector
f = Matrix([x1**2 + x2**2 + x3, sin(x1) + cos(x2)])
# Step 3: Define the variable vector
x = Matrix([x1, x2, x3])
# Step 4: Compute the Jacobian matrix
J = f.jacobian(x)

- 따라서 코드를 이용해서도 동일한 결과를 얻을 수 있음을 확인하였습니다.
- 다음으로 임의의 입력에 대하여 Jacobian 행렬 연산 방법을 확인해 보겠습니다. 연산은
numpy
를 사용하도록 코드를 작성하였습니다.
# Step 5: Convert the Jacobian to a NumPy function
jacobian_func = lambdify([x1, x2, x3], J, modules='numpy')
def jacobian_func_np(x1, x2, x3):
matrix = np.array([
[2*x1, 2*x2, 1],
[np.cos(x1), -np.sin(x2), 0]
])
return matrix
# Step 6: Example usage with NumPy
input_vector = np.array([1.0, 2.0, 3.0])
jacobian_result = jacobian_func(*input_vector)
print("Jacobian matrix with lambdify at", input_vector, "is:")
print(np.array(jacobian_result))
print()
# Jacobian matrix with lambdify at [1. 2. 3.] is:
# [[ 2. 4. 1. ]
# [ 0.54030231 -0.90929743 0. ]]
print("Jacobian matrix with numpy at", input_vector, "is:")
jacobian_result = jacobian_func_np(*input_vector)
print(np.array(jacobian_result))
# Jacobian matrix with numpy at [1. 2. 3.] is:
# [[ 2. 4. 1. ]
# [ 0.54030231 -0.90929743 0. ]]
- 위 코드의 2가지 결과 모두 동일함을 알 수 있습니다. 첫번째
jacobian_func
는lambdify
라는 모듈을 이용하여 Jacobian 행렬을 별도 변환 없이 바로 사용한 경우입니다. 반면jacobian_func_np
는 직접numpy
배열로 변환하여 사용한 것으로jacobian_func
를 확인하기 위한 용도로 별도 정의하였습니다. - 따라서 실제 사용할 때에는
jacobian_func
를 사용하여jacobian
을 구하고 계산된 결과만numpy
로 받아서 사용하는 것을 권장드립니다.
- 다음은 원의 방정식에 대한 Jacobian을 구하는 형태의 예제를 살펴보도록 하겠습니다.
- 원의 방정식 (x−a)2+(y−b)2=r2 에서 a,b,r 에 대한 편미분을 통해 Jacobian을 계산합니다.
- 첫번째 예제로 복수 개의 식을 나열하기 위하여 직접 (x,y) 를 대입하여 n 개의 식을 만들어 Jacobian을 구하는 방법과 (x,y) 또한 변수화 하여 대수적으로 Jacobian을 구하는 방식을 차례대로 확인해 보겠습니다.
- (x−a)2+(y−b)2=r2
- (a,b): center coordinates of the circle
- r: radius
- Jacobian with respect to the circle parameters (a, b, r)
- residual function: ri=√(xi−a)2+(yi−b)2−r
from sympy import symbols, Matrix, sqrt, lambdify
import numpy as np
# Define symbolic variables for the circle parameters and points
a, b, r = symbols('a b r')
# Example data points
points = np.array([[1, 7], [5, 8], [9, 8]])
# Example circle parameters (a, b, r)
params = [5.0, 5.0, 3.0]
# Define the residual function for a single point
residuals = Matrix([])
for x, y in points:
residuals = residuals.row_insert(residuals.shape[0], Matrix([sqrt((x - a)**2 + (y - b)**2) - r]))
# Compute the Jacobian matrix of the residual function
jacobian = residuals.jacobian([a, b, r])
# Convert the Jacobian to a numerical function using lambdify
jacobian_func = lambdify([a, b], jacobian, 'numpy')
# Print the Jacobian matrix
print("Jacobian matrix (3x3):")
jacobian_result = jacobian_func(0, 0)
print(jacobian_result)

- 위 식에서 F 로 정의한
residuals
와 J 인jacobian
을 구한 결과는 위 식과 같습니다.
- 이번에는 약간 (x,y) 또한 변수화 하여 Jacobian 행렬을 생성해 보도록 하겠습니다. 코드의 편의상 사용한 것이며 개념적으로 달라진 것은 없습니다.
from sympy import symbols, Matrix, sqrt, lambdify
import numpy as np
# Define symbolic variables for the circle parameters and points
a, b, r = symbols('a b r')
x, y = symbols('x y')
# Define the residual function for a single point
residuals = Matrix([sqrt((x - a)**2 + (y - b)**2) - r])
# Compute the Jacobian matrix of the residual function
jacobian = residuals.jacobian([a, b, r])
# Convert the Jacobian to a numerical function using lambdify
jacobian_func = lambdify([a, b, r, x, y], jacobian, 'numpy')
# Function to compute the Jacobian matrix for multiple points
def get_jacobian_results(params, points):
a, b, r = params
return np.array([jacobian_func(a, b, r, x, y) for x, y in points])
# Example data points
points = np.array([[1.0, 7.0], [4.0, 8.0], [9.0, 8.0]])
# Example circle parameters (a, b, r)
params = [5.0, 5.0, 3.0]
# Compute the 3x3 Jacobian matrix
jacobian_result = get_jacobian_results(params, points)
# Print the Jacobian matrix
jacobian_result_matrix = np.vstack(jacobian_result)
print("Jacobian matrix (3x3):")
print(jacobian_result_matrix)

Hessian의 정의 및 예시
Hessian
은 앞에서 간략히 정리한 바와 같이scalar-valued function
(1개의 함수)에 대하여 2차 편미분을 적용한 결과를 행렬로 나타낸 것을 의미하며 다음과 같이 정의됩니다.- 먼저 2차 편미분은 다음과 같은 방식으로 표현합니다.
- ∂∂x(∂f∂x)=∂2f∂x2
- ∂∂x(∂f∂y)=∂2f∂x∂y
- ∂∂y(∂f∂x)=∂2f∂y∂x
- ∂∂y(∂f∂y)=∂2f∂y2
- Symmetry of second derivatives: ∂2f∂x∂y=∂2f∂y∂x
- Hf=[∂2f∂x2∂2f∂x∂y∂2f∂x∂z⋯∂2f∂y∂x∂2f∂y2∂2f∂y∂z⋯∂2f∂z∂x∂2f∂z∂y∂2f∂z2⋯⋮⋮⋮⋱]
- 위
Hessian
은scalar-valued function
f 에 대하여 2차 편미분을 계산한 것을 확인할 수 있습니다. 또한Hessian
의 결과를 보면Symmetry of second derivatives
성질로 인하여Symmetric Matrix
가 됨을 알 수 있습니다. - 다음 예제를 살펴보도록 하겠습니다.
- Hessian of f(x,y)=x3−2xy−y6 at the point (1,2)
- fx(x,y)=∂∂x(x3−2xy−y6)=3x2−2y
- fy(x,y)=∂∂y(x3−2xy−y6)=−2x−6y5
- fxx(x,y)=∂∂x(3x2−2y)=6x
- fxy(x,y)=∂∂y(3x2−2y)=−2
- fyx(x,y)=∂∂x(−2x−6y5)=−2
- fyy(x,y)=∂∂y(−2x−6y5)=−30y4
- Hf(x,y)=[fxx(x,y)fxy(x,y)fyx(x,y)fyy(x,y)]=[6x−2−2−30y4]
- Hf(1,2)=[6(1)−2−2−30(2)4]=[6−2−2−480]
Hessian
은 각 성분이 2차 편미분의 결과를 저장하고 있습니다. 2차 편미분은curvature
(곡률, 변화율)을 의미합니다.- 따라서
Hessian
의Eigenvalue
와Eigenvector
는curvature
의Principle Component
가 됩니다. - 만약 모든
Eigenvalue
의 곱이 양수이면Eigenvalue
각각이 모두 양수이거나 모두 음수인 경우가 됩니다. 즉, 곡률의 방향이 모두 같은 방향이 되어convex
한 형태를 가지게 되고global optimization
을 구할 수 있는 형태가 됩니다. 반면 모든Eigenvalue
의 곱이 음수이면 곡률의 방향이 다른 성분이 있으므로saddle point
형태가 되어global optimization
을 구할 수 없습니다.- 링크 그림 참조 : https://gaussian37.github.io/math-mfml-multivariate_calculus_and_jacobian/#hessian-1
- 만약
global optimization
이 있는 상태라면Hessian
행렬의 가장 왼쪽 상단의 값 하나만 추가적으로 확인하면 됩니다. 만약 좌상단의 값이 양수라면curvature
가 양수이므로 아래로 볼록한convexity
형태를 가지게 되어global minimum
을 가지고 반대로 좌상단의 값이 음수라면 위로 볼록한concavity
형태를 가지므로global maximum
을 가지게 됩니다. - 모든
eigenvalue
의 곱은determinant
를 의미하기 때문에determinant
가 양수인 지 음수인 지를 통하여global optimization
유무를 구할 수 있습니다.
eigenvalue
는Positive/Negative (Semi) Definite Matrix
와도 연관이 있습니다. 따라서 다음과 같이 정리할 수 있으며 앞에서 다룬 내용과 동일한 의미를 가집니다.- 참조 : https://gaussian37.github.io/math-la-positive_definite_matrix/
- Hf: convex on set A if, and only if, its Hessian matrix is positive semidefinite at all points on the set.
- Hf: strictly convex on set A if, and only if, its Hessian matrix is positive definite at all points on the set.
- Hf: concave on set A if, and only if, its Hessian matrix is negative semi-definite at all points on the set.
- Hf: strictly concave on set A if, and only if, its Hessian matrix is negative definite at all points on the set.
Hessian
이 사용되는 대표적인 케이스는multivariable function
의Taylor Series
에서 2차 도함수를 구하는 데 사용됩니다. 가장 기본적인single variable function
의Taylor Series
는 다음과 같이 전개됩니다. 다음은 점 a 에서의 근사화 방법입니다.
- T(x)=∞∑n=0f(n)(a)n!(x−a)n=f(a)+f′(a)(x−a)+12f″(a)(x−a)2+16f‴(a)(x−a)3+⋯
- 위 식을
multivariable function
의Taylor Series
로 나타내면 다음과 같습니다.
- T(x)=f(a)+(x−a)T∇f(a)+12(x−a)THf(x−a)+⋯
Python을 이용한 Hessian 계산
Hessian
또한 앞에서 사용한sympy
를 이용하여 구할 수 있습니다. 아래 예제는 앞에서 사용한 예시를 이용하였습니다.
import sympy as sp
# Step 1: Define symbolic variables
x, y = sp.symbols('x y')
# Step 2: Define the function f(x, y)
f = x**3-2*x*y-y**6
# Step 3: Compute the gradient of f
grad_f = [sp.diff(f, var) for var in (x, y)]
# Step 4: Compute the Hessian matrix
hessian = sp.Matrix([[sp.diff(g, var) for var in (x, y)] for g in grad_f])
hessian_func = sp.lambdify((x, y), hessian, 'numpy')
# Evaluate the function with numpy arrays (or numbers)
result = hessian_func(1, 2) # Evaluating at x=1, y=2, z=3
# Display the Hessian matrix
print("Hessian Matrix: \n")
sp.pprint(Hessian)
# ⎡6⋅x -2 ⎤
# ⎢ ⎥
# ⎢ 4⎥
# ⎣-2 -30⋅y ⎦
print("Result: \n", result)
# Result:
# [[ 6 -2]
# [ -2 -480]]

- 위 결과와 같이 원하는
Hessian
값을 코드를 통하여 구할 수 있습니다.
Quadratic approximation
Taylor Series
를 통하여 임의의 함수를 n 차 ( ∞ 차 ) 미분을 통하여 근사화 할 수 있음이 알려져 있습니다.- 참조 : https://gaussian37.github.io/math-mfml-taylor_series_and_linearisation/
- 하지만 어떤 함수를 근사화 할 때에는 계산 효율화를 위하여 무한 차수의 미분을 사용하지 않고 1차 미분만을 이용하여 선형 근사화(
linear approximation
)를 하거나 2차 미분 까지 이용하는 것(quadratic approximation
)이 일반적입니다. - 지금까지 살펴본 내용 중
Gradient
와Hessian
은scalar-valued function
에 대한 1차 미분, 2차 미분의 결과임을 확인하였습니다. - 이 내용을 바탕으로
Gradient
와Hessian
을 모두 사용하는Quadratic approximation
을 적용하는 방법에 대하여 알아보면서 이 글을 마치도록 하겠습니다.
- 만약 f 가 2개의 변수를 가지는 함수라고 가정해 보겠습니다. 그러면 특정 점 (x0,y0) 부근에서 근사화를 진행해야 합니다. 이 때,
Quadratic approximation
을 위한 식은 다음과 같습니다.
- Qf(x,y)=f(x0,y0)+fx(x0,y0)(x−x0)+fy(x0,y0)(y−y0)+12fxx(x0,y0)(x−x0)2+fxy(x0,y0)(x−x0)(y−y0)+12fyy(x0,y0)(y−y0)2
- 위 식에서 빨간색은
Constant
, 초록색은Linear Term
그리고 파란색은Quadratic Term
입니다. 따라서Vector
형태로 수식을 표현한다면 다음과 같이 표현할 수 있습니다. - 아래 수식에서 x,x_{0} 는
vector
를 나타내며 x=(x,y), x=(x0,y0) 로 생각할 수 있습니다.
- Qf(x)=f(x0)+∇f(x0)⋅(x−x0)+12(x−x0)THf(x0)(x−x0)
- f: function with multi-dimensional input and a scalar output
- ∇f(x0): gradient of f evaluated at x0
- Hf(x0): Hessian matrix of f evaluated at x0
- x0: input we are approximating near.
- x: variable input
Gradient
와Hessian
을 이용하여 벡터 형태로 표현한 식과 함수 별로 풀어서 쓴 식을 대응하면 다음과 같습니다. 벡터 형태로 표현한 식을 풀어서 써보겠습니다.
- ∇f(x0)⋅(x−x0)=[fx(x0,y0)fy(x0,y0)]⋅([xy]−[x0y0])=[fx(x0,y0)fy(x0,y0)]⋅[x−x0y−y0]=fx(x0,y0)(x−x0)+fy(x0,y0)(y−y0)
- ∴∇f(x0)⋅(x−x0)=fx(x0,y0)(x−x0)+fy(x0,y0)(y−y0)
- (x−x0)THf(x0)(x−x0)=[x−x0y−y0]T[fxx(x0,y0)fxy(x0,y0)fyx(x0,y0)fyy(x0,y0)][x−x0y−y0]=[(x−x0)(y−y0)][fxx(x0,y0)fxy(x0,y0)fyx(x0,y0)fyy(x0,y0)][x−x0y−y0]=[(x−x0)(y−y0)][fxx(x0,y0)(x−x0)+fxy(x0,y0)(y−y0)fyx(x0,y0)(x−x0)+fyy(x0,y0)(y−y0)]=fxx(x0,y0)(x−x0)2+fxy(x0,y0)(y−y0)(x−x0)+fyx(x0,y0)(x−x0)(y−y0)+fyy(x0,y0)(y−y0)2=fxx(x0,y0)(x−x0)2+2fxy(x0,y0)(y−y0)(x−x0)+fyy(x0,y0)(y−y0)2
- ∴12(x−x0)THf(x0)(x−x0)=12fxx(x0,y0)(x−x0)2+fxy(x0,y0)(x−x0)(y−y0)+12fyy(x0,y0)(y−y0)2
- 벡터 형태로 표현한 식은 2개의 입력값이 아니라 n 개의 입력값이 사용되더라도 동일하게 적용가능하다는 장점이 있습니다. 따라서 이와 같이
Quadratic approximation
을 표현할 수 있습니다.
- 지금까지
Quadratic approximation
에 대하여 알아보았습니다. 그러면 실제Quadratic approximation
예제를 하나 다루어 보도록 하겠습니다.
- f(x,y)=sin(x)cos(y), approximating near (x,y)=(π3,π6)
- Qf(x,y)=f(x0,y0)+fx(x0,y0)(x−x0)+fy(x0,y0)(y−y0)+12fxx(x0,y0)(x−x0)2+fxy(x0,y0)(x−x0)(y−y0)+12fyy(x0,y0)(y−y0)2
Constant Term
부분은 다음과 같습니다.
- f(π3,π6)=sin(π3)cos(π6)=√32√32=34
Linear Term
부분은 다음과 같습니다.
- fx(x,y)=∂∂xsin(x)cos(y)=cos(x)cos(y)
- ∴fx(π3,π6)=cos(π3)cos(π6)=12√32=√34
- fy(x,y)=∂∂ysin(x)cos(y)=−sin(x)cos(y)
- ∴fy(π3,π6)=−sin(π3)sin(π6)=−√3212=−√34
Quadratic Term
부분은 다음과 같습니다.
- fxx(x,y)=∂∂x∂∂x(sin(x)cos(y))=∂∂xcos(x)cos(y)=−sin(x)cos(y)
- ∴fxx(π3,π6)=−sin(π3)cos(π6)=−√32√32=−34
- fxy(x,y)=∂∂x∂∂y(sin(x)cos(y))=∂∂xsin(x)(−sin(y))=−cos(x)sin(y)
- ∴fxy(π3,π6)=−cos(π3)sin(π6)=−1212=−14
- fyy(x,y)=∂∂y∂∂y(sin(x)cos(y))=∂∂y−sin(x)sin(y)=−sin(x)cos(y)
- ∴fyy(π3,π6)=−sin(π3)cos(π6)=−√32√32=−34
- 따라서
Quadratic approximation
식은 다음과 같이 쓸 수 있습니다.
- Qf(x,y)=f(x0,y0)+fx(x0,y0)(x−x0)+fy(x0,y0)(y−y0)+12fxx(x0,y0)(x−x0)2+fxy(x0,y0)(x−x0)(y−y0)+12fyy(x0,y0)(y−y0)2=34+√34(x−π3)+−√34(y−π6)+12⋅−√34(x−π3)2+−14(x−π3)(y−π6)+12⋅−34(y−π6)2
- 아래는 f(x,y)=sin(x)cos(y) 의 그래프 입니다.

- 아래는 (x0,y0)=(π3,π6) 에서
Quadratic approximation
을 구한 Qf(x,y) 의 그래프 입니다.
