깨작깨작 공부

CS231n Lecture 3 | Loss Functions and Optimization 본문

머신러닝 | 딥러닝 강의 정리/CS231n Spring 2017

CS231n Lecture 3 | Loss Functions and Optimization

CodezTree 2019. 9. 24. 02:31

https://www.youtube.com/watch?v=h7iBpEHGVNc&list=PL3FW7Lu3i5JvHM8ljYj-zLfQRF3EO8sYv&index=3

 

# 영상 시작 부 ~ 5분정도 : 전시간 복습 - loss function / optimization

 

# loss function(손실 함수)

-> 우리의 분류기가 얼마나 올바르게 작동하는 지를 알려줌.

 

  - Loss(손실) 는 수치 값 (of 각 데이터 쌍(입력-목표)의 loss 값의 평균)

 

 

# Multiclass SVM의 Loss 형태

 - 수식을 대충 보면, s 는 모델이 출력한 값을 의미하는데, 연산은 정답 라벨이 아닌 출력 값 $s_{j} (j \ne y_{i}$) 값들로 Hinge Loss를 적용한 형태. 즉, 정답 라벨이 아닌 나머지 출력값이 정답값 보다 한참 미만으로 이루어지도록 유도하는 loss function임을 알아볼 수 있음. ( Hinge Loss 는 아래서 설명 )

 

 

# Hinge Loss

$$L_{i}=\sum_{j \ne y_{i}}max(0,s_{j}-s_{y_{i}}+1)$$

 

  - Hinge Loss의 형태는 $s_{y_{i}}$의 값에 따라 정해지는데, 이 값이 정답에 해당하는 출력값이 나머지 출력값들인 $s_{j}$보다 1 커야지만 손실이 0이 되게 함으로써, 우리의 모델의 정답 출력값이 모든 출력값에 비해 우월(?)하게 크고 돋보이게 한다고 해석할 수 있다. 

 

 

 

 

 

 

# Multiclass SVM Loss에 대한 여러 질문들

 

Q1. 만약 정답 출력값이 가장 큰 상황에서 (1.3, 4.9, 2.0) 정답 출력값이 아주 조금의 변동을 보이면 loss 값은 바뀔까?

-> 올바른 정답의 출력값이 무엇보다 중요하므로 각 출력값들이 약간의 변동을 보여도 정답만 가장 크다면 loss는 항상 0 (학습이 잘되었음)

 

Q2. 가능한 최대/최소의 손실값은 무엇인가?

-> 최솟값은 0 ( 정답 출력값이 가장 크면 나머지 출력에 대한 loss 계산은 식에 의해 모두 0 이므로 ) 최댓값은 $\infty$ . ( Hinge Loss의 그래프에서 정답 출력값이 음의 무한대로 갈 경우 loss는 무한대가 되어버림 )

 

Q3. 최초 초기화 시에 W 값이 너무 작아서 모든 출력값이 0에 가깝다. (0 이라고 하자) 그렇다면 손실 값은 무엇인가?

-> 분류 범주 수 - 1 이다. 모든 출력값이 0 이라면 $s_{j}-s_{y_{i}}$ 값이 0 이므로 남는건 1. 정답 출력값 빼고 나머지에 대해서만 계산하므로, 분류 범주의 수 - 정답 분류 수 ( 1 )을 뺀 값이 손실 값이 되는 것.

 

Q4. 만약 합의 수식 ( $\sum$ )이 정답 출력값까지 계산한다면 무슨 일이 일어날까? ( 즉, $j = y_{i}$ 포함 )

-> 손실 값이 원래 값에서 1 늘어난다. 정답 출력값을 계산한다면 $s_{j}-s_{y_{i}}$ 값이 0 ( $s_{y_{i}}-s_{y_{i}}$ 를 계산하게 되니까 ) 이므로 정답 분류에서 손실이 1 추가된다. 보통 이 분야에서 손실은 0이 되는 것이 잘 학습되었다는 점을 의미있게 나타내 준다고 보기에 정답 출력값을 제외하는 것. ( 계산한다면 최솟값은 1 인셈 )

 

Q5. 만약 합 대신에 평균을 쓴다면 어떻게 될까?

-> 아무일도 일어나지 않는다. 학습에도 문제가 되지 않고 단지 이것은 손실의 값을 키우거나 줄이는 (Scaling) 작업을 하는 것 뿐 의미상으로 합과 동일하다.

 

Q6. 만약 loss 식을 $L_{i}=\sum_{j \ne y_{i}}max(0,s_{j}-s_{y_{i}}+1)^2$ 이렇게 바꾸면 어떻게 될까? ( max를 제곱 )

