CS231N - Lecture 3 | Loss Functions and Optimization

Loss Function이다.optimization이라고 한다.
Loss Function은 Classifier가 얼마나 좋은지 나타낸다 !
그리고 이 값을 최소화하는 를 찾는 것이 목표이다.

SVM Loss는 Support Vector Machine Loss의 줄임말이다. SVM은 주로 분류 문제에 사용되며 서로 다른 클래스 간의 Margin을 두어 두 클래스가 일정 거리이상에 위치하도록 한다.

SVM Loss는 굉장히 간단한 손실 함수 중 하나이다.
car iamge를 조금 바꾼다고 해서 loss가 바뀌지 않는다. SVM Loss는 오직 정답 클래스가 다른 클래스에 비해 높은지에만 관심이 있기 때문이다.
위에 있는 hinge loss 그래프를 보면 알 수 있듯이 최소는 0이고, 최대는 무한대이다.
클래스 수 - 1 의 값이 나온다. 이 방법은 디버그용으로 많이 사용한다. 즉, 0으로 해주면 loss가 잘 나오는지를 검사해보는 것이다. 이걸 sanity check라고도 부른다.
최종 loss값이 1이 증가된다. 우리의 목표는 loss값이 0이 되도록 하는 것인데 이렇게 되면 1이 가장 좋은 값이 된다. 그렇기 때문에 정답 클래스를 빼서 loss가 0이 되도록 하는것이다.
Sum 대신 Mean을 사용해도 별 차이는 없다. 단지 scale만 작아진다. 우리는 loss가 크고 작고에 관심이 있는 것이기 때문에 scale이 커지든 작아지든 상관없다.
제곱을 하게 되면 다른 결과가 나온다. 우선 제곱을 하게 되면 non-linear 해진다. 그렇게 되면 hinge loss 그래프에서 직선이 아니라 곡선으로 올라가게 되고, '매우매우 좋다' 또는 '매우매우 나쁘다'를 표현할때 유용할 수 있다.
그리고 저렇게 제곱을 해서 사용하는 square hinge loss라는 방법이 따로 있다.


Softmax function은 모든 스코어들을 exp 취하고, 다 더한 뒤에 원하는 클래스의 점수를 exp 취해서 나눈다. 그리고 내가 원하는 정답 클래스에 를 취해서 loss를 구한다.

각 점수마다의 확률을 구하여 오차값을 구하는 방식을 Softmax라고 부른다.

x축이 확률, y축이 loss라고 생각하면 를 보면 확률이 1에 가까워질수록(정답률이 높아질수록) loss가 0에 가까워진다. 그래서 를 사용한다.

Loss가 0이 되는 순간, 자기 할 일 다 한 것이다. max값만을 구하기 때문에, 정답 카테고리가 y [0]이고, 점수가 [10,9,9,9]같이 나오더라도 Loss값은 0이 된다. 그리고 이걸 완벽한 Loss로 본다.
또한, datapoint를 약간 흔들어주는 경우에도 정답 클래스가 정답이 아닌 클래스에 비해 높은지에 신경쓰기 때문에 딱히 영향이 없다. 즉, 둔감하다.
최대한 정답 카테고리의 확률을 높이기를 원하기 때문에, 계속해서 확률을 높이려고 노력한다. 쭉쭉 올라가서 점수가 [1000,5,3,1] 같아져도 계속해서 확률을 높이기 위한 방향으로 나아간다. 0에 굉장히 근접한 값은 나올 수 있지만 웬만해선 loss가 0이 나오지 않는다.
또한, datapoint를 약간 흔들어주는 경우를 보면 softmax는 확률로 계산되기 때문에 조금만 데이터가 변형되어도 바로 확률에 영향을 미친다. 즉, 민감하다.
: 복잡해진 classifier에 페널티를 가해서 최대한 간결하고 심플하게 만들어주는 방법이다.

우리가 값을 잘 조정해서 loss값을 0으로 만들었다고 이게 완벽한 classifier인 것은 아니다. 우리가 loss 값이라고 만들어 놓은 것은 결국 train set에 대한 loss값이기 때문이다.
우리가 실질적으로 궁금한 것은 test set에 대한 loss값이다!
파란점이 train data, 초록점이 test data이다. 여기서 우리가 train data에 대해서 loss값을 0으로 만들면 파란선과 같은 classifier가 작동할 것이다. 그리고 이 classifier로 test data를 예측한다면 엉망인 결과를 도출할 것이다. 이것을 Overfitting(과적합)이라고 한다. train data에 맞춰진 나머지 test data에 대해서 성능이 좋지 못하는 문제를 말하는 것이다.
그리고 초록선과 같은 classifier가 우리가 지향하는 classifier가 될 것이다. train set에도 어느정도 잘 맞으면서 test set에도 어느정도 잘 맞추는 선이기 때문이다.
우리는 classifier가 최대한 간결하고 심플하게 되는 것을 선호한다!

