부스트캠프 Ai tech/1주차
3일 - 심화과제
소갱
2022. 1. 19. 19:41
심화과제에서 많은 고민을 했던 부분을 위주로 작성
처음에는 왜 선형회귀에 경사하강법이 나오는지 궁금했다.
선형회귀는 일차함수고, 경사하강법은 이차함수에 사용한다고 생각했던터라 이해가 안가는 부분이 많았다.
유투브와 블로그를 찾아다니면서 공부하던중에 선형회귀에서 쓰는 손실함수를 활용하는데 있어서 경사하강법을 쓰는 것을 알게 되었다.
선형회귀는 output을 통해 일차함수를 얻어내는데 이 과정은 다음과 같다.
train_x = (np.random.rand(1000) - 0.5) * 10
train_y = np.zeros_like(train_x)
def func(val):
fun = sym.poly(7*x + 2)
return fun.subs(x, val)
for i in range(1000):
train_y[i] = func(train_x[i])
# initialize
w, b = 0.0, 0.0
lr_rate = 1e-2
n_data = len(train_x)
errors = []
for i in range(100):
## Todo
# 예측값 y
_y = w * train_x + b
# gradient
gradient_w = np.sum((w * train_x - train_y + b) * 2 * train_x) / n_data
gradient_b = np.sum(w * train_x - train_y + b) / n_data
# w, b update with gradient and learning rate
w = w - lr_rate * gradient_w
b = b - lr_rate * gradient_b
# L2 norm과 np_sum 함수 활용해서 error 정의
error = np.sum((_y-train_y)**2) / n_data
# Error graph 출력하기 위한 부분
errors.append(error)
print("w : {} / b : {} / error : {}".format(w, b, error))
우선 y = 7x + 2 라고 설정을 해서 y값들을 얻어낸다. 초기 w(기울기)와 b(y절편)은 0으로 세팅을 하고 결과값과의 분산을 통해서 조금씩 수정해 나가는데 이때 lr_rate (학습률) 설정은 매우 중요하다.
학습률이 클 경우엔 정교하지 못하고, 작을 경우엔 처리 시간이 늘어나기 때문이다.
gradient_w는 손실함수를 w에 대해서 미분을 해서 얻었고 gradient_b는 손실함수를 b에 대해서 미분을 해서 얻었다.
이 값을 통해 w 에 경사하강법을 적용해서 꾸준히 값을 변경시켜주었다.
Backpropagation
def output_gradient(y, t):
return 2. * (y - t)
def backward_gradient(X, S, grad_out, wRec):
"""
X: input
S: 모든 input 시퀀스에 대한 상태를 담고 있는 행렬
grad_out: output의 gradient
wRec: 재귀적으로 사용되는 학습 파라미터
"""
# grad_over_time: loss의 state 에 대한 gradient
# 초기화
grad_over_time = np.zeros((X.shape[0], X.shape[1]+1))
grad_over_time[:, -1] = grad_out
# gradient accumulations 초기화
wx_grad = 0
wRec_grad = 0
'''
TODO
'''
for k in range(X.shape[1],0,-1):
wx_grad += np.sum(np.mean(grad_over_time[:,k]*X[:,k-1]))
wRec_grad += np.sum(np.mean(grad_over_time[:,k]*S[:,k-1]))
grad_over_time[:,k-1] = grad_over_time[:,k] * wRec
return (wx_grad, wRec_grad), grad_over_time
이 문제에선 wx_grad와 wRec_grad를 구하게 되는 과정이 너무 어려웠다.
많은 고민 끝에 얻게 된 결과로는
위 과정을 통해서 wx_grad와 wRec_grad의 값을 구할 수 있었다.