반응형

 

심층 신경망 훈련하기

  • 그레이디언트 소실 또는 그레이디언트 폭주 문제
  • 대규모 신경망을 위한 훈련 데이터의 부족, 레이블 작업 비용 문제
  • 훈련이 극단적인 시간 소요
  • 수백만 개의 파라미터를 가진 모델은 훈련 세트에 과대적합될 위험이 존재

 

그레이디언트 소실과 폭주 문제

  • 경사 하강법이 하위층의 연결 가중치를 변경하지 않은 채로 훈련되어 좋은 솔루션으로 수렴하지 못하는 상태를 그레이디언트 소실
  • 그레이디언트가 점점 커져서 여러 층이 비정상적으로 큰 가중치로 갱신되어 알고리즘이 발산하는 상태를 그레이디언트 폭주
  • 일반적으로 불안정한 그레이디언트는 심층 신경망 훈련을 어렵게 만듬

 

글로럿과 He 초기화

  • 예측을 할 때는 정방향, 그레이디언트 역전파할 때는 역방향으로 양방향 신호가 적절하게 하는것이 그레이디언트 문제를 완화함

    • 이를 위해서 각 층의 출력에 대한 분산이 입력에 대한 분산과 같아야 한다고 주장
    • 역방향에서 층을 통과하기 전과 후의 그레이디언트 분산이 동일해야 한다고 주장
  • 층의 입력과 출력 연결 개수(팬인, 팬아웃)가 같지 않다면 위의 두 가지 주장을 보장 할 수 없음

    • 각 층의 연결 가중치를 무작위로 초기화 하여서 두 가지의 주장을 보안함
  • keras는 기본적으로 균등분포의 글로럿 초기화를 사용

    • kernel_initializer="he_uniform" 혹은 kernel_initializer="he_normal" 로 바꾸어서 He 초기화 사용가능
    keras.layers.Dense(10, activation="relu", kernel_initializer="he_normal")
  • fan in 대신 fan out 기반의 균등분포 he 초기화를 사용하고 싶다면 Variance Scaling을 사용할 수 있음

    init = keras.initializers.VarianceScaling(scale=2., mode='fan_avg', distribution='uniform')
    keras.layers.Dense(10, activation="relu", kernel_initializer=init)

 

수렴하지 않는 활성화 함수

  • 활성화 함수를 잘못 선택하면 자칫 그레이디언트의 소실이나 폭주로 연결될수 있음

    • 이전에는 대부분 생물학적 뉴런의 방식과 비슷한 시그모드 활성화 함수를 사용
    • 현재는 생물학적 뉴런과 다른 활성화 함수가 훨씬 더 잘 작동함
  • Relu는 특정 양숫값에 수렴하지 않음, 계산속도 빠름

    • dying Relu문제가 존재, 훈련하는 동안 일부 뉴런이 0이외의 값을 출력하지 않는 경우
    • 훈련 세트에 있는 모든 샘플에 대해 입력의 가중치 합이 음수가 되면 뉴런이 죽게 됨
    • 음수는 0으로 출력하기 때문
  • dying Relu 문제를 해결하기 위해 LeakyRelu와 같은 Relu 함수의 변종을 사용

    • dying Relu 현상 발생시 일반적으로 0.01 기울기로 출력하기 때문에 기울기가 없어지지 않음
  • 이외에도 기울기를 주어진 범위에서 무작위로 선택하고 테스트 시에는 평균을 사용하는 RRelu, 기울기가 훈련하는 동안 학습되는 PReLU도 존재

  • ELU

    • 해당 활성화 함수는 모든 RelU 변종의 성능보다 높음

    • 훈련 시간이 줄고 신경망의 테스트 세트 성능도 더 좋음

    • 몇 가지 특성을 제외하면 ReLU와 매우 유사함

      • 기울기가 음수일때 활성화 함수의 평균 출력이 0에 더 가까워 짐, 이를 통해 그레이디언트 소실 문제를 완화해줌
      • 모든 구간에서 매끄럽게 경사 하강법의 속도를 높여줌
    • 단점

      • 지수함수를 사용하기 때문에 RelU나 다른 변종들보다 계산이 느리다는 점이 존재
  • SELU

    • 스케일이 조정된 ELU 활성화 함수의 변종
    • dense 연결 층만 쌓아서 신경망을 만들고 모든 은닉층이 SELU 활성화 함수를 사용한다면 네트워크가 자기 정규화 된다는 것을 발견
      • 훈련하는 동안 각 층의 출력이 평균 0과 표준편차 1을 유지하는 경향이 존재
      • 그레이디언트 소실과 폭주 문제를 막아 줌
    • 자기 정규화가 발생하기 위한 몇가지 조건
      • 입력 특성이 반드시 표준화 (평균 0 표준편차 1)
      • 모든 은닉츠의 가중치는 르쿤 정규분포 초기화로 초기화 (keras에서는 kernel_initializer = "lecun_normal")
      • 네트워크는 일렬로 쌓은 층으로 구성되어야 함 (스킵 연결과 같은 순차적이지 않는 구조는 안됨)

