반응형

이번 시간에는 W를 어떻게 정할까를 고민하고 최적의 W를 구하는 방법에 대해 이야기할 예정이다.

지난시간 임의의 W를 가지고 이미지에 대한 10개의 클래스 스코어를 계산했다.

밑에 예시를 보면 왼쪽에 고양이 이미지에 대해 고양이 클래스는 2.9 스코어를 준 반면 개구리 클래스는 3.7 스코어를 줬다. 우리는 정답 클래스가 제일 높은 클래스 스코어를 주기를 바란다. 그러므로 임의의 W를 가지고 만든 이 분류기는 잘 동작하지 않는 것을 알 수 있다. 중간에 자동차 이미지에 대한 클래스들의 스코어를 보면 여기서는 자동차 클래스가 다른 클래스들 보다 6.04로 제일 높은 스코어를 줬는데 이것은 좋은 예시이다. 하지만 개구리 이미지는 개구리 클래스가 -4.34라는 다른 클래스의 점수보다도 낮은 점수를 줬기 때문에 안좋은 예측을 했다고 할 수 있다. 

<손실함수>

우리는 최적의 W를 구하기 위해서 지금 만든 W가 좋은지 나쁜지를 정량화 할 방법이 필요하다. W를 입력으로 받아서 각 스코어를 확인하고 이 W가 지금 얼마나 나쁜지 (예측을 못하는지)를 정량적으로 말해주는 것이 바로 우리가 손실함수라고 부르는 것이다. 이번 강의에서는 이미지 분류 문제에서 사용할 수 있는 다양한 손실함수에 대해 알아볼 것이다. 

 

손실함수가 주어진 W값에 대해 이것이 좋은지 나쁜지 정량화할 수 있게 해준다. 하지만 우리가 진짜 원하는 것은 어떠한 효율적인 과정을 통해 W가 될 수 있는 모든 경우의 수를 찾아보고 가장 덜 안좋은(안 구린) W가 무엇인지 알아내는 것이다. 이 과정이 바로 최적화 과정이다.

 

손실함수 L_i를 정의하면 예측함수 f (입력 이미지 x와 행렬 W를 입력으로 받아서 y(정답 레이블)를 예측) 그 트레이닝 샘플을 얼마나 나쁘게 예측하는지를 정량화 시킨 값을 준다. 최종 Loss인 L은 전체 데이터 셋에서
각 N개의 샘플들의 대한 Loss의 평균이 된다.

<SVM loss>

먼저 이미지 분류 문제에 적합한 손실함수 중 하나인 multi-class SVM loss에 대해 알아보자. Loss L_i를 구하는 방법은 True 카테고리 Y_i (정답 카테고리)를 제외한 나머지 카테고리 Y의 합을 구하고 정답 카테고리의 스코어와 틀린 카테고리의 스코어를 비교한다. 만약 정답 카테고리의 점수와 틀린 카테고리의 점수의 격차가 일정 마진(safety margin) 이상 (밑에 예시에서는 1로 설정)으로 정답 카테고리의 점수가 더 높으면 True 카테고리의 스코어가 다른 false 카테고리들보다 훨씬 더 크다는 것을 의미한다. 그렇게 되면 Loss는 0이 된다. 이런식으로 정답이 아닌 카테고리의 모든 값들을 합치면 그 값이 바로 한 이미지의 최종 Loss 가 되는 것이다. 그리고 전체 트레이닝 데이터 셋에서 그 Loss들의 평균을 구한다.

그래프 모양때문에 이런 Max(0, value)와 같은 식으로 만든 손실함수를 hinge loss라고 부르기도 한다. x축은 S_Yi로 실제 정답 클래스의 스코어이고 y축은 Loss다. 정답 카테고리의 점수가 올라갈 수록 Loss가 선형적으로 줄고 Loss가 0이 된 이후에서 Safety margin을 넘어설 때까지 줄어든다. Loss가 0이라는건 잘 분류가 된다는 뜻이다.

*S는 분류기의 출력으로 나온 예측된 스코어 (1이 고양이고 2가 개면 S_1은 고양이 스코어 S_2는 개 스코어)

*Y_i는 이미지의 실제 정답 카테고리 입니다. 정수 값

*S_Y_i는 트레이닝 셋의 i번째 이미지의 정답 클래스의 스코어

