바위타는 두루미

CS231n 한글 정리 | Lecture 3 | Loss Fuctions and Optimization ( Optimization , gradient ) 본문

Study/Vision

CS231n 한글 정리 | Lecture 3 | Loss Fuctions and Optimization ( Optimization , gradient )

DoRoMii 2020. 3. 5. 18:18
728x90

자, 그럼 이제는 어떻게 실제 Loss를 줄이는 W를 찾을 수 있는걸까요?


이 질문을 우리는 "최적화 (Optimization) " 라고 합니다.


최적화를 한다는 것은 우리가 다양한 산과 계곡이 있는 엄청 큰 골짜기를 걷고 있는 것입니다.

내가 위치하고 있는 곳의 높이가 Loss가 되는것이고 우리의 임무는 이 골짜기의 밑바닥을 찾는 것입니다. 

하지만 이문제는 매우 어렵습니다. 그래서 우리는 다양한 iterative한 방법을 사용합니다.


가장 먼저 생각할 수 있는것은 "Random search(임의 탐색)" 입니다.

*매우 구린방법입니다.

CIFAR-10에서는 클래스가 10개니까 임의확률은 10%가 되고, 무작위 시행을 거치게 되면 약 15%의 정확도를 보이는군요.

최신 알고리즘의 성능 SOTA가 95%인것을 생각하면 매우 좋지 않죠.


두번째 방법은 "local geometry(기하학적 특성 이용하기)" 입니다.

우리는 발로 경사를 느끼고 어느 방향으로 가야 내려갈 수 있을지를 알 수 있을 것입니다.  

경사를 느끼고 방향을 정하는 것을 계속 반복하다보면 골짜기를 다 내려갈 수 있을 것입니다.

이 방법은 우리가 NN이나 Linear Classifer같은 것은 훈련시킬때 일반적으로 사용합니다.


그렇다면 경사(slope)는 무엇일까요? 미분 수업이 기억나나요? 

어떤 점 (x)에서 도함수(derivative)를 계산해보면 작은 스텝(h)가 있고 그 스탭간의 함수 차이를 비교하기 위해 뺄셈을 하고, 그 스텝사이즈를 0에 가깝게 만들면 이것이 바로 그 점(x)에서의 경사가 됩니다.


이 개념은 다변수함수(multi-variable function)로도 확장시킬 수 있습니다.

실제로 x는 스칼라가 아니라 벡터입니다. x가 벡터이기 때문에 이 개념을 다변수로 확장시켜야 합니다.

다변수인 상황에서 미분으로 일반화 시키면 gradient이고 gradient는 벡터 x의 각 요소를 편도함수들의 집합입니다.

입력이 3개면 gradient도 3개가 되겠죠.

그리고 이 gradient의 각 요소가 알려주는 것은 바로 "우리가 그쪽으로 갈때 함수 f의 경사가 어떤지" 일것입니다.

즉 gradient는 편도함수들의 벡터가 되고, 방향은 함수에서 "가장 많이 올라가는 방향"이 됩니다.

gradient의 방향이 반대가 되면 가장 많이 내려가는 방향이 되겠죠.


그렇다면 특정방향에서 얼마나 가파른지 알고싶으면 어떻게 해야할까요?

그것은 그 방향의 유닛벡터와 gradient벡터를 내적한 것과 같습니다.


gradient는 매우 중요합니다. 

왜냐하면 gradient가 함수의 어떤 점에서의 선형 1차 근사 함수를 알려주기 때문입니다.

그래서 실제로 많은 딥러닝 알고리즘들이 gradient를 계산하고 파라미터 벡터를 반복적으로 업데이트 하는데에 사용합니다.


컴퓨터로 gradient를 유용하게 사용할 수 있는 방법은 유한 차분법(finite difference method)를 이용하는 것입니다.

다시 gradient의 극한식으로 돌아가봅시다.

왼쪽에 W가 있습니다 .이 W의 loss는 1.25정도 되는군요.

우리가 첫번째 요소에 아주작은값 h (0.0001)을 더해보고 loss를 구해봅시다. 그러면 1.24342에서 1.24322로 감소하는 군요.

이제 극한식을 이용하여 gradient를 구합니다.

이것을 각 요소마다 반복합니다


실제로는 시간이 매우 많이 걸리므로 매우 끔찍합니다.

하지만 우리는 미적수업을 들었으므로 미분이라는 마법을 이용하여 바로 gradient를 구할 수 있습니다.

아래와 같은 식으로 간단히 구할 수 있죠.

