지난 시간 복습

  • 지난 시간에 함수를 Computational graph로 표현하는 방법을 배움
    • 어떤 함수든 위 그림처럼 표현할 수 있음

  • 또한, Neural Network에 대해서 배웠음
    • Linear Layer가 있고, 중간 중간에 비선형 연산자(activation function)을 끼워 넣으면서 여러 층으로 쌓음

  • CNN은 Spatial Structure를 사용하기 위해 Convolution Layer를 사용하는 Neural Network의 특수한 형태

  • Convolutional 필터입력 이미지를 슬라이딩해서 계산한 값들이 모여 출력 Activation map을 만듦

  • Convolution Layer는 일반적으로 다수의 필터를 사용
    • 각 필터는 서로 다른 Activation map을 생성
    • 위 그림에서, 어떤 입력이 있고 Depth가 있음
      • 이제 Activation map을 만들어야 하는데, Activation map은 필터의 개수만큼 존재
      • 각 activation map은 입력의 공간적인 정보를 보존하고 있음
    • 이제 우리가 하고싶은 것은 가중치, 즉 파라미터를 업데이트하고 싶음

  • 이전에 배웠던 것 처럼, Optimization을 통해서 Network의 파라미터를 학습할 수 있음
    • Loss가 줄어드는 방향으로 이동하고 싶음 (경사 하강법)
      • 이는 gradient의 반대 방향으로 이동하는 것과 동일

  • 이를 Mini-batch Stochastic Gradient Descent라고 함
    • Mini-batch SGD는…
      1. 우선 데이터의 일부만 가지고 Forward pass를 수행한 후 Loss를 계산
      2. 이후, Backpropagation을 진행하며 gradient를 계산
      3. 계산된 gradient를 이용하여 파라미터를 업데이트

Training Neural Network

  • 이제부터는 Neural Network의 학습에 대해서 다룰 예정

  • 우선, Neural Network 학습을 처음 시작할 때 필요한 기본 설정에 대해 알아볼 것
    • Activation function 선택, 데이터 전처리, 가중치 초기화, Regularization, gradient checking 등이 이에 속함
  • 또한, Training dynamics에 대해서도 다룰 예정
    • 학습이 잘 되고 있는지 확인하는 방법에 대해서 배움
    • 어떤 방식으로 파라미터를 업데이트할 것인지 배움
    • 가장 적절한 하이퍼파라미터를 찾기 위한 하이퍼파라미터를 Optimization하는 방법도 배움
  • Evaluation 과정에서 적용할 수 있는 내용도 다룸
    • Model ensemble에 대해서도 배움

  • Lecture 6은 part 1으로, 다음의 내용을 학습
    • Activation Function
    • Data Preprocessing
    • Weight Initialization
    • Batch Normalization
    • 학습 과정 다루기
    • Hyperparameter Optimization