-> 다른 분류 알고리즘이 될 것이다. 이것은 Squared Hinge Loss를 의미한다. Loss 함수가 선형성을 잃고 곡선을 띄게 된다. 이러한 방법으로 우리가 필요한 다른 종류의 Loss Function을 만들어 낼 수 있다. ( 어쩌나 저쩌나 손실함수 본래 기능에 충실하면 되는데 이 경우는 바꾼다고 해서 손실함수의 의미를 잃진 않는다. 단지 Hinge 에서 주는 페널티가 n 이라면 square는 n^2 만큼 많이많이 페널티를 준다는 것 뿐  )

 

 

 

 

 

# Multiclass SVM Loss Code 예제

 

def L_i_vectorized(x, y, W):
    scores = W.dot(x)
    margins = np.maximum(0, scores - scores[y] + 1)
    margins[y] = 0  # 정답에 대한 계산 값은 0으로 만들어 줌
    loss_i = np.sum(margins)
    return loss_i

 

 

 

# 또 질문

 

그렇다면 위 상황에서 계속 진행되어 손실 값이 0 이 되는 ( L = 0 ) W 값을 찾았다고 하자. 그러면 그 W 값은 유일한가?

 

-> 아니다. 2W도 L = 0 을 만족하는 W 값이 될 수 있다. 단지 모든 출력값들이 2배가 될 것이다.

 

그렇다면 W 값이 유일하지 않다면 Loss Function을 정의한 이유와 불일치 하지 않나? L = 0 을 만드는 여러 W 중에 무엇을 찾아야 되는것인가?

 

-> 그 이유는 우리가 단지 주어진 Data에 대한 L = 0을 만족하는 W를 찾는 것에 대해 얘기했기 때문이다. 기계학습의 본질은 학습을 해서 'Test(시험) Data'에 적용시키는 것이다. 우리는 모델이 Train Data에서 퍼포먼스를 보여주는 것보다 Test Data에서의 퍼포먼스를 더욱 중요하게 생각한다. (학습되지 않은 실제 데이터에서의 폭넓은 적용이 핵심)

 

예시로 들자면

 

여기에 파란 데이터들이 있다. 이 데이터를 예측하는 회귀 그래프를 학습한다고 하자. 그러면 학습 데이터에 대해 학습이 이루어지면 그림처럼 파란 구불거리는 선이 나올 수 있다. 그러나 초록 데이터는 실제 시험 데이터인데 우리가 학습한 그래프는 시험 데이터에서 나쁜 성능을 낼 수 있다. 원래는 학습이 아래 그림의 초록색 직선처럼 이루어져야 더욱 적절한데 말이다.

 

 

 

즉, 위 상황이랑 덧붙여 말하자면 ( 요약자 추가 ) 우리가 방금 구한 파란선을 형성하는 W 값은 학습 데이터에서는 올바를 수 있지만, 시험 데이터에서는 그렇지 않다. 그렇기에 모델의 Loss을 줄이는 여러 W 중에서 적절한 W의 선택은 시험 데이터까지 고려해야 얘기할 수 있는 것.

 

그래서 머신러닝에서는 손실 함수를 다음처럼 변화를 준다.

 

Regularization ( 일반화 )의 용도는 머신러닝 모델이 좀더 '단순'해지는 것이 목적이다. 위와 같은 상황은 너무나 '세밀'하고 '정확'해서 일어나는 문제이므로 이를 더욱 '단순한 직선'이 되도록 (더 '단순'한 W를 선택하도록) 유도하는 것이 Regularization의 역할이다. $\lambda$는 일반화 계수(Regularization의 강도를 결정)이고 (하이퍼파라미터 일종) $R(W)$는 일반화를 진행하는 함수이다.

 

 

다양한 Regularization 방법들

 

여기서 L2 Regularization은 Euclidean Norm으로 우리가 흔히 알고 있는 거리 측정 방법이다. L1 Regularization은 Weight Vector가 sparse 하게 ( 많은 0을 가지도록 ) 해주는 특징을 가지고 있다. 각 Regularization 방법은 각자 나름대로 Weight Vector에 대해 ( $W$ 에 대해 ) 페널티를 부여하는 역할을 맡는다.

 

 

L1 과 L2 의 차이점...? 그리고 선택법...?

 

-> W의 분포가 sparse하게 만들고 싶다면 L1 ( 몇 개의 의미있는 특징을 잡아내고 싶다면 ) , 그렇지 않고 전체적으로 평이한 페널티를 주고 싶다면 L2를 선택하면 되는데, 어쨌든 데이터의 특성과 우리가 하고 싶은 방법에 따라 선택하는 것이 올바르다. 참고로 L1 Norm은 0 지점에서 미분이 불가능해 Gradient-Based 학습 방법에서 문제가 생길 수 있다.

 

 

 

 

# Softmax Classifier ( Multinomial Logistic Regression )

 

