11장: Deep Neural Network (p.353)

개요 :

우리가 사는 세상에서 해결해야 하는 문제는 숫자 맞추기 문제가 아니다. 고해상도의 이미지, 영상에서 수 종의 물체를 감지해야 하는 문제들이다. 이런 문제를 해결하려면 아주 많은 은닉층과 뉴런 수가 필요할 것 같다. 그에 대한 문제도 발생하게 되는데 이런 문제들을 중심으로 이 장을 공부해본다.

 

  1. vanishing gradient (or exploding gradient) 문제
  2. 대규모 신경망에서는 훈련이 극단적으로 느려질 것이다.
  3. 수백만 개의 파라미터를 가진 모델은 훈련 세트에 과대적합될 위험이 크다.

 

 

 

 


Vanishing Gradient / Exploding Gradient

 

vanishing gradient : gradient descent를 하려고 오차역전파를 하는데 하위층으로 갈수록 기울기가 점점 작아져 아래 층의 가중치는 전혀 학습이 되지 않는 상태

exploding gradient : 반대로 gradient가 점점 커져 여러개의 층이 비정상적으로 큰 가중치로 갱신되면 알고리즘은 발산하게 된다.(순환 신경망에서 자주 발생)

 

예시 : sigmoid function

시그모이드 함수에 대한 이미지 검색결과

이 sigmoid function을 예로 들자면 이에 대한 미분은 sigmoid(x) = y 라 두었을 때 y(1-y)가 된다.(y의 범위: (0,1) ) 그러므로 y가 0.5일때 가장 큰 미분값을 가지며 그 값은 0.25가 된다.

시그모이드 함수 미분에 대한 이미지 검색결과

문제는 오차역전파로 진행할 때 이 함수의 미분 값 (0, 0.25)이 곱해져서 전해지는데 1 보다도 현저하게 낮은 0.25가 (이 값이 심지어 제일 큰 값) , 심층신경망에서는 층마다 활성화 함수를 사용하는데 시그모이드 함수를 사용하게 되면 (0, 0.25) 의 값을 매층 마다 곱해지게 되며 이는 결국 0에 가까워지는 아주 작은 값들이 만들어지게 된다. sigmoid 를 사용했을 때 나오는 대표적인 vanishing gradient 문제다.

 

Xavier Glorot 와 Yoshua Bengio 는 논문을 통해 주요한 발견을 발표했는데 이 중 로지스틱 시그모이드 활성화 함수와 가중치 초기화 방법의 조합이 있다. 이 초기화 방법은 평균이 0 표준편차가 1인 정규분포를 사용한 무작위 초기화이고 시그모이드와 함께 사용했을 때 각 층에서 출력의 분산이 입력의 분산보다 크다는 것을 밝혔다. 신경망의 위쪽으로 갈수록 분산이 계속 커져 활성화 함수가 0 또는 1로 수렴하게 된다. 이 경우 기울기가 0에 가까워지는 것을 위에서 확인했다.

 

 

 


Xavier 초기화, He 초기화

 

Xavier와 Bengio는 그들의 논문에서 이 문제를 완화시키는 방법을 제안한다. 예측을 할 때는 정방향, 역방향 즉 양방향 신호가 적절하게 흘러야 한다. 이들의 주장은 적절한 신호가 흐르기 위해서는 각 층의 출력에 대한 분산이 입력에 대한 분산과 같아야 한다고 말한다. 그리고 역방향에서 층을 통과하는 전과 후가 그래디언트 분산이 같아야 한다고 주장한다.(기울기가 1로 일정하게) 사실 층의 입력과 출력 연결 개수가 같지 않다면 이 두 가지를 보장할 수 없다. 하지만 이들은 실전에서 잘 작동하는 대안을 제안했다.

각각의 대안들은 정규분포와 균등분포를 따르는 두 가지 방법이 있다.

그림 출처 : https://reniew.github.io/13/

Xavier 초기화

 

He 초기화

(왜 그러한가에 대해서 나중에 공부하기)

 

 

