본 포스팅은 naver d2 이활석님의 발표자로를 글과 이해가 쉽도록 만든 Figure들로 재구성했음을 알립니다.

 

요약


  1. MSE로 최적화하는 것과 MLE로 최적화 하는 것은 동치이다. 
  2. sigmoid을 출력값으로 하는 경우 MSE로 최적화하는 것보다 CE로 하는 경우, 학습이 더 빨리 된다. 이는 activation function(sigmoid)의 도함수를 한 번 계산하지 않아도 되기 때문이다.

1. Backpropgation (역전파) 과정에 대한 가정(Assumption)


역전파알고리즘을 이용하기 위해서는 2가지 가정이 일단 필요하다 [1].

  1. Average $E = 1/n \sum_{x}E_{x}$: $n$개의 training 데이터에 해당하는 각각의 $x$에 대한 손실함수의 합의 평균은 손실함수 전체와 같다. 이는 각 훈련데이터를 각각 구한것의 그레디언트를 전체 오차함수에 대해서 일반화을 위하기 때문이다.
  2. 신경망의 출력값($\hat{y}$)에 대해서 손실함수를 표현할 수 있어야 한다는 것이다.

 

직관적으로 생각해보면 아래와 같다.

첫 번째로, MSE로 종류의 $E$(error)을 설정했다고 하자. 그리고, 이 오차함수는 예측값($y'$)과 실측값($y$)의 이를 구하게 된다. 그러면 다음과 같이 표기할 수 있다. 가령, $E(y, y')= (y-y')^{2}$가 라고 하자. 이는 일단 두번째 조건을 만족한다. 왜냐하면 $y'$은 신경망의 두번째 출력값으로 표현되었기 떄문이다. 그리고, 이러한 $y'$을 출력하기위한 입력값 $x$가 있을 것이다. 이 $x$가 $n$개가 있다고하면 각각의 $n$개의 오차의 합은 전체 $E$가 될 수 있다는 것이다. 즉, 다음과 같은 식으로 표현할 수 있다. $E=1/n \sum_{x} (y-y')^{2}$. 이렇게되면 1번 가정도 만족한다. 

 

위의 가정을 만족할 수 있으면, 이제 손실함수를 최소화시키는 최적의 파라미터($\theta$)을 찾으면된다. 보통 우리는 아래와 같이 표현한다.

$\theta^{*} = argmin_{\theta \in \Theta} L(f_{\theta}(x), y)$

위 식을 친절하게 해석해보면 다음과 같다.

  1. $\theta^{*}$: 우리가 원하는 최적의 파라미터를 의미한다. 
  2. $L(f_{\theta}(x), y)$: $\theta$가 어떤 것이 지정되냐에 따르는 손실함수($y$와 예측치 $f_{\theta}(x)$의 차이)를 의미한다.
  3. $argmin_{\theta \in \Theta} L$ : $\theta$가 될수 있는 모든 수 중에 $L$을 가장 작게만드는 $\theta$을 의미한다.

 

 

2. Gradient descent (경사하강법): 경사하강법으로 최적의 파라미터를 찾아간다.


위의 $\theta^{*} = argmin_{\theta \in \Theta} L(f_{\theta}(x), y)$식의 최적의 해를 찾는 방법으로 경사하강법(Gradient descent)가 이용된다. 이는 Iteration으로, 같은 로직을 여러번 반복하는 것을 의미한다. 식이 회귀방정식이라면 close form solution으로 직접 전개해서 풀면되지만, 활성화 함수랑 이것저것 엮여있는 DNN은 open form solution이어서 직접 추정해서 구해야한다.

 

경사하강법으로 최적의 파라미터($\theta$)을 구할 때, 고려사항과 각각의 방법은 아래의 표처럼 정리할 수 있다.

고려사항 방법
어느정도만큼 파라미터를 업데이트 할 것인가?
(= $\theta -> \theta + \Delta\theta$)
새로운 $\theta + \Delta\theta$로 손실을 측정할 때가 더 작을 때
(= $L(\theta + \Delta\theta) < L(\theta)$)
언제 멈출 것인가? 더 이상 업데이트가 변화하지 않을 때
$L(\theta + \Delta\theta) < L(\theta)$
어떻게 업데이트할 만큼($\Delta\theta$)을 찾을 것인가? $\Delta\theta = -\mu \nabla\theta$ where $\mu > 0 $

 

그림1. 이미지 출처: https://builtin.com/data-science/gradient-descent

 