밑에 예시처럼 각각 이미지에 대해 Loss값을 구하고 전체 트레이닝 데이터 셋에서 그 Loss들의 평균을 구하면 ( L = (2.9 + 0 + 12.9) / 3 = 5.27) 전체 트레이닝 셋의 최종 Loss이다. 이것이 의미하는 바는, 우리의 분류기가 5.3점 만큼 이 트레이닝 셋을 틀리게 분류하고 있다는 "정량적 지표" 가 되는 것입니다.

safety margin을 1로 설정했었는데 왜 1로 설정했는지 결론부터 이야기 하자면, 사실 1 이라는게 별 상관이 없다. 왜냐하면 우리는 사실 손실함수의 스코어가 정확이 몇인지 신경쓰지 않고 우리가 궁금한건 여러 스코어 간의 상대적인 차이이기 때문에 우리가 관심있어 하는건 오로지 정답 스코어가 다른 스코어에 비해 얼마나 더 큰 스코어를 가지고 있는지 이다. (온라인 코스노트 참고)

 

SVM의 Loss는 0 ~ 무한대이다. 모든 스코어 S가 거의 0에 가깝고 값이 서로 거의 비슷하다면 Loss는 클래스의 수 - 1의 값일 것이다. 왜냐하면 Loss를 계산할때 정답이 아닌 클래스를 순회하므로 C - 1 클래스를 순회한다. 비교하는 두 스코어가 거의 비슷하니 Margin때문에 우리는 1 스코어를 얻게 될 것이고 Loss는 C - 1을 얻게 된다. 우리가 손실함수를
아래와 같이 제곱 항으로 바꾸면 결과가 달라진다. 좋은것 과 나쁜것 사이의 트레이드 오프를 비선형적인 방식으로 바꿔주는 것인데 그렇게 되면 손실함수의 계산 자체가 바뀌게 된다. 제곱 항을 고려하면 분류기가 만드는 다양한 Loss들 마다 상대적으로 패널티를 부여할 수 있다.  Loss에 제곱을 한다면 이제 틀린 것들은 정말로 많이 틀린 것(나쁜 것)이 된다. 반면에 hinge loss는 "조금 잘못된 것" 과 "많이 잘못된 것" 을 크게 신경쓰지 않는다. 둘 중 어떤 loss를 선택하느냐는 우리가 에러에 대해 얼마나 신경쓰고 있고, 그것을 어떻게 정량화 할 것인지에 달려있다.

손실함수를 구현한 numpy코드를 보면 margins[y]=0을 했는데, 이 이유는 정답 클래스에 대한 손실을 0으로 설정해 굳이 전체를 순회할 필요가 없게 해주는 일종의 vectorized 기법이다. 전체 합을 구할 때 제외하고 싶은 부분만 0으로 만든다.

Loss가 0이 되게 하는 W를 찾았다면 그 W는 유일하게 하나만 존재하는 것일까? 다른 W도 존재한다. 2W 같이 스케일이 변해도 Loss가 0이 된다. W와 2W가 있다면, 정답 스코어 와 정답이 아닌 스코어의 차이의 마진(margins)또한 두배가 될 것이다. 하지만 모든 마진(margins)이 이미 1보다 더 크면 우리가 두배를 한다고 해도 여전히 1보다 클 것이고 Loss는 0이다. 

손실 함수 라는 것이 분류기에게 우리는 어떤 W를 찾고 있고 어떤 W에 신경쓰고 있는지를 말해주는 것이라면 여기서 조금 이상한 점이 있다는 것을 우리는 깨달아야된다. 다양한 W중 Loss가 0인 것을 선택하는 것은 모순이다. 왜냐하면 여기서는 오직 데이터의 loss만 신경쓰며 분류기에게 트레이닝 데이터에 꼭 맞는 W를 찾으라고 말하는 것 과 같은데, 머신러닝의 핵심은 트레이닝 데이터를 이용해서 찾은 어떤 분류기를 테스트 데이터에 적용하는 것이기 때문이다. 그러므로 우리는 이 분류기의 트레이닝 데이터의 대한 성능에 관심이 있는게 아니라 테스트 데이터에 적용했을 때의 성능에 관심이 있는 것이다. 밑에 예시를 보면 분류기가 모든 트레이닝 데이터를 완벽하게 분류해 내기 위해 파란색 곡선을 만들었지만 새로운 데이터 (테스트 데이터)가 들어왔을 때 파란 곡선은 완전 틀리게 되고 사실 우리가 의도했던 것은 초록색 선이다. 이를 해결하기 위해 Regularization 항을 추가한다. "Data Loss Term"에서는 분류기가 트레이닝 데이터에 핏하게 하고, "Regularization term"을 추가해 모델이 좀 더 단순한 W를 선택하도록 도와주는 것이다.

