티스토리 뷰

딥러닝

신경망 학습 알고리즘 구현

4567은 소수 2021. 1. 12. 23:15

공부 : 밑바닥부터 시작하는 딥러닝 1 chapter 4.5~4.6

 

1. 2층 신경망 클래스 구현 (필요한 내용 주석으로)

import sys, os
sys.path.append(os.pardir)
from common.functions import *
from common.gradient import numerical_gradient

class TwoLayerNet: # 2층 신경망, input_size = 입력층 노드 수, hidden_size = 은닉층 노드 수, output_size = 출력층 노드 수
    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) # 1층의 가중치
        self.params['b1'] = np.zeros(hidden_size) #1층의 편향
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) # 2층의 가중치
        self.params['b2'] = np.zeros(output_size) # 2층의 편향
        
    def predict(self, x): # x : MNIST 이미지 데이터, predict = 2층 신경망 추론 결과 도출
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        
        a1 = np.dot(x, W1) + b1 # 데이터와 가중치, 편향 연산 (1층)
        z1 = sigmoid(a1) # 활성화 함수 : 시그모이드
        a2 = np.dot(z1, W2) + b2 # 데이터와 가중치, 편향 연산 (2층)
        y = softmax(a2)  # 출력함수 : 소프트맥스
        
        return y
    
    def loss(self, x, t): # x : 이미지데이터, t : 정답 레이블, loss : 손실함수 계산
        y = self.predict(x)
        
        return cross_entropy_error(y, t)
    
    def accuracy(self, x, t): # accuracy : 정확도 계산
        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
    
    def numerical_gradient(self, x, t): # 가중치, 편향의 기울기 계산
        loss_W = lambda W: self.loss(x,t)
        
        grads = {} # 기울기 값 저장
        grads['W1'] = numerical_gradient(loss_W, self.params['W1']) # 1층의 가중치의 기울기
        grads['b1'] = numerical_gradient(loss_W, self.params['b1']) # 1층의 편향의 기울기
        grads['W2'] = numerical_gradient(loss_W, self.params['W2']) # 2층의 가중치의 기울기
        grads['b2'] = numerical_gradient(loss_W, self.params['b2']) # 2층의 편향의 기울기
        
        return grads
    
    def gradient(self, x, t): # 기울기 계산 성능 개선
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        
        grads = {}
        
        batch_num = x.shape[0]
        
        # 앞에서부터
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        # 뒤에서부터
        dy = (y - t) / batch_num
        grads['W2'] = np.dot(z1.T, dy)
        grads['b2'] = np.sum(dy, axis=0)
        
        da1 = np.dot(dy, W2.T)
        dz1 = sigmoid_grad(a1) * da1
        grads['W1'] = np.dot(x.T, dz1)
        grads['b1'] = np.sum(dz1, axis=0)
        
        return grads
        
        

2. 미니배치 학습 구현

미니배치의 크기를 100으로 하여 mnist의 60,000개의 훈련 데이터 중 100개를 임의로 선택하여 매개변수 값을 갱신

=> 손실함수 값 최소화하도록 매개변수 값 갱신

import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1

train_loss_list = []

for i in range(iters_num):
    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) # 성능 개선 (속도 증가)
    
    for key in ('W1', 'W2', 'b1', 'b2'):
        network.params[key] -= learning_rate * grad[key]
        
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)
    

train_loss_list 결과

그래프는 train_loss_list의 결과이다. train_loss_list는 미니배치 학습 과정에서의 손실함수 값이고, 해당 결과가 0에 가까워서 최소화를 함을 알 수 있다. 

 

3. 시험 데이터로 평가하기

훈련데이터는 60,000개 중 100개를 임의로 뽑아 10,000번 반복하여 손실함수 값을 최소로 만들었다. 하지만 이것만 가지고는 모든 데이터에 대해 적용했다고 할 수는 없다. 

epoch (에폭)을 이용해 시험 데이터(테스트 데이터)에 대한 정확도를 구해보자. (훈련 데이터와 다른 데이터)

import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1

train_loss_list = []
train_acc_list =[]
test_acc_list =[]

iter_per_epoch = max(train_size / batch_size, 1)

for i in range(iters_num):
    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) # 성능 개선 (속도 증가)
    
    for key in ('W1', 'W2', 'b1', 'b2'):
        network.params[key] -= learning_rate * grad[key]
        
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)
    
    if i%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("train_acc, test_acc : " + str(train_acc)+','+str(test_acc))

주황색 : test_acc, 파란색 : train_acc

에폭 : 60,000개의 데이터를 100개씩 배치해 실행하므로 600회 반복이 1epoch이다. 정확도의 일치여부를 판단하는 것이므로 시험 데이터를 600회 반복할 때마다 train_acc, test_acc 에 정확도 (accuracy)를 추가한다. 

이를 통해 600회 반복마다의 훈련데이터와 시험데이터에 대한 정확도가 얼마나 일치하는 지 알 수 있다.

=> 두 그래프가 거의 일치하므로 손실함수를 최소화하는 과정이 잘 이루어졌다.

 

4. 4장 내용 정리

- 기계학습에서 사용하는 데이터셋은 훈련 데이터와 시험 데이터로 나눠 사용한다. 

- 훈련 데이터로 학습한 모델의 범용 능력을 시험 데이터로 평가한다. (매개변수 갱신이 잘 되었는지)

- 신경망 학습은 손실 함수를 지표로, 손실 함수의 값이 작아지는 방향으로 가중치 매개변수를 갱신한다.

- 가중치 매개변수를 갱신할 때는 가중치 매개변수의 기울기를 이용하고, 기울어진 방향으로 가중치의 값을 갱신하는 작업을 반복한다.

- 아주 작은 값이 주어졌을 때 차분으로 미분하는 것 : 수치 미분

- 수치 미분을 이용해 가중치 매개변수의 기울기 (gradient)를 구한다.

- 수치 미분을 이용하여 매개변수의 기울기를 계산하면 시간이 걸린다. (구현 짧음) 오차역전파법은 기울기를 빠르게 구할 수 있다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함