728x90
반응형


출처 : 밑바닥 부터 시작하는 딥러닝 (한빛미디어)




신경망 학습이 이루어지는 순서는 다음과 같다. 



전제

신경망에는 적응 가능한 가중치와 편향이 있고, 이 가중치와 편향을 훈련 데이터에 적응하도록 조정하는 과정을 "학습" 이라고 한다. 신경망 학습은 아래와 같이 4단계로 수행하게 된다.


1단계 미니배치

훈련 데이터 중 일부를 무작위로 가져온 뒤 미니배치의 손실 함수 값을 줄이는 과정을 거친다.


2단계 기울기 산출

미니배치의 손실 함수 값을 줄이기 위해 각 가중치 매개변수의 기울기를 구한다. 기울기는 손실함수의 값을 가장 작게 하는 방향을 제시하게 된다.


3단계 매개변수 갱신

가중치 매개변수를 기울기 방향으로 아주 조금 갱신한다.


4단계 반복

1~3 단계를 반복한다.



이는 6절에서 다루었던 경사 하강법을 이용하여 매개변수를 갱신하는 방법이며, 이때 데이터를 미니배치로 무작위로 선정하기 때문에 "확률적 경사 하강법(Stochastic Gradient Descent)" 이라고 한다. 확률적으로 무작위로 골라낸 데이터에 대해 수행하는 경사 하강법이라는 뜻이다.


대부분의 딥러닝 프레임워크는 확률적 경사 하강법의 영어 머리글자를 딴 SGD 라는 함수로 이 기능을 구현하고 있다. 


2층 신경망 클래스를 구현하려면 하나의 클래스를 먼저 구현해야한다.

신경망을 파이썬으로 구현할 때 제일 먼저 조심해야 할 것은 들여쓰기와 오타인점을 숙지하길 바란다. 필자는 들여쓰기를 하나 잘못해서 에러가 났었다... 들여쓰기 덜하고 더했다고 코드 인식이 안되는 경우가 있었다.


밑바닥부터 시작하는 딥러닝 코드는 아래 링크에 있다. 


https://github.com/WegraLee/deep-learning-from-scratch



코드를 실행하는 방법은 각 장의 디렉터리로 이동한 후 파이썬 명령을 실행하면 된다. 다른 디렉터리에서 하면 안될 수 있으므로 주의하자. 나는 직접 구현을 목표로 하고있기 때문에 단순히 돌려보는 식이 아닌 직접 써가면서 하나씩 이해하려고 한다..



먼저 필요한 함수들을 import 해주거나, 직접 구현해준다. (Sigmoid, ReLu, ...)


    


이 TwoLayerNet의 구현은 스탠퍼드 대학교의 CS231n 수업에서 제공한 파이썬 소스 코드를 참고했다고 한다. 이 수업이 유명해서 방학을 이용해 다 들어보려고 한다. 


그 다음 2층 신경망을 하나의 클래스로 구현하는 것 부터 시작한다.



이 TwoLayerNet 클래스가 사용하는 변수는 아래와 같다.


 변수

설명 

Params

 신경망의 매개변수를 보관하는 딕셔너리 변수 (인스턴스 변수)

params['W1']은 첫번째 층의 가중치, params['b1']은 첫번째 층의 편향 

params['W2']는 두번째 층의 가중치, params['b2']은 두번째 층의 편향 

 grads

기울기 보관하는 딕셔너리 변수 (numerical_gradient(), gradient() 메소드의 반환값) 

grads['W1']은 첫번째 층의 가중치의 기울기, grads['b1']은 첫번째 층의 편향의 기울기

grads['W2']은 두번째 층의 가중치의 기울기, grads['b2']은 두번째 층의 편향의 기울기



TwoLayerNet 클래스의 메소드는 아래와 같다. 


 메소드

설명 

__init__(self, input_size, hidden_size, output_size)

 초기화를 수행한다. 인수는 순서대로 입력층의 뉴런수, 

 은닉층의 뉴런수, 출력층의 뉴런수

 predict(self, x)

 예측(추론)을 수행한다. 인수 x는 이미지 데이터 

 loss(self, x, t)

 손실함수의 값을 구한다. 인수 x는 이미지 데이터, t는 정답 레이블

 accuracy(self, x, t)

 정확도를 구한다. 인수 x는 이미지데이터, t는 정답 레이블

 numerical_gradient(self, x, t)

 가중치 매개변수의 기울기를 구한다. 

 인수 x는 이미지데이터, t는 정답 레이블

 gradient(self, x, t)

 가중치 매개변수기울기를 구한다. 

 numerical_gradient 함수의 성능 개선판 (시간 축소!)



TwoLayerNet 클래스는 딕셔너리인 params 와 grads를 인스턴스 변수로 갖는다. params 변수에는 가중치 매개변수가 저장되는데, 예를 들어 1번째 층의 가중치 매개변수는 params['W1'] 키에 넘파이 배열로 저장된다. 편향도 마찬가지이다. 그리고 이 변수에 저장된 가중치 매개변수가 예측처리(순방향 처리)에서 사용된다. 


grads 변수에는 params 변수에 대응하는 각 매개변수의 기울기가 저장된다. 


초기화 함수(__init__)에서는 예를 들어 손글씨 숫자 인식에서는 크기가 28x28 인 입력이미지가 총 784개이고, 출력은 10개가 된다. 은닉층의 값은 적당한 값을 설정한다. 


초기화 함수에서 가중치 매개변수도 초기화 해주는데 (weight_init_std = 0.01) 이 값은 신경망 학습의 성공을 좌우하기도 한다. 


