Gradiend Descent 로 부터 Adam까지 optimizer 정리

BASE

GD(Gradient Descent)

  • 전체 데이터를 관찰하고 파라미터 업데이터(속도 느려, 메모리 잡아먹어)SGD(Stochastic Gradient Descent) - vanila
  • Mini batch 적용
  • 자주 파라미터 업데이트 되지 속도 빨라 메모리 효율적으로 사용돼
  • 하지만 여전히 local minima 에 빠짐

개선 갈래 1 (관성을 이용하자. 직전 step의 변화량을 사용

Momentum

  • 관성(탄력)을 이용하는 방법
    • "이전에 이렇게 많이 움직였는데... 갑자기 급브레이크를? 자연스럽지 않잖아!" 자연스럽게 바꾸자!
  • 이전 스텝에서 계산된 그래디언트를 일정비율로 (현재 스텝의 그래디언트에) 더해줌
  • /수식을 보면 저 이전스텝적용 비율대로 step이 진행됨에 따라 decay 되는 것을 확인할 수 있음/

Nesterov Accelerated Gradient (NAG)

  • 이전에 계산된 위치에 관성을 먼저 적용시켜불고 거기서 로스를 구해서 그래디언트를 구해부러! (모멘텀 텀은 그대로 존재)

개선 갈래 2 (parameter 마다 step을 다르게 주자..., Adaptive Learning Rate)

  • param1은 미니마에 거의 도착했고 param2는 아직 도착 못햇으면 param1는 작은 LR를 적용하고 param2는 큰 LR를 적용해야 하는거 아냐? 라는 생각으로 부터 적용

Adaptive Gradient (Adagrad)

  • Learning rate 에 상수가 아닌 분모에 변화를 줘서 파라미터마다 다르게 적용할 수 있도록 함 (상수가 아닌 파라미터갯수만큼의 벡터를 사용)
  • Gt 라는 놈에 각 파라미터가 얼마나 많이 변해왔는지를 계산해서 넣어둠 (그 값의 루트값을 분모로 취해줌. 즉, 많이 변한놈은 lr을 작게 만듦)
  • (궁금증) 초기값이 애초에 너무 어긋나 있으면...?? 그럼 실제로 열심히 찾아가야 하는데 많이 움직였다고 브레이크를 걸어??? 음...

RMSProp

  • Adagrad 에서 분모가 무한발산해서 학습률이 엄청 작아지는 문제를 개선하기 위해 (위에서의 궁금증 부분) 일정 비율로 Gt 값이 업데이트 되도록 개선하였음
  • Gt = r*Gt-1 + (1-r)(파라미터미분값제곱합)

AdaDelta

  • 얘는... learning_rate의 분자까지 계산식이 들어가는데...(즉 상수인 lr이 사용되지 않음, 그래서 하이퍼파라미터에 없음)
  • 근데 생각보다 잘 동작하지 않는다고 함

개선 갈래를 합치차 (Momentum 사용 + Adaptive Learning Rate 사용)

Adaptive Moment Estimation (ADAM)

  • Mt, Vt 를 사용해서 계산하는데...
  • Mt
    • Gradient 에 Momentum을 적용한 항
  • Vt
    • Gradient 에 Adaptive LR 를 적용한 항 (Gradient 의 제곱을 사용)
  • 첫 스텝에 너무 큰 스텝을 밟지 않게 하기 위한 Mt, Vt 를 변경하는 계산을 더해줌
  • 최종 수식은 Mt를 모멘텀 적용된 변화량으로 사용, Vt를 Learning Rate 계산용으로 사용하여 최종 업데이트가 진행됨.

TO-DO

  • NAdam, RAdam, AdamW 등 더 개선된 놈들이 실제 practical 한 지..의 관점으로 더 살펴보기

Ref

'기계학습' 카테고리의 다른 글

GCN (Graph Convolution Network)  (0) 2021.12.29
[정리노트] XGBoost 이해하기 (Regression)  (0) 2020.08.25
Gradient Boost for classification (binary)  (0) 2020.08.20
K-means Algorithm  (0) 2015.11.25

구조

  • 노드 피쳐 메트릭스
  • 인접행렬
    • 노드피쳐 메트릭스 , filter weights, 인접행렬을 곱하면 message passing 이 된다.
  • Inception
    • message passing을 몇 번 반복하느냐에 따라 receptive field의 크기를 조절할 수 있다.
  • Readout Layer
    • 그래프의 노드 순서와 상관없이 학습되도록 하는 방법 중 하나
    • MLP로 연결해버림
  • skip connection
    • resNet 처럼 연결하면 된다
    • gated skip connection을 적용할수도 있다. (두 입력을 어느정도의 비율로 적용할지 비율을 계산하여 반영하는 방법)
  • Attention
    • 인접 노드들의 정보를 합칠때 Attention 기법을 이용하여 weighted sum 형태로 구현 가능하다

 

'기계학습' 카테고리의 다른 글

Optimizer 종류  (0) 2022.01.01
[정리노트] XGBoost 이해하기 (Regression)  (0) 2020.08.25
Gradient Boost for classification (binary)  (0) 2020.08.20
K-means Algorithm  (0) 2015.11.25

Overview

  • Text classification 모델을 생성한다.
  • 간단하게 Character embedding layer를 두고 문서의 character embedding 평균 백터를 구하여 Fully Connected Layer를 두어 (2개층) 최종적으로 binary classification을 수행하도록 한다.

Network Module 구현하기

  1. nn.Module을 상속받아 클래스를 생성한다.
  2. init 함수에 네트워크에서 필요한 Layer들(주로 pytorch에서 기본 제공되는 Layer들을 정의함. 물론 사용자 정의 모듈도 정의 가능함)
  3. forward 함수 안에 모듈의 input 부터 output까지 네트워크의 흐름을 구현해준다.

이번 구현에서 필요한 pytorch 기본 제공 모듈 살펴보기

  1. torch.nn.EmbeddingBag
    • Text 관련 네트워크에서 사용하는 Embedding Layer에 평균/합계/최대값 등 특정 계산값을 구하는 부분이 추가된 모듈이다.
    • 이번 예시에서는 EmbeddingBag을 사용하나. 실제로는 주로 Embedding 레이어를 더 많이 사용한다.
  2. torch.nn.Linear
    • 기본적인 Fully Connedted Layer 이다.
    • (주의사항) activation func 는 포함되지 않으며 input * weight 까지만 수행한다.
  3. torch.nn.BatchNorm1d
    • 1차원 batch normalization layer 이다.
    • batch normalization 은 다른 포스팅 혹은 유투브 강의를 살펴보면 된다. "Internal Covariate Shift(ICS)" 라는 term만 잘 이해하면 되긴 한다. (다만,  batch normalization 의 성능향상 효과는 ICS 와는 상관이 없었다능... 결국 loss function의 landscape가 smoothing 되는 효과 때문이라능... 그게 요 논문)
    • Andrew Ng 강의를 보면 batch normalization은 regularization 기능도 한다고 한다. 하지만 주 목적은 학습을 빠르게 하는 것이다.
    • (추가) 비교적 최신(최신이라기엔 시간이 많이 흘렀지만..)인 transformers 같은 network 상에서 사용하는 normalization을 보면 Batch normalization 보다 Layer Normalization을 사용하는 것을 볼 수 있다. 요 차이는 normalization을 수행하는 차원은 B(batch)차원으로 하느냐 L(layer) 차원으로 하느냐 차이이다. Batch Normalization이 아래와 같은 한계점 때문에 Layer Normalization 을 더 많이 사용한다고 하니 참고하면 좋을 듯 하다.
      • Batch Normalization 은 Batch 사이즈를 적절히 조절했을 때 제대로 동작한다. 따라서 메모리를 상당히 많이 사용하는 복잡한 모델을 돌릴때 상대적으로 batch 사이즈를 크게 가져갈 수 없는 경우가 발생하고 이에 따라 Batch Normalization 이 제대로 동작하지 않을 수 있다.(Batch 가 너무 커도 잘 동작하지 않는다고 한다.) 반면 Layer 단위로 Normalization을 진행할 경우 이러한 Batch size에 영향을 받지 않는다. (자세한 사항은 batch / layer normalization을 설명한 다른 포스트들을 찾아보면 좋다)
      • (참고사항)배치 정규화를 사용할 경우 학습되는 파라미터 중 bias 부분에 해당하는 베타(학습되는 값)가 있는데 이러한 부분이 기존 fc 에서 별도로 추가해서 사용할 수 있는 bias 와 역할이 동일하다. 따라서 배치 정규화를 사용하는 경우 굳이 바이어스를 사용할 필요가 없다고 한다.
  4. torch.nn.Relu
    • activation layer의 한 종류. 다른 activation 함수들도 살펴 보면 좋다.
    • Relu 의 출현은 'vanishing gradient' 와 관계가 있으니 관련 내용도 찾아보면 좋다.
  5. torch.nn.Dropout
    • Overfitting 방지를 위한 layer 이다.
    • 기본 동작은 일정 확률로 뉴런을 죽이거나 혹은 살린다. DL 프레임워크마다 파라미터로 넘겨주는 값이 때로는 죽이는 확률일때도 있고 살리는 확률일때도 있다. 따라서 사용중인 프레임워크의 기본 파라미터의 의미를 잘 알고 사용하는 것이 좋다. pytorch는 죽이는 확률이 기본 값으로 들어간다.
    • (참고사항) 사실 대부분 high level API를 사용하기 때문에 Dropout을 직접 구현할일이 없지만. 직접 구현시에 단순히 일정 확률로 죽이는것으로 끝나는 것이 아니라 backpropagation에서 죽었던 뉴런에 대한 처리를 따로 해주어야 하기 때문에 추가적인 구현이 필요하다. 이 부분은 Andrew Ng 교수님의 강의에 대략적으로 설명이 되어있다.

(유의사항1) BatchNorm, Activation, Dropout 의 적절한 위치는??

  • Fully Connected Layer를 구축할 때 사용되는 모듈들의 순서를 어떻게 해야할 지 모르겠는 경우가 있다. 특히 위 제목에 있는 것들...
  • 다행히 이러한 궁금증에 대한 대답은 여러 군데에서 찾을 수 있다. 여기에서도.
  • 결론은 FC - BATCH - ACTIVATION - DROPOUT 순이다.
  • 자세한 이유는 구글링...

(유의사항2) Softmax Layer의 부재... 왜?

  • 이전 포스팅에서 대답이 되었지만....
  • 구현상의 이슈로 인해 (exp 함수로 인한 overflow 문제) Softmax 와 log 함수를 합한 log_softmax 함수를 주로 사용하며
  • NLL_loss 를 사용하면 log_softmax를 모듈의 마지막 레이어에 넣어주어야 하며,
  • CrossEntropyLoss 를 사용하려면 log_softmax layer를 생략해야한다.

구현 예시

class MeanCharEmbeddingClsf(nn.Module):
    def __init__(self, vocab_size, char_emb_dim, hidden_dim1, hidden_dim2, class_cnt):
        '''
        define network structure
        :param vocab_size:
        :param char_emb_dim:
        '''
        super(MeanCharEmbeddingClsf, self).__init__()

        self.char_emb_bag = nn.EmbeddingBag(num_embeddings=vocab_size, embedding_dim=char_emb_dim, mode="mean")

        self.fc1 = nn.Linear(char_emb_dim, hidden_dim1)
        self.fc2 = nn.Linear(hidden_dim1, hidden_dim2)
        self.layer_out = nn.Linear(hidden_dim2, class_cnt)

        self.batchnorm1 = nn.BatchNorm1d(hidden_dim1)
        self.batchnorm2 = nn.BatchNorm1d(hidden_dim2)

        self.do = nn.Dropout(0.2)
        self.relu = nn.ReLU()

    def forward(self, char_seqs):
        # char_seqs (B, CSL, CED)
        mean_vec = self.char_emb_bag(char_seqs)

        h1 = self.fc1(mean_vec)
        h1 = self.batchnorm1(h1)
        h1 = self.relu(h1)
        h1 = self.do(h1)

        h2 = self.fc2(h1)
        h2 = self.batchnorm2(h2)
        h2 = self.relu(h2)
        h2 = self.do(h2)

        out = self.layer_out(h2)
        return out

'pytorch' 카테고리의 다른 글

CrossEntropyLoss in pytorch (feat. log_softmax, nll_loss)  (0) 2020.09.30
01. DataSet  (0) 2020.09.28

+ Recent posts