일반적으로 SELU > ELU > LeakyRelU > RelU > tanh 순서로 추천

 

  • LeakyRelU 활성화 함수를 사용하려면 LeakyRelU층을 만들고 모델에서 적용하려는 층 뒤에 추가
model = keras.models.Sequential([
    ...
    keras.layers.Dense(300, kernel_initializer="he_normal"),
    keras.layers.LeakyReLU(alpha=0.2),
    ...
])
  • PReLU를 사용은 keras.layers.PReLU()로 사용

 

배치 정규화

  • 그레이디언트 소실과 폭주 문제를 해결하기 위한 방법
  • 각 층에서 두 개의 새로운 파라미터로 결과값의 스케일을 조정하고 이동
  • 신경망의 첫 번째 층으로 배치 정규화를 추가하면 훈련세트를 표준화할 필요가 없음
  • keras의 BatchNormalization층을 통해 수행
  • 모든 신경망에서 배치 정규화가 성능을 크게 향상시킴
  • 배치 정규화는 규제와 같은 역할을 수행해 다른 규제 기법의 필요성을 줄여 줌
  • 단점
    • 모델의 복잡성을 키움
    • 시간소요가 큼
  • 하지만 소요되는 시간이 결과적으로 수렴되는 시간이 빨라져서 상쇄

 

케라스로 배치 정규화 구현하기

  • 은닉층의 활성화 함수 전이나 후에 BatchNormalization층을 추가하면 됨

  • 예시

    model = keras.models.Sequential([
        keras.layers.Flatten(input_shape=[28, 28]),
        keras.layers.BatchNormalization(),
        keras.layers.Dense(300, activation="relu"),
        keras.layers.BatchNormalization(),
        keras.layers.Dense(100, activation="relu"),
        keras.layers.BatchNormalization(),
        keras.layers.Dense(10, activation="softmax")
    ])
    • 배치 정규화 층은 입력마다 4개의 파라미터
      를 추가
      • 해당 파라미터는 역전파로 학습되지 않기 때문에 Non-trainable 파라미터
  • 일반적으로 활성화 함수 이전에 배치 정규화 층을 추가하는 것이 좋음

  • 배치 정규화 층은 입력마다 이동 파라미터를 포함하기 때문에 이전 층에서 편향을 뺄 수 있음 (use_bias=False)

    model = keras.models.Sequential([
        keras.layers.Flatten(input_shape=[28, 28]),
        keras.layers.BatchNormalization(),
        keras.layers.Dense(300, use_bias=False),
        keras.layers.BatchNormalization(),
        keras.layers.Activation("relu"),
        keras.layers.Dense(100, use_bias=False),
        keras.layers.BatchNormalization(),
        keras.layers.Activation("relu"),
        keras.layers.Dense(10, activation="softmax")
    ])
  • axis라는 파라미터가 존재하는데 해당 파라미터는 정규화할 축을 결정

    • 기본값은 -1 : 마지막 축을 정규화
    • 입력 배치가 2D면 각 입력 특성이 배치에 있는 모든 샘플에 샘플에 대해 계산한 평균과 표준편차를 기반으로 정규화
  • 일반적으로 모든 모델에서 BatchNormalization층이 생략되어 있다고 생각하면 됨

 