위의 전략대로 아래와 같이, 일단 새로운 파라미터에 대해서 손실함수를 구하고자한다. 헷갈리지 말아야할 것은 $x$에 대해서 구하는게 아니라, 최적의 $\theta$을 찾는 것이다. 위의 그림과 같이 x1, x2축에 해당하는 w, b에따라서 손실함수의 크기 $J(w, b)$가 달라지는 것이다. 즉, $\theta$가 우리의 목표이다.

전체 데이터 포인트 X가 있으면, 아래와 같이 풀이가 가능하다.

  • $L(\theta_k, X) = \sum_{i}{L(\theta_{k}, x_{i}})$: 각 데이터포인트($x_{i}$)의 합은 전체와 같다.
  • $\nabla L(\theta_k, X) = \sum_{i}{\nabla L(\theta_{k}, x_{i}})$: 위의 식을 양변에 $\theta$에 대해서 미분한다. 
  • $\nabla L(\theta_k, X) \triangleq \sum_{i}{\nabla L(\theta_{k}, x_{i}})/ N$: 최적화만 구하면되니까, 이 미분값이 N으로 나눠도 된다. 
  • $\nabla L(\theta_k, X) \triangleq \sum_{j}{\nabla L(\theta_{k}, x_{j}})/M, ~ where ~M< N$: 전체 훈련데이터에 해당하는 데이터포인트를 다넣어서 N개의 연산을 해도되지만,너무 연산이 많이드니, 적당히 작은 M으로 나눠서 해를 찾을 수 있다. 이 때 랜덤으로 M개의 데이터 j개를 뽑는다.

즉, 결국에 X개 계산한다음에 업데이트하고싶지만, 계산이 많이 드니 M개만큼 쪼개서 업데이해볼 수 있다는 것이다.수식으로는 $\nabla L(\theta_k, X)$ 만큼 움직이는 것 대신에 $\sum_{j}{\nabla L(\theta_{k}, x_{j}})/M$ 만큼 움직여서 업데이트할 수 있다는 것이다.

그리고, 아래와 같이 다음(k+1)의 파라미터틀 업데이트한다. 우리는 이 k를 iteration, M개를 넣는 작업을 step이라고한다. tensorflow에는 iteration은 epoch, M개의 미니배치로 계산하는 것은 step이라는 표현으로 사용한다.

$\theta_{k+1} = \theta_{k} - \mu \nabla L(\theta_{k},X)$

 

 

 

3. Backpropgation에 따라서 각 레이어의 파라미터를 업데이트


위에서 구한 것과 같이 손실함수(loss function)은 $L(\theta_{k},X)$라고 했다. 헷갈리지 말아야할 것이, 파라미터($\theta$)에 해당하는 것은 각각의 레이어의 $w, b$을 의미한다. 2개의 표현식을 통틀어 크게는 $\theta$라고 표현한다. 

파라미터 업데이트는 $\theta_{k+1} = \theta_{k}-\mu\nabla L(\theta_{k}, X)$ 가 목표다. 이를 각각 w와 b에 대해서 풀어쓰면 다음과 같다.

  • $w_{k+1}^{l} = w_{k}^{l} - \mu\nabla L_{w_{k}^l}(\theta_{k}, X)$ : $k$번째 업데이트 할 때, $l$번째 레이어의 $w$에 대해서 미분이 필요하다
  • $b_{k+1}^{l} = w_{k}^{l} - \mu\nabla L_{b_{k}^l}(\theta_{k}, X)$: $k$번째 업데이트 할 때, $l$번째 레이어의 $b$에 대해서 미분이 필요하다

위의 두 식을 보면 각 레이어 $l$에 대해서 매 업데이트시(k)마다 미분이 필요하다. 이건 너무 계산이 많이들어 딥러닝이 못했던 허들이기도 하다.

 

그렇기에 이를 해결하고자 했던, 역전파로 해결한다 [2]. 이 계산을 알기위해서는 forward방향에서의 오차를 먼저 알아야한다. 그림4처럼 L번쨰 레이어의 i번째에 원래 뉴런이 하는 작업을 $\sigma$ (활성화함수아님)라 하자. 그러면, $z_{j}^{l}$이 입력이 오던걸, $\nabla z_{j}^{l}$만큼 변경하면, 출력값은 $\sigma(z_{j}^{l} + \nabla z_{j}^{l})$로 바뀐다. 그러면 최종적으로 전체 손실함수값은 $\frac{\partial C}{\partial z^l_j} \Delta z^l_j$만큼 바뀐다고 알려져있다.

그림 4.

