2023-11-13 48th Class
Gradient-based Learning
토막 상식 (?)
layer가 지날떄마다 데이터 분포가 바뀜-> batch normalization
레이어 지날때마다 data standardization하면 성능이 높아질 수있다는 논문
하지만 내부적인 다른 문제를 해결해줬기 때문에 성능이 높아진거다라는 연구 발표
#️⃣ The Object of GBL
Gradient Based Learning의 목적은 임의의 x에서 시작하여 함숫값 y를 최소로 만드는 x를 찾는 것
SGD = Stochastic Gradient Descent
graph
- argmin은 오른쪽에 쓴 함수가 가장 작아지는 값, 즉 min() 임
- 위의 1/10 x2 함수에서는 min값이 0임
gradient based leaerning에서는
- f=-3 에서 업데이트: f’(-3) = -0.6 이므로 업데이트 하면 x:= -3 -(-0.6) = -2.4로 x값이 바뀜
- f=-2 에서 업데이트: f’(-2) = -0.4 이므로 업데이트 하면 x:= -2.4 -(-0.4) = -1.6으로 x값이 바뀜
- f=-1 에서 업데이트: f’(-1) = -0.2 이므로 업데이트 하면 x:= -1 -(-0.2) = -0.8으로 x값이 바뀜
- f=1 에서 업데이트: f’(1) = 0.2 이므로 업데이트 하면 x:= -3 -(-0.6) = -2.4로 x값이 바뀜
- f=2 에서 업데이트: f’(2) = 0.4 이므로 업데이트 하면 x:= 2 - 0.4 = 1.6
- f=3 에서 업데이트: f’(3) = 0.6 이므로 업데이트 하면 x:= 3 - 0.6 = 2.4
초기의
#️⃣ gradient based learning 연습
연습.1 임의의 x에 대해
연습.2 ITERATIONS를 증가시키면 같은 x에서 시작했을 때, 더욱 x*에 가까워 지는 것을 확인
code
def f(x):
return 1/10 * x**2
def df_dx(x):
return 1/5 * x
x = 3
ITERATIONS = 20
print(f"Initial x: {x}")
for iter in range(ITERATIONS):
dy_dx = df_dx(x)
x = x - dy_dx
print(f"{iter+1}-th x: {x:.4f}")
'''
Initial x: 3
1-th x: 2.4000
2-th x: 1.9200
3-th x: 1.5360
4-th x: 1.2288
5-th x: 0.9830
6-th x: 0.7864
7-th x: 0.6291
8-th x: 0.5033
9-th x: 0.4027
10-th x: 0.3221
11-th x: 0.2577
12-th x: 0.2062
13-th x: 0.1649
14-th x: 0.1319
15-th x: 0.1056
16-th x: 0.0844
17-th x: 0.0676
18-th x: 0.0540
19-th x: 0.0432
20-th x: 0.0346
'''
연습.3 x* 가 다른 함수
도함수 f’(x) = 1/5(x-2)
visualization full code
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return 1/10 * x**2
def df_dx(x):
return 1/5 * x
x = 3
ITERATIONS = 20
x_track = list()
x_track.append(x)
y_track = list()
y_track.append(f(x))
print(f"Initial x: {x}")
for iter in range(ITERATIONS):
dy_dx = df_dx(x)
x = x - dy_dx
x_track.append(x)
y_track.append(f(x))
print(f"{iter+1}-th x: {x:.4f}")
function_x = np.linspace(-5, 5, 100)
function_y = f(function_x)
fig, axes = plt.subplots(2, 1, figsize=(8, 4))
axes[0].plot(function_x, function_y)
axes[0].scatter(x_track, y_track, c=range(ITERATIONS+1) , cmap='rainbow')
axes[0].set_xlabel('x', fontsize=15)
axes[0].set_ylabel('y', fontsize=15)
axes[1].plot(x_track, marker='o')
axes[1].set_xlabel('iteration', fontsize=15)
axes[1].set_ylabel('x', fontsize=15)
fig.tight_layout()
plt.show()
#️⃣ gradient exploding problem
함수의 계수가 높아지면 이동 보폭이 커짐
def gradient_exploding():
def f1(x): return 1/10 * x**2
def df1_dx(x): return 1/5 * x
def f2(x): return 1/5 * x**2
def df2_dx(x): return 2/5 * x
def f3(x): return 1/3 * x**2
def df3_dx(x): return 2/3 * x
x1, x2, x3 = 3, 3, 3
ITERATIONS = 10
x_track1, y_track1 = [x1], [f1(x1)]
x_track2, y_track2 = [x2], [f2(x2)]
x_track3, y_track3 = [x3], [f3(x3)]
for iter in range(ITERATIONS):
dy1_dx = df1_dx(x1)
dy2_dx = df2_dx(x2)
dy3_dx = df3_dx(x3)
x1 = x1 - dy1_dx
x2 = x2 - dy2_dx
x3 = x3 - dy3_dx
x_track1.append(x1)
y_track1.append(f1(x1))
x_track2.append(x2)
y_track2.append(f2(x2))
x_track3.append(x3)
y_track3.append(f3(x3))
fig, axes = plt.subplots(3, 1, figsize=(6, 6))
function_x = np.linspace(-5, 5, 100)
axes[0].plot(function_x, f1(function_x), label='f1(x)', color='C0')
axes[1].plot(function_x, f2(function_x), label='f1(x)', color='C1')
axes[2].plot(function_x, f3(function_x), label='f1(x)', color='C2')
axes[0].scatter(x_track1, y_track1, c=range(ITERATIONS+1), cmap='rainbow')
axes[1].scatter(x_track2, y_track2, c=range(ITERATIONS+1), cmap='rainbow')
axes[2].scatter(x_track3, y_track3, c=range(ITERATIONS+1), cmap='rainbow')
for ax in axes: ax.tick_params(labelsize=15)
fig.tight_layout()
plt.show()
gradient_exploding()
함수의 계수가 높아지면 발생하는 문제
계수가 증가할 수 록 x*에 접근하는 속도가 빨라짐
계수가 크니까 미분계수가 크게 잡혀서 업데이트 되는 스텝이 커짐
함수의 계수를 더 높여 다음과 같이 설정하면
x가 지그재그를 돌면서 minima에 접근함
함수의 계수가 더 높은경우
값이 튀어나가게 됨 -> Gradient Exploding Problem
#️⃣ gradient exploding code (bigger)
code
def gbl2():
def f(x): return 2 * x ** 2
def df_dx(x): return 4 * x
x = 3
ITERATIONS = 3
x_track, y_track = [x], [f(x)]
print(f"Initial x: {x}")
for iter in range(ITERATIONS):
dy_dx = df_dx(x)
x = x - dy_dx
x_track.append(x)
y_track.append(f(x))
print(f"{iter + 1}-th Iteration")
print(f"{dy_dx = :.4f}")
print(f"next x: {x:.4f}\n")
gbl2()
'''
Initial x: 3
1-th Iteration
dy_dx = 12.0000
next x: -9.0000
2-th Iteration
dy_dx = -36.0000
next x: 27.0000
3-th Iteration
dy_dx = 108.0000
next x: -81.0000
'''
- 미분 계수의 절댓값이 너무 커서 x* 방향으로 가긴 하지만, x* 보다 훨씬 먼 값으로 업데이트 됨
- 이 현상이 반복되면 x는 minima로 학습되지 않고,
- x와 미분계수는 무한대로 발산하게 됨
#️⃣ 학습률 (learning rate)
0 < a < 1의 값을 미분 계수에 곱하여 x가 발산하는 문제를 막음
이렇게 미분계수를 suppress 시키는 값을 learning rate(학습률)이라고 함
def gbl2_lr():
def f(x): return 2 * x ** 2
def df_dx(x): return 4 * x
x = 3
ITERATIONS = 3
LR = 0.1
x_track, y_track = [x], [f(x)]
print(f"Initial x: {x}")
for iter in range(ITERATIONS):
dy_dx = df_dx(x)
# x = x - dy_dx 기존
x = x - LR * dy_dx
x_track.append(x)
y_track.append(f(x))
print(f"{iter + 1}-th Iteration")
print(f"{dy_dx = :.4f}")
print(f"next x: {x:.4f}\n")
gbl2_lr()
'''
Initial x: 3
1-th Iteration
dy_dx = 12.0000
next x: 1.8000
2-th Iteration
dy_dx = 7.2000
next x: 1.0800
3-th Iteration
dy_dx = 4.3200
next x: 0.6480
'''
learning rate을 도입하면 발산하던 f(x) = 2x 의 학습이 정상적으로 변하는 것을 알 수 있음
즉 learning rate은 학습의 안정성을 위해 미분계수를 얼만큼 suppress시킬지 결정하는 값
α = 0.1 ⟶ 미분계수의 10%만 반영하여 update
α = 0.01 ⟶ 미분계수의 1%만 반영하여 update
#️⃣ Multivariate Case
함숫값을 최소로 만들기 위해선 임의의 x1, x2 에서 출발하여 x1, x2 모두 함숫값을 감소시키는 방향으로 학습되어야 함
x1, x2가 각각 함숫값 y를 최소로 만드는 방향으로 학습되는 식
함숫값은 점점 작아지며, x1는 x1* = 0 에 가까워지고 x2는 x2* = 0에 가까워짐
multivariate case code
# multivariate case
def f(x1, x2): return x1**2 + x2**2
def df_dx(x): return 2*x
x1, x2 = 3, -2
ITERATIONS = 10
LR = 0.1
print(f"Initial (x1, x2): ({x1}, {x2})")
print(f"Initial y: {f(x1, x2)}")
for iter in range(ITERATIONS):
dy_dx1 = df_dx(x1)
dy_dx2 = df_dx(x2)
x1 = x1 - LR * dy_dx1
x2 = x2 - LR * dy_dx2
print(f"{iter +1}-th (x1, x2): ({x1:.3f}, {x2:.3f})")
print(f"y: {f(x1, x2):.3f}")
'''
Initial (x1, x2): (3, -2)
Initial y: 13
1-th (x1, x2): (2.400, -1.600)
y: 8.320
2-th (x1, x2): (1.920, -1.280)
y: 5.325
3-th (x1, x2): (1.536, -1.024)
y: 3.408
4-th (x1, x2): (1.229, -0.819)
y: 2.181
5-th (x1, x2): (0.983, -0.655)
y: 1.396
6-th (x1, x2): (0.786, -0.524)
y: 0.893
7-th (x1, x2): (0.629, -0.419)
y: 0.572
8-th (x1, x2): (0.503, -0.336)
y: 0.366
9-th (x1, x2): (0.403, -0.268)
y: 0.234
10-th (x1, x2): (0.322, -0.215)
y: 0.150
'''
#️⃣ contour plot
contour plot: 등고선
# multivariate case
def f(x1, x2): return x1**2 + x2**2
def df_dx(x): return 2*x
x1, x2 = 3, -2
ITERATIONS = 10
LR = 0.1
x1_track, x2_track = [x1], [x2]
y_track = [f(x1, x2)]
print(f"Initial (x1, x2): ({x1}, {x2})")
print(f"Initial y: {f(x1, x2)}")
for iter in range(ITERATIONS):
dy_dx1 = df_dx(x1)
dy_dx2 = df_dx(x2)
x1 = x1 - LR * dy_dx1
x2 = x2 - LR * dy_dx2
x1_track.append(x1); x2_track.append(x2); y_track.append(f(x1, x2))
print(f"{iter +1}-th (x1, x2): ({x1:.3f}, {x2:.3f})")
print(f"y: {f(x1, x2):.3f}")
# Bivariate Function을 Contour Plot으로 시각화 하기
def f(x1, x2): return x1**2 + x2**2
function_x1 = np.linspace(-5, 5, 100)
function_x2 = np.linspace(-5, 5, 100)
function_X1, function_X2 = np.meshgrid(function_x1, function_x2)
function_Y = np.log(f(function_X1, function_X2))
fig, ax = plt.subplots(figsize=(10, 10))
ax.contour(function_X1, function_X2, function_Y, levels=100, cmap='Reds_r')
ax.plot(x1_track, x2_track, marker='o', label='Optimization Path')
ax.set_xlabel("x", fontsize=15)
ax.set_ylabel("y", fontsize=15)
ax.tick_params(labelsize=15)
fig.tight_layout()
plt.show()
'''
Initial (x1, x2): (3, -2)
Initial y: 13
1-th (x1, x2): (2.400, -1.600)
y: 8.320
2-th (x1, x2): (1.920, -1.280)
y: 5.325
3-th (x1, x2): (1.536, -1.024)
y: 3.408
4-th (x1, x2): (1.229, -0.819)
y: 2.181
5-th (x1, x2): (0.983, -0.655)
y: 1.396
6-th (x1, x2): (0.786, -0.524)
y: 0.893
7-th (x1, x2): (0.629, -0.419)
y: 0.572
8-th (x1, x2): (0.503, -0.336)
y: 0.366
9-th (x1, x2): (0.403, -0.268)
y: 0.234
10-th (x1, x2): (0.322, -0.215)
y: 0.150
'''
딥러닝에서 bayes’ theorem에서 하이퍼파라미터 최적화에 사용됨
Backpropagation
#️⃣ Training Model’s Parameters
딥러닝 모델은 수많은 뉴런으로 이루어져있음
모든 뉴런은 weight과 bias로 이루어져 있음
모델 학습은 모델이 목적에 맞는 출력을 내도록 weight과 bias를 학습한다는 것을 의미
J 는 yhat과 y의 차이를 수치화하는 함수
모델의 파라미터는 J를 감소시키기 위한 방향으로 학습되어야 함
-> Gradient Based Learning (GBL)을 이용해 loss를 줄이는 방법으로 학습할 수 있음
#️⃣ Chain Rule을 이용하여 합성함수의 미분계수 구하기
!Pasted image 20231113222924.png
각 미분계수를 곱하여 최종 입력에 대한 최초 출력의 미분계수 구하기
# Chain Rule을 이용하여 미분계수 구하기
class Function1:
def forward(self, x):
z = x - 2
return z
def backward(self, dy_dz):
dz_dx = 1
dy_dx = dy_dz * dz_dx
return dy_dz
class Function2:
def forward(self, z):
self.z = z
y = 2 * (z**2)
return y
def backward(self):
dy_dz = 4 * self.z
return dy_dz
function1, function2 = Function1(), Function2()
x = 5
z = function1.forward(x)
print(f"{z=}")
y = function2.forward(z)
print(f"{y=}")
dy_dx = function1.backward(function2.backward())
print(f"{dy_dx=}")
'''
z=3
y=18
dy_dx=12
'''
한개의 class로 묶어서 실행하기
class Function:
def __init__(self):
self.func1 = Function1()
self.func2 = Function2()
def forward(self, x):
z = self.func1.forward(x)
print(f"{z=}")
y = self.func2.forward(z)
print(f"{y=}")
return y
def backward(self):
dy_dz = self.func2.backward()
print(f"{dy_dz=}")
dy_dx = self.func1.backward(dy_dz)
print(f"{dy_dx=}")
return dy_dx
fn = Function()
y = fn.forward(5)
dy_dx = fn.backward()
'''
z=3
y=18
dy_dz=12
dy_dx=12
'''
쪽지 시험
'Education > 새싹 TIL' 카테고리의 다른 글
새싹 AI데이터엔지니어 핀테커스 11주차 (수) - Multi Layer Perceptron (0) | 2023.11.16 |
---|---|
새싹 AI데이터엔지니어 핀테커스 11주차 (화) - Backpropagation (1) | 2023.11.14 |
새싹 AI데이터엔지니어 핀테커스 10주차 (금) - Loss Function & Differentiation (0) | 2023.11.10 |
새싹 AI데이터엔지니어 핀테커스 10주차 (목) - Artificial Neuron & MLP (2) | 2023.11.09 |
새싹 AI데이터엔지니어 핀테커스 10주차 (수) - DL Preliminaries (Game using Class) (2) | 2023.11.08 |