그레이디언트 클리핑

  • 역전파될 때 일정 임곗값을 넘어서지 못하게 그레이디언트를 잘라내는 것, 이를 그레이디언트 클리핑

  • kears 에서 그레이디언트 클리핑 구현

    optimizer = keras.optimizers.SGD(clipvalue=1.0)
  • 그레이디언트 벡터의 모든 원소를 -1.0과 1.0 사이로 클리핑 수행

    • 손실의 모든 편미분 값을 -1.0에서 1.0으로 잘라냄, 임계값은 하이퍼파라미터로 튜닝할수 있음
    • 그레이디언트 벡터의 방향을 바꿀 수 있음
      • 그레이디언트 벡터 방향을 바꾸지 못하게 하기위해서는 clipvalue 대신 clipnorm을 지정하여 노름으로 클리핑 수행

 

사전훈련된 층 재사용하기

  • 일반적으로 아주 큰 규모의 DNN을 처음부터 새로 훈련하는 것은 좋은 방법이 아님
  • 이미 학습된 신경망을 찾고 해당 신경망의 하위층을 재사용하는 것이 좋음, 이를 전이 학습 이라고 함
  • 일반적으로 원본 신경망의 출력층을 변경함
  • 재 사용할 층의 개수를 정하는 것도 중요함

 

케라스를 사용한 전이 학습

  • 출력층만 제외하고 모든 층 재사용
model_A = keras.models.load_model("my_model_A.h5")
model_B_on_A = keras.models.Sequential(model_A.layers[:-1])
model_B_on_A.add(keras.layers.Dense(1, activation="sigmoid"))
  • model_A와 model_B_on_A는 일부 층을 공유
    • model_B_on_A를 훈련할 때 model_A도 영향을 받음 이를 막기 위해서는 재사용 전에 model_A를 clone하고 사용
    • clone_model() 메서드로 모델 A의 구조를 복제한 후 가중치를 복사
model_A_clone = keras.models.clone_model(model_A)
model_A_clone.set_weights(model_A.get_weights())
model_B_on_A = keras.models.Sequential(model_A_clone.layers[:-1])
model_B_on_A.add(keras.layers.Dense(1, activation="sigmoid"))
  • 새로운 출력층이 랜덤 초기화 되어 있기 때문에 초반에 큰 오차를 생성
    • 따라서 큰 오차가 그레이디언트가 재사용된 가중치를 망칠 가능성이 존재
    • 이를 피하기 위해서 처음 몇 번의 에포크 동안 재사용 된 층을 동결하고 새로운 층에게 적절한 가중치를 학습할 시간을 주는 것이 좋음
for layer in model_B_on_A.layers[:-1]:
    layer.trainable = False

model_B_on_A.compile(loss="binary_crossentropy",
                     optimizer=keras.optimizers.SGD(learning_rate=1e-3),
                     metrics=["accuracy"])

history = model_B_on_A.fit(X_train_B, y_train_B, epochs=4,
                           validation_data=(X_valid_B, y_valid_B))

for layer in model_B_on_A.layers[:-1]:
    layer.trainable = True

model_B_on_A.compile(loss="binary_crossentropy",
                     optimizer=keras.optimizers.SGD(learning_rate=1e-3),
                     metrics=["accuracy"])
history = model_B_on_A.fit(X_train_B, y_train_B, epochs=16,
                           validation_data=(X_valid_B, y_valid_B))
  • 몇번의 epoch 동안 출력층을 동결하고 이후 다시 활성화 하여 모델 학습
  • 전이학습은 심층 신경망에서 더 잘 작동 완전 연결층 보다

 

비지도 사전훈련

  • 레이블된 훈련 데이터가 많지 않은 복잡한 문제가 있을때 비슷한 훈련을 한 모델이 없는 경우
    • 먼저 더 많은 레이블된 훈련데이터를 수집후 비지도 사전학습을 수행
    • 오토인코더나 적대적 생성 신경망과 같은 비지도 학습 모델을 훈련할 수 있음
    • 그다음 오토인코더나 gan 판별자의 하위층을 재사용하고 그 위에 새로운 작업에 맞는 출력층을 추가할 수 있음

 