이제 역전파로 바꿔생각해보자. 이를 구하기위한 각 notation은 아래 와 같다. 그리고, 레이어의 개수가 $l$개라고하자(=$l$ 레이어가 마지막레이어).

  • $\delta_{j}^{l}$: $j$번째 뉴런(유닛)의 $l$번째의 레이어의 변화량. 쉽게 표현하면, j번째 뉴런이 조금변경되면, 오차가 얼마나 변화하는지를 의미한다. 상세히는 w, b로 표현하면 $\partial C / \partial w^l_{jk}$, $\partial C / \partial b^l_j$도 된다. $\delta_{j}^{l}$을 활성화 함수가 포함된 합성함수라고 생각하면 다음과 같이 미분된다 [3]. $\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma'(z^L_j).$.
  • $a_{j}^{L}$: $l$레이어에 존재하는  $j$번재 아웃풋
  • $C$: cost function을 의미. 예를 들어 $C=1/2 \sum _{j}(y_{i}-a_{j}^{L})^{2}$
  • $z^{L}$: L번째 레이어에서 출력한 결과

 

다음과 같이 역전파를 진행한다.

순서 수식 의미
1 $\delta^L = \nabla_a C \odot \sigma'(z^L)$ l번째 레이어의 출력값이 변하면, 손실함수가 얼마나 변할까?
그리고 그 계수에 해당하는 activation()만큼 변하겠지?

$\nabla_a C$은 예측값과 출값의 차이니까 이를 대입한다. (단순히 MSE라고 생각)
가령, $\delta^L = (a^L-y) \odot \sigma'(z^L).$ 을 구할 수 있다.
2 $\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma'(z^l)$ $l$번째 레이어와 $l+1$번째 레이어에서의 관계식을 의미한다. 

일단 다음 레이어인 $l+1$번째의 오차를 먼저알기 때문에, 이때 계산에 쓰였던 파라미터 $w^{l+1}$을 전치한다음에 곱하고, 활성화함수만 곱해주면 이전 연산의 에러를 구할 수 있다는 것이다.

3 $\frac{\partial C}{\partial b^l_j} = \delta^l_j.$ 1,2을 이용하여 각 b에 대해서 편미분을 구할 수 있다.
4 $\frac{\partial C}{\partial w^l_{jk}} = a^{l-1}_k \delta^l_j.$ 1,2을 이용하여 각 w에 대해서 편미분을 구할 수 있다.

 

 

 

 

MSE와 CrossEntorpy 비교: 왜 굳이 이진분류를 할 때 Xentopry을 사용할까?


 

TLTR: CrossEntropy을 이용할 수 있으면, gradient vanishing에서 조금이나마 MSE보다는 이득이기 떄문이다.

 

MSE와 CE을 이용하는 각각의 모델에서, 우리 모델의 마지막 레이어가 sigmoid로 활성화 함수를 썼다고 가정하자. MSE은 출력레이어에서의 오차를 $\delta^L = \nabla_a C \odot \sigma'(z^L)$처럼 계산한다고 했다. 자세히보면 오차를 계산할 때, 오차를 계산하자마자 $\sigma'(z^L)$을 한 번 한다. C은 간단히 y-a(마지막 아웃풋과의 차이)이라고하자. 그러면 MSE을 계산하려면 $\delta^L = (a-y) \sigma'(z^L)$.가 된다.

반대로 CE을 이용하자고하자 CE의 loss은 $C=-[ylna+(1-y)ln(1-a)]$이다. 이걸 a에 대해서 미분하면 다음과 같다.

  1. $\nabla_{a}C = \frac {1-y} {(1-a)a}$.
  2. $\sigma'(z^L)$도 미분하면, $\sigma'(x)=\frac{d}{dx}\sigma(x)=\sigma(x)(1-\sigma(x))$을 따르므로, $a(1-a)$가 된다.
  3. $\delta^L = \nabla_a C \odot \sigma'(z^L)$ 라고 했기 때문에,
  4. $\delta^L = \frac {1-y} {(1-a)a} a(1-a) = (a-y)$ 이므로,  $\sigma'(z^L)$가 상쇄된다. 

정리하면, MSE을 이용할경우 backpropagation에서 gradient decay가 한 번 발생하고 역전파하기 때문에, 학습이 늦게되는 반면, CE을 이용한 경우 gradient decay가 한번 없이 역전파해서 상대적으로 학습이 빠르게 된다

그림3. sigmoid function의 원함수와 미분된 함수의 값

 

 

 

 

MSE의 최적화와 Likelihood을 이용한 최적화의 비교