Activation Functions

  • 지난 시간까지 배운 내용에 따르면,
    • 데이터 입력이 들어오면 가중치와 곱해줌
      • FC나 CNN이 해당
    • 그 다음 Activation Function, 즉 비선형 연산을 거침

  • Activation Function의 종류에는
    • Sigmoid, tanh, ReLU, Leaky ReLU, Maxout, ELU 등
    • 지난 시간까지는 Sigmoid만 학습
    • 이번 시간에는 좀 더 다양한 종류의 Activation function과 이들간의 trade-off에 대해서 다뤄볼 예정

  • 가장 먼저 Sigmoid에 대해서 살펴보면,
    • 각 입력을 받고, 그 입력을 [0, 1] 사이의 값이 되도록 해줌
      • 값이 작으면, 0에 가까울 것
    • 0 근처 구간(regime)을 보면 선형함수 같아 보임 (/ 모양)
      • 이는, Sigmoid가 일종의, 뉴런의 firing rate를 saturation 시키는 것으로 해석할 수 있기 때문 (firing rate = 활성률, 반응속도)
      • 즉, 어떤 값이 0에서 1사이의 값을 가지면, 이를 firing rate라고 생각할 수 있음
    • Sigmoid는 3가지 문제를 갖고 있음
      1. Sigmoid는 입력 값을 [0, 1] 사이의 값으로 saturation 시키기 때문에, gradient를 죽일 수 있음
      2. Sigmoid의 출력이 zero centered 하지 않다는 것
      3. exp()로 인해 계산 비용이 크다는 것

  • Sigmoid가 갖는 문제 1. gradient가 죽는다
  • 만약, 데이터 x가 존재하고, 그에 따른 sigmoid의 출력이 있다고 하자
    • 우선 dLdσ\frac{dL}{d\sigma}가 역전파 될 것이고, dσdx\frac{d\sigma}{dx}와 곱해지게 될 것
      • 이런 값들이 연쇄적으로 backpropagation 될 것
    • 만약, x=10x = -10이라면, gradient는 어떻게 될까?
      • Sigmoid에서 음의 큰 값이면, sigmoid가 flat하게 되고, gradient가 0이 될 것
      • 즉, 거의 0에 가까운 값이 backpropagation 될 것
      • 결국 이 부분에서 gradient가 죽어버리고, 이후로 0이 계속 전달되게 될 것
    • x=0x = 0이라면 어떻게 될까?
      • 이 구간에서는 gradient 0이 아닌 다른 값으로 존재하기 때문에, 잘 동작함
    • x=10x = 10에서는 어떻게 될까?
      • x 값이 큰 양수일 경우에도, sigmoid가 flat하기 때문에, gradient를 다 죽이게 됨
      • 결국, gradient가 잘 흐르지 않음

  • Sigmoid가 갖는 문제 2. sigmoid의 출력이 zero centered 하지 않음
  • 뉴런의 입력이 항상 양수일 때, 어떤 일이 발생하는지 살펴보면,
    • 모든 x가 양수일 때, 이 x는 어떤 가중치와 곱해지고 activation function을 통과하게 될 것
    • 이때 가중치 W에 대한 gradient를 한번 생각해보자
      • 이 Layer에서의 local gradient가 어떻게 될지 한번 생각해보면,
      • 우선 dLd(activationfunction)\frac{dL}{d(activation function)}을 계산할 것이고, 이 Loss가 backpropagation 될 것
      • 그리고, local gradient가 있을텐데, 기본적으로 그냥 x
      • 즉, backpropagation 과정에서 곱해지는 local gradient인 x는 전부 양수이기 때문에, dLd(activationfunction)\frac{dL}{d(activation function)}의 부호가 유지가 될 것
      • 결론적으로, gradient가 전부 양수 또는 전부 음수가 될 것

  • 다시 얘기하면,
    • 위에서 dLd(activationfunction)\frac{dL}{d(activation function)}가 넘어오는데, 이 값이 음수 또는 양수가 될 것
    • 이 값은 local gradient와 곱해질 것이고, 이때 local gradient인 d(activationfunction)dW\frac{d(activation function)}{dW}는 그냥 x가 될 것임
    • 결국, gradient의 부호는, upstream gradient의 부호와 같음
      • 이것이 의미하는 바는 가중치 W가 모두 같은 방향으로만 움직일 것임을 의미
      • 파라미터를 업데이트 할 때, 다 같이 증가하거나, 다 같이 감소할 수 밖에 없음
    • 이런 gradient 업데이트 방식은 아주 비효율적
  • 따라서, 우리는 일반적으로 zero-mean data를 원함
    • 입력 x가 양수/음수 모두를 가지고 있으면, 전부 같은 방향으로 움직이는 일은 발생하지 않을 것

  • 다음으로 살펴볼 activation function은 tanh
    • sigmoid와 유사
    • 가장 큰 차이점은 zero-centered라는 것
      • 범위가 [-1, 1]
      • 이를 통해서 Sigmoid의 두 번째 문제를 해결
    • 그러나, saturation 때문에 여전히 gradient가 죽음
      • 여전히 gradient가 flat 해지는 구간이 존재
    • sigmoid 보다는 조금 낫지만, 그래도 여전히 문제점은 존재

  • 다음으로는 ReLU (자주 쓰임)
    • 이전 강의에서 Convolution layer 사이 사이에 ReLU가 있었음
    • ReLU 함수는 f(x)=max(0,x)f(x) = max(0, x)
      • 이 함수는 element-wise 연산을 수행하며, 입력이 음수이면 값이 0이 됨
      • 양수이면, 입력 값 그대로를 출력
    • 기존의 sigmoid와 tanh이 갖고 있던 문제점을 어느정도 해결
      • ReLU 함수의 특성 상, 적어도 입력의 절반은 saturation 되지 않음 (ReLU의 가장 큰 장점)
      • 기존의 Sigmoid는 함수 안에 지수 항이 존재했지만, ReLU는 단순히 max 연산이므로 계산이 매우 빠름
    • ImageNet 2012에서 우승한 AlexNet이 처음 ReLU를 사용
    • 그러나, ReLU가 갖고 있는 문제점은,
      • 더이상 zero-centered가 아니라는 것
        • tanh가 이 문제를 해결했는데, ReLU는 다시 이 문제를 가지게 됨
      • 또한, ReLU는 양수에서 saturation이 되지 않지만, 음수에서는 saturation이 된다는 것

  • 조금 더 자세히 살펴보면,
    • x=10x=-10이면, gradient는 0이 될 것
    • x=10x=10이면, gradient는 선형 영역(linear regime)에 속함
    • x=0x=0이면, gradient는 0
    • 즉, ReLU는 gradient의 절반을 죽여버리는 셈
      • 따라서, dead ReLU (죽은 ReLU)라는 현상을 겪을 수 있음

  • Data cloud (=training data)가 있을 때,
    • ReLU는 평면의 절반만 activate 된다는 것을 알 수 있음
      • 각 평면(초록, 빨간색 직선)이 각 ReLU를 의미
    • ReLU가 data cloud에서 떨어져 있는 경우에 dead ReLU가 발생할 수 있음 (빨간 직선)
      • dead ReLU에서는 activate가 일어나지 않고 update 되지 않음
      • 반면, active ReLU는 일부는 active되고, 일부는 active되지 않을 것
  • 몇 가지 이유로 이런 일이 발생할 수 있음
    1. 초기화를 잘못한 경우
      • 그림에서 dead ReLU 처럼 생긴 경우
      • 즉, 가중치 평면이 data cloud에서 멀리 떨어져 있는 경우
      • 이런 경우, 어떤 데이터 입력에서도 activate 되는 경우가 존재하지 않을 것이고, backpropagation도 일어나지 않을 것임
      • 즉, update 되지도, activate 되지도 않을 것
    2. 더 흔한 경우는, Learning rate가 지나치게 높은 경우
      • 처음에는 적절한 ReLU로 시작할 수 있다고 해도, 만약 update를 지나치게 크게 해서 가중치가 날뛴다면, ReLU가 데이터의 manifold를 벗어남
      • 이런 일들은 학습 과정에서 충분히 일어날 수 있음
      • 그래서, 처음에 학습이 잘 되다가 갑자기 죽어버리는 경우가 생기는 것
  • 실제로 학습을 다 시켜놓은 Network를 살펴보면, 10~20% 가량은 dead ReLU가 되어 있음
    • 이것은 문제이긴 하나, ReLU를 사용하고 있는 대부분의 Network는 겪을 수 있는 문제
    • 그러나, 이 정도면 Network 학습에 크게 지장이 있진 않음
  • 따라서, 실제 ReLU를 초기화할 때, positive bias를 추가해주는 경우가 있음
    • update 시에 active ReLU가 될 가능성을 조금이라도 더 높혀주기 위함
      • 하지만, 도움이 된다는 의견도 있고, 그렇지 않다는 의견도 있음
    • 이 방법을 항상 사용하는 것은 아니고, 대부분 zero-bias로 초기화 함

  • ReLU 이후에 조금 수정된 버전이 나왔음 (Leack ReLU)
    • ReLU와 유사하지만, negative regime에서 더 이상 0이 아님
    • negative에서 기울기를 살짝 주게 되면, 앞서 설명했던 문제를 상당 부분 해결할 수 있음
    • Leaky ReLU의 경우,
      • negative regime에서도 saturation되지 않음
      • 계산이 효율적 (max 연산이기 때문에)
      • dead ReLU 문제를 해결
  • 다른 예시로는, PReLU가 있음
    • PReLU는 negative space에서 기울기가 존재한다는 점이 Leaky ReLU와 유사
      • 단, PReLU에서의 기울기는, α\alpha라는 파라미터로 결정됨
      • α\alpha를 정해놓는 것이 아니라, backpropagation으로 학습시키는 파라미터로 만듦

  • 다른 예시로는 ELU
    • ReLU의 이점을 그대로 가져옴
    • 또한, zero-mean output을 출력 (Leaky ReLU, PReLU의 이점)
    • 하지만, Leaky ReLU와 비교해보면, ELU는 negative space에서 saturation
      • 즉, 음수 영역에서 gradient가 없음
      • 그러나, 이런 saturation이 noise에 더 robustness 함
      • 즉, deactivation이 모델에 robustness를 향상시킬 수 있다는 주장
        • 이에 대한 타당성을 논문에서 다양하게 제시
    • ELU는 ReLU와 Leaky ReLU의 중간 정도

  • Maxout Neuron
    • 지금까지 본 activation function과는 조금 다르게 생김
    • 입력을 받아들이는 기본 형식을 미리 지정하지 않음
      • 대신, w1w_1xx를 내적한 값과 +b1+b_1, w2w_2xx를 내적한 값과 +b2+b_2의 최대값을 사용
      • Maxout은 이 두 함수 중 최대값을 취함
    • Maxout은 ReLU와 Leaky ReLU의 좀 더 일반화된 형태
      • Maxout은 이 두개의 선형 함수를 취하기 때문
    • 또한, 선형이기 때문에 saturation 되지 않으며, gradient가 죽지 않음
    • 문제점은 뉴런 당 파라미터의 수가 2배가 된다는 것
      • 이제는 w1w_1w2w_2를 지니고 있어야 함

  • 일반적으로 ReLU를 많이 사용하며, 잘 동작함
    • 다만, ReLU를 사용할 때, Learning rate를 잘 결정해야함
      • learning rate에 따른 가중치 업데이트 → dead ReLU 문제 발생
  • 또한, Leaky ReLU, Maxout, ELU와 같은 다양한 activation function을 사용할 수 있음
    • tanh 또한 사용할 수 있지만, 일반적으로 ReLU or ReLU의 변형이 더 잘 동작함
    • sigmoid는 사용하지 않는 것이 좋음 (가장 구식)
  • 데이터의 특성에 따른 적절한 activation function을 찾는 것이 좋음

