728x90

오늘(지금 12시가 지났으니 어제지만) 그래프 이론에 대해서 

 

중간에 NP 문제 때문에 계산 복잡도 내용이 더 많아지게 되었으나

 

그래프 이론을 정리하고

 

딥러닝에 대해서도 정리를해야 한다.

 

 

지난번에 계속 진도를 나갔어야 햿지만 대칭 깨짐 존재하지 않는다는게 No symmetry breaking이

 

왜 학습에 안좋은지 정리를 하다보니 분량을 너무 뺏기고 말았다.

 

일단 자기 전까지 가중치 초기화 부분이라도 마무리 하고자한다.

 

 

 

 

 

 

 

잠깐 지난 시간에 본 대칭 깨짐을 다시 생각해보자.

 

아무튼 지난 시간에 봤다시피 가중치 행렬의 모든 원소가 0이나 동일한 상수로 초기화를 해버린다면

 

중간에 가중치에 대한 그라디언트 행렬이 값이 같아져버리는 이상한 형태가 됬었다.

 

지난번에 symemtry breaking에 대해서 검색 해봤을 때

 

물리학에서의 대칭 깨짐이 나와서 못찾았는데

 

이번에 잠깐 검색해보니 머신러닝에서의 대칭 깨짐에 대해 누가 정리해놓은 글이 있더라

 

 

 

 

아래 글에 따르면 가중치 행렬의 모든 원소로 똑같은 값으로 초기화해서 대칭이 되는 경우 학습이 잘 안되고

 

가중치 행렬이 대칭이 깨어져야, 대칭이 깨어진 형태여야만 올바르게 학습을 할수 있다는 의미에서

 

대칭 깨짐이 있어야 한다고 하고,

 

 

위의 저스틴 존슨 교수님의 강의에서 no symmetry breaking이란 말은

 

가중치 행렬의 대칭 형태가 부숴지지않아, 다시말하면 대칭 형태로 되어있다는 말이고

 

그래서 대칭 형태가 되어있을때 학습이 안된다 = 대칭 깨짐이 없다 = no symmetry breaking 으로 표현한것 같다.

 

말 자체는 정말 간단한데 의역을 잘 못해서 생긴 문젠듯 하다. 

 

ref : machinelearning.wtf/terms/symmetry-breaking/

 

 

 

아무튼 다시돌아와서

 

그런 이유 때문에 실제로 신경망을 초기화 할때 작은 임의의 수로 초기화를 한다.

 

위의 예시에서는 가중치 행렬을 정규 분포로 초기화를 시키고 0.01을 곱하여 표준 편차를 줄여주고 있ㄴ느데

 

이런 가우시안 분포로 가중치 행렬을 할때에는 평균이 0으로 지정하나, 표준 편차의 경우 위의 0.01과 같이 하이퍼 파라미터로 설정 할 수 있다.

 

 

 

 그래서 이렇게 작은 임의의 가우시안 분포를 따르는 값으로 초기화하는 경우는 얕은 신경망에서 잘 동작하지만 깊어질수록 잘 동작하지 않는 문제가 있다고 한다. 왜 그런지 활성화 함수에 관한 통계량을 보면서 알아보자.

 

 

 

어떻게 진행되는지 일단 이 코드 스니팻/코드 조각을 보면서 어떻게 계산되는지 6층 신경망이 순방향으로 가면서, 은닉층의 크기는 4096개라고 하면

 

-> 일단 이 코드 스니팻/조각을 보면서 어떻게 활성 통계량들이 전파되는과정에서 계산되는지 은닉층의 유닛이 409개인 6층 완전 연결 신경망의 예시로 한번 보자.

