Sunwoo Kim's Computer Vision, Machine & Deep Learning Blog search

CS231n-Lecture07(training neural network 2)

|

저번 강의 때 배웠던 부분을 살펴보자.

먼저, 일부 활성화 함수에 대해서 살펴보는 시간을 가졌었다.

그리고 가중치 초기화의 중요성에 대해서도 살펴보았다.

data processing에 대해서도 간략히 살펴보았으며, zero centered하게 데이터를 정규화 시켜주는게 중요하다고 하였었다.

네트워크를 훈련 시키면서 내부 공변량 이동(internal covariant shift)가 일어남으로 이를 방지하기 위한 방법인 배치 정규화(batch normalization)방법에 대해서 살펴보았다.

그 후, 훈련을 시킬 때, 적절한 하이퍼파라미터가 무엇인지 찾기 위하여 이를 바꾸어 나가면서 그래프를 살펴보는 시간을 가졌었다.

적절한 하이퍼 파라미터를 고르기 위하여 1,2,3과 같은 정해진 구역보다 1.1, 2.5 와 같은 지점에도 최적의 파라미터 값이 존재할 수 있으므로, 구간 내 랜덤 탐색이 최적의 파라미터를 찾기 더 좋은 방법이라고 배웠다.

Fancier optimization

최초 초기화한 가중치 지점에서 최적의 파라미터 지점까지 경사 하강법을 통하여 최적화를 진행하였다.

SGD를 사용할 때, 한 방향으로는 그라디언트가 빠르게 바뀌지만(즉, 그라디언트가 큰 방향과 작은 방향의 크기의 비율이 높다면), 다른 방향으로는 느리게 바뀐다면 경사 하강법은 어떻게 움직일까? 바로, shallow dimension(일부 몇개의 차원만을 의미하는 것 같다.)에서 매우 느리게 업데이트되며, 가파른 방향으로 진동(jitter)한다고 한다. 지그재그로 업데이트되 기 때문에 속도가 더 느려진다. 이러한 문제는 고차원에서 많이 발생하는 문제라고 한다.

SGD에서 문제가 되는 점은 무엇을까? 바로 local minima와 안장점(saddle point)이다. local minima는 모든 방향의 그라디언트가 지역적으로 최소인 지점이고, saddle point는 한쪽으로는 로스가 증가하고 한쪽으로는 로스가 감소하는 방향에서의 극점(기울기가 0)인 지점이다. 저차원에서는 local minima 가 saddle point에 비해서 더 자주 나타나지만, 고차원으로 갈수록 saddle point와 같은 양상이 더 많이 보이게 된다.쉽게 생각해서, 100만 차원이 존재할때, 100만개의 방향이 지역적으로 모두 최소인것보다, 일부 방향이 saddle point에 빠지는 것이 훨씬 가능성이 높을것이다.

SGD의 또다른 문제점은 그라디언트가 미니 배치로부터 구해진다는 것이다. 그렇기 때문에 위 그림과 같이 검은색 부분으로 보이는 데가 있는데, 불규칙한 진동을 보이면서 최적점에 다가가고 있는 모습이다. 이것은 노이즈 때문에 발생하는 문제점이다.

그렇다면, local minima 및 안장점에서 생기는 문제가 미니 배치를 사용했기 때문일까? 그것은 아니다. 좀 더 안정적으로 학습이 진행될 뿐, 여전히 발생하는 문제이다. 그렇다면 이 문제를 어떻게 해결할까?

해당 문제를 해결하기 위하여 SGD에 모멘텀(momentum)이라는 것을 추가하였다. 이것은 일반물리에서 가속도(acceleration)의 개념과 비슷하다. 즉 기존의 그라디언트는 그대로 구하는데, 그것이 속도개념이 되어서, 새로운 속도 개념이 되고, 기존의 속도의 반영 비율을 나타내는 것이 로(rho)이다. 크면 클수록 기존의 속도를 반영하겠다는 것을 의미한다. 그리고 그것을 다시 학습률에 곱해서 가중치를 업데이트 하는 방식이다.

모멘텀은 local minima 및 saddle point에 빠졌을 때 벗어나는데 도움을 주는데, 그 때 도움을 주는것이 기존의 속도를 반영하는 것이다. 현재 포인트에서 그라디언트가 0이 나왔을 지라도 기존의 속도를 반영하는 부분 때문에, 일정 포인트를 더 이동할 수 있게 된다. 이로써 극점에 빠져있을 확률을 줄여준다.

오른쪽 그림을 보면, 그라디언트가 가파른 방향으로 기존의 방향까지 추가해서 이동하기 때문에 기존의 SGD보다 더 빠르게 이동하는 모습을 볼 수 있다.

모멘텀을 주는것에도 여러가지 방식이 있는데 이번세 살펴볼 모멘텀은 네스테로브 모멘텀(Nesterov momentum)이다. 위 식을 보면, $\nabla f(x_t + v_t)$인 점이 특이하다는 것을 알 수 있다. 나는 이식을 보고 미리 그 곳을 가보고 갈 방향을 정한다는 느낌이 들었다. 간단히 말하자면 다음과 같다. 원래 우리는 $x_t$지점에서 그라디언트를 구하고 그 쪽 방향으로 더 이동한다. 그래서 $x_t + v_t$지점에 도달했다고 하자. 그런데 막상 이 지점에서 $\nabla f(x_t + v_t)$를 구하고 보니, 얕은 기울기 혹은 극점 혹은 증가하는 지점이었던 것이다. 즉 안 좋은 지점에 도착한 것이다.

그러므로 미리 그 지점의 그라디언트를 가져와서 반영하는 것이다. $v_{t+1} = \rho v_t - \alpha \nabla f(x_t + \rho v_t)$의 식에 이 개념을 대입하면, 미리 가보고, 그라디언트가 양수가 나온다면 속도가 줄어, 그 방향으로 덜 가게 되고, 음수가 나온다면 더 내려가도 된다는 뜻이므로 더 가파르게 다음 방향쪽으로 이동할 수 있게 된다.

위 슬라이드를 보면 네스테로브 모멘텀이 다른 방식에 비해서 빠르게 이동하는 모습을 볼 수 있다. (연두색이 없어진것 처럼 보이지만, 빨간색과 겹쳐져 색이 진해졌다…)

다음으로 설명할 것은 에이다(혹은 아다) 경사하강법(AdaGrad, 아다그라드)방법이다. 아다그라드는 변수의 업데이트 횟수에 따라 학습률(Learning rate)를 조절하는 옵션이 추가된 최적화 방법이다. 여기서 변수란 가중치(W) 벡터의 하나의 값(w[i])을 말한다. 아다그라드는 많이 변화하지 않은 변수들은 학습률(step size)를 크게하고, 반대로 많이 변화한 변수들에 대해서는 학습률을 적게한다. 이는 많이 변화한 변수는 최적값에 근접했을 것이라는 가정하에 작은 크기로 이동하면서 세밀한 값을 조정하고, 반대로 적게 변화한 변수들은 학습률을 크게하여 빠르게 loss값을 줄인다.

다음으로 살펴볼 optimizer는 RMSProp이다. RMSprop은 아다그라드에서 G(t)가 무한히 커지는 것을 방지하기 위해 나온 방법이라 한다. RMSprop은 지수이동평균을 이용한 방법이다. 지수이동평균은 지난 값과, 현재값에 $\alpha, (1-\alpha)$라는 가중치를 주어 계산 하는 방식이다. 이렇게 되면, 예전 값에는 $(1-\alpha)^{n}$이 곱해져, 결과적으로 업데이트가 되면 될 수록 영향력이 적어지게 된다. 이러한 $\alpha$를 forgetting factor, 혹은 decaying factor (여기서는 decaying rate)이라 불린다.

즉 위 슬라이드를 보면 아다그라드에서 바뀐점은 G(t)가 지수이동평균을 이용하여 더해진다는 점이다.

RMSProp이 SGD보다는 빠르게,SGD+Momentum보다는 보다 안정적으로 최적값에 도달해가는 모습을 볼 수 있다.

Adam은 RMSProp과 momentum를 합쳐놓은 방법이다. first momentum과 second momentum을 보면 각각 어느 부분이 그 역할을 하는지 알 수 있다. 하지만 위 슬라이드에서 Adam을 사용할 때, 첫 번째 가중치를 업데이트 할 때 나타나는 문제점이 무엇인지에 대해서 물어보고 있다. 그것은 바로 두 모멘텀이 초기에 0으로 초기화 되었을 때 문제가 나타난다는 것이다. 첫 번째 업데이트시 거의 0에 가까운 값으로 업데이트 되며(0으로 편향이 발생) 이것은 학습의 저하를 초래한다는 것이다.

