Deep learning : Decay로 과적합 줄이기
이번에 다뤄볼 주제는 다소 지루할 수 있는 주제입니다. 바로 “Weight Decay”에 대해서 알아봅니다. Weight Decay는 직역하면 “하중 감쇠” 같은 느낌이 됩니다. Weight Decay는 과적합을 억제하는 학습 기법의 하나입니다. 과적합된 학습이라는 것은 학습(훈련) 데이터에 적합하게 남아서 학습(훈련) 데이터와 다른 데이터에 대한 정답률이 낮아지는 것입니다. 과잉 학습은 중량(Weight)이 큰 값을 가짐으로써 발생하는 것이 많다는 사실에서 학습 과정에서 가중치(Weight)가 크지 않게 페널티를 부과하는 방법입니다. 즉, 특정 네트워크가 가중치가 큰 경우 이를 낮춰주는 것이죠. 뉴럴 네트워크 학습은 손실 함수(층으로 하면 Categorical Cross Entropy 정도)에서 얼마나 정답과 차이가 있을지를 구하고, 그 차이가 작아지도록, 흥분도(역 전파) 가중치와 편견의 값을 갱신하는 것입니다. 그 과정에서 손실 함수의 값에 어떤 값을 페널티로 가산해서 하면 가중치(Weight)가 크게 매겨지지 않을 것입니다. 그런 이론입니다. 그럼 그 어떤 값은 무엇일까요? 몇 가지 방법은 있는 것 같은데요, 많이 쓰이고 있는 것이 가중치의 각 요소의 제곱을 합친 것에 임의의 계수를 곱하단 것입니다. 이 “가중치의 각 요소의 제곱을 합친 것”을 페널티에 쓰는 방법을 “L2법칙 정규화 또는 L2정규화”라고 부릅니다. 수식으로 이해하고 싶으시면 L2법칙 정규화 등에서 구글에서 찾아보시다 보면 아마 얼마든지 정보가 나오라고 생각합니다만, 그쪽에서 부디 Weight Decay라는 항목은, Neural Network Console의 Config탭의 Optimizer항목에 있을 것 같습니다. 레퍼런스를 보면 일단 설명은 찾을 수 있었습니다. 쓰고 있는 것은 단 2곳. Weight Decay(L2정칙화)의 강도를 설정하려면 Weight Decay에 계수를 지정합니다. 상기의 설명을 읽은 뒤면 Config태그에서 지정하는 Weight Decay의 계수라는 것은 위에서 말하는 “임의의 계수”에 해당하는 게 알 거라고 생각합니다. 그러나 거기까지 모르는 사람에게는 이해가 쉽지 않을 수 있습니다. Weight Decay의 계수의 적절한 값이란? 이 수치에 두면 무엇이든 만능 같은 수치는 없습니다. (자신이 모르는 건지도 모르지만 알기는 쉽지 않겠죠.) 본격적으로 한다면, 베이즈 최적화 등 하이퍼 파라미터의 자동 최적화의 기법은 여러 가지 있는 것 같은데요, 취미로 하는 사람에게는 너무 과할 수 있습니다. 솔직히 서적에 따라서도 이 계수에 대해서는 여러 가지 의견이 있습니다. 0.1 정도를 설 정라는 사람도 있고 0.000001로 했더니 편리했다는 사람도 있습니다. 어쩔 수 없으니, 이따금 시도하면서 결과를 보고 있습니다. 그 결과. 저는 Neural Network Console에서 하는 경우는 0.0001에서 시작한 것이 최근에는 많습니다. 경험적으로 최선이 아니라 해도 비교적 더 좋은 결과를 기대할 느낌이라 좋습니다. 만약에 참고가 되면 말이죠. Neural Network Console의 Optimizer의 기본 값은 “Adam”입니다. 기본적으로 Adam은 수습이 빠르고 일단 선택하고 문제가 없는 Optimizer입니다. 하지만 학습 데이터와 다른 데이터에서 정답률을 높이는 목적으로 Weight Decay를 사용할 때는 Adam은 최상의 선택이라고 할 수 없게 됩니다. 이쪽의 트위터에 붙어 있는 링크(논문의 PDF 파일)에 그 이유가 설명되고 있습니다. 간단히 말한다면 Weight Decay의 계수를 0 이외로 변경해도, Adam을 사용하고 있는 한 과잉 학습 경향이 별로 개선되지 않습니다. 학습한 결과가 이런 그래프가 되고 있는 CNN의 네트워크를 다룹니다. Traiing에러가 깨끗하게 개선되는데 Validation에러는 중간부터 반대로 증가하고, 점점 빠져나가고 있습니다. 이제 전형적인 과적합된 학습상태입니다. 평가한 결과 Accuracy도 “97.65%”로 꽤 낮습니다. 여기에 Optimizer는 Adam에서 설정한 그대로 Weight Decay의 계수를 “0.0001”로 설정해보겠습니다. 결과는 어떤가 한번 확인해보시기 바랍니다. 그래도 형식적으로 별로 달라지지 않았습니다. 과적합된 학습 추세는 남아 있습니다. Optimizer의 Updater를 “sgd”로 변경하고 살펴보겠습니다. 나머지는 똑같습니다. 그러면 학습 결과 그래프 모양이 극적으로 바뀝니다. training에러와 Validation오류의 차이가 거의 없습니다. 꽤 좋게 분류를 하고 있다고 기대할 수 있습니다. 단지, 유감스럽지만 SGD는 처리가 늦어지는 것으로 50 epoch에서는 처리되지 않습니다. 이 시점에서 평가한다면, Accuracy는 97% 초반밖에 없습니다. 그냥 억울해서 epoch 수를 늘리고 재도전하여 최종적으로는 여기까지 갔습니다. 뭐, 원래의 네트워크 구성이 좋지 않았을 수도 있습니다. 이런 아주 기분 좋은 일 같으니라고.. Weight decay의 값을 0 이외(예를 들면 0.0001등)로 하면 L2정규화가 되고, 과적합 학습 억제 효과가 있습니다. 다만 Optimizer탭에서 “Adam”을 선택하고 있다고 해서 매칭 되는 문제는 별로 효과가 없습니다. 옵션을 “sgd”로 변경하면 Weight decay의 범화 효과가 최대한으로 발휘되지만 이번에는 학습이 늦어져서, Max Epoch의 수를 늘리는 등의 대응이 필요하게 됩니다. 결국 상황에서 지금 어디에 중점을 두어야 할 것인가 에서 어느 것을 선택할지를 판단하지 않으면 안 된다는 것이지요. 그럼 이번 글은 여기까지 하겠고요. 앞으로도 관련된 글을 많이 올려보고자 하니 기대 많이 해주셨으면 좋겠습니다. 감사합니다.