Assignment 3: Simple Neural Network - gradient 적용 업그레이드

 
 Assignment2에서 구현한 간단한  Neural Network 모델에 Gradient Descent를 적용하여 성능 향상을 시킨 버전 구현
   개요:
     1. 이번에 사용할 자료는 과제 2에서 좀 더 발전 시킨 SimpleNetData2.csv
10000*201 배열로 되어 있다. 이 행렬의 마지막 열은 이전과 마찬가지로 0-9 사이의 정답 숫자로 되어 있다. .
     2. 과제2를 발전시켜 교재 137페이지에 있는 class TwoLayerNet을 그대로 사용하라. 이 class를 위한 관련 모듈과 함수는 import 하지 말고 한 프로그램에 같이 명시하라 (softmax, gradient 등)  

     3. load_csv 모듈은 이제 SimpleNetData2.csv 자료를 80%는 training으로 20%는 test자료로 랜덤하게 분할하도록 한다.  

     4. filename: Assginment3_yourhakbun.py

(교재 100page, 또는 Deep Learning From Scratch source codes 의 ch04/two_layer_net.py)

import sys, os
sys.path.append(os.pardir)
from csv import reader
import numpy as np

class TwoLayerNet:

     def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01):

    def predict(self, x):

    def loss(self, x, t):

    def accuracy(self, x, t): def gradient(self, x, t):

         #교재의 numerical_gradient는 사용하지 말 것.

     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]

        # forward

        a1 = np.dot(x, W1) + b1

        z1 = sigmoid(a1)

        a2 = np.dot(z1, W2) + b2

        y = softmax(a2)

        # backward

        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

 

# Load a CSV file
def load_csv(filename):
   
x_train = list()
    t_train = list()

    x_test = list()
    t_test = list()

    
    with open(filename, 'r') as file:
        csv_reader = reader(file)
   
(여기에 코드 작성)
    읽어 온 자료를 numpy 배열로 바꾸고 이 때 x_train과 y_train은 각각 float형과 int형으로 한다. 80%를 훈련자료로, 20%를 시험자료로 나누고  훈련자료와 정답을 분리
    참고: 강의 자료 중

How to Implement Simple Linear Regression From Scratch with Python 참조

    return x_train, t_train, x_test, t_test

def one_hot_encoding(x):
 
     
t_train, t_test 정답 값을 one-hot encoding으로 변형. sklearn, pandas, keras 등에서 제공하는 모듈을 쓰지말고 numpy로 구현해 볼 것 

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T

    x = x - np.max(x) # 오버플로 대책
    return np.exp(x) / np.sum(np.exp(x))


filename = '
SimpleNetData2.csv'
x_train, t_train, x_test, t_test= load_csv(filename)
x_train = one_hot_encoding(x_train)

t_test = one_hot_encoding(t_test)

network = TwoLayerNet(input_size=200, 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 = []

 

# 1에폭당 반복 수

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', 'b1', 'W2', 'b2'):

        network.params[key] -= learning_rate * grad[key]

 

    # 학습 경과 기록

    loss = network.loss(x_batch, t_batch)

    train_loss_list.append(loss)

 

    # 1에폭당 정확도 계산

    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))