딥러닝과 Loss 함수의 이해
딥러닝.. 내겐 여전히 블랙박스 같은 존재이다. 하지만 딥러닝도 크게 보면 기계학습 방법의 하나로서 딥네트워크를 이용한 모델링과 파라미터 추정 방법으로 볼 수 있다. 그래서 전통적으로 기계학습을 연구했던 사람들은 아마도 보다 넓은 시야를 가지고 딥러닝을 이해할 수 있을 것으로 생각한다.
이 글은 딥러닝에 대한 나름의 이해를 정리한 글이다. Loss 함수, 파라미터 공간, 최적화 기법 등이 어떻게 딥러닝과 연결되는가 주 내용이다. 딥러닝의 세부적인 내용보다는 전체적인 틀을 바라보고 해석한 글로 볼 수 있다.
딥러닝과 파라미터 추정
딥러닝도 크게 보면 x에서 y로의 함수관계 fw(·)를 찾는 문제로 볼 수 있다.
x → fw(·) → y
이 때 함수의 구조와 복잡도를 정하는 것이 모델링 과정인데, 딥러닝에서는 어떤 네트워크 아키텍쳐를 사용할 것인지, 몇 개의 층을 사용할 것인지, activation 함수로는 무엇을 사용할 것인지 등을 정하는 것이 모델링에 해당한다. 예를 들어 아키텍쳐로는 VGG, ResNet 등을 사용할 수 있고 activation 함수로는 ReLU나 sigmoid 등을 사용할 수 있다.
모델이 정해지면 모델의 파라미터가 정해지는데 딥네트워크에서는 입력층과 출력층 사이에 존재하는 모든 weight들이 모델 파라미터가 된다. 모델 파라미터는 모델에 종속되어 정해지는 것으로서 예를 들어 돌맹이의 궤적을 2차 다항식 f(t) = at2 + bt + c로 근사하기로 결정했다면 모델은 2차 다항식이고 모델 파라미터는 a, b, c가 된다.
모델과 모델 파라미터가 정해지면 이제 남은 일은 모델 파라미터의 값을 정하는 것이다. 주어진 입력(x)에 대해 원하는 출력(y)이 나오도록 모델 파라미터 값을 조정하는 것이 목적이다. 수집된 관측값들이 (xi; yi), i = 1, 2, ..., n라면 각각의 i에 대해 최대한 yi = fw(xi)가 되도록 파라미터 값을 찾게 되는데, 이 과정이 딥러닝의 학습과정 또는 파라미터 추정 과정에 해당한다.
그런데, 파라미터 추정을 위해서는 먼저 파라미터의 좋고 나쁨을 판단하는 기준이 있어야 한다. 그것이 바로 loss 함수를 정하는 일이다. 앞서 과정에서 모델과 모델 파라미터가 정해지면 일종의 파라미터 공간(parameter space)이 생성된다. 이 공간의 차원은 모델 파라미터의 개수와 동일하며 아직은 차원만 정해진 빈 공간이다. 그런데, loss 함수가 정해지면 이 공간에 산맥이 생기고 골짜기가 생긴다. 즉, Loss 함수에 따라서 각 파라미터 값에 대한 score(or 손실)가 매겨지기 때문에 이 score에 따라서 파라미터 공간에 높고 낮음이 생성된다.
딥러닝 학습에 있어서 마지막 선택은 주어진 산맥과 골짜기의 파라미터 공간에서 어떻게 최적의 답을 찾아갈 것인가이다. 파라미터 공간이 정해지면 이미 최적의 답도 같이 정해진다. 하지만 무한한 파라미터 공간을 미리 다 evaluation 해볼 수는 없기 때문에 현실적으로는 시작 위치에서 조금씩 해를 찾아갈 수 밖에 없다. 즉, gradient descent 방법, Gauss-Newton 방법, LM 방법 등과 같은 최적화 기법(optimizer)이 필요하다.
※ 일반적으로는 Newton, LM 방법 등의 성능이 더 좋다. 하지만 딥러닝에서는 현실적인 이유(파라미터 공간이 너무 고차원)로 gradient descent, 특히 stochatic gradient descent 류의 방식이 주로 사용된다.
이상의 내용을 정리해 보면 다음과 같다.
- 학습데이터: problem의 domain을 정의
- 네트워크 구조: 함수의 복잡도와 power를 정의, 모델 파라미터를 정의
- loss 함수: 파라미터에 대한 evaluation(cost)을 정의
- optimizer: 파라미터 공간에서의 탐색 방법을 정의
이중 어떤 요소가 더 중요할까? optimizer는 해 자체를 바꾸지는 못하지만 optimizer에 따라 해를 잘 찾을 수도 있고 못 찾을 수도 있다. 네트워크의 구조와 복잡도를 정하는 것은 비유컨데 닭 잡는데 소 잡는 칼을 쓸 것인지 아니면 소 잡는데 닭 잡는 칼을 쓸 것인지를 정하는 문제로 볼 수 있다. 물론 적당한 규격의 칼이 좋을 것이다. 학습데이터와 loss 함수는 선택된 칼의 규격 내에서 최적의 칼이 되기 위한 기준을 잡아준다.
Loss 함수의 역할
Loss는 영어 단어로는 상실, 손실을 의미한다. 그리고 기계학습에서의 Loss는 어떤 학습된 모델을 실제 데이터에 적용했을 때 모델의 추정 오차로 인해 발생하는 손실을 의미한다. 학습된 모델을 fw(·), 관측 데이터를 (xi; yi)라 하자. 이 때, 입력 xi에 대한 모델 추정값과 실제 관측값 사이의 오차를 residual이라 부르며 xi에 대한 residual은 ri = yi - fw(xi)로 계산된다. Residual이 단순히 모델 추정값과 참값(관측값) 사이의 차이를 말하는 반면에, Loss는 이 차이로 인해 발생하는 실제 계산상의 손실을 의미한다. 사실 Loss는 우리가 마음데로 정할 수 있으며 예를 들어 residual의 절대값을 Loss로 정하거나(L(xi) = ‖yi - fw(xi)‖), residual의 제곱을 Loss로 할 수도 있다(L(xi) = ‖yi - fw(xi)‖2). 이 외에도 문제나 응용에 따라서 focal loss, triplet loss 등 다양한 형태의 Loss 함수 정의가 가능하다.
앞서 Loss 함수는 파라미터에 대한 evaluation(cost)을 정의한다고 했다. 아래 두 파라미터 추정 문제의 예를 살펴보자. 식 (1)은 일반적인 L2-norm을 Loss로 정의한 경우이고, 식 (2)는 L2-norm에 파라미터 크기를 함께 고려하여 Loss로 정의한 경우이다.
$$\min_{w} \; {\left \| y - f_w (x) \right \|^2}\tag{1}$$
$$\min_{w} \; {\left \| y - f_w (x) \right \|^2 \!+\lambda \left \| w \right \|^2} \tag{2}$$
식 (1)과 같이 Loss를 정의하면 정답(학습데이터)에만 초점을 맞추어 파라미터를 추정하게 된다. 그런데, 파라미터 공간은 워낙 고차원이기 때문에 그림1(좌) 경우처럼 식 (1)을 만족하는 해(w)가 너무 많아서 오히려 수렴이 어려울 수도 있다. 또는 반대로 파라미터 공간이 너무 굴곡이 심해서 쉽게 발산할 수도 있다. 하지만, 식 (2)와 같이 Loss를 정의하면 가능한 해들 중에서 크기가 최소화되는 해를 찾기 때문에 그림1(우)처럼 파라미터 공간이 안정화되어 상대적으로 쉽게 해를 찾을 수도 있다.
※ 기계학습 분야에서는 식 (2)와 같은 regularization term을 추가한 파라미터 추정 기법을 ridge regression이라 부르는데, ridge를 추가하는 것이 아니라 제거하기 때문에 ridge regression이라 부른다.
위 예는 기계학습 or 파라미터 추정에서 Loss 함수가 미치는 영향을 설명하기 위한 하나의 예시이며 이 외에도 다양한 형태의 Loss 함수 정의가 가능하다. Loss 함수를 어떻게 정의하느냐에 따라서 파라미터에 대한 evaluation 즉, 학습의 지향점이 달라지기 때문에 기계학습을 한다면 한 번쯤은 Loss 함수에 대해 고민해 볼 필요가 있다.
※ Loss 함수가 중요하긴 하지만 그렇다고 파라미터 공간을 마음대로 바꾸는 것은 아니다. 잘 생각해보면 학습에 사용되는 관측 데이터 자체가 이미 답을 제시한다. 즉, xi에 대해서는 yi가 나오도록 하는 파라미터를 찾아라고 알려준다. 따라서, 보다 정확하게 말하면 학습 데이터는 기준점을 제시하고 Loss 함수는 기준점에서 벗어날을 때의 패널티와 부가적인 제약조건을 정의한다고 볼 수 있다. 그리고 부가적인 제약조건에 따라서 학습의 지향점이 조금씩 달라질 수 있다.
딥러닝 Loss 함수
마지막으로 딥러닝에서 사용되는 Loss 함수들에 대해 간단히 살펴보려고 한다. 사실 Loss 함수도 워낙 종류가 많기 때문에 대표적인 몇 가지만 살펴보도록 하자. 먼저, yolo에서는 weighted least squares loss를 사용한다. 기본적으로는 L2-norm인데 요소(추정된 box와 ground truth box와의 중심거리, 박스 크기, 박스 overlap 등)별로 다른 가중치를 적용한다. 그리고 classification 문제에서는 대부분 cross entropy loss라는 것을 사용한다. 멀티 클래스 classification 문제에서는 클래스 개수만큼의 출력층 노드가 존재하는데, 학습시 입력 데이터의 클래스에 대응되는 출력노드의 출력은 1, 그 외의 출력노드의 값은 0이 되도록 학습하는 것이 일반적이다. 만일 입력 학습데이터의 클래스가 Ci이고 Ci에 대응되는 출력노드의 출력값을 pi라고 하면 x∈Ci에 대한 cross entropy loss는 L = -log(pi)로 계산된다 (일반적으로 딥러닝에서는 출력층 값에 softmax를 적용하기 때문에 pi는 항상 0 ~ 1 사이의 값을 갖는다). Cross entropy loss를 개선한 버전들도 존재하는데, balanced cross entropy loss는 클래스간 샘플 데이터의 불균형을 해결하기 위해 희소 클래스일수록 높은 가중치를 주도록 x∈Ci에 대해 L = -1/αi * log(pi)로 Loss를 계산한다 (αi: 전체 학습 데이터들 중에서 클래스 Ci에 속하는 데이터들의 비율). 그리고 hard example에 대해 좀더 높은 가중치를 주는 focal loss도 발표된 바 있다 (“Focal Loss for Dense Object Detection.” ICCV 2017).
그외 얼굴인식이나 image retrieval 분야에서는 ranking loss라는 것을 사용하는데, 입력 query 영상에 대해 정답 영상들(positives)과는 거리가 가깝게 하고 정답이 아닌 영상들(negatives)과는 거리가 멀게 하도록 Loss 함수를 설계한다. 예를 들어, 얼굴인식 응용에서 철수 얼굴 영상들을 p1, p2, ..., pn, 다른 사람들의 얼굴들은 q1, ..., qm라고 했을 때, pi들끼리는 거리를 최소화하고 pi와 qj 사이의 거리는 크게 하도록 Loss 함수를 정의한다. 이러한 응용에서는 query영상과 가장 가까운 DB 영상을 정답으로 찾는 것이 목적이기 때문에 계산된 거리값(distance) 자체보다는 그 거리값들의 상대적인 순서를 맞추는 것이 중요하다(pi들끼리의 거리가 pi와 qj 사이의 거리보다 작기만 하면 된다). 그래서 ranking loss라고 부르며 그 대표적인 예로는 triplet loss나 pairwise loss 등이 있다 (ranking loss도 굉장히 많은 변형들이 있다).
이 글에서는 개별 Loss 함수들을 설명하는 것이 목적이 아니기 때문에 기존의 Loss 함수들에 대해서는 간단히만 설명하였다. 중요한 것은 Loss 함수의 의미를 이해하고 활용하는 것이라 생각한다. 그리고 나아가서 자신의 문제에 맞는 Loss 함수를 직접 만들 수 있다면 더 좋을 것이다.
by 다크 프로그래머