ReLU 함수 중에서도  LeakyReLU 와 ELU

 

LeakyReLU : ReLU함수에서 0보다 작은 음수의 소실문제를 해결하기 위해 음수에 작은 계수를 곱한 식.

leaky relu에 대한 이미지 검색결과

 

 

ELU :

exponential linear unit에 대한 이미지 검색결과

Relu 함수와 다른점 :

z < 0 일 때 음수 값이 들어오므로 활성화 함수의 평균 출력이 0에 더 가까워진다. 이는 앞서 이야기한 vanishing gradient 문제를 완화해준다. 하이퍼파라미터 a 는 z가 큰 음수 값일 때 ELU가 수렴할 값을 정의한다. 보통 1로 설정하지만 필요에 따라 달리 정의가능.

z < 0이어도 gradient가 0이 아니기 때문에 dying 뉴런을 만들지 않는다.

a = 1일 때 이 함수는 z = 0에서 급격히 변동하지 않고 z = 0을 포함해 모든 구간에서 매끄러워 gradient descent 속도를 높여준다.

단점 : 지수함수를 사용하기에 다른 ReLU보다 계산이 느리다. 훈련 동안에는 수렴 속도가 빠르기 때문에 상쇄되지만 테스트 시에는 ELU 신경망이 ReLU 신경망보다 느릴 것이다.

 

 * tf.nn.swish() 함수 : 

공식 : Swish(z) = z sigmoid (z) 구글 브레인팀에서 만든 함수 , 다른 ReLU계열 함수보다 성능이 좋다.

 

 

*여러 활성화 함수를 사용한 결과 (앞장 조기 종료 코드에 초기화 함수만 바꿈):

ELU 함수

훈련 : 테스트 :

 

Leaky ReLU

훈련 : 테스트 :

 

Swish 함수

훈련 : 테스트 :

 

 

 

 

Batch Normalization

논란이 많은 배치정규화(나중에 더 자세히 들여다보기로 꼭) , 개념은 Deep Learning from scratch 배치 정규화 참고

구현 코드:

 

훈련 :     테스트 :

 

Batch Normalization을 위의 코드와 논문의 Notation을 따라 본 정리와 내가 생각한 문제점:

잘못된 부분 수정:

 

*batch normalization에서 moving average 개념:

위의 코드를 보면 shuffle_batch 함수 정의에서 중복되지 않은 배열을 mini_batch shape으로 호출한다. 이는 각각의 mini_batch의 평균이 서로 독립적이다. 결국 전체 training dataset의 평균이 1 epoch을 돌린 mini_batch들의 평균의 평균과 일치한다. 문제점 : shift β 는 일치하나  scale  γ 는 일치하지 않는다. 

 

 

 

 

 

 


Gradient Clipping

개념만 : gradient exploding 문제를 줄이는 쉬운 방법은 역전파될 때 일정 임곗값을 넘어서지 못하게 gradient를 단순히 잘라내는 것이다.

 

 


Reusing Pretrained Layers

아주 큰 DNN을 처음부터 학습한다면 좋지 않은 방법이다. 이미 그런 비슷한 부류의 neural network가 존재하는지 보고 존재한다면 하위 층을 가져다 쓸 수 있는 좋은 방법이 있다. (직관적으로도 그러한) 이것을 transfer learning 이라한다. 이 방법은 훈련의 속도를 증가시켜줄 뿐만 아니라 필요한 훈련 데이터도 훨씬적다.

 

 

아래 코드는 위의 배치 정규화 코드를 재사용해서 구현한 코드이다.

코드를 보면서 name 의 활용중요성을 느낀다.

결과 : 

결과를 보면 알다시피 앞선 배치 정규화 때 구해놓은 변수들과 연산자들을 사용하기 때문에 시작부터 높은 정확도를 보이는 것을 볼 수 있다.

 

하지만 일반적으로 transfer learning을 하려하면 원래 모델의 일부만을(낮은 층) 사용하는 것이기 때문에 다른 방법이 필요하다.

 

다음포스팅에 이어서

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다