보조 작업에서 사전훈련

  • 레이블된 훈련 데이터가 많지 않다면 마지막 선택 사항은 레이블된 훈련 데이터를 쉽게 얻거나 생성할 수 있는 보조 작업에서 첫 번째 신경망을 훈련하는 것

  • 신경망의 하위층을 실제 작업을 위해 재사용, 첫 번째 신경망의 하위층은 두 번째 신경망에 재사용될 수 있는 특성 추출기를 학습하게 됨

  • 자기 지도 학습 : 데이터에서 스스로 레이블을 생성하고 지도 학습 기법으로 레이블된 데이터셋에서 모델을 훈련하는 방법

 

고속 옵티마이저

  • 아주 큰 신경망의 훈련 속도는 심각하게 느릴 수 있음
  • 연결 가중치에 좋은 초기화 전략 사용하기, 좋은 활성화 함수 사용하기, 배치 정규화 사용하기, 사전훈련된 네트워크의 일부 재사용하기등 존재
  • 훈련 속도를 크게 높일수 있는 또 다른 방법으로 표준적인 경사 하강법 옵티마이저 대신 더 빠른 옵티마이저를 사용할 수 있음
    • 모멘텀 최적화, 네스테로프 가속 경사, AdaFrad, RMSProp, Adam, Nadam

 

모멘텀 최적화

  • 처음에는 느리게 출발하지만 종단속도에 도달할 때까지는 빠르게 가속

    • 반대로 표준적인 경사 하강법은 경사면을 따라 일정한 크기의 스텝으로 조금씩 천천히 내려감
    • 그래서 맨 아래에 도착하는 데 시간이 더 오래 걸림
  • 경사 하강법은 가중치에 대한 비용함수

    의 그레이디언트
    에 학습률
    를 곱한 것을 바로 차감하여 가중치
    를 갱신

  • 공식은

    • 해당 공식은 이전 그레이디언트가 얼마인지는 고려하지 않음
    • 해당 공식은 국부적으로 그레이디언트가 아주 작으면 매우 느려짐
  • 모멘텀 최적화는 이전 그레이디언트가 얼마였는지를 상당히 중요하게 생각

  • 매 반복에서 현재 그레이디언트를 모멘텀 벡터 m에 더하고 이 값을 빼는 방식으로 가중치를 갱신

    • 그레이디언트를 속도가 아니라 가속도로 사용
    • 일종의 마찰저항을 표현하고 모멘텀이 너무 커지는 것을 막기 위해 이 알고리즘에는 모멘텀이라는 새로운 파라미터 등장 (
      )
      • 값은 0(높은 마찰저항)과 1(마찰저항 없음) 사이로 설정, 일반적인 값은 0.9
      • 공식
  • 그레이디언트가 일정하다면 종단속도는 학습률

    를 곱한 그레이디언트에
    을 곱한 것과 같음

    • 면 종단속도는 그레이디언트와 학습률을 곱하고 다시 10을 곱한 것과 같아서 모멘텀 최적화가 경사 하강법 보다 10배 빠르게 진행
    • 이를 통해서 모멘텀 최적화가 경사 하강법보다 더 빠르게 평편한 지역을 탈출하게 도와줌
    • 경사 하강법이 가파른 경사를 꽤 빠르게 내려가지만 좁고 긴 골짜기에서는 오랜 시간이 걸림
      • 반면에 모멘텀 최적화는 골짜기를 따라 최적점에 도달할때 까지 점점 더 빠르게 내려감
      • 모멘텀 최적화를 사용하면 지역 최적점을 건너뛰는데 도움을 줌
  • kears 모멘텀 최적화 구현하는 방법

    optimizer = keras.optimizers.SGD(learning_rate=0.001, momentum=0.9)

 

