핸즈온머신러닝&딥러닝

심층 신경망 훈련하기 3

threegopark 2021. 4. 9. 14:10
728x90

사전훈련된 층 재사용하기

 

아주 큰 규모의 신경망 모델을 처음부터 새로 훈련하는 것은 매우 비효율적이다. 내가 해결하려는 것과 비슷한 유형의 문제를 처리한 신경망이 이미 있는지 찾아본 다음, 그 신경망의 하위층을 재사용하는 것이 보다 효율적이다. 이를 전이학습 이라고 한다.

 

보통 상위 은닉층보다 하위 은닉층(저수준)을 재사용하는 경우가 많은데 기존 상위 은닉층은 새로운 작업에서 유용한 상위 은닉층의 특성과는 상당히 다르기 때문이다.

 

 

 

 

이때 주의할 점은 재사용할 모델에 적용되는 입력 값의 크기가 원래 모델에 사용된 입력 값의 크기가 다르다면 스케일링하여 입력의 크기를 맞춰줘야한다. 왜냐하면 전이 학습은 저수준 특성이 비슷한 입력에서 잘 작동하기 때문이다.

 

 

재사용하는 방법을 간략하게 말하자면

 

1. 먼저 재사용하는 층을 모두 동결시킨다.

(경사 하강법으로 가중치가 바뀌지 않도록 훈련되지 못하는 가중치로 만든다.)

 

2. 모델을 훈련하고 성능을 평가한다.

 

3. 맨 뒤에 있는 한 두개의 은닉층의 동결을 해제하고 역전파를 통해 가중치를 조정하여 성능이 향상되는지 확인한다.

(훈련 데이터가 많을 수록 동결을 해제할 수 있는 은닉층의 수를 늘릴 수 있다. 그리고 훈련시킬 때 학습률을 줄이는 것이 좋다.)

 

4. 만약 성능의 차이가 없거나 저조하다면 동결을 해제한 상위 은닉층을 제거하고 남은 은닉층을 다시 동결해보며 재사용할 은닉층의 적절한 개수를 찾아나간다.

 

 

 

 

케라스를 사용한 전이 학습

 

만약 내가 mnist의 패션 데이터셋을 분류하는 모델 model_A를 사전에 만들었다고 가정하자. 샌들과 셔츠 이미지를 구분하는 이진 분류기를 훈련해야 하는 프로젝트가 생겼을 때 나는 model_A의 몇 가지 은닉층을 재사용하여 새로운 프로젝트를 해결하는데 도움을 받을 수 있다.

 

 

기존 mnist_model_A의 출력층만 제외하고 모두 재사용하는 것이 좋을 것 같다고 판단되어

 

앗 그런데 이렇게 훈련하게 되면 model_B_on_A를 훈련할 때 기존 참조한 model_A까지 영향을 받게 된다.

클론을 만들어서 기존의 모델에는 영향이 없도록 한다.

 

 

이제 마음놓고 model_B_on_A를 훈련할 수 있다. 하지만 기존의 거의 완벽(?)했던 model_A의 출력층을 제외한 층을 가지고왔는데 새로 만들 모델의 출력층은 아주 엉망진창이다. 랜덤하게 초기화되어있다... 그렇기 때문에 새로운 모델 model_B_on_A 를 바로 훈련시키면 큰 오차로 인한 오차 그레이디언트가 재사용된 가중치를 망칠 수 있다.

 

이러한 문제점을 피하기 위한 한 가지 방법은 처음 몇 번의 에포크 동안 재사용된 층을 동결하고 새로운 층에게 적절한 가중치를 학습할 시간을 주는 것이다. (선행학습한 학생들에게 잠깐 쉬라고 하고 이제 막 공부시작한 학생들에게 쫓아갈 시간을 주는 것)

이를 위해 모든 층의 trainable 속성False로 지정하고 모델을 컴파일한다.

 

동결층을 제외하고 어느 정도 모델이 학습되었다면 재사용층의 동결을 해제한 후에 학습을 계속하며 모델을 튜닝한다.

 

아,,, 그리고 일반적으로 재사용된 층의 동결을 해제한 후에는 학습률을 낮추는 것이 좋다. 이렇게 하면 재사용된 가중치가 망가지는 것을 막아준다고 한다.