그래서 0으로 편향되는 것을 막기 위하여(bias correction) 각각 일정 값으로 나눠준다고 한다.

그림에서 보는것과 같이 Momentum과 RMSProp의 모습과 비슷한 형태로 학습하는 것을 볼 수 있다.

여태까지 다룬 모든 optimizer들은 learning rate를 필요로 한다. 그렇다면 어떤 learning rate가 최적의 learning rate가 될 수 있을까?

사실 이 질문은 tricky하다고 한다. 왜냐하면 처음에 높은 learning rate을 설정한 다음, learning rate을 decaying(하락) 시키면 된다는 것이다. 지수적으로 하락시키거나, 1/t씩 하락시키는 방법이 있다고 한다. 다른 방법들도 있을 것이다.

learning rate가 일어난다면 learning loss curve는 다음과 같이 바뀌게 될 것이다. 이러한 weight decay는 SGD방법에서 더 많이 쓰이며, Adam에서는 잘 쓰이지 않는다고 한다. (아무래도 가중평균이 적용되어 조절해주는 부분이 있어서 그런게 아닐까? 라고 짧게 생각해본다…)

그것을 아는가? 우리아 여태까지 살펴본 optimizer는 모두 first-order optimizer다 그것이 무슨소리냐면, 한번 미분한 가중치만 반영하는 optimizer만 살펴보았다는 것이다. 위 슬라이드를 보자. 한번 미분을 하게되면, 그 그라디언트를 따라 이동하게 되는데, 그럴경우 우리는 많은 범위의 이동을 할 수가 없다 왜냐하면 근사의 한계가 있기 때문이다. 우리가 대학교에 들어오자마자 배웠던 미적분학에서 등장한 테일러 급수를 떠올려보자. 추가되는 항이 많아질수록, 즉, 고차항이 많아질수록 근사를 정확히 할 수 있었다.

이러한 관점에서 second-order optimizer가 등장하였다. 위 슬라이드에서 볼 수 있듯이, 더욱 정확한 근사를 통하여 많은 범위를 움직일 수 있게 된다. 일차 미분을 할 때, 자코비언이 필요했다면, 이차미분의 행렬도 불리는 이름이 있는데 그것이 바로 헤세 행렬(Hessian matrix)이다.

이차 테일러 급수가 위 슬라이드에 나와있다. $1/2 (\theta - \theta_0)^T H (\theta - \theta_0)$인 부분이 이차항을 나타내며 계산해보면 qudaratic form을 나타내게 된다. 이 파라미터 업데이트 방식은 뉴턴 방법(Newton method)라고 한다. 여기서 식을 보면 헤세 행렬의 역행렬을 사용하는데, 이 때 시간복잡도가 엄청난 것을 볼 수 있다. 가중치의 차원이 몇 백만 차원인 것을 생각해보면 이것을 사용하지 않는게 좋을 것이라는 생각이 바로 든다.

이를 보완한 방법이 콰시-뉴턴 방법(Quasi-Newton methods)라고 한다.

우선 여기서는 full batch에서 잘 작동하고, mini-batch 에서는 잘 작동하지 않는다는 점만 알아두자.

실제 에서는Adam이 모든 케이스에서 거의 기본적인 optimizer로 최초에 사용된다고 한다.

지금 까지 트레이닝 시에 사용되는 optimizer에 대해서 살펴봤다. 그런데 가장 중요한 것은 트레이닝이 아니다. 바로 아직 보지 않은 데이터(unseen)데이터에 대한 정확도이다. 그렇기에 train dataset의 정확도와 validation set과의 차이가 적은 모델이 좋은 모델이라고 할 수 있다. 그렇다면 이 둘의 차이는 어떻게 줄일 수 있을까?

그 방법중 하나로 강의에서는 모델 앙상블(Model ensembles)을 소개한다.여러 종류의 모델을 독립적으로 훈련 시킨후, 그 파라미터를 평균을 내어 적용하는 것을 뜻한다. 약 2%정도의 성능 향상을 얻을 수 있다. 아무 고민하지 않고, 모델만 주구장창 돌려서 이 정도 성능이면 아주 좋은 것 같다.

Regularization

그렇다면, 여러 모델을 사용하는게 아니고, 단일 모델만을 사용할 때, 성능을 높힐 수 있는 방법은 무엇이 있을까? 강의에서는 그 방법중 하나인 규제(regularization)에 대해서 소개한다.

Add term to loss

이 슬라이드는 우리가 예전에 보았던 슬라이드일 것이다. CS231n-Lecture03 에서 L1, L2 regularization의 원리에 대한 간략한 설명을 한 적이 있다.

드랍아웃(Dropout)

포워드 패스를 진행할 떄, 일정확률로 랜덤하게 특정 뉴런의 값을 0으로 만드는 것이다. 보통 50%의 확률이 적절하다고 한다.

그렇다면 어떻게 이것이 좋은 아이디어가 될 수 있을까? 첫 번째로, 불필요한 표현을 제거하여 그런 뉴런들의 상호작용을 줄여준다는 것이다.

두 번째 관점으로는 드랍아웃 자체로 앙상블의 효과를 낼 수 있다는 것이다. 왜냐하면 그 때 마다 제거되는 뉴런이 다르기 때문에, 그 자체로 하나의 독립적 네트워크가 될 수 있다는 뜻이다.

그렇다면 드랍아웃 적용시, 테스트 때는 어떻게 헤야할까? 우리가 아주아주 사랑하는 평균을 이용하면 된다. 그렇다면 위의 식과 같이 인테그럴을 이용하여 식을 표현할 수 있을텐데, 드랍아웃 되는 모든 경우의수를 더해서 평균을 낸다는게 사실상 불가능 하다. 그렇다면 어떤 방법을 사용해야 할까?

생각해보면 경우의 수는 4가지 밖에 없다. 위의 슬라이드 처럼 말이다. 여기서는 빨간 글씨로 드랍아웃 확률을 그냥 곱해주면 된다고 나와있다. 위 슬라이드의 식을 조금더 풀어쓰면, $p^2(a+b) + p(1-p)(a+0)+p(1-p)(0+b)+(1-p)^2(0+0) = (p^2 + p(1-p))(a+b) = p(a+B)$가 나오기 때문이다. 그렇기 때문에 어떤 드랍아웃 확률을 쓰던 테스트 시에는 p를 곱해주면 되는 것이다.

regularization의 훈련시와 테스트시 적용의 일반적인 패턴에 대해서 설명한다. 즉, 훈련 시키고 테스트시에는 훈련시에 고정된 어떤 값을 이용한다는 뜻이다. 그 이유는 CS231n-Lecture06의 배치 정규화 부분을 살펴보자.

규제의 다른 방법으로 데이터 증강(data augmentation)이 있다. 즉 기존의 훈련 데이터에 약간의 변형을 가하여 데이터를 변형하는 것이다.

위의 슬라이드들은 규제의 일반적인 패턴들을 설명하고 있다.

일반적인 경우로는 BN으로도 충분하지만 그렇지 않을경우 dropout도 고려해보라고 강의에서 말하고 있다.

Transfer Learning

우리는 항상 딥러닝 네트워크를 훈련시키기 위하여 엄청나게 큰 데이터셋이 필요할까? 그렇지 않을 수도 있다.

transfer learning을 이용하면 된다. IMAGNET으로 우선 네트워크를 한 번 훈련 시킨다. (여기서 부터 이미 큰 데이터가 필요한게 아닌가?…. 하지만 다음 우리가 훈련시킬 데이터는 그렇지 않으니까.) IMAGNET으로 훈련시킨 가중치는 손쉽게 온라인에서 가져올 수 있다. 그렇다면 우리가 훈련시키고 테스트를 원하는 데이터셋이 CIFAR-10 같이 10class인 small datset이면 두 번째와 같이 마지막 FC layer만 다시 훈련시켜준다. 그 밑에 레이어 들의 가중치는 고정시킨다.

만약에 더 큰 데이터셋을 훈련시킨다면, 그 조금 더 밑의 FC layer까지 훈련시키도록 한다.

이런 방법은 우리가 앞서 배웠던 CNN의 특징에 기인한다. 즉 네트워크의 끝으로 갈수록 조금 더 high level의 feature를 가지게 된다. 그 말은 밑에 레이어들은 물체들의 일반적인 특징들을 가지고 있다는 것이다.