Data Preprocessing

  • 이제는 실제 Network를 훈련시켜 볼 예정

  • 실제 입력 데이터가 있을 때, 우리는 일반적으로 입력 데이터를 전처리 함
    • 가장 대표적인 전처리 과정은 zero-mean으로 만들고, normalize 하는 것
    • normalization은 보통 표준편차로 함
      • 앞서, 모든 입력이 전부 양수인 상황을 살펴봄 (zero-centered)
      • 이때, 모든 뉴런이 양수의 gradient를 얻게 됨
      • 따라서 최적화 과정에서, 최적화 방향으로 바로 진행하는 것이 아니라, 지그재그로 움직이면서 최적화를 진행하게 됨
      • 전부 양수일 때 뿐만 아니라, 음수일 때, 0일 때 모두 해당
      • normalization을 해주는 이유는, 모든 차원이 동일한 범위 안에 있게 해줘서, 동등한 기여를 하도록 하게 함
      • 이미지의 경우, 전처리로 zero-centering 정도만 해줌
      • normalization을 하지 않는 이유는, 이미지는 이미 각 차원 간 스케일이 어느 정도 맞춰져 있기 때문 (0~255 사이의 pixel로 이뤄져 있기 때문에)

  • Machine learning 에서는, PCA나 whitening과 같은 복잡한 전처리 과정도 존재
    • 그러나, 이미지에서는 zero-centering 정도만 사용하고, normalization을 비롯한 여러 복잡한 방법들을 잘 사용하지 않음
    • 일반적으로 이미지를 다룰 때, 굳이 입력을 더 낮은 차원으로 projection 하지 않음

  • 이미지를 다룰 때, 기본적으로 zero-mean으로 전처리를 해줌
    • 평균 값은 전체 training data에서 계산
    • 보통 입력 이미지의 사이즈를 서로 맞춰주는데, Network에 들어가기 전에 평균 값을 빼줌
    • Test time에서, test data에도 training data에 계산한 평균 값으로 빼줌
  • 실제로, 일부 Network는 채널 전체의 평균을 구하지 않고, 채널마다 평균을 독립적으로 계산하는 경우도 존재
    • 채널 별 평균이 비슷할지, 독립적으로 계산할 지는 판단하기 나름