가 regularization의 식이고, 가 너무 강해져버리면 너무 간결함만을 유지하고자해서 loss값을 맞춰주는게 큰 의미가 없어지고, 너무 작으면 regularization을 하는 의미가 없어지기 때문에 를 하이퍼파라미터로 사용하여 의 값을 적당히 맞춰주는 역할로 활용할 것이다.

가 L2 Regularization이고, 가 이미지 픽셀값이라고 했을 때,
과 를 이용해 dot product를 구하면 1이라는 동일한 값이 나온다.
이때 L2 Regularization은 어떤 값을 더 간결하다고 생각할까?
는 값들의 제곱을 더했기때문에 가 더 좋다고 생각할 것이다.
즉, L2는 값이 최대한 평평하게, 너무 큰 값 없이 최대한 비슷한 값으로만 이루어지게 하고 싶은 것이다. 이러면, 이미지에 가는 가중치들이 다들 비슷비슷해 지므로, 조금 더 전체적인 그림을 볼 수 있지 않을까? 하는 느낌인 것이다.

(x, y)의 데이터셋을 가지고 있을 때, 점수를 dot product를 통해서 구한 후, SVM 또는 Softmax와 같은 loss function으로 얼마나 오차가 있는지를 알아낼 것이다.
또한, Regularization , 즉 를 함께 더해서 최종 loss값을 구할 수 있다.

Random Search는 가장 멍청한 방법이다. Random Search라는 단어 그대로 의 값을 랜덤하게 바꿔가면서 최적의 값을 찾아나가는 방법이다.

Random Search를 test set에다가 적용시키면 15.5 % 정도의 정확도가 나온다. SOTA(State Of The Art : 현대 기술)로는 95 % 정도까지 나오는 것을 생각하면 아주 좋지 않은 결과라고 볼 수 있다.

를 찾는 과정이 산골짜기에서 산을 내려오는 것이라고 생각했을 때, 땅 주변에 발을 가져다 대 보면서 좀 낮은 곳으로 조금 움직인 다음 다시 한번 발을 갖다 대 보며 더욱더욱 낮은 곳으로 내려가보는 방법이다. 그리고 이 방법은 경사하강법이다.
여기서 미분이라는 개념이 등장한다. 우선 간단하게 '미분은 어떤 함수의 기울기를 구한다'라고 생각하자. 대충 미분을 쓸 거고, 위의 식 을 써볼 거다라는 것만 알아두면 된다.


이렇게 계속 0.0001씩 더해서 미분하는 것은 굉장한 시간 낭비가 될 것이다.


그렇기 때문에 뉴턴과 라이프니치의 방법으로 수학적으로 미분을 간단하게 할 수 있고, 미분값들이 구해진 것을 볼 수 있다.

한 것이 numerical, 그냥 미분 공식으로 나온 것이 analytic이다.
numerical로 하면, 느리고, 정확하진 않지만(컴퓨터가 소수점을 약간은 빼버리니깐..) 코드 작성은 쉽다.
analytic으로 하면 빠르고, 정확하지만 코드 작성이 어렵다.

Gradient Descent, 즉 기울기 하강을 통하여 가장 적절한 W값을 찾아낼 것이다. evaluate_gradient에서 미분 값을 계산하고, weights를 step_size * 기울기만큼 빼면서 최적의 값을 찾는다.
여기서 step size란 learning rate라고도 불리며 앞선 예시에서 0.0001과 같은 하이퍼파라미터 값을 말한다.

위의 그래프가 3차원 그릇같은 모양이라고 했을 때, 우리는 가장 움푹 파인 부분인 가운데로 가야한다. 이때 step size가 너무 크게되면 가운데를 지나쳐 보라색까지 갈 것이고, 너무 작으면 가운데까지 도달하는데 엄청 오랜 시간을 학습해야 할 것이다.
그렇기 때문에 step size를 최대한 적절하게 조정해서 원하는 곳까지 도달하게 해야한다.

모든 사진들을 앞서 설명한 방법대로 계산하기에는 엄청난 시간이 걸릴것이다. Imagenet Challenge에서는, 대략 1.3 Million, 즉 130만 개의 training set이 있는데, 이 사진 하나하나를 죄다 미분하고 계산하고 하기엔 너무 느리고, 오래 걸린다.
SGD는 iteration마다 mini batch라는 랜덤한 샘플들을 뽑아서 그 샘플들에 대한 loss를 계산하고, weight를 계산하는 방법이다. 이렇게 되면 전체 개의 대해서 gradient descent를 구하는 것보다 훨씬 시간을 절약할 수 있게 된다.