juuuding

[CS231n] Lecture 3. Loss Functions and Optimization (2) 본문

인공지능/cs231n

[CS231n] Lecture 3. Loss Functions and Optimization (2)

jiuuu 2023. 12. 8. 15:32

 Optimization

 

 Optimization은 loss를 최소화하는 best W를 찾기 위한 과정이다. 

 한 사람이 산의 한 꼭대기에 올라왔다고 생각해보자. 이 사람은 산의 가장 낮은 골짜기 부분으로 가야한다. 여기서 내려갈 때 아무런 길로 가는 것이 아니라, 가장 빠르게 골짜기로 향할 수 있는 길을 선택해야한다. 이것이 optimization의 기본 아이디어이다. 산의 높이는 해당 지점의 w로 인해 발생한 loss의 값을 의미한다. 다음으로 optimization을 하는 방법에 대해 알아보자. 

 

 

① Random search

import numpy as np

bestloss=float("inf")   # bestloss 변수에 float 형식에서 가장 큰 값 넣기
for num in range(1000):
    W=np.random.randn(10,3073) * 0.0001
    loss=L(X_train,Y_train,W)
    if loss < bestloss:
        bestloss=loss
        bestW=W

 

 이 방법은 w 값을 랜덤하게 선택해 loss 값을 구하고 그것이 기존의 최소 loss 값보다 작으면 best w 값과 함께 이를 갱신하는 것이다. 하지만 이 방법은 단순하기만 하고 좋지 않은 방법이다. 

 

② Follow the slope

 두번째 방법은 경사를 따라 가장 효율적인 w로 최소 loss 값으로 향하는 방법이다. 일차원의 상황으로 가정하여 보면 해당 지점에서의 기울기를 골라 가장 가파른 경사인 w값 방향으로 향한다. 다차원에서도 마찬가지로 적용되지만 각 차원마다의 derivative 값을 구해주어야 한다. 아래는 multiple dimension에서 gradient를 각각 구해주어 가장 가파르게 loss 값으로 향할 수 있는 w 값을 구해주는 방법의 예시다. 

 

 

 하지만 이 방법(numerical gradient)은 w의 모든 차원에 대해서 계산을 일일이 해주어야 하기 때문에 아주 느려 좋지 않은 방법이다. 그래서 실제로는 이 방법보다 "미분"이라는 방법을 사용하여 이를 한 번에 gradient가 계산되어 나온다. w의 모든 원소를 하나씩 보며 계산하는 것이 아니라 gradient를 나타내는 식이 뭔지만 찾아내고 이것을 수식으로 나타내어 gradient dW를 계산해내는 것이다. 이 방법은 analytic gradient라고도 부른다. 

 

미분 사용

 

 실제에서는 이 analytic gradient를 사용하지만, 실행이 잘 되는지 확인할 때는 numerical gradient를 사용한다. 하지만 parameter의 스케일이 클 때에는 확인이 너무 오래 걸리기 때문에, 이때는 parameter rescale을 해주어 numerical gradient를 진행한다. 이 방법을 사용하여 확인하는 방법을 "gradient check"라고 한다. 

 

[Gradient Descent]

while True:
    weights_grad = evaluate_gradient(loss_fun, data, weights)
    weights += -step_size*weights_grad

 

 위의 코드에서 step_size는 learing rate으로 gradient 계산 시 ,해당 방향으로 얼만큼 나아갈 것인가에 대한 hyperparameter이다.

 

 

[Stochastic Gradient Descent]

 아래 식은 gradient descent를 하여 loss 값을 갱신해 나가는 식이다. 하지만 예를들어 dataset으로 전에 보았던 imageNet을 사용하면 N 값이 약 1.3million이기 때문에 계산이 너무 느려 실제에서 사용할 수 없다. 그래서 우리는 Stochasitc Gradient Descent(SGD)를 사용한다. SGD란 모든 training data를 사용하는 대신 training data의 작은 sample set을 사용하여 Gradient Descent를 하는 것을 말한다. 

 

while True:
    data_batch = sample_training_data(data,256)     #256개의 예제를 샘플링
    weights_grad = evaluate_gradient(loss_fun, data, weights)
    weights += -step_size*weights_grad      # parameter update

 

 


 

 