Weight Initialization

  • 다음으로는, Weight를 어떻게 초기화 시켜야 하는지 알아볼 예정

  • Two Layer Neural Network 예시를 보면, (우리가 할 일은 가중치 업데이트)
    • 맨 처음에 어떤 초기 가중치들이 있음
    • 그리고, gradient를 계산해서 가중치를 업데이트 할 것임
    • Q1. 만약, 모든 가중치 = 0이면 어떻게 될까?
      • 가중치가 0이라서, 모든 뉴런은 모두 다 같은 연산을 수행함
      • 출력도 모두 같을 것이고, 결국 gradient도 서로 같음
      • 결국, 모든 뉴런이 모두 똑같이 생기게 됨
      • 이것이 모든 가중치를 동일하게 초기화 시키면 발생하는 일
    • 즉, 초기 가중치를 적당한 값으로 초기화 해줘야 함

  • 초기화 문제를 해결하는 첫 번째 방법은, 임의의 작은 값으로 초기화 하는 것
    • 이 경우, 초기 W를 표준정규분포(standard gaussian)에서 샘플링
    • 좀 더 작은 값을 위해, 스케일링을 진행
      • 0.01로 나눠서, 표준 편차를 0.01로 만들어 줌
  • 그러나, 이 방법은 깊은 Network에서는 문제가 생길 수 있음

  • Layer 당 500개의 neuron이 있고, 이런 layer 10개로 이루어진 Network
    • 이때, 가중치를 임의의 작은 값으로 초기화
    • 데이터를 랜덤으로 만들어주고, 이 데이터를 forward 시켰을 때, 각 layer 별 activation 수치를 통계화 시켜보면, 다음 이미지와 같음
    • activation function은 tanh를 사용

  • 각 layer 출력의 평균과 표준 편차를 계산
    • 평균은 항상 0 근처에 있음 (tanh 특성 - zero centered)
    • 표준 편차를 보면, layer를 지날수록 점차 줄어듦
      • 아주 가파르게 줄어서, 0에 수렴
  • 가장 아래의 그래프를 보면, (forward pass)
    • 첫 번째 layer에서는 가우시안 분포와 비슷한 형태의 분포를 형성하고 있음
    • 그러나, W를 곱할수록 출력 값이 급격하게 줄어듦 (W가 너무 작은 값들이라서)
    • 결국 layer를 거치다 보면, 표준 편차가 0이 됨
    • 따라서, 모든 activation function의 결과가 0이 됨
  • Backward pass로 다시 생각해보면,
    • 각 layer의 입력이 엄청 작은 값들이기 때문에, 입력 값이 점점 0에 수렴
    • Backpropagation 과정에서, local gradient는 x (W×xW\times x)
    • 이때 x는 엄청 작은 값이기 때문에 gradient도 작음 (결국 업데이트가 잘 일어나지 않음)

  • 가중치를 조금 더 큰 값으로 초기화하는 경우, (편차가 0.01이 아닌, 1)
    • 큰 가중치를 통과한 출력을 구하고, 이를 tanh를 거치게 된다면, 값들이 모두 saturation 될 것임 (tanh 특성 - [-1, 1] 사이의 값을 갖는다)
    • 즉, 출력이 항상 -1 이거나 1일 것임
    • 모든 출력이 saturation 될 것이고, 따라서 gradient는 0이 될 것임
      • 즉, 가중치 업데이트가 일어나지 않음

  • 널리 알려진 좋은 방법 중 하나는 Xavier Initialization
    • Standard Gaussian으로 뽑은 값을 입력의 수로 스케일링 함
    • 기본적으로 Xavier Initialization이 하는 일은, 입출력의 분산을 맞춰주는 것
      • 식에서 직관적으로 얻을 수 있는 것은, 입력의 수가 작으면 더 작은 값으로 나누고 좀 더 큰 값을 얻음
      • 추가적으로 더 큰 가중치가 필요함
        • 작은 입력의 수가 가중치와 곱해지기 때문에, 가중치가 더 커야만 출력의 분산 만큼 큰 값을 얻을 수 있음
      • 반대로, 입력의 수가 많은 경우에는 더 작은 가중치가 필요

  • 그러나, Xavier Initialization은 ReLU를 쓰면 잘 동작하지 않는다는 문제가 존재
    • ReLU는 출력의 절반을 죽임 (음수 구간)
    • 출력의 절반은 항상 0이기 때문에, 출력의 분산을 반토막 냄

  • 이 문제를 해결하기 위한 방법이 He Initialization을 사용하는 방법
    • 뉴런들 중 절반이 없어진다는 것을 고려하기 위해서, 기존 Xavier Initialization 식에서 2를 나눠줌
    • 실제 입력(fan_in)은 절반만 들어가므로, 반으로 나눠주는 텀을 추가 (분모에서 fan_in/2)
      • 실제로 잘 동작함
    • 결과를 보면, 전체적으로 좋은 분포를 형성하고 있음