그리고 마지막으로 중요한 numerical_gradient() 메소드는 각 매개변수의 기울기를 계산하게 된다. 수치 미분 방식으로 각 매개변수의 손실 함수에 대한 기울기를 계산하게 된다. 마지막 gradient() 함수는 오차역전파법을 사용하여 기울기를 효율적이고 빠르게 계산한다 (5장 오차역전파법 에서 구현 될 내용이지만 예제를 돌려보는 겸 이용해보기로 한다)


참고로 수치 미분 방식으로 매개변수의 기울기를 계산하게 되는데 오차역전파법을 이용한다면 거의 같은 결과를 빠르게 얻을 수 있다고 한다. 이 정도만 알고 넘어간 뒤 다음 장에서 배워보도록 해야겠다.


그리고 나서 신경망 학습 구현이 완료되면 앞에서 설명했던 미니배치 학습을 활용하여 결과를 확인해 볼 수 있다. 모든 데이터를 돌리면 시간이 많이 소요되고 GPU 성능도 배제할 순 없기 때문에 미니배치 학습을 이용해보기로 한다.


참고로 미니배치 학습이란 일부를 무작위로 꺼내고 그 미니배치에 대해서 경사법으로 매개변수를 갱신하는 방법이다.


여기서는 MNIST 데이터 셋을 사용하여 학습을 수행해 보기로 한다. 

역시나 밑바닥부터 시작하는 딥러닝에서 제공된 소스코드를 참고하였다.

일단 MNIST 데이터셋을 읽어온다. 



여기서는 미니배치 크기를 100으로 설정하였다. 즉, 매번 60,000개의 훈련데이터에서 임의로 100개의 데이터를 추려낸다. (이미지 데이터와 정답 레이블 데이터)


그리고 그 100개의 미니배치를 대상으로 확률적 경사 하강법을 수행해 매개변수를 갱신한다.


"학습을 반복하면 반복할수록 손실함수의 값은 점차 줄어들게 된다."




손실함수의 값이란 정확히는 훈련 데이터의 미니배치에 대한 손실함수의 값이다.


훈련 데이터의 손실 함수 값이 작아지는 것은 신경망이 잘 학습하고 있다는 방증이지만, 이 결과만으로는 다른 데이터셋에도 비슷한 실력을 발휘할지는 테스트해봐야 알게 된다.


신경망 학습에서는 훈련 데이터 외의 데이터를 올바르게 인식하는 지를 확인해야한다. 다른 말로 오버피팅을 일으키지 않는지 확인해야한다. 오버피팅(과적합) 되었다는 것은 예를 들어 훈련 데이터에 포함된 이미지만 제대로 구분하고, 그렇지 않은 이미지들은 식별 할 수 없다는 뜻이다.


신경망 학습의 원래 목표는 범용적인 능력을 익히는 것이기 때문에, 훈련 데이터에 포함되지 않은 데이터들도 사용하여 평가해보아야 한다. 


다음 구현에서는 학습 도중 정기적으로 훈련데이터와 시험데이터를 대상으로 정확도를 기록한다. 


* 에폭 : 에폭은 하나의 단위이다. 1에폭은 학습에서 훈련데이터를 모두 소진했을 대의 횟수에 해당한다. 훈련 데이터 10,000개를 100개의 미니배치로 학습할 경우, 확률적 경사 하강법을 100회 반복하면 모든 훈련 데이터를 소진하게 되는데, 이때 100회가 1에폭이 된다. 


다음은 미니배치 학습을 이용한 정확도 측정 구현 소스와 그에 대한 결과이다. 




여기서는 1에폭마다 모든 훈련 데이터와 시험 데이터에 대한 정확도를 계산하고, 그 결과를 기록한다. 정확도를 1에폭마다 계산하는 이유는 for문안에서 매번 계산하기에는 시간이 오래걸리고, 또 그렇게까지 자주 기록할 필요도 없기 때문이다. 

 

 

 


 


위 그래프에서는 훈련 데이터에 대한 정확도를 실선으로, 시험데이터에 대한 정확도를 점선으로 그렸는데 에폭이 진행될 수록 (학습이 진행될 수록) 훈련 데이터와 시험 데이터를 사용하고 평가한 정확도가 모두 좋아지고 있는 양상을 보인다. 두 선이 거의 겹쳐있기 때문에 두 정확도에는 차이가 없음을 나타낸다. 그렇기 때문에 이 양상은 오버피팅이 일어나지 않았다고 할 수 있다. 


만약 한쪽 데이터에만 편향된 오버피팅(과적합)이 일어나게 된다면 시험데이터에 대한 정확도가 점차 떨어지는 양상을 보이게 된다. 이 순간을 포착해 학습을 중단하게 된다면 오버피팅을 효과적으로 예방 할 수 있는데 이 때 이 기법을 조기종료(Early Stopping) 이라고 하며, 다음에 배울 가중치 감소, 드롭아웃과 함께 등장하는 오버피팅 예방법들 중 하나이다. 








다시 정리해보자면 신경망이 학습을 수행할 수 있도록 손실 함수라는 지표를 도입하게 되었는데, 이 손실 함수를 기준으로 그 값이 가장 작아지는 가중치 매개변수 값을 찾아내는 것이 신경망 학습의 목표이다. 또, 가능한 한 작은 손실 함수의 값을 찾는 수법으로 경사법이 있는데 이는 함수의 기울기를 이용하는 방법이다. 







728x90
반응형