Multiclass SVM에서는 계산을 통해 class들에 매겨진 점수들에 대해 큰 해석을 부여하지 않았다. 그저 정답인 class의 점수값이 나머지보다 커야한다는 것이 신경쓰는 점이었다.

 

Sofmax Classifier은 점수에 의미를 부여하는 방식이다. 이 점수들은 class 간의 확률 분포를 나타내는 측도로 이용된다. 

 

Class의 출력 점수에 자연상수의 지수함수를 취해줌으로써 가장 점수가 높은 class를 부각시킨다. 위 수식을 통해 class의 점수를 확률로 변환시킬 수 있으며, 각 출력은 0에서 1 사이의 값을 가지게 된다. 

 

$$L_{i}=-logP(Y=y_{i}|X=x_{i})$$

 

Softmax를 이용한 손실함수는 위와 같은데, 이는 손실함수에서 올바른 class의 negative log likelihood를 최소화하는 것을 목표로 한다. 결국 이 손실함수는 정답 class의 softmax 출력이 1에 ( 확률이 1에 ) 가까워지도록 유도하는 역할을 한다. ( 수식으로 보면 입력 값 $x_{i}$에 대한 목푯값 $y_{i}$의 확률을 높이고 싶다라는 뜻 )

 

 

이 과정을 한 수식으로 정리하면 다음과 같다.

 

$$L_{i}=-log(\frac{e^{s_{y_{i}}}}{\sum_{j}e^{s_{j}}})$$

 

 

# 여러가지 질문들

 

Q1. $L_{i}$가 가능한 출력값의 최대/최솟값은 무엇인가?

-> 이론상으로는 정답이어야 하는 클래스의 출력이 1일때 $-log(1)=0$이므로 0이다. 만약 출력이 0이라면 $-log(0)=+\inf$이므로 정해지지 않는다. ( 발산한다 )

 

Q2. 보통 $W$의 초기화 값은 작아서 출력 $s$가 거의 0이다. 그때 손실값은 어떻게 되는가?

-> 정리한 수식에 의해 log 진수 값의 분모는 정답에 해당하는 출력값도 0이므로 $e^{0}=1$이고, 분자도 모든 class별 출력값이 0에 가까우므로 class의 수가 될 것이다. 영상에서는 c (constant)를 사용해서 $-log(\frac{1}{c})=log(c)$라고 얘기한다.

 

( 여러가지가 아니라 2개군요... ^^ )

 

 

 

# Softmax vs. SVM

 

$$L_{i}=-log(\frac{e^{s_{y_{i}}}}{\sum_{j}e^{s_{j}}}) \qquad\qquad L_{i}=\sum_{j \ne y_{i}}max(0, s_{j}-s_{y_{i}}+1)$$

 

Q. 만약 출력 점수를 ( $s$ 값들 ) 조금 변형을 준다면 전체 손실값의 변화가 있는가?

-> SVM loss는 정답 class 점수가 다른 class보다 크기만 한다면 손실값의 변화가 없다. 하지만 Softmax는 확률값을 1로 만드는 것이 목적이기 때문에 손실값이 변한다.

 

" SVM은 마치 허들 넘기처럼 정답값이 다른 값보다 크면 더 이상 신경쓰지 않는다. Softmax는 항상 모든 시점에서 더 좋은 점수를 내려고 할 것이다. "

 

 

 

 

# 요점

 

요약을 참 잘해놨다. 데이터 상관 관계가 잘 보이는 그래프도 있다!

 

 

 

 

Q. 그렇다면 Loss를 줄이는 좋은 W 값은 어떻게 찾아내는 것일까?

 

 

# Optimization

 

( 나도 곧잘 쓰는 비유법이긴 하다 ) 당신이 골짜기에서 돌아다니고 있다고 생각해보자. 그런데 당신은 골짜기에서 가장 낮은 지점으로 가고 싶어한다. 그러면 어떻게 하는게 좋을까? 

 

 

# 목표점을 찾는 방법 2개

 

 

1. 무작위 검색

 

그냥 범위를 지정하고 임의로 다 때려박고 가장 최적인 W를 구한다. 쓸데없이 많은 시간을 낭비할 수 있고, 범위 내에 최적의 W가 존재한다는 보장도 할 수 없다. => 나쁜 알고리즘

 

2. 기울기를 이용한다.

 

1차원에서 함수의 미분은 다음과 같다

 

$$\frac{df(x)}{dx}=\lim_{h\to0}\frac{f(x+h)-f(x)}{h}$$

 

다차원에서 gradient 는 각각 차원을 편미분한 값으로 구성된 벡터이다. gradient는 함수의 함숫값이 커지는 방향을 나타내주기에 negative gradient를 이용하면 함수의 함숫값이 작아지는 방향을 얻을 수 있다. => 함수의 최소지점을 찾을 수 있게 된다. ( 이는 2차원에서도 마찬가지다 )

 