해석적으로 푸는 것이 수치적으로 푸는 것보다 더 효율적입니다. (물론 디버깅을위해 수치적으로 계산하는 방식이 쓰일 수는 있습니다.)


그럼 우리가 구한 gradient를 이용하여 gradient의 반대방향으로 업데이트를 하고 아주 조금씩 이동하여 결국 수렴할 것입니다!

하지만 스텝사이즈(이동하는 정도, learning rate)는 하이퍼파라미터입니다.

스텝사이즈를 올바르게 결정하는 것도 매우 중요한 문제입니다.


근데 앞으로 더 쩌는 스탭들을 볼 수 있을 것입니다.

기본은 gradient를 이용하는 것이지만 다음 스텝을 결정하기 위해서 이전의 모든 스탭의 gradient의 정보를 이용하는 방법들도 있습니다.


우리가 배워야할 한가지가 더 있습니다.


손실함수를 정의한 것을 다시 상기해보면, Loss를 구할때 전체 트레이닝셋 loss의 평균으로 사용했습니다.

하지만 실제로는 N이 매우 커질 수 있습니다. ImageNet 데이터 셋의 경우 N은 130만개입니다.

그러면 시간이 매우 걸리게 되겠죠.

gradient 계산하는 과정을 살펴보면 Loss는 그저 각 데이터 Loss의 Gradient의 합이라는 것을 알 수 있고, 그러니 N개의 전체 트레이닝셋을 한번 더 돌면서 계산해야하는 것입니다.


그래서 실제로는 stochastic gradient descent라는 방식을 사용합니다.

전체 데이터 셋의 gradient와 loss를 계산하기 보다는 Minibatch라는 작은 트레이닝 샘플로 나누어서 학습하는 방식입니다.

보통 2의 승수로 정하며 32,64,128로 쓰는편입니다.

그래서 이 작은 minibatch를 이용하여 Loss의 전체합의 추정치와 실제 gradient의 추정치를 계산하는 것입니다.


앞으로 이 더 간지나는 update rules들이 정확히 어떻게 여러 gradient들을 통합시키는지 알아보겠습니다.

또한 방금 설명한 SGD는 거의 모든 DNN알고리즘에 사용되는 기본적인 학습 알고리즘입니다.


사실 Linear Classifier는 이미지에서는 그리 좋은 방법은 아닙니다. 

그래서 DNN이 유행하기 전에 Linear Classifier를 이용하기 위해서는 두가지 스테이지를 거쳐서 사용했습니다.


첫번째는, 이미지의 여러가지 특징표현을 계산하는 것입니다. 

이미지나 모양새와 같은 특징표현을 연결하여 특징 벡터로 만들고


두번째는, 이 특징벡터를 Linear Classifier에 입력값으로 주는 것입니다. 


특징변환의 한 예로는 컬러 히스토그램이 있습니다. 

이미지에서 Hue값만 뽑아서 모든 픽셀을 양동이에 넣고 각 양동이에 담긴 픽셀의 갯수를 세는것입니다. 

이 개구리의 경우에는 초록색이 많은 것을 알 수 있습니다. 


또다른 예로는 HoG가 있습니다. 

이번에는 이미지를 8*8 픽셀로 나누어서 각 픽셀의 지배적인 edge방향을 계산하고 각 edge들에 대해서 양동이에 넣는것입니다. 

그럼 edge에 대한 히스토그램이 되는것이죠 


이러한 방법도 있습니다. 바로 Bag of words 입니다.

NLP에서 영감을 받은 방식으로, 어떤 문장에서 여러 단어들의 발생빈도를 세서 특징벡터로 사용하는 방식을 이미지에 적용한것입니다.

우리는 이미지에 적용하기 위해 이미지들을 임의대로 조각내고, 각 조각을 K-means와 같은 알고리즘으로 군집화 합니다. 

다양하게 구성된 각 군집들은 다양한 색과 다양한 방향에 대한 edge도 포착할 수 있습니다.

(이러한 것들을 시각 단어 (visual words) 라고 부릅니다. ) 


그래서 5-10년전에는 대부분 이런식으로 특징벡터를 뽑아서 Linear Classifier의 input으로 사용했습니다. 

사실 이 개념들은 CNN과 DNN으로 넘어간다고 크게 달라지는 개념은 아닙니다. 

유일하게 다른 점이 있다면 이미 만들어 놓은 특징을 쓰기 보다는 데이터로부터 특징을 직접 학습하려 한다는 점입니다. 


다음시간에는 CNN에 대해 심도있게 살펴볼 것이고 역전파(Backpropagation)에 대해 알아보겠습니다. 








Comments