transfer learning은 아주아주아주아주 자주 사용되는 기법이다. (거의 매번?)

Comment  Read more

CS231n-Lecture06(training neural network 1)

|

우리는 저번 강의때, 컨볼루션 네트워크에서 컨볼루션이 진행되는 방식에 대해서 배웠었다.

이번 시간에는 최적화를 통해서 네트워크의 파라미터들을 어떻게 학습시키는지 살펴보도록 하자.

우리는 네트워크를 Mini-batch SGD형식으로 훈련시킬 것이며 과정은 위와 같다. 전체 데이터를 n개의 batch(n개의 batch를 전부 훈련시키면, 전체 데이터 1회 훈련)로 나누어 그 중 한 개의 배치를 입력하고, forward한 후, loss를 얻고, 역전파를 통해서 파라미터를 업데이트 시키는 것이다.

우선적으로 one time setup에 있는 부분은 네트워크 훈련을 시작할 때, 최초에 설정해 놓는 부분이다. 그 후, 훈련을 진행하면서 상황에 따라, training dynamics에 있는 부분을 조정하고, 최종적으로 모델을 평가하게된다.

이번 6강에서는 위 part1에 있는 부분에 대해서 살펴보고, 나머지 부분은 lecture07에서 살펴보도록 하자.

Activation Functions

활성화 함수(activation function)은 컨볼루션 레이어 혹은 완전 연결 레이어(fully connected layer)에서 가중치 곱을 한 후, 비선형성(non-linearity)를 갖기 위하여 지나가는 관문이라고 볼 수 있다.

활성화 함수의 종류중 일부가 위 슬라이드에 나타나 있으며, 위 종류 말고 더 많은 수의 활성화 함수가 존재한다.

처음에 살펴볼 활성화 함수는 시그모이드(sigmoid) 함수이다. 시그모이드 함수의 식은 위와 같다. 그런데, 시그모이드 함수에는 한 가지 치명적인 단점이 있다. 바로, 포화 상태가 된 뉴련이 그라디언트를 죽일 수 있다는 뜻이 된다. 이 말이 어떤 말인지 다음 슬라이드에서 살펴보도록 하자.

위 슬라이드를 살펴보자. 만약에 x가 -10일 때, 미분을 하면 기울기가 어느정도일지 예상할 수 있을 것이다. 바로 거의 0에 근접하다고 생각할 수 있다. 반대로 x가 0이면 기울기는 거의 1에 가까우며, x가 10일 때는 -10일 때와 마찬가지로 기울기가 0에 가까울 것이다.

우리는 그라디언의 전파가 체인룰을 이용한 역전파로 이루어진다고 배웠다. 만약에 0에 가까운 그라디언트가 곱해졌다면, 해당 그라디언트는 0으로 거의 수렴하게 되어 아무리 그 뒤의 그라디언트가 크더라도 해당 그라디언트가 0으로 죽어버려 전파되지 못하는 현상이 발생한다. 이것이 바로 위에서 설명한 시그모이드의 치명적인 단점이다.

만약에, 입력 데이터가 모두 양수(혹은 음수)라면 가중치는 어떻게 업데이트가 될까? 위 그림처럼 지그재그로 업데이트 되면서 한쪽 방향으로만 업데이트가 될 것이다. 이것은 업데이트식을 생각해보면 금방알 수 있다. $W = W - \nabla W$ 와 같은 방식으로 업데이트 된다. 이 때, 위 식에서 W의 기울기는 X이기 때문에 X의 부호가 오직 하나로 고정되어 있다면, 한쪽 방향으로만 업데이트 되는것은 당연하다.

지그재그로 업데이트 되는 이유는 X의 값에 따른 기울기의 차이이며, X값과 b(bias)가 모두 양수일 때, X 의값이 b의 값보다 작을 경우, 위로 살짝 올라가는 형식의 업데이트가 진행될 것이다.

그렇기 때문에, 우리는 훈련을 시킬 때, 데이터를 zero-mean에 맞추어 normalization을 해주어야 한다.

시그모이드 함수는 이외에도 2가지 문제점이 더 있다고 한다. 시그모이드의 출력값이 zero-centered가 아니라는 점이다. 이것은 시그모이드 함수의 형태를 보면 바로 알 수 있다. 0이 아닌 1/2 centered인 모습을 볼 수 있다.

그리고 expernential 연산은 다른 연산에 비하여 컴퓨팅 연산을 많이 소모하기 때문에, 자원 활용 측면에서도 좋지 않다고 한다.

이런 단점을 보완한 활성화 함수가 바로 tanh(x)함수이다. zero-centered가 되어 있으며, [-1,1]사이로 스쿼싱되있는 모습이다. 하지만 시그모이드와 동일한 모습을 가지고 있기 때문에, 그라디언트가 죽어버리는 현상이 여전히 문제로 남게된다.

이번 활성화 함수는 AlexNet에서 등장한 ReLU함수이다. ReLU함수는 위 두 함수에 비해서 훨씬 연산이 효율적이며 saturated 되지 않는다는 장점이 존재한다.

그렇다면 ReLU의 경우 x=-10,0,10 일 때, 기울기가 어떻게 계산될까? 답은 간단히 1,0,1 일 것이다. 즉 기울기가 1로 그대로 전달 되기 때문에, 0 이후의 부분은 살아남는게 보장이된다. 하지만 0이하의 값들은 모두 죽어버릴 것이다 .이게 위 슬라이드에 an annoyance라는 문제로 설명이 되어있다.

annoyance에 대해서 active ReLU, dead ReLU라고 설명이 되어있다. 즉, 0이상인 값은 active ReLU 0미만인 값은 dead ReLU인 것이다. learning rate이 높게 되면, 훈련되는 값이 이리저리 튀게 되면서, -로 가는 값이 많아진다. 그렇기 때문에 ReLU를 사용할 시, learning rate설정에 신경을 써야한다.

이를 해결하기위해서 나온것이 Leaky ReLU 이다 ReLU와 달리 0이하의 부분의 기울기가 0.01로 되어있어, 기울기를 완전히 소실시키지 않는다. 또한 기울기를 0.01과 다르게 한다면 그것은 Parametric Rectifier(PReLU)라고 부른다.

똑같은 PReLU의 형태를 띠지만, 입력값에 exponential 값을 취하고 1을 뺀것을 ELU라고 한다. 기울기를 보았을때, 음수쪽은 saturation시키는 형태를 가지고 있으며, 이런 특징이 조금 더 노이즈에 대한 강인함을 증가시킨다고 한다. 하지만 exponential 연산을 사용하기 때문에, 코스트 문제가 생기게된다.

maxout neuron은 두 뉴런의 입력중 큰 쪽을 선택하여 통과시킨다는 것이다. 이것은 ReLU와 LeakyReLU를 일반화 시킨 형태라고 한다. 어느 한 쪽을 버리지 않지만, 선택한 쪽을 그대로 통과시키기 때문에, 두 값이 0이상이건 아니건 신경쓰지 않는다. 이런 면에서 ReLU와 LeakyReLU를 일반화 시켜 놓은것이라고 한 것 같다. 하지만 이렇게 두 개의 뉴런을 모두 사용하기 때문에, 우리가 같은 크기의 네트워크를 만들고자 할 때, 파라미터가 2배 더 필요하다는게 아주아주 큰 단점이다.

그러므로 위으 특징으로 미루어보아 정리하면 위와 같다. 실제로는 해당 activation fucntion을 사용 할 때, ReLU는 learning rate를 조심해서 설정하고, Leaky ReLU/ Maxout/ ELU 등을 사용하는게 좋으며, tanh에 대해서는 그렇게 큰 기대를 하지말고, sigmoid는 사용하지 않는다는 것이다.

Data Preprocessing

위에서 살펴보았을 때, 처음에 데이터를 zero-centered로 설정하는게 필요하다고 설명하였다. 훈련전에 이렇게 데잍러를 처리하는 과정을 data-preprocessing(데이터 전처리)이라 한다. 데이터의 스케일(scale) 즉 표현범위를 일관되게 하기 위하여 normalization을 하기도 하며, PCA와 같이 데이터의 특성에 따라 데이터를 전처리 하기도 한다.

AlexNet에서는 이미지의 평균을 빼고 훈련을 시작하거나, VGGNet에서는 각 채널별 평균을 낸 다음 그 값을 뺀 후 훈련을 시작하기도 하였다.