* 이렇게 긴덩어리는 풀기 너무 힘들다.

 

 그래서 여기서는 tanh를 활성화 함수로 쓸건데, 그 이유는 얼마전 슬라이드에 봤었던 어드바이스들을 안따랏을때 어떻게 되는지 보려고한다.(tanh를 사용한 경우 입력이 x가 -inf, +inf에 가까워질수록 y는 각각 -1, +1에 가까워졌으며 그라디언트 소멸이 발생함)

 

 

 순방향으로 처리하고, 각 계층들의 은닉층 값 그러니까 다음층의 입력에서 사용되는 값(이전 계층에서 활성화 함수의 출력)의 히스토그램을 보여주고 있다.

 

 일단 여기서 가중치 행렬을 곱하고, tanh를 적용한 결과로 여기서 보면 값들이 어떤 분포 형태를 따르는걸 볼 수 있다. 하지만 신경망이 깊게 들어가면 들어갈수록 활성화 함수가 모든 출력들을 0에 가까운 수가 나오도록하게 만든다.

 

 그래서 이렇게 되면 모든 활성화 함수의 출력에 0이 가까워지고, 그라디언트도 근사적으로 0에 가까워지기 지다보니 결국 역전파를 계산하기 힘들어져 좋다고 할 수 없다.

 

 첫번째 계층 행의 경우 tanh를 통과하다보니 모든 값들이 -1과 1 범위 사이안에 존재하게 되었고, 이게 처음으로 통과하다보니 히스토그램의 값이 고르게 분포가 되어있다.

 

 하지만 두번째 계층의 경우 다시 tanh를 거쳐 출력하는 만큼 1층보다 -1 혹은 1에 가까워질 경우의수 빈도가 줄어들다보니 첫번째 계층의 은닉층 값 만큼 고르게 분포되어 있지 않다.

 

 세 번째 층, 넷, 다섯, 여섯 번째 층까지 순전파가 진행되는 과정에 tanh라는 활성화 함수로 인해 대부분의 출력 값들이 0에 가깞게 분포하게 되어 처음 표준 편차가 0.49이던것에서 0.05로 줄어들었다.

 

 그래서 이 신경망은 활성정도가 0에 가까워지면서 그라디언트의 갱신치도 0에 가까워지고 효율적으로 학습을 할 수 없게 되는게 이렇게 가중치 초기화시키는 경우의 문제라고 할 수 있겠다.

 

 

 잠깐 여기서 말이 햇갈리는게 tanh의 입력이 -inf, inf에 가까운경우 그라디언트가 0에 가까워지는건 이해가 되는데 왜 활성 정도가 0으로 되면 그라디언트가 0에 가까워진다는건지 이해가 되지않는다.

 

 

 그냥 내 생각에는 가중치 갱신치를 계산하는데 입력 그러니까 이전 은닉층의 활성 정도가 0에 가까우니 가뜩이나 작은 가중치 갱신치가 매우 작아져 학습이 제대로 되지 않는다고 생각된다.

 

 

 

 그래서 표준 편차를 0.01로 아주 작게 해서 가중치를 초기화하는 바람에 이런 문제가 생겼고 대신에 0.05로 초기화 하는 경우를 한번 보면,

 

 

 

 이번에는 가중치 행렬이 너무 커져지다보니 tanh 비선형 활성화 함수의 포화 영역으로 입력값들을 밀어 넣게 된다. 그래서 히스토그램을 보면 이렇게 큰 값으로 가중치 행렬을 초기화 시킨 결과 대부분 tanh 함수의 출력 값들이 포화영역에 위치한걸 볼수 있다.

 

 그래서 이렇기 때문에 로컬 그라디언트는 0이 되고 학습이 제대로 되지않는다. 그래서 지금까지 가중치를 너무 작게 설정했을때 그라디언트에 0에 가까워지던 경우랑 가중치를 너무 크게 설정하여 활성 정도가 포화 영역에 빠져버리던걸 봤었다.

 

 

 그래서 우리는 가중치를 너무 작지도 않고, 크지도 않지만 좋은 성능을 보이는 골디락스 존을 찾아서 초기화 시켜야 한다. 위 슬라이드의 아래에 인용된 논문에서는 표준 편차를 하이퍼 파라미터로 사용하지 않고, 표준편차를 1/sqrt(Din)으로 사용하여 가중치 행렬을 초기화 시키는 방법을 자비에 초기화 Xaiver Initialization이라고 정의 하였다.

 

 

 

 

 그래서 이런 골디락스 영역으로 가중치를 초기화 시킨경우 활성 히스토그램이 아주 좋게 조정된 분포 scaled distribution로 나오게 되며 더 이상 신경망 깊이이 깊어지면서 가중치가 사라지는 문제가 줄어들었다.

 

 

 그리고 완전 연결 신경망 뿐만이 아니라 합성곱 계층 경우에도 잘 동작한다. 이런 자비에 초기화 방법은 출력의 부산이 입력의 분산과 동일하게 해주는 방법이라고 할수 있겠다. 이후 내용은 정의에 관한 건데 정리 하기 힘들고 일단 이 부분에서 자비에 초기화가 입력의 분산과 출력의 분산이 같게 만들어주는 초기화 기법인지에 대한 증명 과정 같은거라 넘어가겠다.

 

 

 하지만 문제는 활성화 함수로 ReLU를 사용하는 경우인데 (생략한) 정리 내용은 랠루 같은 힌지 비선형 함수를 고려한게 아니라 문제가 된다.

 

 제가 지금까지 예시에서 tanh를 사용한 이유는 이 함수로 선형 연산 계층에 대해서만 이야기했기 때문이며, 이런 선형 함수에서 tanh처럼 0 주위로 대칭이 되는 비선형 함수를 사용할 수도 있기 때문이다.

 

 

 

 

 선형 계층들의 분산들이 tanh를 사용했을때 일치되어/다 비슷비슷 해져서 괜찬지만, ReLU를 사용하는 경우에는 같은 방식으로 초기화 하면 문제가 생긴다.

 

 위 그림을 보면 ReLU를 활성화 함수로 사용한 경우를 볼수 있는데 활성 통계량이 망가져서 히스토그램이 이상하게 만들어지는걸 볼수 있다. 이 이유는 ReLU가 x = 0을 기준으로 힌지 형태이기 때문이며 ReLU가 0이하의 모든 값들을 제거하기 때문이다.

 

 이번에는 히스토그램의 0이 아닌 부분을 위주로 보면 심층으로 갈수록, 활성 정도가 0에 가까워지는걸 볼 수 있고 로컬 그라디언트가 0이되어 학습하기 어려워지게된다. 

 

 

 이런 문제가 있다보니 ReLU 활성화 함수에 적합한 다른 초기화 방법이 필요한데, 이 문제를 고치려면 2로 표준 편차를 나눈걸  곱해주면 된다.

 

 자비에 초기화에서는 sqrt(1/Din)을 표준편차로 사용했었지만, ReLU 함수의 경우 sqrt(2/Din)을 표준편차로 사용하면 된다. 여기서 2인건 ReLU가 입력의 절반을 죽이던거에 대처하기 위함이며이런 초기화 방법을 초기에 나왔을때는 Kalming 초기화 혹은 논문 저자가 마이크로소프트 아시아 연구팀에 있었다보니 MSRA 초기화라고도 부르고 있다.

 

 그래서 우리가 이런 비선형 함수를 초기화를 할때 MSRA 초기화 방법이 필요할 수도 있을거고, 써보면 잘 동작하는걸 볼수 있다고 한다. 그리고 지난 시간에 VGG 모델에 대해서 이야기 했었는데, 그 아키텍처가 만들어진 2014년 당시에는 아직 배치 정규화가 없다보니 괴상한 트릭을 사용하지 않고서는 VGG를 수렴시킬수가 없었다.

 

 하지만 이 Kalming 초기화 기법 덕분에 VGG는 초기화 방법만 간단하게 바꿈으로서 학습을 할수 있어졌고, 크게 유명한모델이 될 수 있었습니다.

 

 

 하지만 기억해야할 건 VGG에 대한 경우이고, 지난 시간에 표준 베이스라인 아키텍처로 ResNet을  사용해야한다고했었습니다. 이 모델에서는 MSAR, Kalming 초기화 방법은 ResNet에 좋은 방법은 아니에요.

 

 그래서 ResNet을 사용한다고 가정할때, 출력의 분포와 입력의 분포를 동일하게 만들어주는 여기에 맞는 합성곱 계층들의 초기화 방법을 만들어야 하는데요. 

 

 이 신경망에서 Residual connection, 스킵 커낵션을 사용하다보니, 스킵 커낵션 이후로는 입력을 다시 더해보리기 때문에 출력의 분산어 더 커지게 될겁니다.

 

 그래서 여기서 MSRA이나 자비에 초기화를 잔류 신경망에다가 사용한다면 활성의 분산은 여러 계층을 거치면 거칠수록 계속 커지다보니 폭발하게 될거고, 최적화 과정에 있어서 좋은 방법은 아니에요.

 

 그래서 ResNet에서 사용할수 있는 해결 방안으로는 Residual Block 잔류 블록의 첫번째 계층은 MSRA로 초기화 시키고, 두번째 계층은 0으로 초기화 시키면 되겠습니다. 그렇게 하면 이 블록은 분산을 완전히 보존하면서도 항등함수처럼 동작할수 있거든요. 이 기법은 ResNet을 초기화 하는데 자주 사용되고 있어요.

 

 -> 이 부분에서 이해가 안되점은 두번째 합성곱 계층의 가중치를 0으로 초기화를 시킨다면 이전 계층에서 뭐가 들어오던간에 활성화 함수의 입력이 0이 된다는 얘기라. 위 그림의 2번째 합성곱 계층 뒤에 입력 x를 더하면 그대로 x가 될텐데 Var(x + F(x) ) = Var(x)라고 표기하는 이유를 잘 모르겠다. 어짜피 F(x) = 0인데도 일단 이부분은 넘어가고 잠깐 이전에 이해되지 않던 Residual Block에 대해 검색해보았다.

 

 