<Regularization>

Regularization에는 여러 종류가 있는데 가장 보편적인 것은 L2 Regularization으로 Weight decay라고도 한다. L2는 분류기의 복잡도를 상대적으로 w1, w2 중 어떤 값이 더 매끄러운지 측정한다. x의 특정 요소에 의존하기 보다 x의 모든 요소가 골고루 영향을 미치길 원하면 L2 쓸 수 있고 L1은 정만대로 L1 Regularization은 가중치 2의 0의 갯수에 때라 모델의 복잡도를 이루는데 L1이 복잡하다고 느끼고 측정하는 것은 0이 아닌 요소들의 갯수이고 L2는 W의 요소가 전체적으로 퍼져있을 때 덜 복잡하다고 생각한다.

* L1: w에 0이 아닌 요소가 많으면 복잡, w에 0이 많으면 덜 복잡

* L2: w가 어느 쪽에 치중되어 있으면 복잡, w에 요소가 전체적으로 퍼져있을 때 덜 복잡

<Softmax>

multi-class SVM loss 외에도 인기있는 Multinomial logistic regression, 즉 softmax는 딥러닝에서 자주 쓰인다. multi-class SVM loss에서는 스코어 자체에 해석으로 고려하지 않고 단지 정답 클래스가 정답이 아닌 클래스들 보다 더 높은
스코어를 내기만을 원한다. 하지만 Multinomial Logistic regression의 손실함수는 스코어 자체에 추가적인 의미를 부여한다. softmax라고 불리는 함수를 쓰는데 스코어를 가지고 클래스 별 확률 분포를 계산한다. softmax 함수는 스코어들을 모두 가지고  스코어들에 지수를 취해 양수로 만들고 그 지수들의 합으로 다시 정규화 시킨다. 그래서 softmax 함수를 거치게 되면 확률 분포를 얻을 수 있고, 그것은 바로 해당 클래스일 확률이 된다. 확률이기 때문에 0에서 1 사이의 값이고 모든 확률들의 합은 1이 된다. 우리가 원하는 것은 정답 클래스에 해당하는 클래스의 확률이 1에 가깝게 계산되는 것이다. 그렇게 되면 Loss는 "-log(정답클래스확률)" 이 된다.

softmax loss의 최솟값은 0 이고 최댓값은 무한대이다. 정답 클래스에 대한 Log 확률이기 때문에 Log(1) = 0 이고, -log(1) 또한 0이다. 그러므로 고양이를 완벽히 분류했다면 Loss는 0이다. Loss가 0이 되려면 실제 스코어는 극단적으로 높아야된다 거의 무한대에 가깝게. S가 모두 0 근처에 모여있는 작은 수일때 Loss는 -log(1/C)가 되고 -log(1/C)는 log(C)이다.

 

지금까지 배운 두 손실함수를 비교해보면 차이점은 바로 얼마나 안좋은지(구린지)를 측정하기 위해 스코어를 해석하는 방식이 조금 다르다는 것이다. SVM에서는 정답 스코어와, 정답이 아닌 스코어 간의 마진(margins)을 신경썼고, softmax (crossentropy) 는 확률을 구해서 -log(정답클래스) 에 신경을 썼다.

 

우리는 어떤 복잡한 함수 f를 정의하고 파라미터 값이 주어졌을때 알고리즘이 얼마나 나쁘게 동작하고 있는지 측정할 손실 함수를 작성하고 모델이 복잡해 지는 것을 어떻게 막을지에 대한 Regularization term을 추가한다. 그리고 그걸 모두 합쳐서, 최종 손실 함수가 최소가 되게 하는 W를 구한다. 어떻게 실제 Loss를 최소화하는 W를 찾을 수 있을까? 

 

<최적화>