네스테로프 가속 경사 (NAG)

  • 기본 모멘텀 최적화보다 거의 항상 더 빠름

  • 현재 위치가

    가 아니라 모멘텀의 방향으로 조금 앞선
    에서 비용함수의 그레이디언트를 계산 하는 것

    • 네스테로프 가속 경사 알고리즘
  • 일반적으로 모멘텀 벡터가 올바른 방향을 가리킬 것이므로 이런 변경이 가능

  • 원래 위치에서 그레이디언트를 사용하는 것 대신에 그 방향으로 조금 더 나아가서 측정한 그레이디언트를 사용

  • NAG가 최적값에 조금 더 가까운 경향이 있고 시간이 지나면서 작은 개선이 반영되어 기본 모멘텀 최적화보다 확연히 빨라지게 됨

    • 일반적으로 NAG가 기본 모멘텀 최적화보다 훈련 속도가 빠름, SGD에 use_nesterov=True로 사용

      optimizer = keras.optimizers.SGD(learning_rate=0.001, momentum=0.9, nesterov=True)

 

AdaGrad

  • 경사 하강법은 전역 최적점 방향으로 곧장 향하지 않고 가장 가파른 경사를 따라 빠르게 내려가기 시작해 골짜기 아래로 느리게 이동

    • 알고리즘이 이를 일찍 감지하고 전역 최적점 쪽으로 좀 더 정확한 방향을 잡으면 더 좋음
    • AdaGrad 알고리즘은 가장 가파른 차원을 따라 그레이디언트 벡터의 스케일을 감소시켜 문제를 해결
  • AdaGrad 알고리즘

      • (/) 는 원소별 나눗셈
  • AdaGrad는 학습률을 감소시키지만 경사가 완만한 차원보다 가파른 차원에 대해 더 빠르게 감소됨, 이를 적응적 학습률이라고 부르며, 전역 최적점 방향으로 더 곧장 가도록 갱신되는데 도움을 줌

  • 학습률 하이퍼파라미터

    을 덜 튜닝해도 되는 점이 강점

  • 단점

    • AdaGrad는 2차방정식 문제에서는 잘 작동하지만 신경망을 훈련할 때 너무 일찍 종료되는 문제가 존재
      • 이 때문에 심층 신경망에서는 사용하면 안됨
      • 대신 선형 회귀와 같은 간단한 작업에는 효과적일수 있음

 

RMSProp

  • AdaGrad는 너무 빨리 느려져서 전역 최적점에 수렴하지 못하는 위험이 존재
  • RMSProp 알고리즘은 가장 최근 반복에서 비롯된 그레이디언트만 누적함으로써 해당 문제를 해결
  • 알고리즘의 첫 번째 단계에서 지수 감소를 사용
  • RMSProp 알고리즘
optimizer = keras.optimizers.RMSprop(learning_rate=0.001, rho=0.9)
  • 일반적으로 AdaGrad보다 훨씬 성능이 좋음
  • Adam 최적화가 나오기 전까지 가장 선호되던 알고리즘

 

Adam과 Nadam 최적화

  • 적응적 모멘트 추정을 의미하는 Adam은 모멘텀 최적화와 RMSProp의 아이디어를 합친것

  • 지난 그레이디언트의 지수 감소 평균을 따르고 RMSProp처럼 지난 그레이디언트 제곱의 지수 감소된 평균을 따름

  • Adam 알고리즘

  • 모멘텀 감쇠 하이퍼파라미터

    로 초기화하는 경우가 많음,

  • kears에서 Adam 옵티마저 예제

    optimizer = keras.optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999)
  • Adam은 적은적 학습률 알고리즘이기 때문에 학습률 하이퍼파라미터

    를 튜닝할 필요가 적음

  • 을 일반적으로 사용

 

  • Adam의 두가지 변종
    • AdaMax
      • 시간에 따라 감쇠된 그레이디언트의 최댓값
      • 실전에서 AdaMax가 Adam보다 안정적이지만 데이터셋에 따라 다르고 일반적으로 Adam이 좋음
      • Adam이 잘 작동되지 않는다면 AdaMax 추천
    • Nadam
      • Adam에 NAG 기법을 합친것
      • 종종 Adam보다 빠르게 수렴
      • 일반적으로 Nadam이 Adam보다 좋았지만 RMSProp가 좋을 때도 존재
  • 소개된 모든 옵티마이저 비교
    • = 나쁨, 보통, 좋음

 

