딥러닝 직접 구현하기 프로젝트 2-4차시 - Model 제작하기
* 모든 코드는 제 깃허브 (cdjs1432/DeepLearningBasic: Deep Learning from scratch)에서 확인할 수 있습니다.
원래는 바로 Optimizer를 제작하려 했으나, 생각해 보니 코드가 이래서는 바로 들어가기는 좀 그럴 것 같습니다.
따라서 이번에는 코드를 대충 정리를 하고 "예쁘게" 만들어 보겠습니다.
(이론 설명같은 건 없다는 뜻)
그냥 어떤 부분이 바뀌었는지, 어떻게, 왜 바꾸었는지 간결하게만 설명하고 넘어가겠습니다.
import numpy as np
import pandas as pd
from Model import Model
import Layers
# load data
train = pd.read_csv("../Data/MNIST_data/mnist_train.csv")
y_train = train["label"]
x_train = train.drop("label", 1)
x_train = x_train.values / x_train.values.max()
y_train = y_train.values
# y to one-hot
one_hot = np.zeros((y_train.shape[0], y_train.max() + 1))
one_hot[np.arange(y_train.shape[0]), y_train] = 1
y_train = one_hot
# initialize parameters
num_classes = y_train.shape[1]
hidden = 50
일단 ModelTest.py (테스트용 파일)을 설명하겠습니다.
저번과 아주 동일한 훈련 방식을 거칠 것이니, 데이터도 그대로 가져옵니다. (복붙)
model = Model()
model.addlayer(Layers.MulLayer(), input_size=(784, 32), name="w1")
model.addlayer(Layers.AddLayer(), input_size=32, name='b1')
model.addlayer(Layers.SigmoidLayer(), activation=True, name='sigmoid1')
model.addlayer(Layers.MulLayer(), input_size=(32, 10), name="w2")
model.addlayer(Layers.AddLayer(), input_size=10, name='b2')
model.addlayer(Layers.SoftmaxLayer(), activation=True, name='softmax')
model.train(x_train, y_train, 10000, 0.01, 128)
달라진 부분은 이 부분입니다.
직접 데이터를 하나하나 넣어주는 것이 아니라, Model이라는 모듈을 만들어서 예쁘게 만들어 주자는 것이 주요 내용입니다.
import numpy as np
from Layers import *
class Model:
def __init__(self):
self.params = {}
self.grads = {}
self.keys = []
self.layers = {}
self.num = 0
self.loss = None
self.pred = None
def addlayer(self, layer, activation=False, input_size=None, name=None):
if name is None:
name = str(self.num)
self.keys.append(name)
self.num += 1
self.layers[name] = layer
if not activation:
self.params[name] = np.random.uniform(-1, 1, input_size)
self.layers[name].param = self.params[name]
def predict(self, x, y):
for i in range(len(self.keys) - 1):
key = self.keys[i]
x = self.layers[key].forward(x)
self.loss = self.layers[self.keys[-1]].forward(x, y)
self.pred = softmax(x)
def train(self, x_train, y_train, optimizer, epoch, learning_rate, batch_size):
for epochs in range(epoch):
batch_mask = np.random.choice(x_train.shape[0], batch_size)
x = x_train[batch_mask]
y = y_train[batch_mask]
self.predict(x, y)
dout = self.layers[self.keys[-1]].backward()
for i in reversed(range(len(self.keys) - 1)):
key = self.keys[i]
dout = self.layers[key].backward(dout)
if key in self.params:
self.grads[key] = self.layers[key].grad
self.params[key] -= learning_rate * self.grads[key]
if epochs % (epoch / 10) == 0:
print("ACC on epoch %d : " % epochs, (self.pred.argmax(1) == y.argmax(1)).mean())
print("LOSS on epoch %d : " % epochs, self.loss)
Model.py 부분입니다.
원래 Main에 있었던 grads, params 등등을 모두 이 Model 안에 넣었습니다.
그 뒤, addlayer로 Layer을 모델에 각각 추가하는 방식으로 모델의 레이어가 구현되도록 하였습니다.
이 때, activation 여부를 확인해서 activation function인 경우에는 grads와 params가 존재하지 않게 막아주었습니다.
(저번 코드의 if 'Relu'... 부분을 바꾼 것입니다.)
predict는 원래 train하는 과정에서의 forward 하는 과정을 따 온 함수입니다.
원래는 train 안에 그대로 넣고자 하였으나, model에서 직접 predict를 해야 할 일이 있을 것 같아서 따로 뺐습니다.
그리고 train 부분은 원래 훈련시키는 부분과 매우 유사합니다.
차이점은, lastlayer를 따로 빼지 않는 대싱 반복문을 range(len(self.keys)-1)로 바꾸어서, 마지막 layer은 따로 빼서 연산하도록 했습니다.
기반은 SGD로 구현하였으나, 다음 차시에 바로 train을 Optimizer 모듈에 구현하게 될 것 같습니다.
그래서 다음 차시에는, SGD 말고도 RMSPROP과 같은 다른 훈련 방식을 사용해 보도록 하겠습니다.
class MulLayer:
def __init__(self, param=None):
self.x = None
self.param = param
self.grad = None
def forward(self, x):
self.x = x
return x.dot(self.param)
def backward(self, dout):
self.grad = np.dot(self.x.T, dout)
return np.dot(dout, self.param.T)
class AddLayer:
def __init__(self, param=None):
self.x = None
self.param = param
self.grad = None
def forward(self, x):
self.x = x
return x + self.param
def backward(self, dout):
self.grad = dout.mean()
return dout
이 부분은 Layers.py 부분입니다.
MulLayer와 AddLayer에서 w, b를 그냥 param으로 통일하고, __init__시에 직접 parameter를 집어넣지 않아도 되게 만들었습니다.
param으로 이름을 통일한 것은 반복문에서의 train때의 편의성을 위함이고, __init__시에 직접 param을 집어넣지 않아도 되게 만든 것은 Model에서의 AddLayer를 만들기 위함입니다.
(위에서 보시면 아시겠지만, model.addlayer()부분에서 MulLayer과 AddLayer에 따로 params를 집어넣지 않고, Input_size만을 넣어서 자동으로 랜덤 값이 들어가도록 했습니다.)
이렇게 코드를 갈아엎어 보았습니다.
다음 시간에는 드디어, Optimizer를 구현해 보겠습니다.
'인공지능 > 딥러닝 직접 구현하기 프로젝트' 카테고리의 다른 글
딥러닝 직접 구현하기 프로젝트 2-5차시 - Gradient Descent Optimizer 구현하기 (2) (2) | 2020.07.07 |
---|---|
딥러닝 직접 구현하기 프로젝트 2-5차시 - Optimizer (Momentum, NAG) 구현하기 (1) (4) | 2020.06.30 |
딥러닝 직접 구현하기 프로젝트 2-3차시 - Activation Function (활성화 함수) 구현하기 (2) | 2020.06.17 |
딥러닝 직접 구현하기 프로젝트 2-2차시 - Multi-Layer Softmax Classification 구현하기 (0) | 2020.06.16 |
딥러닝 직접 구현하기 프로젝트 2-1차시 - Single-Layer Gradient Descent 구현하기 (0) | 2020.06.16 |