[Image Features]

 지금까지 linear classifier이 raw 이미지 픽셀을 입력 받아왔다. 하지만 이는 좋은 방법이 아니다. 전 강의에서 본 말 머리 2개 현상처럼 modality과 같은 문제가 발생할 수 있기 때문이다. 그래서 실제로 DNN이 유행하기 전 주로 썼던 방법은 2가지 stage를 거치는 방법이었다. 첫번째로 이미지를 여러가지 feature로 표현하고 두번째로 이를 concatenate하여 하나의 feature vector로 만드는 것이다. 그러면 이 feature vector가 linear classification로 입력된다. 

 

 

 이러한 아이디어의 모티브는 다음과 같다. 

 

 

 왼쪽 그림을 보면 빨간 점과 파란 점이 분포해 있는 것으로 볼 수 있다. 이것은 직선인 linear classifier로 decision boundary를 그릴 수 없는 문제가 발생한다. 그래서 우리가 적절하게 feature을 변환하면 오른쪽 그림과 같이 바꿀 수 있다. 데이터가 이렇게 분포되어 있다면 linear classifier로 decision boundary를 생성할 수 있게 된다. 이미지를 이와 같은 극좌표계로 변환하는 것은 말이 안될 수 있지만, 이것을 일종의 feature 변환이라 생각한다면 말이 된다. 이런 식으로 feature 변환을 한 이미지는 raw 이미지를 분류기에 넣는 것보다 성능이 더 좋을 것이다. 

 

 이제  image feature 변환 예시에 대해 살펴보자. 아래는 color histogram 예시다.

 

Color Histogram

 

 이미지에서 휘도 값만 추출하여 모든 픽셀을 각 휘도 값에 따라 분류하여, 휘도 값에 맞는 픽셀들의 개수를 세어 만든 히스토그램이다. 

 

 다음으로 feature 변환 예시 중 하나인 Histogram of  Oriented Gradients(HOG)에 대해 알아보자. 이미지를 우선 8x8 픽셀로 나눈 후 8x8 픽셀 부분 내에서 가장 우세한 edge의 방향을 계산하고 이 edge 방향을 양자화하여 9개의 bin에 넣는 것이다. 그리고 다양한 edge orientations에 대한 히스토그램을 계산한다. 

 

 

 위 두 feature 변환 방법 모두 feature을 변환하여 히스토그램으로 다시 feature을 표현한다. 하지만 첫번째는 이미지 전체적으로 어떤 색이 있는지에 대한 것이고, 두번째는 이미지가 전반적으로 어떤 방향의 edge를 가지고 있는지에 대한 것이다. 

 다음으로 feature을 표현하는 또 다른 방법이 있다. "Bag of Words(BoW)"라는 것인데 이 아이디어는 NLP에서 영감을 받은 것이다. BoW에서 문장을 표현하는 방법은 문장의 여러 단어 발생 빈도를 세서 feature 벡터로 사용하는 것이다. 이것을 이미지에 적용하면 "visual word"라는 것을 생성하여, 어떤 이미지에서의 visual word 발생 빈도를 통해 이미지를 인코딩하여 이 이미지가 어떻게 생겼는지에 대한 정보를 제공해주는 방법으로 활용된다. 여기서 visual word를 만들어 사용하는 2단계(codebook -> encoding)로 표현된다. 먼저 굉장히 많은 이미지를 가지고 그 이미지들을 임의로 조각내고 이 조각을 k-means 같은 알고리즘으로 군집화한다. 군집화를 거치면 visual words는 다양한 색, 다양한 방향 edge를 포착해낸다. 이러한 방법으로 visual word의 집합인 codebook이 생성하고 나면, 어떤 이미지에서의 visual words 발생 빈도를 통해 이미지를 인코딩하여 이 이미지가 어떻게 생겼는지에 대한 다양한 정보를 얻을 수 있게 된다.

 

Back of Words

 

 

[Image features vs. ConvNets]

 이렇게 feature이 한 번 추출되면 classifier를 트레이닝 하는 동안 feaure extractor는 변하지 않는다. 트레이닝 중에는 오직 linear classifier만 훈련된다. CNN/DNN도 이와 마찬가지인데, 유일하게 다른 점은 CNN/DNN은 만들어 놓은 특징을 쓰기보다는 데이터로부터 특징들을 직접 학습하려 한다는 것이다. 그리하여 CNN에는 raw image가 그대로 들어가 여러 layer을 거치며 feature 표현을 만들어 낸다. 따라서 CNN/DNN은 트레이닝할 때 linear classification을 훈련하면서 가중치 전체를 한꺼번에 학습한다.