학습률 스케줄링

  • 컴퓨팅 자원이 한정적이라면 차선의 솔류션을 만들기 위해 완전히 수렴하기 전에 훈련을 멈춰야함

  • 일정한 학습률로 수백 번 반복하여 좋은 학습률을 찾을수 있지만 일정한 학습률 보다 더 좋은 방법이 존재

    • 큰 학습률로 시작하고 학습 속도가 느려질 때 학습률을 낮추면 최적의 고정 학습률보다 좋은 솔류션을 더 빨리 발견할 수 있음

    • 훈련하는 동안 학습률을 감소기키는 전략에는 여러 가지가 존재, 이런 전략을 학습 스케줄이라고 함

      • 거듭제곱 기반 스케줄링

        • 학습률을 반복 횟수 t에 대한 함수

          로 지정한다. 초기 학습률
          , 거듭제곱 수 c, 스텝 횟수 s는 하이퍼파라미터

        • optimizer = keras.optimizers.SGD(learning_rate=0.01, decay=1e-4)
      • 지수 기반 스케줄링

        • 학습률을

          으로 설정한다. 학습률이 s 스텝마다 10배씩 줄어든다.

        • def exponential_decay_fn(epoch):
              return 0.01 * 0.1**(epoch / 20)
      • 구간별 고정 스케줄링

        • 일정 횟수의 에포크 동안 일정한 학습률을 사용하고, 그다음 또 다른 횟수의 에포크 동안 작은 학습률을 사용하는 방식

        • def piecewise_constant_fn(epoch):
              if epoch < 5:
                  return 0.01
              elif epoch < 15:
                  return 0.005
              else:
                  return 0.001
      • 성능 기반 스케줄링

        • N 스텝마다 검증 오차를 측정하고 오차가 줄어들지 않을 경우 λ배만큼 학습률을 감소시킨다.

        • lr_scheduler = keras.callbacks.ReduceLROnPlateau(factor=0.5, patience=5)
      • 1사이클 스케줄링

        • 훈련 절반 동안 초기 학습률
          을 선형적으로
          까지 증가시킨다. 그다음 나머지 절반 동안 선형적으로 학습률을
          까지 다시 줄인다. 최대 학습률
          은 최적의 학습률을 찾을 때와 같은 방식을 사용해 선택하고 초기 학습률
          은 10배 정도 낮은 값을 선택한다.

 

규제를 사용해 과대적합 피하기

  • 심층 신경망은 전형적으로 수만 개, 때로는 수백만 개의 파라미터를 가지고 있음
    • 이 때문에 네트워크의 자유도가 매우 높음
    • 대규모의 복잡한 데이터셋을 학습할 수 있다는 뜻
    • 하지만 이런 높은 자유도는 네트워크를 훈련 세트에 과대적합되기 쉽게 만듬
      • 규제가 필요
  • 신경망에서 널리 사용되는 다른 규제 방법을 소개
    • , 드롭아웃, 맥스-노름 규제

 