Batch Normalization

  • Gaussian의 범위로 activation을 유지시키는 또 다른 아이디어
    • 우리는 layer의 출력이 unit Gaussian이길 원함
    • Batch Normalization은 강제로 unit Gaussian을 따르게 끔 만듦

  • 어떤 레이어로부터 나온 Batch 단위 만큼의 activation이 있다고 했을 때,
    • 우리는 이 값들이 unit Gaussian 이길 원함
      • 모든 데이터들에서 평균을 뺀 후, 분산으로 나눠줌으로서, 평균을 0으로 만들고, 분산을 1로 만듦
    • 누구나 이 데이터를 unit Gaussian으로 만들 수 있음
      • 현재 Batch에서 계산한 mean과 variance를 이용해서 normalization을 수행
      • 가중치를 잘 초기화 시키는 것 대신, 학습할 때 마다 각 layer에 이런 작업을 수행해서 모든 layer가 unit Gaussian이 되도록 해줌
    • 이제부터 할 일은, Network의 forward pass 동안에 그렇게 되도록 명시적으로 만들어 주는 것
      • 각 뉴런을 평균과 분산으로 normalization 해줌으로서, 이런 일을 함수로서 구현하는 것
      • Batch 단위로 한 layer에 입력으로 들어오는 모든 값들을 이용해서, 평균과 분산을 구하고, 이를 이용하여 normalization을 수행
      • 이 함수를 보면, 입력 x평균, 분산이라는 상수를 가지고 있는 함수이기 때문에, 미분이 가능함 (즉, Backpropagation 이 가능)

  • Batch 당 N개의 학습 데이터가 있고, 각 데이터가 D차원이라고 가정하면,
    • 각 차원별로 평균과 분산을 구함
    • 한 Batch 내 이걸 전부 계산해서 normalize 함

  • 이 연산은 FC나 Conv layer 직후에 넣어줌
    • 깊은 Network에서 각 layer의 W가 지속적으로 곱해지기 때문에 Bad scaling effect가 발생했지만, normalization은 그 bad effect를 상쇄시킴
    • BN은 입력의 스케일만 살짝 조정해주는 역할이기 때문에, FC와 Conv 어디에든 적용할 수 있음
      • Conv layer에서 차이점이 있다면, normalization을 차원마다 독립적으로 수행하는 것이 아니라, 같은 activation map의 같은 채널에 있는 요소들은 같이 normalize 함
      • Conv layer의 경우, activation map(채널, depth)마다 평균과 분산을 하나만 계산
      • 그 후, 현재 Batch에 있는 모든 데이터로 normalize 함
  • Batch Normalization이 갖는 한 가지 문제점은,
    • FC layer를 거칠 때마다, 매번 normalization을 해주는 것에 대한 의문
    • 정말로 tanh의 입력이 unit Gaussian이길 바라는 건지?
    • normalization이 하는 일은, 입력이 tanh의 linear한 영역에만 존재하도록 강제하는 것
      • 즉, 평균이 0이고, 분산이 1이 되도록 강제로 만들어줌
      • 이렇게 하면, saturation이 전혀 일어나지 않음
      • 하지만, saturation이 전혀 일어나지 않는 것 보단, 얼마나 saturation이 일어날지를 조절하면 더 좋음

  • 위 문제를 해결하기 위해서, 기존의 BN에서 scaling 연산을 추가
    • Unit Gaussian으로 nomarlize된 값들을,
      • 감마는 스케일링의 효과
      • 베타는 이동의 효과
    • 즉, 이 값들을 학습을 통해 조절함으로서, normalize 정도를 조절할 수 있음
    • 이를 이용하면, normalized 된 값들을 다시 원상복구 할 수도 있음
      • 이때는, 감마 = 분산, 베타 = 평균 으로 진행

  • 입력이 주어졌을 때,
    • mini-batch에서의 평균과 분산을 계산
    • 이 후, 평균과 분산으로 normalize
    • 다시 추가적인 scaling, shifting factor를 사용
  • BN은 gradient의 흐름을 보다 원활하게 해주며, 결국 학습이 더 잘되도록 (robust) 해줌
  • 또한, learning rate를 더 키울 수도 있고, 다양한 초기화 기법을 사용해볼 수 있음
    • BN을 쓰면 학습이 더 쉬워진다 (BN을 써야하는 이유)
  • BN은 regularization의 역할도 함
    • 각 layer의 출력은 해당 데이터 뿐만 아니라, batch안에 존재하는 모든 데이터들의 영향을 받음 (평균, 분산)
      • 각 layer의 입력은 해당 batch의 평균으로 normalize 되기 때문에
    • 따라서, layer의 출력은 오직 하나의 샘플에 대해서 정해지는 값이 아님
    • 즉, layer의 출력은 조금씩 바뀌게 되고, 이는 regularization 효과를 줌

  • test time에서 batch normalization이 어떻게 동작하는지 살펴보면,
    • BN에서 구한 평균과 분산은 train data에서 구한 것
    • test time에서 추가적인 계산은 하지 않음
    • training time에서, running average 같은 방법으로 평균 분산을 계산하고, test time에서 사용

