관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

합성곱 신경망 13 - Knowledge Distillation 본문

인공지능/딥러닝

합성곱 신경망 13 - Knowledge Distillation

huenuri 2024. 11. 3. 15:57

지금까지 학습한 내용을 통해서 딥러닝 모델이 깊고, 넓고, 학습할 파라미터의 수가 많으면 학습이 잘 된다는 사실을 배웠다. 마치 인간의 뇌가 다른 동물과 달리 주름이 많은 것처럼, 파라미터 수가 많을수록 딥러닝 모델 학습이 잘 될 확률이 높아진다.

하지만 딥러닝 모델을 실무에 적용하려면, 파라미터 개수가 많은 넓고 깊은 모델을 사용할 수 없는 경우까 많다. 예를 들어 CCTV와 같은 작은 IoT 디바이스에서 촬영한 이미지로부터 객체를 검출하는 모델을 탑재해야 하는 경우, 사용할 리소스는 굉장히 제한적이다. 고성능 CPU나 GPU를 사용할 수 없고 디바이스에 내장된 메모리도 작은 편이기 때문이다.

 

이럴 때는 어떻게 해야 할까? 파라미터 개수가 많은 큰 모델이 선생님이 되어 크기가 작은 모델을 가르치는 개념으로 Knowledge Distillation이라고 부른다. 우리말로 직역하면 '지식 증류'가 된다. 다음 그림과 같이 큰 모델의 예측과 작은 모델의 예측의 오차와 작은 모델의 손실함수를 줄여 나가는 방향으로 작은 모델의 파라미터를 최적화하게 된다.


 

 

 

지식 증류 실습해보기

필요한 라이브러리를 불러온다.

 

 

 

 

학습에 적용할 주요 파라미터를 설정한다. 다음과 같이 @파라미터를 설정하면, 셀 오른쪽에 표시된 옵션ㅇㄹㅡ 바로 변경하여 적용할 수 있어 편리하다.

 

파라미터 설정이라고 제목을 쓰지도 않았는데 저절로 설정되었다. 

 

 

 

케라스에서 제공하는 mnist 데이터셋을 가져와서 필요한 전처리를 한다. 테서플로 학습이 잘 이루어지도록 자료형을 변환하고 픽셀 값을 정규화한다. load_data 함수는 넘파이 배열로 정리하기 때문에, 다음 코드와 같이 넘파이 reshape 명령으로 사용할 수 있다. 배치 사이즈가 들어갈 축을 axis = 0에 추가한다.

 

 

 

합성곱 레이어를 활용하여 비교적 복잡한 모델을 구성하고, 선생님에 해당하는 teacher 모델로 사용한다. 대략 140만 개의 파라미터를 가지고 있다.

 

 

 

Dense 레이어 2개로 구성된 단순한 구조의 student 모델을 정의하고 s_model_1 변수에 저장한다. 성능을 비교하기 위해 clone_model() 함수를 사용하여 똑같은 구조를 갖는 모델을 복제하고 s_model_2 변수에 저장한다.

 

 

 

 

앞서 정의한 teacher 모델과 student 모델, 비교 모델을 컴파일한다. 파라미터가 약 2만 개로 teacher 모델의 약 1/70에 불과하다.

 

 

 

선생님 모델의 경우 3 epoch 만에 약 96%의 정확도를 보인다.

 

 

 

Knowledge Distillation 학습에 필요한 student loss와 distillation loss를 정의한다. KLDivergence 손실함수는 서로 다른 두 개의 확률 분포를 비교해 유사성을 측정하는 지표이다. 서로 유사할수록 값이 작아지고, 분포에 차이가 클수록 값이 커진다.

 

 

 

 

훈련 셋의 배열 크기를 확인한다.

 

 

 

앞의 배열에서 이미지 개수가 6만 개라는 것을 알 수 있다. 배치 크기로 나눠주면 총 배치의 개수를 알 수 있고, 다음과 같이 배치별로 student loss와 distillation loss를 계산할 수 있다. 모델 학습에 적용하는 총 손실함수는 student loss와 distillaiton loss를 가중 평균한다. 파라미터 설정에서 alpha 값을 변경하여 가중치를 조절할 수 있다.

 

하지만 코드 오류가 계속 떠서 실행이 안 된다. 어떻게 해결할 수 있을까? 이 오류는 tf.keras.optimizers.Adam 옵티마이저가 처음 인식한 변수 집합에 대해 작동하도록 설정된 후, 다른 변수를 학습하려 할 때 발생하는 오류이다. 즉, 옵티마이저는 s_model_1의 변수로 초기화되었고, 이후에 s_model_2의 변수 집합을 업데이트하려고 시도했기 때문에 오류가 발생한 것이다.

이 문제를 해결하려면 s_model_2의 업데이트에 대해 별도의 옵티마이저 인스턴스를 생성하여 사용해야 한다.

 

 

 

 

 


 

 

 

 

학습을 마치고

코드를 실행 중에 코랩 오류가 있어서 끝까지 학습이 되지 못했다. 몇 번을 했는데 되지 않아서 나중에 내용을 확인하려고 한다. 코드를 수정해서 오류는 없는 코드였는데 가끔씩 GPU 연산을 할 때 먹통이 될 때가 있다. GPU를 구입해도 잘 안되니 정말 답답하다.

이 내용은 수업 시간에 다루지 않은 내용이라 조금 생소했지만 그래도 새로운 개념을 배울 수 있어서 좋았다.