Weight Initialization

만약에 훈련을 시작할 때 첫 가중치가 모두 0 이라면 훈련이 될까? 정답은 훈련이 되지 않는다는 것이다. 왜 훈련이 되지 않을까? 만약에 모든 가중치가 최초에 0이라면, 곱해져서 그 다음 레이어로 가는 값은 모두 0일 것이다 그리고 최종적으로 모두0이란 값을 내뱉을 것이다. 그 다음 loss를 구하고 역전파를 하려고 하면 모두 같은 0이라는 값을 주었으므로, 역전파가 될 때, 같은 기울기 값이 역전파가 될 것이다. 그 이후도 모두 같은 양상이도 모두 같은값이 왔으므로, 모두 같은 값이 역전파가 되어 네트워크는 결국 모두 같은 값을 가지게 되며 훈련은 진행되지 않는다.

그렇다면 가중치의 초기화는 어떻게 이루어져야 할까? 첫 번째 방법은 충분히 작은 랜덤한 수로 초기화를 시키는 것이다. 하지만 이것은 작은 네트워크에서는 비교적 잘 작동하지만, 크기가 커지고 깊어질수록 잘 작동하지 않는다는 단점이 존재한다.

여기에 10개짜리 레이어와 500개의 뉴런을 가지고 있고, tanh를 사용하고, 충분히 작은 랜덤한 수로 가중치를 초기화 시키는 네트워크가 있다.

이 때, 훈련을 시킬수록 가중치가 어떻게 변하는지 살펴보자. 파란색 그래프를 유심히 살펴보자. 파란색 그래프는 히스토그램이다. 처음에는 가중치가 골고루 분포해있는 모습을 볼 수 있지만, 급격히 모든 가중치들이 0에 수렴하는 값들을 가지고 있는 모습을 볼 수 있다. 왜 이렇게 되는 것일까?

위의 코드처럼 처음 셋팅시 $N(0,1) * 0.01$의 값을 지니도록 모든 가중치가 초기화 됬다고 해보자. 이 때, 활섬화 함수를 제외하고 레이어를 지나면서 곱해진 값을 표현하면, $x_{10} = w_{10}(…w_3(w_2(w_1x_1 + b_1)+b_2)…+b_{10})$ 와 같이 식을 표현할 수 있을 것이다. 그런데 이 모습을 보자. $N(0,1) * 0.01$의 값들은 모두 0.1 미만의 작은 소수이기 때문에, 위 식은 0.1미만의 작은 수의 값이 계속해서 곱해지는 모습을 볼 수 있을 것이다. 그렇게 된다면, 처음 입력의 값이 점점 0에 수렴하는 모습을 보이게 될 것이다. 그 모습이 바로 위 슬라이드의 파란색 히스토그램으로 잘 표현되어있다. 히든레이어의 값이 모두 0으로 수렴되있는 모습을 볼 수 있다.

이렇게 된다면, 역전파 에서도 마찬가지로 문제가 생기게된다. 가중치를 역전파 시키는 와중에 체인룰에 의하여 0에 수렴한 값이 곱해지기 때문에, 제일 첫번째 레이어에 대응되는 가중치를 업데이트 하려고 할 때, 그라디언트가 0에 가까워 거의 업데이트가 되지 않아 학습이 되지 않을 것이기 때문이다.

그렇다면, 모든 가중치의 값을 $N(0,1) * 1.0$으로 바꾼다면 히든레이어값의 히스토그램은 어떻게 변할까? 위의 예시처럼 히든레이어의 값이 0으로 수렴하지는 않고 [-1,1]안의 범위에서 진동을 할것이다 하지만, 학습을 진행함에 따라서 tanh의 성질에 따라서, -1과 1로 saturation되게 될 것이다. 그 이유는 다음과 같다. tanh 함수를 보면, -1,과 1에 근접할수록 기울기가 1에서 0으로 수렴하는 모습을 보인다. 이 성질이 핵심이다. 히든 레이어의 값이 진동하다가, -1과 1에 근접하게 되면 기울기가 0에 가까워져, 그라디언트가 0에 가까워지기 때문에, 가중치가 더이상 업데이트 되지 않게 된다. 즉, 계속 반복하게 되면 가중치가 히든레이어의 값을 1 또는 -1로 만들도록 고정되게되는 것이다.

가중치 초기화는 이처럼 아주 중요한 역할을 한다. 그렇다면 어떻게 초기화를 해야 좋은 초기화를 할 수 있을까? 그것을 위한 방법으로 2010 년에 Xavier initialization방법이 나온다. 이 방법은 우리의 입력에 크기에 맞추어 가중치를 변화시키는 방법이다.

하지만 Xavier initialization 방법과 ReLU를 같이 사용하는 것은 아주 좋지 않은 방법이다. 왜냐하면 두 방법을 같이 사용하면, 한 값으로 수렴하는 방법을 피하게 만들기 위한 xavier initialization 방법이 통하지 않고, 0으로 수렴하는 모습을 보인다.

그렇다면 ReLU와 어떤 initialization 방법을 사용해야할까? 바로 He initialization 방법을 사용하면 된다.

weight initialization은 이처럼 네트워크 훈련 자체를 좌우하는 아주 중요한 요소중 하나이기 때문에, 활발하게 연구되고 있는 분야중 하나라고 한다.

Batch Normalization

훈련시에 성능을 높힐 수 있는 또다른 방법으로는 배치 정규화(batch normalization)이 존재한다. 배치 정규화는 내부 공변량 변화(internal covariant shift)에 의한 네트워크의 성능저하를 막고, 규제(regularization)의 효과가 있다고 한다. 앤드류 응 교수님의 유튜브 강의 에서 그 이유가 간략히 설명되어 있다.

배치 정규화는 위 슬라이드와 같이 배치에서 서로 같은 특징을 표현하는 채널(CNN에서는 (H,W,C)= (H,W,1)이 한 개의 특징을 표현한다. 그래므로 배치의 크기가 n이라면 (n, H,W,1) 의 평균과 분산을 구한 후 정규화를 하는 것이다.)끼리 연산하여 평균과 분산을 구한후 정규화를 시키는 과정이다. 위 식 처럼 정규화를 시키면 $N(0,1)$인 분포가 되는것을 확률과 통계시간에 배웠을 것이다.

배치 정규화는 레이어로써 네트워크에 넣을 수 있으며, 역시 역전파가 가능하다. 또한, 주로 활성화 함수를 통과하기 직전위치에 FC layer, conv layer 뒤에 넣는다고 한다. 여기서 위 슬라이드에 질문이 있다. 과연 우리는 표준 가우시안 분포($N(0,1)$)를 필요로하는가? 라는 질문이다.

이 슬라이드만 봐도 위 질문에는 아니라는 답이 나온다. $\gamma, \beta$라는 학습가능한 파라미터를 추가해주어, 적절한 평균과 분산을 찾게 해주며, 정규화 시킨 파라미터를 원래 상태로 되돌리는 identity mapping을 가능하게 한다.

배치 정규화의 알고리즘은 위에 나온것과 같이 매우 간단하게 표현할수 있다.

위 슬라이드를 보면 테스트시에는 훈련 시 학습해놓은 하나의 고정된 평균과 분산값을 사용한다고 나와있다. 이것은 우리가 총을 쏠 때 영점조준을 해놓은 것과 비슷하게 생각해볼 수 있다. 우리는 훈련데이터에 대해서 적절한 평균과 분산값(기준점)을 알아 놓았다. 그렇다면 테스트 데이터를 집어넣어 어떤 클래스에 속하는지 알려면, 훈련데이터 기준으로 어느 지점에 매핑이 되는지를 파악하면 되는 것이다.

이것은 비슷하게 KNN(K-Nearest Neighbor)를 생각하면 된다. 테스트 데이터가 들어왔을 때, 훈련데이터들이 기준 지점이 되어 그 기준에서 어디에 속하는지를 파악하게 된다. 그렇기 때문에, 배치 정규화도 테스트시에는 훈련때 학습한 평균과 분산이 테스트시에 그 기준이 되는 것이고, 그 값을 가지고 정규화를 해야 훈련데이터 기준 어느쪽으로 치우쳐져 있는지 알 수 있는 것이다.

Babysitting the Learning Process

