본문 바로가기
DeepLearning Framework & Coding/Pytorch

[pytorch 따라하기-3] 경사하강법을 통한 선형회귀 구현

by 노마드공학자 2021. 7. 25.

[pytorch 따라하기-1] 구글 Colab에 pytorch 세팅하기 https://limitsinx.tistory.com/136

[pytorch 따라하기-2] Tensor생성 및 Backward https://limitsinx.tistory.com/137 

 

※이 전글에서 정리한 코드/문법은 재설명하지 않으므로, 참고부탁드립니다

※해당 글은 PC에서 보기에 최적화 되어있습니다.

 


 

 

Gradient Descent(경사하강법)

출처 : Wikimedia, Gradient Descent

 

이 이차함수 그래프를 봐주시기 바랍니다.

 

cost는 (내가 추정한값-실제값)의 제곱이라고 했습니다.

그러면 위와 같은 아래로 볼록한 이차함수가 나오게 되겠죠?

 

즉, 이 이차함수 자체가 "Cost"입니다.

그럼 cost가 가장작은값은 가장 아래에 있는 붉은점이지 않을까요?

 

이때의 붉은점은 미분했을때 기울기가 0인 유일한 점입니다. (변곡점)

즉, Cost(비용)을 아래로 볼록한 2차함수로 만들고, 미분했을때 0인 지점의 W와 b값이 이상적인 결과 라는것입니다.

 

 코드

import torch

import torch.nn as nn

import torch.optim as optim

import torch.nn.init as init

#import torch 및 nn은 pytorch의 Neural Network 라이브러리 (nn.Linear())를 사용하기 위해 불러오며

#Optim은 Optimizer(Adam이나 Gradient Descent,...같은 cost function 최적화를 위한) 호출용 라이브러리

#init은 말그대로, 학습을 시작하는 제일 첫단계에서 초기화를 어떻게할것이냐를 설정하는 라이브러리 입니다.

 

num_data = 1000

num_epoch = 500

#머신러닝에서 epoch이란 반복횟수를 의미합니다. 즉, Error Backpropagation이라는 과정을 거쳐 Gradient Descent의

#최적화가 이루어 지는데 Input부터 Output까지 몇번왔다갔다할래?가 epoch입니다.

#epoch수가 높을수록 머신러닝이 잘되긴 하지만, 연산횟수가 많아진다는 단점이 있습니다.

 

## 변수선언부

x = init.uniform_(torch.Tensor(num_data,1),-10,10)

# x는 1000행 1열짜리 Tensor를 가지며, -10과 10사이의 수로 초깃값을 가짐

noise = init.normal_(torch.FloatTensor(num_data,1),std=1)

# Noise또한 1000행 1열짜리로 만들며, Gauss함수의 형태로 Standard Deviation(표준편차) = 1이 되도록 만듬

y = 2*x+3

y_noise = y + noise

# y=2x+3에 noise를 섞어준 수식이며, 이것을 최적화 하는것이 목표 -> 학습시켜 noise가 낀 값들을 토대로 수식을 역추정했을때 y=2x+3이 나오면 학습성공



model = nn.Linear(1,1)

#선형 모델을 선언하는 것으로 nn.Linear(number of x feature, number of y feature)입니다. 현재 x와 y는 모두 [1000,1]로 1개의 Feature를 가지는 1000개의 데이터이기에 (1,1)

loss_func = nn. L1Loss()

#pytorch에서 L1Loss는 average(ABS(y-target))입니다. 즉, 차이의 절댓값의 평균입니다. 이런 Loss가 최소화되는 수식을 찾는것이 머신러닝입니다.

optimizer = optim.SGD(model.parameters(), lr = 0.01)

#Optimizer의 방법으로 SGD,GD,Adam,RMS같은 다양한 방법들이 존재하며, Lr은 Learning rate의 약자로 0.01로 선정하였습니다.

#Learning rate가 너무 크면 발산할 수 있으며, 너무 작으면 목표값으로 수렴하는데 오랜시간이 걸릴 수 있습니다.

 

print('Tensor X Shape : ',x.shape) #1000행 1열

print('Tensor Y Shape : ',y.shape) #1000행 1열

for i in range(num_epoch): #num_epoch만큼 학습 반복)

    optimizer.zero_grad()

    # for문을 돌며 매번 epoch을 할때마다 Gradient(w)를 0으로 초기화하며 학습을 시도합니다.

    output = model(x)

 

    loss = loss_func(output,y)

    #Loss 함수 = 학습하여 나온 추정값에서 목표값 y의 차이를 손실로 정의

    loss.backward()

    optimizer.step()

    #위에서 정의한 Loss가 최소화 되도록 Backpropagation과 Optimizer를 시행(optimizer = SGD,learning rate = 0.01로 위에 선언)

 

    if i % 10 ==0:

        print(loss.data)

        param_list = list(model.parameters())

        #model은 nn.Linear(1,1)로 선언했는데, y=wx+b라는 선형회귀함수라고 하면, w(x절편)와 b(y절편)를 List화하여 저장하는방법입니다. 

        print(param_list[0].item(), param_list[1].item())

 

결과값

500번 시행

 

저희의 목표값은 y = 2x+3을 찾는것이었습니다.

 

500번의 epoch을 시행했을때 결과값으로, y=1.9684x+3.00012라고 나오는데요

거의 근접하게 추정했다는것을 확인할 수 있습니다.

 

3000번을 시행해보면 500번의 반복보다 훨씬 더 근접한 결과값이 나오게 됩니다.

 

3000번 시행

댓글