L1, L2 규제

  • 간단한 선형 모델에 했던 것처럼 신경망의 연결 가중치를 제한하기 위해 L2 규제를 사용하거나 희소 모델을 만들기 위해 L1 규제를 사용할 수 있음

  • keras 층의 연결 가중치에 규제 강도 0.01을 사용하여 L2 규제를 적용하는 방법 예시

    layer = keras.layers.Dense(100, activation="elu",
                               kernel_initializer="he_normal",
                               kernel_regularizer=keras.regularizers.l2(0.01))
    • L2 함수는 훈련하는 동안 규제 손실을 계산하기 위해 각 스텝에서 호출되는 규제 객체를 반환
    • L1 규제는 keras.regularizers.l1 사용, 둘다는 keras.regularizers.l1_l2 사용
  • 일반적으로 네트워크의 모든 은닉층에 동일한 활성화 함수, 동일한 초기화 전략을 사용하거나 모든 층에 동일한 규제를 적용하기 때문에 매개변수 값을 반복하는 경우가 많음

  • python의 functools.partial() 함수를 사용하여 기본 매개변수 값을 사용하여 함수 호출을 감싸는 방법

    • 동일한 매개변수 값을 사용하는 경우 버그 방지를 위한 방법
    from functools import partial
    
    RegularizedDense = partial(keras.layers.Dense,
                               activation="elu",
                               kernel_initializer="he_normal",
                               kernel_regularizer=keras.regularizers.l2(0.01))
    
    model = keras.models.Sequential([
        keras.layers.Flatten(input_shape=[28, 28]),
        RegularizedDense(300),
        RegularizedDense(100),
        RegularizedDense(10, activation="softmax")
    ])
    model.compile(loss="sparse_categorical_crossentropy", optimizer="nadam", metrics=["accuracy"])
    n_epochs = 2
    history = model.fit(X_train_scaled, y_train, epochs=n_epochs,
                        validation_data=(X_valid_scaled, y_valid))

 