이제 이 gradient를 이용해서 파라미터를 업데이트 시켜주면 된다. 

 

그런데 컴퓨터를 통해 gradient를 계산하려면 각 벡터의 원소를 일일히 하나씩 작은 값을 더하고 빼주며 기울기 값을 원소마다 구해줘야한다. -> 매우 비효율적인 방법이다. ( 이를 numerical, 수치적 gradient라고 한다 )

 

그래서 gradient를 구할 때는 항상 analytic gradient ( 해석적 gradient. 해석적 미분이란 우리가 흔히하는 함수 미분 )를 사용한다. 그러나 해석적 gradient가 잘 계산되는지 확인할 때는 수치적 gradient를 통해 둘 값을 비교해 사용한다. 이를 gradient check 라고 한다. ( 왜냐면 해석적인 것은 사람의 계산 실수가 있을 수 있지만, 수치적인 것은 컴퓨터가 계산하여 계산이 정확하다 )

 

 

 

요약하자면...

 

- 수치적 gradient : 느리고, 사용하기 쉽고, 추정치의 특성

 

- 해석적 gradient : 정확하고, 빠르고, 오류가 발생하기 쉽다

 

 

- 수치적 gradient는 디버깅 도구로 사용하자. gradient check

 

 

 

# Gradient Descent

 

매 계산마다 gradient를 구하고, 가중치를 gradient의 역방향으로 조금 이동시켜주는 방법. 3줄짜리 코드면 된다.

# Vanilla Gradient Descent

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

step_size는 learning_rate로 불리는 하이퍼파라미터로 가장 중요한 하이퍼파라미터 중 하나이다.

학습의 속도를 결정한다.

 

 

 

( 학습 과정 영상 보여주는 중.... 다양한 Descent 방법 있다고 티저 유출.. )

 

 

 

# Stochastic Gradient Descent (SGD)

 

확률적 경사 하강법. 모든 데이터 셋을 한꺼번에 돌리면 보통의 경우 숫자가 무지무지하게 커지고 gradient계산까지 너무 오래걸린다. 그래서 매 계산반복마다 조그만한 묶음의 데이터셋을 sampling해서 minibatch라고 불리는 데이터 묶음을 만든다. 이를 minibatch를 통한 gradient를 이용하여 전체 데이터에 대한 학습을 '확률적'으로 진행하는 방식이다.

 

# Vanilla Minibatch Gradient Descent

while True:
	data_batch = sample_training_data(data, 256) # sample 256 examples
	weights_grad = evaluate_gradient(loss_fun, data, weights)
	weights += - step_size * weights_grad  # perform parameter update

그래봤자 4줄이라고 합니다.

 

 

 

 

( Web demo 시연중... )

http://vision.stanford.edu/teaching/cs231n-demos/linear-classify/

들어가서 해보세용. 관찰..

 

 

 

# Image Features

 

raw 픽셀 값을 분류기에 넣는 것은 잘 작동하지 않을 수 있다. 그래서 이미지에서 특징 (feature)을 추출해서 이를 통해 linear classifier을 적용하는 것이 더욱 효율적이다.

 

선형 분류가 되지 않는 데이터들은 특징점들 변형시켜주면 ( feature transform ) 분류가 가능한 경우들이 있다.

ex) 극좌표로의 변환을 통해 분류

 

Color Histogram을 이용하는 방법도 있다. 특정 색의 발현수치를 통해 특징을 잡아낼 수 있다.

 

Histogram of Oriented Gradients (HoG)라는 방법도 있는데 사람의 vision system에서 테두리 (edge)정보는 중요하게 작용한다는 점을 이용해서 이미지를 여러 구역으로 나누어 각 구역별 픽셀들의 기울기 방향을 계산해서 feature로 이용하는 방법이다.

 

Bag of Words 방법은 이미지에서 랜덤으로 이미지 patch (그냥 조그마한 잘린 이미지)를 추출해서 patch들을 이용해 visual words의 codebook을 형상하고 이를 이용해 이미지를 부호화시킨다. (패치들이 이미지 상에서 발현하는 수치 값들을 이미지의 feature로 사용)

 

 

 

(Image features vs ConvNets)

( 딥러닝 이용하면 단순 feature 방법보다 더 잘할 수 있다 스포중... )

 

 

 

# 다음시간

 

신경망의 기초

 

역전파

 

 

 

 

( 내용이 꽤 많아서 정리하는데 진 다빠지네요 ㅠㅠ 앞으로의 고난이 예상됨... )

 

 

 

이 포스트에 쓰인 모든 컨텐츠의 저작권은 전적으로 Stanford CS231n Spring 2017 Course에 있음을 알립니다.

Comments