Babysitting the Learning Process

  • 지금까지는 네트워크 설계를 배웠고, 이제부터는 학습 과정을 어떻게 모니터링하고 하이퍼파라미터를 조절할 것 인지 배움

  • 첫 단계는 데이터 전처리
    • 앞서 배운 것 처럼, zero-mean을 사용

  • 다음으로 architecture를 선택
    • 이번 예시에서는, 하나의 hidden layer와 50개의 뉴런을 가진 모델

  • 다음으로 할 일은, Network를 초기화 시키는 것

  • 학습을 진행할 준비가 끝났으면, 학습을 진행
    • 처음 시작할 때 좋은 방법은, 데이터의 일부만 우선 학습 시켜 보는 것
    • 데이터가 적으면 당연히 overfitting이 생길 것 이고, Loss가 많이 줄어들 것임
    • 이때는 regularization을 사용하지 않음
    • loss가 감소하는지 확인하는 것

  • 이제부터는 정말로 학습을 시작할 차례
    • 전체 데이터셋을 사용할 것 이고, regularization을 약간만 주면서 적절한 learning rate를 찾아야 함
    • learning rate는 가장 중요한 하이퍼파라미터 중 하나이며, 가장 먼저 정해야만 하는 하이퍼파라미터
    • learning rate가 지나치게 작으면, loss가 잘 줄어들지 않음

  • learning rate가 지나치게 높으면, loss가 발산
    • 따라서, 적절한 learning rate를 찾는 것이 중요
    • 일반적으로, 1e-3 ~ 1e-5 사이의 값을 사용
    • 이 사이의 값을 사용해서 cross-validation을 수행

