학습 알고리즘 구현하기
1단계 - 미니배치
훈련 데이터 중 일부를 무작위로 가져온다. 이렇게 선별한 데이터를 미니배치라 하며, 그 미니배치의 손실 함수 값을 줄이는 것이 목표이다.
2단계 - 기울기 산출
손실함수에 대한 각 가중치 매개변수의 기울기를 구한다.
3단계 - 매개변수 갱신
가중치 매개변수를 learning rate 만큼 기울기 방향으로 갱신한다.
4단계 - 반복
1~3단계를 반복한다.
2층 신경망 클래스 구현하기
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
# 가중치 초기화
self.params = {}
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params['b1'] = np.zeros(hidden_size)
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
생성자는 매개변수를 초기화한다. 가중치는 표준편차가 weight_ini_std 인 정규분포가 되도록 랜덤 샘플링한다.
def predict(self, x):
W1, W2 = self.params['W1'], self.params['W2']
b1, b2 = self.params['b1'], self.params['b2']
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = sigmoid(a2)
return y
forward 부분
def loss(self, x, t):
y = self.predict(x)
return cross_entropy_error(y, t)
def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1)
t = np.argmax(t, axis=1)
accuracy = np.sum(y == t) / float(x.shape[0])
return accuracy
손실함수는 cross_entropy_error 사용
def numerical_gradient(self, x, t):
loss_W = lambda W: self.loss(x, t)
grads = {}
grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
return grads
가중치 매개변수 갱신을 위한 수치미분 부분이다. numerical_gradient는 loss_W라는 손실함수에 대한 각 파라미터의 수치미분을 계산하고 각각의 grads라는 딕셔너리 변수에 저장한다.
이 클래스를 가지고 학습을 진행하면 속도가 매우 느린데, numerical_gradient가 중심 차분으로 기울기를 구하기 때문이다. 매 iteration 마다 이러한 계산을 하면 느릴 수 밖에 없다. 왜냐하면 수치미분보다는 해석학으로 미분값을 구하는 것이 더 빠르기 때문이다.
예를 들어 $y = x^2$이 있고 우리는 해석적으로 y의 도함수가 $2x$임을 알고 있다. 하지만 수치미분은 이를 중심 차분으로 구하기 때문에 계산량이 많아져 느릴 수 밖에 없다. 이 부분은 다음 장에서 개선한다.
학습 구현
이 클래스를 가지고 학습을 진행하는 것은 시간이 오래 걸리고 비효율적이라 gradient를 어떻게 갱신하는지만 알아보겠다.
for i in range(iters_num):
# 미니배치 만들기
batch_mask = np.random.choice(num_train, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
# gradient 계산하기
grad = network.numerical_gradient(x_batch, t_batch)
# 계산된 gradient로 매개변수 갱신하기
for key in grad.keys():
network.params[key] -= learning_rate * grad[key]
매 iteration마다 미니배치를 만들고 미니배치에 대한 gradient를 구한 뒤 네트워크의 파라미터를 갱신한다.
'책 > 밑바닥부터 시작하는 딥러닝' 카테고리의 다른 글
5장 오차역전파법 (2) (0) | 2023.09.19 |
---|---|
5장 오차역전파법 (1) (0) | 2023.09.19 |
4장 신경망 학습 (1) (0) | 2023.09.13 |
3장 신경망 (0) | 2023.09.13 |
2장 퍼셉트론 (0) | 2023.09.13 |