우리는 여태까지 convolution layer, FC layer, regularization ,normalization, preprocessing, optimization등 네트워크를 훈련시키기 위해 필요한 기본적인 토대를 배웠다. 우리는 이 지식을 가지고 네트워크를 훈련 시킬수 있을 것이다. 그렇다면 좋은 성능을 내는 네트워크를 찾기 위해서 우리가 배운것과 같이 적절한 preprocessing, network의 깊이, weight initialization, regularization, learning rate등을 고려하지 않을 수 없다. 이것을 자동으로 찾아주는 연구가 진행되고 있지만 현재는 사람이 직접 찾아주고 있는 추세다. 어떻게 가능한 최적의 값을 찾을 수 있을까?

처음 loss가 어느정도 되는지 체크를 한다.

1e3 정도의 규제항을 넣어준다. 이 때 loss가 증가했다면, 규제가 잘 되고 있다는 것이다. (첫 loss를 가져왔으므로.)

위와 같은 네트워크를 훈련시킨다고 해보자. 훈련 정확도가 100%가 나온 모습을 볼 수 있다.

이번에는, learning rate 을 1e6으로 바꾸어보자. 그리고 regularization을 1e-6으로 설정하고 epoch수가 200 에서 10으로 낮추었다. 그런데 1e-6을 학습률이 적절한 학습률인지 알아보고 올바르지 않다면 올바른 학습률을 찾는 것을 고민해보자

일반적으로 loss가 너무 낮다면 학습률이 너무 낮은것이고, Nan이 떠서 숫자를 표시하지 못한다면 이것은 거의 항상 높은 학습률을 의마한다.

학습률=3e-3으로 해놓아서 확 낮췄으나 여전히 많이 높은것 같다. cost=inf이니 말이다. 그렇다면 learning rate를 더 낮춰보는 방법이 좋겠다.

이런 식으로 하나씩 값을 조율해나가며 적절한 파라미터를 찾는 엔지니어링 과정을 해주어야한다.

Hyperparameter Optimization

최적의 파라미터 값을 찾기 위해서 처음에는 파라미터의 값의 범위를 넓게 잡은후 점차 좁혀 나가는 방식을 선택하는게 좋다고 한다.

reg와 lr에 주목하면 좋을것 같다. 이 범위에서 최적의 validation accuracy는 0.48로 꽤 좋은것 같다. 이제 범위를 더 좁혀보자

이렇게 말이다. 그랬더니 validation accuracy가 0.53이 나왔다. 와우 더 좋아졌다. 하지만 꼭 그렇지 않을 수 있다. 왜냐하면 우연히 이 수치에 잘맞는 데이터가 뽑힌 것일 수 있기 때문이다.

이렇게 세부적인 범위안에 있는 값을 찾듯이, 최적의 파라미터의 값은 그리드 레이아웃 처럼 딱딱 떨어지는 지점에 존재하는게 아니고, 연속된 영역 어디든 존재할 수 있기 때문에, random search로 찾아주는 것이 효과적이라 할 수 있다.

강의에서는 이것을 디제잉하는 작업과 비슷하다고 말한다.

강의하시는 분도 실제로 이렇게 엄청나게 많은 경우를 테스트해본다고 한다.

이것이 아주 중요한 그림일 것 같은데, learning rate의 설정값에 따라서 그래프의 양상을 보여준다.

이런 양상은 좋지 않은 learning rate설정이다.

이렇게 훈련과 검증(validation)데이터셋 간의 정확도 차이를 꼭 시각화 해서 비교해보는걸 추천하고 있다. 당연히 적을수록 파라미터 설정이 잘된 것이다.

Comment  Read more

CS231n-Lecture05(convolution network)

|

저번 시간에는 선형 분류기에서 어떻게 가중치가 곱해지고 역전파가 되며, 최적화가 되는지 살펴보았다.

이번 시간에는 computer vision에서 아주 눈에띄는 성능의 향상을 불러 일으킨 컨볼루션 네트워크(convolution network)에 대해서 배울 것이다.

History of ConvNet

현재와 같은 뉴럴 네트워크의 구조를 가지는데 역사적인 네트워크가 있다. 그것이 바로 위 사진에 나온 Mark I Perceptron이다. 이 퍼셉트론은 activation function이 0과 1의 아웃풋만 가지며, 현재와 비슷한 update rule을 가진 모습을 확인할 수 있다. 다만 현재와 같은 그라디언트를 이용해서 업데이트 하는 방식은 아니다. 퍼셉트론 보다 조금 더 발전한 방식이 adaline, madaline이라닌 네트워크이다.

그리고 첫 번째로 Rumelhart가 1986년에 back-propagation을 유행시켰다고 한다.

2006년에 Hinton 과 Salakhutdinov가 다시금 deep learning에 대한 연구를 활발하게 만들었다고 한다. 위 그림의 구조를 보면 지금과 같은 딥러닝의 구조를 비슷하게 띄고 있는것 같다.

첫 번째로 딥러닝이 강력한 성능을 보이며 주목받기 시작한 연구는 2012년에 딥러닝을 이용한 speech recognition과 우리가 익히 알고있는 이미지 인식에 관한 논문인 AlexNet이다.

사실 이러한 구조는 우리 피질(cortex)에서 아이디어를 얻었다고 한다. 인간 대뇌 피질은 바깥 쪽에서는 간단한 구조를 인식하고 그와 연결된 뉴런을 타고타고 깊이 들어갈수록 이 정보들을 조합해 복잡한 정보를 인식한다고 한다. 이러한 구조를 계층적(hierarchical)하다고 표현하고 있다. 이에 착안해서 나온 논문이 Neurocognitron이다.

그리고 이를 더 발전 시킨 논문이 AlexNet이다.

컨볼루션 네트워크가 활용되는 응용분야는 위와 같다. 이것 말고도 더욱 많은 분야들이 있을 것이다.

Convolutional Network

위 그림은 우리가 전에 봤었던 Fully connected layer(FCL)이다. FCL은 전체를 1차원의 벡터로 펼쳐 가중치와 곱을하게 된다. 이렇게 되면 이미지 혹은 특징맵이 1차원으로 펼쳐져 가중치 행렬과 곱해지기 때문에, 전체 원소(혹은 픽셀)의 관계를 파악하는 역할을 한다고 볼 수 있다.

컨볼루션 레이어는 위에서 보았던 FCL과 다른점이 있다. 첫번 째는 지역적(local)적인 특성을 띤다는 것이다. 그리고 원소곱(element-wise multiplication)이다. 이것을 슬라이드에서는 dot product(내적)이라고 표현을 하고 있다. 같은 말이다. 내적의 공식을 보면 같은 뜻임을 알 수 있다. FCL은 가중치 W행렬과 행렬곱을 이룬 반면, 컨볼루션은 필터와 원소곱을 한 후, 그 원소곱이 끝난 원소의 합이 다시 한 픽셀의 값이 된다.

만약 필터가 두 개라면 필터링을 한 후의 activation map은 filter의 개수만큼 존재하게 된다. 우리가 5x5x3 필터를 6개 가지고 있다면 위 그림처럼 6개의 activation map을 얻을 수 있다.

컨볼루션 네트워크는 위 슬라이드와 같이 컨볼루션 레이어 사이에 ReLU와 같은 activation function을 사이에 넣는다고 한다.

우리는 위에서 컨볼루션 네트워크가 대뇌 피질에서 동작하는 방식같이 작동한다고 설명을 하였다. 우리가 의도적으로 앞에 층에는 low level feature, 뒷 층에는 high level feature을 학습하라고 설계한것은 아니지만, 실제로 그와 비슷하게 작동하고 있는 모습을 볼 수 있다.

위 두 슬라이드를 참고하면, 컨볼루션 네트워크의 필터는 이미지의 특징을 추출하는 역할을 하는 것을 볼 수 있다. 무작정 아무 특징이나 추출하는것이 아니고, 이미지의 엣지, 블롭등 해당 이미지가 지니는 특징을 잘 추출하도록 학습이 진행되는 것이다. ReLU activation function을 보면 컨볼루션을 수행한 후의 특징맵이 ReLU함수를 거치면 보다 특징적인 부분만 선택되어 남아있는 것을 확인할 수 있다.

그렇다면 이제 위 슬라이드의 컨볼루션 연산을 표본으로 어떻게 컨볼루션이 이루어지는 것인지 조금 더 자세하게 살펴보자.

