이 포스팅은 밑바닥부터 시작하는 딥러닝을 공부하고 정리한것 입니다.
def function_2(x):
return x[0]**2 + x[1]**2
기울기
모든 변수의 편미분을 벡터로 정리한 것을 기울기(gradient)라고 한다.
def numerical_gradient(f,x):
h=1e-4 #0.0001
grad=np.zeros_like(x)
for idx in range(x.size):
tmp_val=x[idx]
#f(x+h) 계산
x[idx]=tmp_val + h
fxh1=f(x)
#f(x-h) 계산
x[idx]=tmp_val - h
fxh2=f(x)
grad[idx]=(fxh1-fxh2) / (2*h)
x[idx] = tmp_val
return grad
그런데 이 기울기라는 게 의미하는 것이 무엇일까? 기울기 그림은 다음 그림처럼 방향을 가진 벡터(화살표)로 그려진다. 이 그림을 보면 기울기는 함수의 '가장 낮은 장소(최솟값)'를 가리키는 것 같다.
위 그림에서 기울기는 가장 낮은 장소를 가리키지만, 실제는 반드시 그렇다고는 할 수 없다. 사실 기울기는 각 지점에서 낮아지는 방향을 가리킨다. 더 정확히 말하자면 기울기가 가리키는 쪽은 각 장소에서 함수의 출력 값을 가장 크게 줄이는 방향이다.
1. 경사법(경사 하강법)
기계학습 문제 대부분은 학습 단계에서 손실 함수가 최솟값이 될 때의 최적의 매개변수를 찾아낸다. 이런 어려운 상황 에서 기울기를 잘 이용해 함수의 최솟값(또는 가능한 한 작은 값)을 찾으려는 것이 경사법이다. 여기에서 주의할 점은 각 지점에서 함수의 값을 낮추는 방안을 제시하는 지표가 기울기라는 것이다. 그러나 기울기가 가리키는 곳에 정말 함수의 최솟값이 있는지, 즉 그쪽이 정말로 나아갈 방향인지는 보장할 수 없다. 실제로 복잡한 함수에서는 기울기가 가리키는 방향에 최솟값이 없는 경우가 대부분이다.
기울어진 방향이 꼭 최솟값을 가리키는 것은 아니나, 그 방향으로 가야 함수의 값을 줄일 수 있다.
경사법은 현 위치에서 기울어진 방향으로 일정 거리만큼 이동한다. 그런 다음 이동한 곳에서도 마찬가지로 기울기를 구하고, 또 그 기울어진 방향으로 나아가기를 반복한다. 이렇게 해서 함수의 값을 점차 줄이는 것이 경사법(gradient method)이다.
경사법을 수식으로 나타내보면 다음과 같다.
기호 n(eta, 에타)는 갱신하는 양을 나타낸다. 이를 신경망 학습에서는 학습률(learning rate)라고 한다. 한 번의 학습으로 얼마만큼 학습해야 할지, 즉 매개변수 값을 얼마나 갱신하느냐를 정하는 것이 학습률이다.
학습률 값은 0.01이나 0.001 등 미리 특정 값으로 정해두어야 하는데 일반적으로 이 값이 너무 크거나 작으면 좋은 장소를 찾아갈 수 없다.
경사 하강법은 다음과 같이 간단하게 구현할 수 있다.
def gradient_descent(f,init_x,lr=0.01,step_num=100):
x=init_x
for i in range(step_num):
grad=numerical_gradient(f,x)
x -=lr*grad
return x
f는 최적화 하려는 함수, init_x는 초깃값, lr는 learning rate를 의미하는 학습률, step_num은 경사법에 따른 반복 횟수를 뜻한다.
이 함수를 사용하면 함수의 극솟값을 구할 수 있고 잘하면 최솟값을 구할 수도 있다.
최종결과는 (0,0)에 가까운 결과가 나왔다. 경사법을 사용한 이 갱신 과정을 그림으로 나타내면 다음처럼 된다.
2. 신경망에서의 기울기
여기서 말하는 기울기는 가중치 매개변수에 대한 손실 함수의 기울기이다.
import sys,os
sys.path.append(os.pardir)
import numpy as np
from common.functions import softmax,cross_entropy_error
from common.gradient import numerical_gradient
class simpleNet:
def __init__(self):
self.W = np.random.randn(2,3)
def predict(self,x):
return np.dot(x,self.W)
def loss(self,x,t):
z=self.predict(x)
y=softmax(z)
loss=cross_entropy_error(y,t)
return loss
net=simpleNet()
print(net.W)
x=np.array([0.6,0.9])
p=net.predict(x)
print(p)
print(np.argmax(p))
t=np.array([0,0,1])
net.loss(x,t)
이어서 기울기를 구해보자. 지금까지처럼 numerical_gradient(f,x)를 써서 구하면 된다.
def f(W):
return net.loss(x,t)
dw=numerical_gradient(f,net.W)
print(dw)
numerical_gradient(f,x)의 인수 f는 함수, x는 함수 f의 인수이다. 그래서 여기에서는 net.W를 인수로 받아 손실 함수를 계산하는 새로운 함수 f를 정의했다.
신경망의 기울기를 구한 다음에는 경사법에 따라 가중치 매개변수를 갱신하기만 하면 된다.
'Deep learning > 모델 구현' 카테고리의 다른 글
7. 오차역전파법(1) (0) | 2021.04.21 |
---|---|
6. 신경망 학습 (3) - 학습 알고리즘 구현하기 (0) | 2021.04.20 |
4. 신경망 학습 (1) - 손실함수 (0) | 2021.04.19 |
3. 신경망(2) - 손글씨 숫자 인식 (0) | 2021.04.19 |
2. 신경망 (1) (0) | 2021.04.19 |