Residual Blcok 잔차 블록

* 그동안 잔류 블록이라 불렀는데 잠깐 검색해보니 잔차 블록이 맞는것 같다. 이 블록이 항등 함수가 되도록 한다는 말의 의미가 잘 이해가 되지 않았는데 아래의 링크를 통해서 이 블록이 항등함수가 되도록 학습한다는 것의 의미를 조금 더 이해할 수 있었다.

ref : a292run.tistory.com/entry/Residual-blocks-Building-blocks-of-ResNet-1

 

 아무튼 기존의 합성곱 블록 같은 경우에는 신경망이 깊어지면서 항등 함수와 동일한 역활을 하는 합성곱 블록이 필요한데, 기존의 블록으로는 항등함수가 되도록 학습을 할수 없는 문제가 있었다. 그래서 스킵 커낵션을 활용해서 나온게 잔차 블록이다.

 

 이전에 통계를 공부할 때 잔차는 (실제 결과 - 예측 결과) 같은 값을 보고 잔차라고 했었고, 최대한 잔차가 줄어드는 방향으로 계수를 구했었다.

 

이 신경망 모델에서의 잔차는 입력 x와 실제 입력 x의 분포인 H(x)의 차이를 잔차라고 하더라

 

신경망에서의 잔차 R(x) = Output - input = H(x) - x

 

H(x)에 대한 식으로 정리하면 H(x) = x + R(x)의 형태가 된다.

 

이 잔류 블록 전체의 출력이 H(x)이고, 잔류 블록의 두 합성곱 계층의 출력이 잔차 R(x)가 된다.

 

기존의 합성곱 블록은 출력 H(x)을 학습하고, 잔차 블록은 잔차 R(x)를 학습다고 할 수 있다.

 

 

아무튼 모델이 항등 함수가 되려면 R(x) = 0이면 되고,

 

신경망은 항등 함수가 되는 방향, 합성곱 계층이 잔차가 0이 되도록 학습한다고 할수 있다고 한다.

 

 

 

 

 

 그래서 여러분들이 자신만의 신경망을 초기화 할때 어떻게 할지 짚고 싶은건, 여러분들은 하나의 초기화 방법만을 사용하고 싶을수도 있지만, 연구되고 있는 다른 방법들을 사용하면 더 좋은 결과가 나올수도 있을 거에요. 

300x250

+ Recent posts