먼저 이미지(혹은 피쳐맵(feature map))의 크기는 7x7 이고 이 때, 필터의 크기는 3x3이라 하자. 그리고 padding=0, stride=1이다. 이때 컨볼루션은 필터가 이미지의 좌 상단에 맞추어지는 지점부터 시작한다. (이 때, 필터의 중심점은 3x3필터의 중심부분이라고 생각해두고 필터가 움직이는 모습을 생각해보자.) stride=1이기 때문에, 현재 위치의 컨볼루션 연산을 수행했다면, 오른쪽으로 한 칸 움직여 컨볼루션을 수행한다. 이렇게 컨볼루션을 수행하면 오른쪽으로 총 4번을 이동할 수 있을 것이다. 그러면 처음 1번의 컨볼루션이 있었으므로, 5번의 컨볼루션이 수행된것이다. 이렇게 오른쪽 끝에 다다랐다면, 다시 좌상단 지점으로 돌아와 중심이 한 픽셀 내려간지점을 기준으로 방금 한 컨볼루션을 반복한다. 이렇게 컨볼루션을 하면 총 5x5의 activation map이 나오게 된다.

이 때, stride=1 에서 stride=2로 변했다면 어떻게 컨볼루션이 진행될까? 그 답은 바로 필터가 2칸씩 움직이면서 컨볼루션이 진행된다는 점이다.

그렇다면, 이미지의 크기와 필터의 크기가 주어졌을 때, 컨볼루션 결과 예상되는 activation map의 크기를 미리 알 수 있는 방법이 없을까? 라고 생각한다면 바로 위 슬라이드에 이에 관한 공식이 적혀져있다.

그런데, 아까 컨볼루션 공식에서 봤듯이, stride=3인경우에 컨볼루션후 활성맵의 크기가 2.33 이라는 소수점으로 나온다. 즉, 이것은 해당 stirde의 크기로는 컨볼루션이 불가능하다는 뜻이다. 그렇다면 나는 stride=3으로 컨볼루션을 하고 싶은데, 이렇게 불가능한 상황이발생한다면 어떻게 해야할까? 그것은 바로 위 슬라이드에 나와있는 것 처럼, 0-padding을 하는 것이다. padding을 함으로써, 컨볼루션 후 우리가 원하는 크기의 활성화맵을 얻을 수 있다.

위 세 장의 슬라이드를 통해서 컨볼루션 시 크기가 어떻게 변화하는지 알 수 있다. 그렇다면 컨보룰션시 사용되는 파라미터의 개수는 어떻게 구할 수 있을 까? 그것은 바로 필터의 개수 x (필터의 크기 + bias=1) 이다.

추가적으로, 컨볼루션은 1x1크기의 필터로 수행될 수 있다. 이경우에는 1x1x64의 필터가 32개가 있고, 그 후 컨볼루션된 결과를 보여준다. 이것은 지역적인 특성은 고려하지않고 비선형성만 증가시키는 결과를 가져온다고 한다.

다시 한번 뇌와 뉴런의 입장에서 컨볼루션 레이어를 살펴보면 이것은 마치 일정 지역의 뉴런들이 지역적으로 연결되어 더 깊숙한 지점의 한개의 뉴런으로 활성화되는 것과 같다고 할 수 있다.

뇌의 뉴런에는 한 개의 뉴런이 한 포인트에 대한 특징을 전달하는데 , 이것은 같은 지점에 대해서 다르게 해석한 뉴런이 존재할 수도 있다는 것을 의미한다. 그렇기 때문에, 컨볼루션 레이어에서 특징맵에 depth가 있다는 것은 같은 지점을 보는 뉴런이 5개 있는데, 그 특징을 각각 다르게 해석한 것이라고 볼 수 있다.

마지막으로 fully connected layer지점은 전체를 보고 한 결정을 내리는 지점이라고도 볼 수 있을것 같다.

우리는 또한 지역적으로 특징을 살피는 컨볼루션 네트워크의 특징에 고안하여, 풀링 레이어(pooling layer)라는 것을 추가하였다. 풀링 레이어는 해당 영역안에서 평균값을 고르거나, max, min등 연산에 해당하는 값을 취하여 영상에서 특정값을 취하여 크기를 downsampling하는 과정이다. 이를 통하여 해당 특징을 더 작은 스케일에 대해서도 학습할 수 있도록 할 수 있다고 생각한다.

Comment  Read more

CS231n-Lecture04(backpropagation, regularization, gradient descent)

|

저번 시간에는 loss function, regularization 및 gradient descent에 대해서 배웠다. 우리는 손실함수에서 가중치에대한 그라디언트를 이용하여 가중치의 최적값을 찾아내는 방법을 공부하였다.

경사하강법은 수치적 방법을 이용한 수치 그라디언트(numerical gradient), 그리고 식을 통해 유도한 분석적 그라디언트를 배웠으며, 주로 해석적 그라디언트(analytic gradient)를 이용하고, 수치 그라디언트를 이용하여 그라디언트 체크를 한다고 했었다.

역전파(Backpropagation)

이번 시간에는 역전파(backpropagation)에 대하여 배울 것이다. 3강에서는 loss함수 직전의 가중치에 대해서만 업데이트하는 방법을 배웠다. 만약에 가중치가 여려층으로 쌓여있다면, 여러 연산이 복잡하게 연관되있다면, 이에대한 가중치 업데이트는 어떻게 해야하는지 배워보자.

이를 쉽게 다루기 위하여 computational graph를 도입하여 살펴보도록 하자.

간단한 연산에 대한 computational graph이다. 여기서 주목해야할 것은, 덧셈과 곱셈에 대한 편미분 결과가 어떻게 나오는지 살펴보는 것이다. +, -와 같은 연산의 경우 모두 편미분 값이 1이 나오며, 곱셈의 경우, 해당 기호와 곱해져있는 계수의 값이 결과로 나오게 된다. 그렇다면 f에 대해서 x, y에 대한 그라디언트는 어떻게 구해야 할까?

정답은 바로 체인룰(chain rule) 을 이용하는 것이다. 체인룰을 이용하면 위의 공식과 같이 x,y에 대한 f의 편미분 값을 구할 수 있게 된다. 방식은 매우 간단하다. f에서 q에 대한 편미분값과 q에서 x에 대한 편미분값을 곱하면 된다.

위와 같은 원리를 이용하여 역전파가 이루어질 수 있다. 그림을 보면 loss와 제일 먼저 연결되어 있는 노드는z이다. 그러므로 먼저 Loss에 대해서 z에 대한 그라디언트를 구한다. 그 후 Z에 연결되어 있는 노드는 x와 y이다. 그러므로 z에서 x, y에 대한 그라디언트를 구한다. 그 후, 우리가 구한 두 개의 그라디언트를 곱해주면 loss에서 x, y에 대한 그라디언트를 구할 수 있게된다. 이런식으로 최전방부터 역으로 그라디언트가 곱해지기 때문에, 역전파라고 이름이 지어졌다.

또 다른 예시를 살펴보자. 식이 무언가 더 복잡해졌다. 하지만 당황할 필요가 없다. 어디서 부터 접근해야할지 고민이라면, 우리가 양파 껍질을 까는 모습을 상상해보자. 아니면 우리가 미분을 배웠을 때로 돌아가봐도 좋다. 요지는 가장 바깥에 감싸고 있는 식 또는 가장 바깥에 어떤 항들이 존재하는지 먼저 파악하는 것이다.

그렇다면 가장 바깥에 있는 식은 무엇일까? 그림에 힌트가 있지만 바로 $1/x$이다. 그런데 바깥에 있는 항을 파악하고 어떻게 backpropagation을 진행하면 되는 것일까? 아래 과정을 보면 어떻게 진행하는지 알 수 있을 것이다.

이렇게 바깥부터 식을 파악하여 역전파를 진행하면 된다.

그런데 이렇게 일일히 식을 펼치지 않고 모아서 역전파를 시킬 수 있다. 우리가 현재 역전파를 하려고 하는 함수는 시그모이드(sigmoid)함수의 형태를 띠기 때문에, 그림에 나와있는 것 처럼, 4개의 노드를 하나의 시그모이드 게이트로 취급하여 역전파를 시킬 수 있다.

그러므로 우리가 미분되는 기본형태만 알면, 아주 손쉽게 역전파를 할 수 있다. + 연산은 미분값이 1, 곱하기 연산은 미분값이 해당 변수에대한 계수, 그리고 각각의 함수의 형태에 대한 미분의 형태가 있을 것이다. 그 미분형태에 미분하고자 하는 변수를 집어넣으면 되는 것이다.

이러한 성질은 마치 각각의 연산에 대한 게이트를 위 슬라이드와 같이 비유할 수 있다.

