7. 오차역전파법 구현하기
7.1 신경망 학습의 전체 그림
딥러닝은 손실함수의 값이 최소로 되도록 가중치와 편향인 매개변수를 조정하는 과정을 학습이라고 한다. 딥러닝 학습은 다음 4단계와 같다.
미니배치(mini-batch) : Train 데이터 중 랜덤하게 샘플을 추출하는데 이것을 미니배치라고 하며, 미니배치의 손실함수 값을 줄이는 것이 학습의 목표이다.
기울기 계산 : 손실함수의 값을 작게하는 방향을 가리키는 가중치() 매개변수의 기울기를 구한다.
매개변수 갱신 : 가중치 매개변수를 기울기 방향으로 학습률(learning rate)만큼 갱신한다.
반복 1~3 단계를 반복한다.
7.2 오차역전파법을 적용한 신경망 구현하기
# two_layer_net.py
import sys,os
sys.path.append(os.pardir) # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
from collections import OrderedDict
from common.layers import *
from common.gradient import numerical_gradient
class TwoLayerNet:
'''2층 신경망 구현'''
def __init__(self, input_size,
hidden_size, output_size, weight_init_std=0.01):
'''
초기화 수행
Params:
- input_size: 입력층 뉴런 수
- hidden_size: 은닉층 뉴런 수
- output_size: 출력층 뉴런 수
- weight_init_std: 가중치 초기화 시 정규분포의 스케일
'''
# 가중치 초기화
self.params = {
'W1': weight_init_std * np.random.randn(input_size, hidden_size),
'b1': np.zeros(hidden_size),
'W2': weight_init_std * np.random.randn(hidden_size, output_size),
'b2': np.zeros(output_size)
}
# 계층 생성
self.layers = OrderedDict({
'Affine1': Affine(self.params['W1'], self.params['b1']),
'Relu1': Relu(),
'Affine2': Affine(self.params['W2'], self.params['b2'])
})
self.last_layer = SoftmaxWithLoss()
def predict(self, x):
'''예측(추론)
Pararms:
- x: 이미지 데이터'''
for layer in self.layers.values():
x = layer.forward(x)
return x
def loss(self, x, t):
'''
손실함수의 값을 계산
Params:
- x: 이미지데이터, t: 정답 레이블
'''
y = self.predict(x)
return self.last_layer.forward(y, t)
def accuracy(self, x, t):
'''
정확도 계산
Params:
- x: 이미지 데이터
- t: 정답 레이블
'''
y = self.predict(x)
y = np.argmax(y, axis=1)
if t.ndim != 1:
t = np.argmax(t, axis=1)
accuracy = np.sum(y==t) / float(x.shape[0])
return accuracy
def numerical_gradient(self, x, t):
'''
미분을 통한 가중치 매개변수의 기울기 계산
Params:
- x: 이미지 데이터
- t: 정답 레이블
'''
loss_W = lambda W: self.loss(x, t)
grads = {
'W1': numerical_gradient(loss_W, self.params['W1']),
'b1': numerical_gradient(loss_W, self.params['b1']),
'W2': numerical_gradient(loss_W, self.params['W2']),
'b2': numerical_gradient(loss_W, self.params['b2'])
}
return grads
def gradient(self, x, t):
# forward
self.loss(x, t)
# backward
dout = 1
dout = self.last_layer.backward(dout)
layers = list(self.layers.values())
layers.reverse()
for layer in layers:
dout = layer.backward(dout)
# 결과 저장
grads = {
'W1': self.layers['Affine1'].dW, 'b1': self.layers['Affine1'].db,
'W2': self.layers['Affine2'].dW, 'b2': self.layers['Affine2'].db
}
return grads
7.3 오차역전파법으로 구한 기울기 검증하기
수치 미분을 통해 구한 기울기와 오차역전파법의 결과를 비교하여 오차역전파를 제대로 구현했는지 검증하는 작업을 기울기 확인(gradient check)이라고 한다.
%%time
# gradient_check.py
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
# mnist load
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
network = TwoLayerNet(input_size=28*28, hidden_size=50, output_size=10)
x_batch = x_train[:3]
t_batch = t_train[:3]
grad_numerical = network.numerical_gradient(x_batch, t_batch)
grad_backprop = network.gradient(x_batch, t_batch)
# 각 가중치의 절대 오차의 평균을 구한다.
for key in grad_numerical.keys():
diff = np.average(np.abs(grad_backprop[key] - grad_numerical[key]))
print(key,":", str(diff))
W1 : 4.479721446541244e-10
b1 : 2.5485543061868916e-09
W2 : 4.349602602871501e-09
b2 : 1.393278526204411e-07
Wall time: 6.78 s
7.4 오차역전파법을 사용한 학습 구현하기
%%time
# train_neuralnet.py
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
# mnist load
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
network = TwoLayerNet(input_size=28*28, hidden_size=50, output_size=10)
# Train Parameters
iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
iter_per_epoch = max(train_size / batch_size, 1)
train_loss_list, train_acc_list, test_acc_list = [], [], []
for step in range(1, iters_num+1):
# get mini-batch
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
# 기울기 계산
#grad = network.numerical_gradient(x_batch, t_batch) # 수치 미분 방식
grad = network.gradient(x_batch, t_batch) # 오차역전파법 방식(압도적으로 빠르다)
# Update
for key in ('W1', 'b1', 'W2', 'b2'):
network.params[key] -= learning_rate * grad[key]
# loss
loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)
if step % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
print('Step: {:4d}\tTrain acc: {:.5f}\tTest acc: {:.5f}'.format(step,
train_acc,
test_acc))
print('Optimization finished!')
Step: 600Train acc: 0.90450Test acc: 0.90560
Step: 1200Train acc: 0.92288Test acc: 0.92570
Step: 1800Train acc: 0.93220Test acc: 0.93200
Step: 2400Train acc: 0.94605Test acc: 0.94460
Step: 3000Train acc: 0.95430Test acc: 0.95210
Step: 3600Train acc: 0.95993Test acc: 0.95870
Step: 4200Train acc: 0.96360Test acc: 0.95870
Step: 4800Train acc: 0.96682Test acc: 0.96320
Step: 5400Train acc: 0.96930Test acc: 0.96380
Step: 6000Train acc: 0.97108Test acc: 0.96450
Step: 6600Train acc: 0.97318Test acc: 0.96690
Step: 7200Train acc: 0.97557Test acc: 0.96890
Step: 7800Train acc: 0.97698Test acc: 0.96760
Step: 8400Train acc: 0.97808Test acc: 0.96990
Step: 9000Train acc: 0.97835Test acc: 0.97030
Step: 9600Train acc: 0.98035Test acc: 0.97020
Optimization finished!
Wall time: 26.6 s
출처: https://excelsior-cjh.tistory.com/171?category=940400 [EXCELSIOR]
'보안' 카테고리의 다른 글
파이썬 IndentationError: unindent does not match any outer indentation level 오류 (0) | 2020.06.11 |
---|---|
파이썬 ModuleNotFoundError (0) | 2020.06.05 |
와이어샤크 No interfaces found 해결법 + 기능소개 (1) | 2019.12.20 |
2019년 상반기 사이버위협 분석 보고서 (0) | 2019.08.16 |
E: Sub-process /usr/bin/dpkg returned an error code (2)? 오류 해결 (0) | 2019.05.22 |