728x90
반응형
1. 신경망 구축에 필요한 Layers
import numpy as np
from common.functions import *
class Relu:
def __init__(self):
self.mask = None
def forward(self, x):
self.mask = (x <= 0)
out = x.copy()
out[self.mask] = 0
return out
def backward(self, dout):
dout[self.mask] = 0
dx = dout
return dx
class Sigmoid:
def __init__(self):
self.out = None
def forward(self, x):
out = sigmoid(x)
self.out = out
return out
def backward(self, dout):
dx = dout * (1.0 - self.out) * self.out
return dx
class Affine:
def __init__(self, W, b):
self.W = W
self.b = b
self.x = None
self.original_x_shape = None
#매개변수의 미분
self.dW = None
self.db = None
def forward(self, x):
# 텐서 대응
self.original_x_shape = x.shape
x = x.reshape(x.shape[0], -1)
self.x = x
out = np.dot(self.x, self.W) + self.b
return out
def backward(self, dout):
dx = np.dot(dout, self.W.T)
self.dW = np.dot(self.x.T, dout)
self.db = np.sum(dout, axis=0)
dx = dx.reshape(*self.original_x_shape) #입력 데이터 모양 변경(텐서 대응)
return dx
class SoftmaxWithLoss:
def __init__(self):
self.loss = None
self.y = None
self.t = None
def forward(self, x, t):
self.t = t
self.y = softmax(x)
self.loss = cross_entropy_error(self.y, self.t)
return self.loss
def backward(self, dout=1):
batch_size = self.t.shape[0]
if self.t.size == self.y.size: #one-hot-encoding으로 되어있는 경우
dx = (self.y - self.t) / batch_size
else:
dx = self.y.copy()
dx[np.arange(batch_size), self.t] -= 1
dx = dx / batch_size
return dx
2. 신경망 모델 구축하기
import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.layers import *
from common.gradient import numerical_gradient
from collections import OrderedDict
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01): #각 layer의 노드 개수와 가중치 초기값 설정시 표준편차
#가중치 초기화
self.params={}
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) #평균이 0이고 표준편차가 0.01인 정규분포를 따라 랜덤 추출, 형상은 (input_size x hidden_size)
self.params['b1'] = np.zeros(hidden_size) #zero벡터 생성
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
#Layer 생성
self.layers = OrderedDict() #순서가 있는 딕셔너리이므로 순서가 정해짐
self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1'])
self.layers['Relu1'] = Relu()
self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2'])
self.lastLayer = SoftmaxWithLoss()
def predict(self, x):
for layer in self.layers.values():
x = layer.forward(x)
return x
def loss(self, x, t):
y = self.predict(x)
return self.lastLayer.forward(y, t)
def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1) #argmax는 요소가 최댓값인 index들을 리스트로 나타냄
if t.ndim != 1 : #ndim은 차원의 수를 나타내며 one-hot-encoding이 되어있는 경우 실행
t = np.argmax(t, axis=1)
accuracy = np.sum(y == t) / float(x.shape[0]) #y==t결과인 T/F에서 T의 개수를 sum(맞힌 개수), shape[0] 행의 개수(정답률)
return accuracy
def numerical_gradient(self, x, t):
loss_W = lambda W: self.loss(x, t) #람다 정규식> lambda 변수: return 식
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
def gradient(self, x, t):
#순전파
self.loss(x, t)
#역전파
dout = 1 #맨 마지막 층이므로 다음 층에서 흘러들어오는 값이 없으므로 1(downstream층에서 곱하기 1하면 無의 효과)
dout = self.lastLayer.backward(dout)
layers = list(self.layers.values())
layers.reverse() #리스트의 순서 바꿈
for layer in layers:
dout = layer.backward(dout)
#결과 저장
grads = {}
grads['W1'] = self.layers['Affine'].dW
grads['b1'] = self.layers['Affine'].db
grads['W2'] = self.layers['Affine'].dW
grads['b2'] = self.layers['Affine'].db
return grads
3. 데이터 학습하기
import sys, os
sys.path.append(os.pardir)
import numpy as np
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.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)
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)
728x90
반응형
'AI > 밑딥' 카테고리의 다른 글
딥러닝) 시소러스 , 통계 기반 기법 , 코사인 유사도 (2) | 2021.04.25 |
---|---|
딥러닝) optimizer ( SGD , Momentum , AdaGrad , RMSProp, Adam ) (0) | 2021.03.23 |
딥러닝) Affine , Softmax , Cross Entropy Error 계층 구현 (0) | 2021.03.16 |
딥러닝) 활성화 함수 ReLU 계층 , Sigmoid 계층 구현 (0) | 2021.03.15 |
딥러닝) 오차 역전파 backpropagation , 연쇄법칙 chain rule , 기울기 효율적으로 구하기 (0) | 2021.03.08 |
댓글