ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [pytorch] optim.SGD 알아보기
    AI-ML 2023. 12. 13. 07:54
    728x90
    반응형

    - 목차

     

    키워드.

    • - Stochastic Gradient Descent

     

    SGD 란 ?

    이번 글에서는 pytorch 의 대표적인 Optimizer 인 SGD 와 그 사용법에 대해서 알아보려고 합니다.

    우리말로 경사하강법이라고 말하는 Gradient Descent 알고리즘은 Neural Network 의 파라미터를 업데이트하는 방식입니다.

    만약 12개의 Weight 로 구성된 Neural Network 가 존재한다고 가정하겠습니다.

    일반적인 DenseNet Layer 이며, 4개의 Input 에 대해서 3개의 Output 을 생성하는 Fully Connected Layer 입니다.

    그래서 4x3 인 Dense Net 은 12개의 Weight 를 가지게 됩니다.

     

    그리고 MSE 와 같은 Loss 에 대해서 모든 Weight 의 Gradient 를 계산해야합니다.

    Loss 에 대한 각 Weight 의 Gradient 를 Learning Rate 를 곱하여 뺄셈 연산을 수행합니다.

    이러한 반복적인 과정을 통해서 Weight 가 업데이트되어 갑니다.

     

    $$ Weight_{11-new} = Weight_{11} - lr \bullet \frac{\delta (Loss)}{\delta (Weight_{11})} $$

    $$ Weight_{12-new} = Weight_{12} - lr \bullet \frac{\delta (Loss)}{\delta (Weight_{12})} $$

    $$ .... $$

    $$ Weight_{43-new} = Weight_{43} - lr \bullet \frac{\delta (Loss)}{\delta (Weight_{43})} $$

     

    간단한 예시를 위해서 일차 선형 회귀를 예시로 들어보도록 하겠습니다.

    $$ y = wx + b $$

    와 같은 구조의 선형 회귀 모델을 가정하겠습니다.

     

    $$ Loss = (y - \hat{y})^{2} = (y - wx + b)^{2} $$

    과 같이 MSE Loss 를 간략히 표현하였습니다.

    이때 w 의 Gradient 를 계산하는 공식은 아래와 같으며,

    $$ \frac{\delta (Loss)}{\delta (w)} = -2x \bullet (y - wx + b) $$

    결과적으로 w 의 Gradient 는 -2(y - wx + b) 가 됩니다.

     

    그래서 w_next = w - lr(-2(y - wx + b))  와 같은 방식으로 Next Weight 를 지속적으로 갱신해나갑니다.

     

    Gradient Descent 의 종류.

    지금까지 Gradient Descent 알고리즘을 활용해서 Weight 가 업데이트되는 방식에 대해서 알아보았습니다.

    이제, Gradient Descent 의 종류인 Stochastic Gradient Descent 와 Mini-Batch Gradient Descent 에 대해서 알아보도록 합니다.

     

    간단하게 아래와 같은 신경망이 존재한다고 가정합니다.

    입력데이터로 이미지가 주어질 때에, 동물 이미지 여부를 판단하는 모델입니다.

     

    위와 같은 경우에 Train Data 로 1개의 데이터만 사용되었습니다.

    그래서 Loss 를 아래와 같이 표현해보겠습니다.

    Train Data 가 곰 이미지 1개이므로 곰 이미지에 대한 Loss 만 구하면 됩니다.

     

    그리고 아래와 같이 3개의 이미지가 Train Data 로 사용된 경우에는 Loss 는 3개의 항으로 이뤄진 다항식이 됩니다.

    제가 하고 싶은 이야기는 Deep Learning 에서는 사용된 Train Data 의 갯수만큼 무수한 다항식이 만들어집니다.

     

     

     

     

    아래와 같이 9개의 Train Data 에 대한 Loss 또한 9개의 다항식으로 이루어집니다.

     

     

    일반적인 Gradient Descent 에 대해서.

    학술적인 또는 개념적인 Gradient Descent 는 1번의 Epoch 에서 모든 Train Data 를 학습합니다.

    그리고 이 모든 Train Data 에 대해서 Loss 를 계산하고, Back Propagation 을 수행하죠.

    마치 위의 그림처럼 총 9 개의 Train Data 에 대해서 Gradient Descent 를 한번에 수행합니다.

     

    이러한 방식의 단점은 시간이 많이 소요되는 문제가 있습니다.

    모든 학습 데이터를 한번에 계산한 후에 Gradient Descent 를 수행하기에 서버의 메모리 제한도 문제가 될 수 있죠.

    이는 이상적인 방식에 가깝기에 SGD 나 Mini-Batch Gradient Descent 가 사용되는 배경이기도 합니다.

     

    Stochastic Gradient Descent.

    Stochastic Gradient Descent 는 확률적인 방식으로 Gradient Descent 를 수행합니다.

    이것이 무슨 의미냐면, 아래와 같이 9개의 Train Data 를 3개의 Batch 로 나누어서 3번의 Iteration 이 수행되었다고 가정합니다.

    그럼 각 Iteration 에서 batch size 는 3이 되겠죠 ?

    SGD 는 각 Iteration 에서 단 1개의 Data 를 확률적으로 추출하여 Gradient Descent 를 수행합니다.

     

     

    각 Batch 에서 랜덤한 확률로 1개의 데이터를 추출하여 Gradient Descent 를 수행합니다.

    1번째 Batch 에서는 무작위로 곰 이미지가 선택되었고, 두번째 Batch 에서는 무작위로 순록 이미지가 선택되었습니다.

     

     

    Mini-Batch Gradient Descent.

    Mini-Batch Gradient Descent 는 SGD 가 Batch 에서 1개의 데이터를 사용하는 것에 반해 모든 Batch 데이터를 활용합니다.

    즉, 아래의 그림과 같이 Iteration 에서 사용된 모든 Batch 데이터들이 Optimize 과정에서 사용됩니다.

     

     

    pytorch 의 optim.SGD 는 SGD 라는 이름을 가지곤 있지만, 사실상 Mini-Batch Gradient Descent 방식을 사용합니다.

    이어지는 글에서 optim.SGD 의 사용법에 대해서 알아보도록 하겠습니다.

     

    pytorch optim.SGD 사용해보기.

    pytorch 의 optim.SGD 의 사용법은 아주 간단합니다.

    아래와 같이 Weight 로 사용할 Parameter 를 생성한 이후에 optim.SGD 의 첫번째 인자로 입력하면 사용이 가능합니다.

    import torch
    import torch.nn as nn
    
    weight = nn.Parameter(torch.tensor([[100.0]], requires_grad=True))
    sgd = torch.optim.SGD([weight], lr=0.001)

     

    위에서 설명드리길, pytorch 의 SGD 는 사실상 Mini Batch Gradient Descent 를 사용한다고 말씀드렸죠 ?

    이 내용에 대해서 코드로써 설명드리겠습니다.

     

    pytorch 의 SGD 는 실제로 Mini Batch Gradient Descent 로 동작한다.

    MSE Loss 에 대해서 1개의 weight 의 Gradient 는 다음과 같습니다.

    $$ Loss = (y - \hat{y})^{2} = (y - wx)^{2} $$

    $$ \frac{\delta (Loss)}{\delta (w)} = -2x \bullet (y - wx) $$

     

    그래서 y = x 를 만족하는 Train Data 와 Label 을 가지고 학습을 진행하게 되면, Weight 는 1 로 수렴해야합니다.

    아래의 예시 코드는 Weight 의 초기값을 100 으로 설정하였구요.

    1회의 Epoch 을 진행합니다.

     

    import torch
    import torch.nn as nn
    
    weight = nn.Parameter(torch.tensor([[100.0]], requires_grad=True))
    sgd = torch.optim.SGD([weight], lr=0.001)
    
    loss_function = nn.MSELoss()
    
    x = torch.tensor([[1]], dtype=torch.float32)
    y = torch.tensor([[1]], dtype=torch.float32)
    pred = torch.matmul(x, weight)
    loss = loss_function(pred, y)
    
    sgd.zero_grad()
    loss.backward()
    sgd.step()
    
    print(weight)
    tensor([[99.8020]], requires_grad=True)

     

     

    그 결과는 99.8020 의 Weight 가 출력되고, 이는 100 에서 0.198 만큼 감소한 수치입니다.

    이러한 결과가 도출되는 계신식을 아래와 같습니다.

    lr = 0.198
    current_Weight = 100
    loss_gradient = -2 (y - wx) = -2 (1 - 100) = 198
    
    next_weight = current_weight - lr * loss_gradient = 100 - 0.198

     

    그럼 Batch Size 를 10 로 늘려서 SGD 를 수행합니다.

    학습 데이터와 라벨은 1 부터 10까지의 자연수를 사용하였습니다.

    import torch
    import torch.nn as nn
    
    weight = nn.Parameter(torch.tensor([[100.0]], requires_grad=True))
    sgd = torch.optim.SGD([weight], lr=0.001)
    
    loss_function = nn.MSELoss()
    
    x = torch.linspace(1, 10, 10, dtype=torch.float32).reshape(-1, 1)
    y = torch.linspace(1, 10, 10, dtype=torch.float32).reshape(-1, 1)
    pred = torch.matmul(x, weight)
    loss = loss_function(pred, y)
    
    sgd.zero_grad()
    loss.backward()
    sgd.step()
    
    print(weight)
    tensor([[92.3770]], requires_grad=True)

     

    위 케이스에서 92.3770 으로 weight 가 업데이트된 과정을 아래와 같이 나타내어보겠습니다.

    데이터 1 에 대한 Gradient 는 198 * 1 로 표현됩니다.

    그리고 데이터 2 에 대한 Gradient 는 198 * 2 * 2 로 도출되는데요.

    이와 같이 1 ~ 10 까지의 MSE Gradient 는 아래와 같으며 92.3770 의 결과를 가집니다.

    즉, pytorch 의 SGD 는 Mini Batch Gradient Descent 의 방식을 사용하고 있습니다.

     

    100 - 0.001 * (
            198*1*1  
            + 198*2*2 
            + 198*3*3 
            + 198*4*4 
            + 198*5*5 
            + 198*6*6 
            + 198*7*7 
            + 198*8*8 
            + 198*9*9 
            + 198*10*10
    ) / 10

     

     

     

     

    반응형

    'AI-ML' 카테고리의 다른 글

    Covariate Shift 알아보기  (0) 2023.12.24
    [pytorch] nn.BatchNorm 알아보기  (0) 2023.12.24
    [Statistics] Odds, Logit 알아보기  (0) 2023.11.24
    [pytorch] nn.Sigmoid 알아보기  (0) 2023.10.30
    Collaborative Filtering 이해하기  (0) 2023.09.25
Designed by Tistory.