드롭아웃

  • 심층 신경망에서 가장 인기 있는 규제 기법

  • 매 훈련 스탭에서 각 뉴런은 임시적으로 드롭아웃될 확률 p를 가짐

    • 즉 이번 훈련 스탭에는 완전히 무시되지만 다음 스탭에는 활성화될 수 있음
    • 하이퍼파라미터 p를 드롭아웃 비율이라고 하고 보통 10%dhk 50% 사이를 지정
    • 순환 신경망에서는 20%30%에 가깝고 합성곱 신경망에서는 40%50%에 가까움
  • 훈련이 끝난 후에는 뉴런에 더는 드롭아웃을 적용하지 않음

  • 일반적으로 출력층을 제외한 맨 위의 층부터 세 번째 층까지 있는 뉴런에만 드롭아웃을 적용

  • 훈련이 끝난 뒤 각 입력의 연결 가중치에 보존 확률 (1-p)를 곱해야 함

  • keras 드롭아웃 예제

    model = keras.models.Sequential([
        keras.layers.Flatten(input_shape=[28, 28]),
        keras.layers.Dropout(rate=0.2),
        keras.layers.Dense(300, activation="elu", kernel_initializer="he_normal"),
        keras.layers.Dropout(rate=0.2),
        keras.layers.Dense(100, activation="elu", kernel_initializer="he_normal"),
        keras.layers.Dropout(rate=0.2),
        keras.layers.Dense(10, activation="softmax")
    ])
    model.compile(loss="sparse_categorical_crossentropy", optimizer="nadam", metrics=["accuracy"])
    n_epochs = 2
    history = model.fit(X_train_scaled, y_train, epochs=n_epochs,
                        validation_data=(X_valid_scaled, y_valid))
    • 모델이 과대적합 되었다면 드롭아웃 비율을 늘릴수 있음

      • 반대로 과소적합이라면 비율 낮춰야함
    • 드롭아웃은 수렴을 느리게 하지만 적절하게 튜닝하면 훨씬 더 좋은 모델을 생성

    • SELU 활성화 함수와 같이 사용하려면 alpha 드롭아웃을 사용해야함

      model = keras.models.Sequential([
          keras.layers.Flatten(input_shape=[28, 28]),
          keras.layers.AlphaDropout(rate=0.2),
          keras.layers.Dense(300, activation="selu", kernel_initializer="lecun_normal"),
          keras.layers.AlphaDropout(rate=0.2),
          keras.layers.Dense(100, activation="selu", kernel_initializer="lecun_normal"),
          keras.layers.AlphaDropout(rate=0.2),
          keras.layers.Dense(10, activation="softmax")
      ])
      optimizer = keras.optimizers.SGD(learning_rate=0.01, momentum=0.9, nesterov=True)
      model.compile(loss="sparse_categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])
      n_epochs = 20
      history = model.fit(X_train_scaled, y_train, epochs=n_epochs,
                          validation_data=(X_valid_scaled, y_valid))

 

몬테 카를로 드롭아웃

  • 드롭아웃을 수학적으로 정의하여 드롭아웃 네트워크와 근사 베이즈 추론 사이에 깊은 관련성을 정립

  • 저자들은 훈련된 드롭아웃 모델을 재 훈련하거나 전혀 수정하지 않고 성능을 크게 향상시킬 수 있는 몬테 카를로 드롭아웃이라 불리는 강력한 기법을 소개함

    • 모델의 불확실성을 더 잘 측정할 수 있고 구현도 쉬움

    • 앞서 훈련한 드롭아웃 모델을 재훈련 하지않고 성능을 향상시키는 MC 드롭아웃 구현

      y_probas = np.stack([model(X_test_scaled, training=True)
                           for sample in range(100)])
      y_proba = y_probas.mean(axis=0)
      y_std = y_probas.std(axis=0)
      • training=True로 지정하여 Dropout 층을 활성화하고 테스트 세트에서 100번의 예측을 만들어 쌓음

      • 드롭아웃이 활성화 되었기 때문에 예측이 변경됨 y_probas는 [100, 10000, 10] 크기의 행렬

        • 첫 번째 차원 (axis=0)을 기준으로 평균하면 한 번의 예측을 수행했을 때와 같은 [10000, 10] 크기의 배열 y_broba를 얻게 됨
      • 예제

        class MCDropout(keras.layers.Dropout):
            def call(self, inputs):
                return super().call(inputs, training=True)
        
        class MCAlphaDropout(keras.layers.AlphaDropout):
            def call(self, inputs):
                return super().call(inputs, training=True)
        
        mc_model = keras.models.Sequential([
            MCAlphaDropout(layer.rate) if isinstance(layer, keras.layers.AlphaDropout) else layer
            for layer in model.layers
        ])
        
        optimizer = keras.optimizers.SGD(learning_rate=0.01, momentum=0.9, nesterov=True)
        mc_model.compile(loss="sparse_categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])
        
        mc_model.set_weights(model.get_weights())
        np.round(np.mean([mc_model.predict(X_test_scaled[:1]) for sample in range(100)], axis=0), 2)

 

멕스-노름 규제

  • 신경망에서 널리 사용되는 또 다른 규제 기법은 맥스-노름 규제

    • 각각의 뉴런에 대해 입력의 연결 가중치 w 가
      가 되도록 제한
      • r은 맥스-노름 하이퍼파라미터고
        는 L2 노름을 나타냄
  • 맥스-노름 규제는 전체 손실 함수에 규제 손실 항을 추가하지 않음, 대신 일반적으로 매 훈련 스탭이 끝나고

    를 계산하고 필요하면 w의 스케일을 조정

  • r을 줄이면 규제의 양이 증가하여 과대적합을 감소시키는데 도움을 줌

  • 맥스-노름 규제는 불안정한 그레이디언트 문제를 완화하는데 도움을 줌

  • keras에서의 맥스-노름 규제

    layer = keras.layers.Dense(100, activation="selu", kernel_initializer="lecun_normal",
                               kernel_constraint=keras.constraints.max_norm(1.))
    • max_norm 함수는 기본값이 0인 axis 매개변수 존재
    • Dense 층은 일반적으로 [샘플개수, 뉴런 개수] 크기의 가중치를 가짐
    • axis=0 사용하면 맥스-노름 규제는 각 뉴런의 가중치 벡터에 독립적으로 적용
    • 일반적으로 합성곱에서는 axis=[0,1,2]

 

요약 및 실용적인 가이드라인

  • 기본 DNN 설정

  • 자기 정규화를 위한 DNN 설정

반응형

'Study > Self Education' 카테고리의 다른 글

핸즈온 머신러닝 - 13  (0) 2024.06.19
핸즈온 머신러닝 - 12  (0) 2024.06.19
핸즈온 머신러닝 - 10  (0) 2024.06.19
핸즈온 머신러닝 - 9  (0) 2024.06.18
핸즈온 머신러닝 - 8  (0) 2024.06.18