(기존 optimizer의 lr 디폴트 값은 1e-2 인데 1e-4로 낮춰서 학습하였다.)

 

 

여기서 주의해야 할 부분이 하나 있다 !! 

 

위의 전이 학습을 활용하면 정확도가 많이 오를 수 있는 '가능성'이 커지는 것이지, 무조건 정확도가 오르는 것은 아니다.

타깃 클래스나 랜덤 초깃값을 바꾸면 성능이 떨어질 수도 있다. 특히 '작은 완전 연결 네트워크' 에서는 잘 동작하지 않는다. 패턴 수를 적게 학습하고 완전 연결 네트워크는 특정 패턴을 학습하기 때문일 것이다. 

전이 학습은 조금 더 일반적인 특성을 감지하는 경향이 있는 심층 합성곱 신경망에서 잘 동작한다.

 

 

 

 

비지도 사전훈련

 

이번에는 다른 프로젝트를 진행한다. 이미지 데이터는 많은데,,, 이미지 데이터에 대한 레이블 데이터가 많지가 않은데 설상가상으로 비슷한 작업에 대해 훈련된 모델도 찾을 수가 없다!

뭐,,, 레이블 데이터를 더 많이 모으는 노가다 방법이 있겠지만 이는 비용이 매우 많이 드는 방법이고... 비지도 사전훈련이라는 방법을 활용하는 것이 적절할 것이다.

 

비지도 사전훈련은 풀어야 할 문제가 복잡하고 재사용할 수 있는 비슷한 모델이 없으며 레이블된 훈련 데이터가 적고 그렇지 않은 데이터가 많을 때 효과를 발휘한다.

 

과거에는 층이 많은 모델을 훈련하는 것이 어려웠기 때문에 탐욕적 층 단위 사전훈련 (greedy layer-wise pretraining)이라는 기법을 사용했다. 먼저 하나의 층을 가진 비지도 학습 모델을 훈련하고 (일반적으로 RBM을 사용했다고 한다.) 이 층을 동결하고 그 위에 다른 층을 추가한 다음 모델을 다시 훈련한다. 그 다음 그 위에 새로운 층을 동결하고 그 위에 또 다른 층을 추가하고... 이 과정을 반복했다.

 

오늘날에는 훨씬 간단하게, 한 번에 전체 비지도 학습모델을 훈련하고 RBM 대신 오토인코더나 GAN을 사용한다.

 

비지도 훈련에서는 비지도 학습 기법으로 레이블이 없는 데이터로 모델을 훈련한다. 그 다음 지도 학습 기법을 사용하여 레이블된 데이터에서 최종 학습을 위해 세밀하게 튜닝한다. 비지도 학습 부분은 그림처럼 한 번에 하나의 층씩 훈련하거나 바로 전체 모델을 훈련할 수도 있다.

 

 

보조 작업에서 사전훈련

 

레이블된 훈련 데이터가 많지 않을 경우 또 다른 방법은 훈련 데이터를 쉽게 얻거나 생성할 수 있는 보조 작업에서 첫 번째 신경망을 훈련하는 것이다. 그리고  이 신경망의 하위 층을 실제 작업을 위해 재사용한다.

 

예를 들어 얼굴을 인식하는 시스템을 만들어야 하는데 개인별 얼굴 데이터가 많지 않은 경우 사람마다 사진을 찍어 수 백개의 데이터를 얻는 비효율적인 방법보다는 인터넷에서 무작위로 많은 인물의 이미지를 수집해서 두 개의 다른 이미지가 같은 사람의 것인지 감지하는 모델을 만들고 재사용하는 것이 현명할 것이다.

 

자연어처리 어플리케이션에서는 수백만 개의 텍스트 문서로 이루어진 코퍼스를 다운로드하고 이 데이터에서 레이블된 데이터를 자동으로 생성할 수 있다. 예를 들어 일부 단어를 랜덤하게 지우고 누락된 단어를 예측하는 모델을 훈련할 수 있다. (What are you saying? --? What ___ you saying? : ___ 자리에 was, were을 예측)

 

이렇게 데이터에서 스스로 레이블을 생성하고 지도 학습 기법으로 레이블된 데이터셋에서 모델을 훈련하는 방법자기 지도 학습 이라고 한다. 이 방식은 사람이 레이블을 부여할 필요가 없으므로 비지도 학습의 형태로 분류된다.