그렇다면, 한 노드(가중치)가 여러 노드에 영향을 줄 경우에 역전파는 어떻게 해야할까? 바로 위 슬라이드에 답이 있다. 그 경우에는 윗노드, 아랫노드에서 전파해온 그라디언트를 더해서 역전파 시키면 된다.

자코비안 행렬

우리는 예전에 선형 분류기를 배울 때, 여러개의 클래스의 이미지를 분류하기 위해서 다차원의 매트릭스를 곱하여 예시를 든 적이 있다. 지금과 같이 하나의 가중치를 구하기 위하여 몇 천번을 한 번씩 왔다갔다 반복계산을 한다면 속도가 현저히 느려질것이다. 하지만 자코비안 행렬(jacobian matrix)를 이용하면 훨씬 간결하고 빠르게 계산을 할 수 있다.

만약에 입력벡터의 크기가 4096이고, 출력벡터의 크기가 4096이라면, 출력벡터에 대한 입력벡터의 미분은 어떻게 표현할까? 바로 위의 예시처럼 자코비언으로 표현할 수 있다. 그러면 자코비언의 크기는 어떻게 될까? 답이 이미 나와있지만, 4096x4096이다. 그 원리는 바로 위에 표시해 놓은 벡터를 벡터로 미분하는 식을 보면 그 이유를 알 수 있다.

그렇다면, f(x)=max(0,x)라고 나와있는데, 이 때, 자코비언의 형태를 예상해보자. 답은 바로 대각행렬의 형태를 띄고 있다. 우선 해당 위치와 관련없는 항들은 0이며, 대각 항에도 0인 부분이 존재하는데 이 부분은 값이 0보다 작아 활성화되지 않은 지점이다.

이제 위와 같은 경우에 backpropagation이 어떻게 되는지 살펴보자. 우선 L2 norm에 대하여 q^2^ 을 미분하게 되면, 2q가 나오게 된다. 그 결과는 위 그림에 잘 나와있다.여기서 중요하게 볼것은 기호를 잘 살펴보는 것이다. ${\partial f}/{ \partial \vec{q}}$ 로 나와 있지 않고, 해당 원소에 대해서 스칼라-스칼라미분 표현을 하고 있다는 것이다. ${\partial f}/{\partial \vec{q}} = \nabla_q{f}$와 같은 표현이다.

이번에는 f에대해서 W에대한 backpropagation결과를 살펴보자. 공부하다 보니까 이게 마치 벡터-행렬 전체에 대해서 미분을 하는거 같아서 matrix calculus를 보는데 계산이 다르게 되는것 같아서 며칠이나 고민을 했던것 같다. (밑에서 행렬 미분, 역전파에 대한 내용은 제 지식부족과 자료를 못찾기 때문에… 아직도 잘 모르긴 합니다. 이 이하는 제 생각이니 틀린 부분이 있을 수 있습니다.)

어쨌든, ${\partial f}/{ \partial W}$ 를 계산하기 위하여 체인 룰을 이용하기 위해 ${\partial \vec{q}}/{ \partial W}$ 을 계산해야 한다. 이것을 단순히 벡터-행렬 미분이라고 생각한다면, 벡터를 행렬에대해 미분을 진행해야 하는데 이럴경우 결과가 3차원의 텐서로 계산된다. 바로 위의 그림처럼 말이다. 하지만 가중치를 업데이트 하기위해서는 우리는 결과로 나온 행렬을 3차원을 축으로 더해야 한다. 마찬 가지로 x에 대하여 미분을 할 때에도 똑같다.

즉, 단순한 벡터-행렬 미분, 벡터-벡터 미분으로 생각하면 결과에 의아해하지 않을 수 없는 것 같다. 분명 중간중간에 자코비언의 형태가 나타나지만, 그것을 그대로 쓰기 보다는, computational graph의 연산에 맞게 활용된다고 생각을 해야할것 같다.

그것이 반영되는게 바로 CS231n의 슬라이드의 수식이다. 그래서 수식의 기호를 잘 보라고 하였다. 단순히 미분연산자의 기호가, 벡터 혹은 행렬로 적혀있는게 아니고, 원소로 적혀져 있어, 스칼라-스칼라 미분으로 표현한 것을 볼 수 있다.

우리가 만약에 모듈화 시켜 구현한다면 위와 같이 구현할 수 있을 것이다. 각 연산에 대한 게이트를 만들고, 해당 연산에 대한 미분값을 반환하면 된다. 여기서 중요한 것은 x,y,z가 모두 스칼라 값이라는 것이다. 위에서 말했던것 처럼, 벡터, 행렬끼리의 연산을 한다면 연산의 형태에 따라서 식이 달라질 수 있을것 같다는게 내 생각이다. 하지만 이를 처리하는 방법도 이미 존재하지 않을까??…

여태까지 우리가 살펴왔던거는 한번 가중치와 입력값을 곱하고 바로 스코어를 출력하는 단층짜리 분류기만 생각해봤다. 이번에는 그 층이 두개인 경우를 살펴보자. 층이 하나 늘어남으로써 선형 분류기는 하지 못하는 좀더 고차원적인 비선형적인 분류를 수행할 수 있게된다. 뉴럴 네트워크의 층이 늘어날 수록 조금씩 더 복잡한 특징들을 분류하고 처리할 수 있게 된다.

중간 층의 개수에 따라서 부르는 말이 달라지기도 한다. 히든 레이어 개수만 가지고 말하기도 하고, input layer를 제외한 개수를 따서 말하기도 한다. 이를 간단하게 구현해 놓은 코드는 위와 같다.

Comment  Read more

CS231n-Lecture02(KNN,dataset,linear classifier)

|

컴퓨터 비전의 핵심 테스크중 하나인 이미지 분류를 생각해보자.

개, 고양이, 트력, 비행기와 같은 클래스가 존재할때, 우리는 왼쪽의 고양이 이미지를 cat으로 분류할 수 있어야 한다.

우리가 보는 방식과, 컴퓨터가 이미지를 보는 방식에는 차이가 존재한다.

컴퓨터는 이미지를 단순한 숫자로 보게 된다.

이번 예시의 경우, 색을 RGB 3채널로 보며, 한 위치(픽셀, (x,y,z))의 값을 [0,255]로 표현한다.

이러한 컴퓨터의 특성 때문에, 이미지 분류를 더 어렵게하는 원인들이 존재하게 된다.

카메라가 고양이를 촬영하는 각도마다, 빛이 들어오는 양, 그리고 각도에 따라 카메라에 담기는 고양이 모습에 변형이 일어나게 된다. 그래서 고양이라는 분류 기준을 정하기 더 어렵게 만든다.

조명이 문제가될 수 있다. 조명이 너무 어둡거나 너무 밝은 경우, 물체의 특성이 가려지게 되고, 모두 까맣게 보이거나 하얗게 보일 수 있게 된다. 이 때 우리는 물체의 특성을 파악하기 어려워 진다.

우리가 분류하고자 하는 물체가 다른 물체에 의해 가려져있을 수 있다. 위 그림을 보면, 고양이가 모두 다른 물체에 가려져 있어서, 고양이 특유의 특징이 잘 드러나지 않는다. 특히 세번째 사진은 집에서 키우는 동물은 개, 고양이 정도로 함축되어 있다는 사전 정보가 없이는 저 꼬리가 고양이 꼬리인지 알기 쉽지 않다.

마지막으로, 클래스 내 분산이 클수록 어려워 진다. 똑같은 고양이더라도 종류에 따라서, 유전적 요인에 따라서 무늬와 색, 신체적 모양이 모두 조금씩 달라질 수 밖에 없다. 이 모든 것을 고려하여 고양이는 어느정도 특징을 가져야 고양이인지 기준을 정할 수 없는 노릇이다.

개별적인 물체의 특징자체도 이미 복잡한데. 위와 같이 방해를 하는 다양한 특징이 있기 때문에, 하드 코딩(일일히, if-else문을 통하여 기준을 정하는것)을 통하여 이를 완벽하게 수행할 수 있는 방법은 존재하지 않는다.

위와 같이 고양이의 이미지에서 엣지를 추출한 다음에, 코너의 방향과 같은 정보를 통하여 찾는 방법이 제시된적이 있었다.