MLE(Maximum likelihood estimation)은 관측한 데이터(x)을 가장 잘 설명하도록 파라미터($\theta$)을 찾는 과정이라고 생각하면 쉽다. 조금 바꾸어 말하면, 모델(f)내에 파라미터가 출력(y)을 가장 잘 설하도록 모델의 파라미터($\theta$)을 찾는 과정이랑 같다. 우리가 모델에서부터 얻는 예측값($f_{\theta}(x))$( =$\hat(y)$ 이기에...)가 정규분포를 따른다면, 평균적으로 실측값(y)을 얻게끔 파라미터를 얻는 과정이다. 따라서 아래와 같이 수식으로 표현할 수 있다.

$\theta^{*} = argmin_{\theta}[-log(p(y|f_{\theta}(x))]$

위의 식이 (-)Negative와 log가 붙은 negative log likelihood 이다. 의미는 모델의 반환값이 어떤 분포를 따른다면, 따른다면, 이 분포의 파라미터를 잘조절에서 y가 잘 나오게해주는 $\theta$을 찾아주세요. 라는 의미이다. 

 

위를 풀기위해 함수를 최적화하기위해 IID 을 가정한다

  • Independent : $p(y|f_{\theta}(x) = \Pi_{i}P_{D_{i}}(y|f_{\theta}(x_{i}))$: 트레이닝 데이터 DB ($D_{i}$)을 최적화하는 것에 대한 모든 곱은 전체와 같다. (독립사건이기에 서로 곱할 수 있다)
  • Identical distribution: $p(y|f_{\theta}(x) = \Pi_{i}p(y|f_{\theta}(x_{i}))$: training데이터는 매번 다른 분포를 같는 것이 아니라, $x1$이 정규분포라면 $x_{2},...x_{i}$가 모두 정규분포이다.

이를 이용하여 다음과 같이 negative loglikelhood을 정리할 수 있다

=> $-log(p(y|f_{\theta}(x))) = -\sum_{i}log(p(y_{i}|f_{\theta}(x_{i})))$: (IID을 이용). 각각의 확률값의 negative log likelhood을 다 더하면 전체의 training DB의 negative loglikelihood와 같다

위의 분포가 정규분포를 따른다면, 정규분포의 Likelihood을 이용해서 파라미터를 찾을 수 있다. 정규분포의 log-likelihood값은 위의 그림2와 같다. x은 관찰값 데이터포인트, $\mu$은 우리가 구하고자하는 파라미터 중에 평균에 해당한다. 이 식을 우리의 문제로 바꿔보자. x가 관찰값이었다면, 우리문제에서는 모델의 매번반환하는 $f(x)$의 평균값이 $\mu$가 되고자하는 것이다. 즉, $f_{\theta}(x_{i}) =\mu_{i}, ~\sigma_{i}=1$ 인 것을 원한다.

그림 2. log-likelihood function .&nbsp;https://www.statlect.com/fundamentals-of-statistics/normal-distribution-maximum-likelihood

$= -\frac{n}{2}ln(2\pi)-\frac{n}{2}(\sigma^{2}) - \frac{1}{2\sigma^{2}}\sum_{j=1}(x_{j}-\mu)^{2}$ 을 

$= -\frac{n}{2}ln(2\pi)-\frac{n}{2}(\sigma^{2}) - \frac{1}{2\sigma^{2}}\sum_{j=1}(f_{\theta}(x) - y_{i})^{2}$: 이렇게 바꿀 수 있다.

위의 식을보면 $y_{i}$와 $f_{\theta}(x_{i})$의 차이의 제곱. 즉 MSE와 같다.

 

반면의 베르누이 분포(=확률(p)에 따라, 결과가 0,1로 나오는 분포)를 따른다면 아래와 같다.

$p(y_{i}|p_{i})=p_{i}^{y_{i}}(1-p_{i})^{1-y_{i}}$

<=> $log(p(y_{i}|p_{i})) = y_{i}logp_{i} + (1-y_{i})log(1-p_{i})$
<=> $-log(p(y_{i}|p_{i})) = -[y_{i}logp_{i} + (1-y_{i})log(1-p_{i})]$

 

 

Reference


[1]  Nielsen (2015), "[W]hat assumptions do we need to make about our cost function ... in order that backpropagation can be applied? The first assumption we need is that the cost function can be written as an average ... over cost functions ... for individual training examples ... The second assumption we make about the cost is that it can be written as a function of the outputs from the neural network ..."

[2] http://neuralnetworksanddeeplearning.com/chap2.html

 

Neural networks and deep learning

In the last chapter we saw how neural networks can learn their weights and biases using the gradient descent algorithm. There was, however, a gap in our explanation: we didn't discuss how to compute the gradient of the cost function. That's quite a gap! In

neuralnetworksanddeeplearning.com

[3] https://j1w2k3.tistory.com/1100

반응형

+ Recent posts