Hyperparameter Optimization

  • 다음으로 하이퍼파라미터는 어떻게 정해줘야 하는지?

  • 하이퍼파라미터를 최적화 시키고, 그 중 가장 좋은 것을 선택하려면 어떻게 하는 것이 좋을까?
    • 첫 번째 전략은 cross-validation
      • cross-validation은 training set으로 학습시키고, validation set으로 평가하는 방법
      • coarse stage에서, 넓은 범위의 값을 골라냄
        • 이를 통해서, 어느 범위에서 잘 동작할지 대충 알게 됨
      • 이후, fine stage에서 좀 더 좁은 범위를 설정하고, 학습을 더 길게 시켜보면서 최적의 값을 찾음

  • 위 코드는, 5 epochs 동안 coarse search를 진행하는 예시
    • 여기서 확인해야하는 것은 validation accuracy

  • 하이퍼파라미터를 찾는 또 다른 방법은, grid search를 이용하는 것
    • 하이퍼파라미터를 고정된 값과 간격으로 샘플링하는 것
      • 실제로 grid search보단, 이전의 random search가 더 좋음

  • 하이퍼파라미터의 종류에는,
    • learning rate, decay schedule, update type, regularization, network architecture 등 여러가지가 있음

  • 우리는 여러가지 하이퍼파라미터를 직접 돌려보고 모니터링해서, 어떤 값이 좋고 나쁜지를 확인해야함
  • 즉, 하이퍼파라미터에 따른 loss curve를 보면서 좋은 것을 찾아서 시도하는 일을 반복해야함
    • loss curve를 모니터링 하는데, learning rate가 굉장히 중요함
    • 따라서, loss curve를 보고, 어떤 learning rate가 좋은지 알아볼 수 있어야 함
    • loss가 발산하면, learning rate가 너무 높은 것이고, linear하면 너무 낮은 것임
    • 빨간색 선과 같이, 가파르게 내려가면서, 지속적으로 잘 내려가는 경우의 learning rate가 좋은 것

  • 초기에는 평평하다가, 중간에 갑자기 loss가 떨어지는 경우
    • 이는 초기화의 문제일 수 있음

  • 만약, train_acc와 val_acc가 큰 차이를 보인다면,
    • 이는 overfitting의 문제일 수 있음
      • 따라서, regularization의 강도를 높여야 함

  • 마지막으로, 우리는 가중치의 크기 대비 가중치 업데이트의 비율을 지켜볼 필요가 있음
    • 이 비율이 대략 0.001 정도 되길 원함
    • 이 비율을 통해서, 업데이트가 지나치게 크거나 작은지에 대한 감을 어느정도 가질 수 있음
profile
코딩하는 물리학도

0개의 댓글