하지만 역시, 높은 성능은 보이지 못했다. 딥러닝과 머신러닝에서 이용되는 방식인 데이터를 이용한 접근 방법이 있다. 이 방법은 데이터를 수집하고, 모든 각각의 이미지에 레이블(정답)을 설정한다. 그 다음, 알고리즘을 통하여 분류기를 훈련 시키고, 새로운 이미지를 통하여 평가한다.

KNN (K-Nearest Neighbor)

첫 번째 분류기는 Nearest Neighbor 방식이다.

훈련시 훈련 데이터와 레이블을 모두 기억하고,

예측시, 입력 이미지와 가장 빗스한 이미지를 찾아 레이블을 예측한다.

이 강의에서 예시로 쓰이는 데이터셋은 CIFAR-10이다.

그렇다면, 우리는 이미지끼리 비교를 어떻게 할 수 있을까?

바로 거리를 제는 것(distance metric)이다.

이 슬라이드에서 보여주는 것은, 각 위치에 대응되는 픽셀값끼리의 차에, 절댓값을 취한다.

이것을 모든 픽셀에 대해서 수행한 후 더하는 작업을 한다.

이미지 한장의 데이터와 레이블을 입력받아 저장한다.

테스트 이미지가 들어오면 저장된 이미지들과 거리비교를 통하여 거리가 가장 낮은 이미지를 찾아낸다. 코드에서는 해당 이미지의 인덱스를 찾아내는 방식이다.

이미지 한장을 기준으로 헀을 때, 시간복잡도이다.

이미지 한장을 train 시키는 것은 해당 정보를 기입하면 되기 때문에, O(1)이다.

하지만 이미지 한 장을 predic하는 것은 n장의 이미지와 비교를 해야 하기 때문에 O(n)이다.

또한, 훈련시에 느린것은 괜찮지만, 테스트시에 더 느린것은 안된다. 왜냐하면 실제롷 활용 될 때에는

빠르가 inference가 되야하기 때문이다.

K=1 일 때에는 서로 다른 클래스끼리 포인트 사이의 거리가 동일할 것이다.

k-=3, k=5가 될 수록 majority voting을 통하여 경계가 더욱 정교해질 것이다. (주변 포인트의 영향을 받기 때문.)

Distance metric에 따라서, 결과가 다르게 나올수도 있다.

응용 분야에 따라서 적합한 distance metric을 사용해야한다.

Distance metric에 따라서, KNN의 경계가 달라진 모습을 볼 수 있다.

적절한 k 그리고 적절한 distance metric을 찾아내기 위해서는 최대한 여러번 반복을 하여 가능한 최고의 하이퍼파라미터를 선택해야 한다.

Train/Validation/Test set split

새로운 데이터가 들어올 때, 더 잘 대응하기 위하여 기존에 가지고 있는 데이터셋을 잘 이용할 필요가 있다. 만약에 idea#1과 같이, 모든 데이터를 훈련을 위해 사용하여 경계를 설정해놓으면 위에서 보았던 것과 같이 K=1에 대해서는 훈련데이터에 대해서는 100%의 정확도를 보인다. 하지만, 이것은 훈련 데이터에 대해서만 성립할 뿐, 새로운 데이터가 들어오게 되면 얘기가 달라진다.

k가 1보다 커지게 되면, 훈련데이터에 대해서 100%들어맞지 않게 되는 모습을 k=3, k=5일 때 이미지에서 찾아볼 수 있다. 하지만 새로운 데이터에 대해서는 k=1일 때보다 정확도가 더 증가하는 모습을 보일 것이다. 이를 확인하기 위하여 test셋을 만들어야 한다. 마치 idea#2처럼 말이다.

그런데 idea#2처럼 해도 무언가 모자르다. 무엇이 모자를까? 우리가 하나의 프로세스를 만든다고 생각해보자. 훈련데이터로 경계를 만들고, 임의의 데이터에 대해서도 잘 동작하는지 검증해보면서 하이퍼파라미터를 조정하고, 최종적으로 진짜 새로운 데이터를 실험해봐야 한다. idea#2는 파라미터를 검증해보고 새로운 데이터를 실험해보는게 아닌, 그냥 새로운 데이터만 실험해보는 과정밖에 없다. 그렇기 때문에 idea#3이 가장 이상적이라 할 수 있다.

딥러닝에서는 잘 사용하지는 않지만, 머신러닝에서 종종 사용되곤 하는 k-fold validation 방법이다. 훈련 데이터셋을 k개의 fold(부분집합)으로 나누고(예제에서는 5개의 fold로 나누었으므로, 5-fold validation), 4개는 training set 나머지 1개는 validation set으로 설정하는 방법이다. 그리고 해당 validation을 통해서 나온 파라미터를 평균을 하는 것으로 최종 파라미터를 결정한다.

하지만 무조건 k가 클수록 좋은것은 아니다. 위 그래프를 통하여 약 k=7에서 잘 작동하는 모습을 볼 수 있으며 이것은 적용하는 데이터, 기법이 무엇인지에 따라 달라질 수 있다.

이미지 도메인에서는 KNN이 잘 사용되지 않는다고 한다. 왜냐하면 distance metric을 통하여 거리를 비교해야 하는데, 위에 나온 예시들 처럼 4개의 이미지는 서로 다른 이미지이지만, distance가 모두 동일하여 어떤 정보도 제공해줄 수 없다.

또한 위 사진 처럼 차원이 증가할 수록 비교해야 되는 픽셀수가 급수적으로 많아쟈, 일일히 비교하기에 너무 느리기 때문이다.

Linear Classifier

이번에는 KNN과 같은 분류기가 아닌 선형 분류기를 살펴볼 것이다. 이 방법이 더욱 딥러닝에 쓰이는 방법과 유사하다 볼 수 있다. 이미지와 이미지를 특정 공간에 매핑 시키는 파라미터W 를 통하여 분류기가 작동한다.

32x32x3 크기의 이미지를 flatten하면, 3072x1의 벡터로 변형이 가능하다. 그리고 CIFAR-10의 클래스의 개수는 10개이므로, 10개의 클래스의 스코어에 대해서 추론하기 위하여 파라미터W 는 10x3072의 형태를 뗘야한다. 이후 행렬곱을 진행하면, 10x1 형태의 스코어를 가진 벡터가 나오게 된다.

이게 선형 분류기인 이유는 위 그림처럼, 마치 분류되는 공간이 선을 여러개 그어 분류하기 때문이다. 즉, 위 식을 해석하자면 3072차원에 10개의 직선이 그어진다고 볼 수 있다. 그렇다면 10개의 직선은 무엇을 뜻할까? 하나의 직선은 binary classifier다. 즉 하나의 직선은 해당 클래스인가 아닌가를 분류하는 기준선을 뜻한다.즉, cifar10-classes = {비행기, 자동차, 새, 고양이, 사슴, 개 , 개구리, 말 배, 트럭}의 총 10가지 클래스가 존재하는데 하나의 직선은, 비행기 인가 아닌가, 자동차인가 아닌가, 새인가 아닌가, 고양이인가 아닌가… 트럭인가 아닌가를 판단하는 직선이 총 10개가 있는 것이다.

이럴 때 클래스가 분류되는 방법은 집합처럼, 비행기인 영역에 속하고, 나머지 클래스가 아닌 영역에 속하면 비행기로 분류될 것이다.

이런 선형 분류기의 성질 때문에, 위와 같은 그림들은 선형 분류기가 분류하기 어려운 사례로 꼽힌다. 클래스가 2개이기 때문에, class1인가 아닌가를 판별하므로, 우리가 쓸수있는 선은 단 한개 뿐이다. 단 한개의 선으로 위 그림을 빨강과 파랑 영역으로 나누기는 불가능 하다.

위에서 말했던것과 같은 선형 분류기의 결과로 나온 스코어를 나타낸 벡터이다.

스코어의 절댓값이 높다는 것은 무엇을 의미할까? 그것은 매핑된 포인트가 경계선으로 부터 거리가 멀다는 뜻이다. 예를 들어, 경계선은 그 포인트가 비행기를 나타내는 포인트인지 아닌지를 결정짓는 마지노선이다. 즉, 경계선으로 부터 멀어질수록 더욱 확실하게 비행기인지 아닌지를 나타낸다는 것이다. 양의 값으로 크다는 것은 경계선으로 부터 거리가 멀다는 뜻이고, 해당 클래스일 확률이 크다는 것을 의미하며, 음의 값으로 크다는 것은 역시 경계선으로부터 거리가 멀다는 것을 의미하고, 해당 클래스일 확률이 낮다는 것을 의미한다.

Comment  Read more