최적화는 골짜기에서 밑 바닥으로 가는 길을 찾는 것이다. 밑 바닥을 찾는 방법으로는 1. 임의 탐색(random search)를 쓸 수 있는데 임의로 샘플링한 W를 모아 Loss를 계산해 어떤 W가 좋은지 보는 것이다. 이것은 가능하나 매우 안좋은 방법이다. 다른 방법은 2. 지역적인 기하학적 특성을 (local geometry)를 이용해 두 발로 경사를 느끼고 어느 방향으로 가야 내려갈 수 있는지를 아는 방법으로 방향을 찾아 골짜기를 내려가는 것이다. 경사(slope)은 1차원 공간에서 어떤 함수에 대한 미분 값이다. 

gradient는 벡터 x의 각 요소를 편도함수들의 집합이다. 그래서 gradient의 모양은 x의 모양과 같다. 그리고 gradient 의 각 요소가 알려주는 것은 바로 우리가 그쪽으로 갈때 함수 f의 경사가 어떤지이다. 정리하자면 gradient는 편도함수들의 벡터이다. Gradient의 요소가 알려줄 수 있는 것은 우리가 특정 방향으로 이동했을 때 Loss가 어떻게 변하는지 인데 이를 유한 차분법으로 계산 할 수 있다. 하지만 실제로는 이렇게 계산하지 않는다. 매우 느리고 하나의 gradient를 얻기 위해 수천개의 함수값을 계산해야되기 때문이다. 

데이터 셋의 Loss를 계산하는 것은 정말 오래걸린다. 아마 수백만번의 계산이 필요할 것이다. 손실 함수를 정의했던 것을 생각해보면 각 트레이닝 샘플을 분류기가 얼마나 나쁘게 분류하는지 계산해 전체 트레이닝 셋의 Loss의 평균을 전체 Loss로 사용했다. 그래서 실제로는 stochastic gradient descent라는 방법을 쓴다. 전체 데이터 셋의 gradient와 loss를 계산하기 보다는 minibatch라는 작은 트레이닝 샘플 집합으로 나눠서 학습하는 것이다. Minibatch는 보통 2의 승수로 32, 64, 128를 자주 쓴다. 따라서 이 작은 minibatch를 이용해서 Loss의 전체 합의 "추정치"와 실제 gradient의 "추정치"를 계산한다.

<이미지의 특징>

지금까지 Linear classifier는 실제 raw 이미지 픽셀을 입력으로 받았다. 하지만 이것은 좋은 방법이 아니다. 이는 Multi-Modality 같은 것 때문이다. 실제로도 영상 자체를 입력으로 사용하는 것은 성능이 좋지 않다. 그래서 DNN이 유행하기 전에 주로 쓰는 방법은 2단계 접근법이었는데,

1. 이미지가 있으이미지가 있으면 여러가지 특징 표현을 계산하는 것인데 이런 특징 표현은 이미지의 모양새와 관련된 것일 수 있다. 그리고 여러 특징 표현들은 한데 연결시켜(Concat) 하나의 특징 벡터로 만들고 그 특정 벡터를 입력값으로 쓰는 것이다.

* Unimodal : 소리, 시각, 언어, 지식

* Multimodal : 시각+언어 / 소리 + 언어

왼쪽에 경우에는 Linear한 경계를 그릴 방법이 없다 하지만 오른쪽 처럼 적절하게 특징 변환을 해본다면 (극좌표계로 바꾼 것) 복잡하던 데이터가 변환 후에 선형으로 분리가 가능하게 바뀐다. 그래서 실제로 Linear classifier로 완벽하게 분리할 수 있다.

특징 변환의 한 예는 컬러 히스토그램이다. 이미지에서 Hue 값만 뽑아서 모든 픽셀을 각 양동이에 넣는 것이다. 한 픽셀은 해당하는 색의 양동이에 넣고 각 양동이에 들어있는 픽셀의 개수를 해면 이미지가 전체적으로 어떤 색인지 알 수 있다. 

또 다른 특징 벡터로는 Histogram of oriented gradients(HOG) (이미지 내에 전반적으로 어떤 종류의
edge정보가 있는지를 나타냄), bag of words (문장을 표현할 때 문장의 여러 단어의 발생 빈도를 세서 특징 벡터로 사용) 등이 있다.

 

반응형