혜온의 이것저것

[Chapter 1 신경망 복습] 4 신경망으로 문제를 풀다 본문

Deep Learning/밑바닥부터 시작하는 딥러닝2

[Chapter 1 신경망 복습] 4 신경망으로 문제를 풀다

혜온 :) 2022. 2. 3. 15:01

1.4.1 스파이럴 데이터셋

import sys
sys.path.append('..')
from dataset import spiral
import matplotlib.pyplot as plt

x,t=spiral.load_data()
print('x',x.shape)	#입력데이터 (300,2)
print('t',t.shape)	#정답레이블 (300,2)

t는 원핫 벡터로, 정답에 해당하는 클래스에는 1이, 그 외에는 0이 레이블 되어 있다.

이 데이터가 어떤 모습인지 그려보면 아래와 같다.

입력은 2차원 데이터이고, 분류할 클래스 수는 3개가 있다. 이 그래프를 보면 직선만으로는 클래스들을 분리할 수 없음을 알 수 있다. 따라서 비선형 분리를 학습해야 한다.

 

1.4.2 신경망 구현

은닉층이 하나인 신경망을 구현한다.

import sys
sys.path.append('..')
import numpy as np
from common.layers import Affine, Sigmoid, SofrmaxWithLoss

class TwoLayerNet:
	def __init__(self, input_size, hidden_size, output_size):
    	I,H,O=input_size, hidden_size, output_size
        
        # 가중치와 편향 초기화
        W1=0.01*np.random.randn(I,H)
        b1=np.zeros(H)
        W2=0.01*np.random.randn(H,O)
        b2=np.zeros(0)
        
        # 계층 생성
        self.layers=[
        Affine(W1,b1),
        Sigmoid(),
        Affine(W2,b2)
        ]
        self.loss_layer=SoftmaxWithLoss()
        
        # 모든 가중치와 기울기를 리스트에 모은다.
        self.parmas,self.grads=[],[]
        for layer in self.layers:
        	self.params+=layer.params
            self.grads+=layer.grads
            
    def predict(self,x):
    	for layer in self.layers:
        	x=layer.forward(x)
        return x
        
    def forward(self,x,t):
    	score=self.predict(x)
        loss=self.loss_layer.forward(score,t)
        return loss
        
    def backward(self,dout=1):
    	dout=self.loss_layer.backward(dout)
        for layer in reversed(self.layers):
        	dout=layer.backward(dout)
        return dout

가중치를 작은 무작위 값으로 설정하면 학습이 잘 진행될 가능성이 커진다.

신경망에서 사용하느 처리 블록들을 계층 단위로 미리 구현해놨으므로 여기에서는 그 계층들의 forward()와 backward()를 적절한 순서로 호출만 하면 된다.

 

1.4.3 학습용 코드

학습을 수행하는 코드이다.

학습 데이터를 읽어 들여 신경망과 옵티마이저를 생성한다. 그리고 앞 절에서 본 학습의 네단계의 절차대로 학습을 수행한다.

import sys
sys.path.append('..')
from common.optimizer import SGD
from dataset import spiral
import matplotlib.pyploy as plt
from two_layer_net import TwoLayerNet

# 1) 하이퍼파라미터 설정
max_epoch=300
batch_size=30
hidden_size=10
learning_rate=1.0

# 2) 데이터 읽기, 모델과 옵티마이저 생성
x,t=spiral.load_data()
model=TwoLayerNet(input_size=2,hidden_size=hidden_size,output_size=3)
optimizer=SGD(lr=learning_rate)

# 학습에 사용하는 변수
data_size=len(x)
max_iters=data_size//batch_size
total_loss=0
loss_count=0
loss_list=[]

for epoch in range(max_epoch):
	# 3) 데이터 뒤섞기
    idx=np.random.permutation(data_size)
    x=x[idx]
    t=t[idx]
    
    for iters in range(max_iters):
    	batch_x=x[iters*batch_size:(iters+1)*batch_size]
        batch_t=t[iters*batch_size:(iters+1)*batch_size]
        
        # 4) 기울기를 구해 매개변수 갱신
        loss=model.forward(batch_x,batch_t)
        model.backward()
        optimzer.update(model.params,model.grads)
        
        total_loss+=loss
        loss_count+=1
        
        # 5) 정기적으로 학습 경과 출력
        if (iters+1)%10==0:
        	avg_loss=total_loss/loss_count
            print('| 에폭 %d | 반복 %d / %d | 손실 %.2f' % (epoch+1, iters+1, max_iters, avg_loss))
            loss_list.append(avg_loss)
            total_loss, loss_count=0,0

1) 하이퍼파라미터를 설정한다. 구체적으로는 학습하는 에폭 수, 미니배치크기, 은닉층의 뉴런 수, 학습률을 설정한다.

2) 데이터를 읽어 들이고, 신경망과 옵티마이저를 설정한다. 이전에 이미 2층 신경망을 TwoLayerNet클래스로, 옵티마이저를 SGD클래스로 구현해놨으니, 여기서는 클래스들을 이용했다.

합습은 미니배치 방식으로 진행되며 데이터를 무작으로 선택한다.

3) 에폭 단위로 데이터를 섞고, 뒤섞은 데이터 중 앞에서부터 순서대로 뽑아낸다.

4) 기울기를 구해 매개변수를 갱신한다.

5) 정기적으로 학습 결과를 출력하고, 10번째 반복마다 손실의 평균을 구해 loss_list변수에 추가한다.

 

이 코드를 실행하여 얻은 결과를 그래프로 그리면 아래와 같다.

학습을 진행함에 따라 손실이 준다. 올바른 방향으로 학습되고 있다는 뜻이다.

학습 후 신경망 영역을 어떻게 분리했는지 시각화해보면 다음과 같다.

학습된 신경망은 나선형 패턴을 올바르게 파악했음을 알 수 있다. 즉, 비선형 분리 영역을 학습할 수 있다.

이처럼 신경망에 은닉층을 추가하면 더 복잡한 표현이 가능해진다. 층을 더 깊게 쌓으면 표현력 또한 더 풍부해지는 것이 딥러닝의 특징이다.

 

1.4.4 Trainer 클래스

이 책에서는 신경망 학습 수행을 많이 하는데 잎 절에서 본 학습코드가 자주 필요하다. 따라서 이 책에서는 학습을 수행하는 역할을 Trainer라는 클래스로 제공한다.

이 클래스의 초기화 메서드는 신경망과 옵티마이저를 인수로 받는다.

model=TwoLayerNet(...)
optimizer=SGD(lr=1.0)
trainer=Trainer(model,optimizer)

fit() 메서드를 호출해 학습을 시작한다.

import sys
sys.path.append('..')
from common.optimizer import SGD
from common.trainer import Trainer
from dataset import spiral
from two_layer_net import TwoLayerNet

max_epoch=300
batch_size=30
hidden_size=10
learning_rate=1.0

x,t=spiral.load_data()
model=TwoLayerNet(input_size=2, hidden_size=hidden_size, output_size=3)
optimizer=SGD(lr=learning_rate)

trainer=Trainer(model,optimizer)
trainer.fit(x,t,max_epoch,batch_size,eval_interval=10)
trainer.plot()

이 코드를 실행하면 이전 절과 같은 신경망 학습이 이뤄진다.

 

Comments