2017/09/27 - 문과생도 이해하는 딥러닝 (1) - 퍼셉트론 Perceptron
2017/10/18 - 문과생도 이해하는 딥러닝 (2) - 신경망 Neural Network
2017/10/25 - 문과생도 이해하는 딥러닝 (3) - 오차 역전파, 경사하강법
2017/12/24 - 문과생도 이해하는 딥러닝 (4) - 신경망구현, 활성화함수, 배치
2017/12/26 - 문과생도 이해하는 딥러닝 (5) - 신경망 학습 실습
지난 시간에는 구축한 신경망을 어떻게 학습해야 하는지 학습에 필요한 개념들에 대해서 다루었고 실제로 학습을 진행해보았다. 경사하강법을 이용해 수치미분으로 기울기를 계산하는 것은 계산 시간이 너무나 오래 걸려서 모델의 학습 시간이 굉장히 길었다. 학습을 할 때 사용되는 하이퍼파라미터(hyperparameter) 들에 대해서 알 수 있었으며 왜 가중치 갱신을 할 때 기울기를 구하는지, 손실함수는 왜 계산하는지, epoch의 정확한 의미는 무엇인지, 미니배치를 왜 사용하는지 등등 딥러닝의 핵심 개념들을 제대로 알 수 있었다.
이번에는 지난 포스팅에서 신경망을 학습하면서 수치미분으로 기울기를 계산하면서 학습시간이 굉장히 길어졌는데 이를 극복할 방법으로 오차역전파법을 살펴보고자 한다.
오차역전파법 실습 1
문과생도 이해하는 딥러닝 (6)
지난 오차역전파 관련 포스팅에서는 오차역전파법이 순전파(foward propagation)로 가중치 학습이 되고 이를 갱신하기 위해서 오차를 반영하여 반대 방향에서 다시 가중치를 업데이트 한다는 식으로만 설명을 했다. 역전파를 사용하는 또 다른 중요한 이유는 역전파를 통해서 '미분'을 효율적으로 계산할 수 있다는 것이다.
먼저 순전파와 역전파 기능을 가진 클래스를 구현한다
class MulLayer:
def __init__(self):
self.x = None
self.y = None
def forward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y
dy = dout * self.x
return dx, dy
순전파 방식으로 구매한 사과 가격을 구하는 예시
apple = 100
apple_num = 2
tax = 1.1
mul_apple_layer = MulLayer()
mul_tax_layer = MulLayer()
# forward propagation
apple_price = mul_apple_layer.forward(apple, apple_num)
price = mul_tax_layer.forward(apple_price, tax)
print(price)
# back propagation
dprice = 1
dapple_price, dtax = mul_tax_layer.backward(dprice)
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print(dapple, dapple_num, dtax)
본 교재에서는 아래와 같은 계산 그래프 방식으로 신경망 학습 모델을 구현하였다.
신경망의 층을 하나의 클래스로 인스턴스를 만들면서 추가하는 방식이다.
class AddLayer:
def __init__(self):
pass
def forward(self, x, y):
out = x + y
return out
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
class Relu:
def __init__(self):
self.mask = None
def forward(self, x):
'''
순전파 시 x <= 0 일 때 값을 0으로 치환한다
기본적으로 x는 numpy 배열임을 가정한다
'''
self.mask = (x <= 0)
out = x.copy()
out[self.mask] = 0
return out
def backward(self, dout):
dout[self.mask] = 0
dx = dout
return dx
class Sigmoid:
def __init__(self):
self.out = None
def forward(self, x):
out = 1 / (1 + np.exp(-x))
self.out = out
return out
def backward(self, dout):
dx = dout * (1.0 - self.out) * self.out
return dx
# Affine 계층
X = np.random.rand(2) # Input
W = np.random.rand(2, 3) # Weight
B = np.random.rand(3) # Bias
print(X.shape)
print(W.shape)
print(B.shape)
Y = np.dot(X,W) + B
class Affine:
def __init__(self, W, b):
self.W = W
self.b = b
self.x = None
self.dW = None
self.db = None
def forward(self, x):
self.x = x
out = np.dot(x, self.W) + self.b
return out
def backward(self, dout):
dx = np.dot(dout, self.W.T)
self.dW = np.dot(self.x.T, dout)
self.db = np.sum(dout, axis = 0)
return dx
Softmax-with-Loss 계층
output layer에서 사용하는 소프트맥수 함수는 입력 값을 확률의 형태로 normalize하여 결과값을 출력한다.
신경망에는 1)학습, 2)추론 이 있다.
추론에는 softmax 함수 같은 활성화함수를 사용하지 않고 affine layer에서 나온 결과 값을 그대로 사용하는 것이 일반적이며 우리가 흔히 말하는 score라고 한다. 추론에는 답을 내리기만 하면 되기 때문에 다른 활성화함수 들을 거쳐 정규화할 필요가 없고 높은 점수가 무엇인지만 파악할 수 있으면 되기 때문이다.
학습에는 softmax 함수를 사용하는데 이는 정규화한 출력 값을 이용해서 모델을 다시 업데이트해야 하기 때문에 정규화가 필요하다.
Softmax with Loss는 마지막 출력 층인 소프트맥스 함수의 결과 값을 손실함수로 오차도 계산하겠다는 의미이다.
<< 활성화함수 별 적합한 손실함수 >>
- Softmax Function ==> Cross Entropy Error
- Identity Function ==> Mean Squared Error
활성화 함수마다 적합한 손실함수가 있어(그렇게 설계되어 있음) 오차의 역전파가 말끔하게 계산된다.
class SoftmaxWithLoss: def __init__(self): self.loss = None # Loss self.y = None # Output self.t = None # Target def foward(self, x, t): self.t = t self.y = softmax(x) self.loss = cross_entropy_error(self.y, self.t) return self.loss def backward(self, dout=1): batch_size = self.t.shape[0] dx = (self.y - self.t) / batch_size return dx
'Data Science > 문과생도 이해하는 딥러닝' 카테고리의 다른 글
문과생도 이해하는 딥러닝 (10) - 배치 정규화 (2) | 2018.01.07 |
---|---|
문과생도 이해하는 딥러닝 (9) - 신경망 초기 가중치 설정 (4) | 2018.01.07 |
문과생도 이해하는 딥러닝 (8) - 신경망 학습 최적화 (6) | 2018.01.07 |
문과생도 이해하는 딥러닝 (7) - 오차역전파법 실습 2 (0) | 2018.01.05 |
문과생도 이해하는 딥러닝 (5) - 신경망 학습 실습 (7) | 2017.12.26 |
문과생도 이해하는 딥러닝 (4) - 신경망구현, 활성화함수, 배치 (10) | 2017.12.24 |
문과생도 이해하는 딥러닝 (3) - 오차 역전파, 경사하강법 (2) | 2017.10.25 |
문과생도 이해하는 딥러닝 (2) - 신경망 Neural Network (2) | 2017.10.18 |
댓글