PyTorch

1-16 PyTorch 코딩 선형회귀법 예제

coding art 2020. 3. 8. 20:45
728x90




그림의 선형회귀법 예제에서 w 를 미지수로 생각하고 regression 기법으로 찾아보자. 웨이트 값 w처음에 random number 나 임의의 상수 값을 준 상태에서 시작하면 된다.

 

이 웨이트 값 w는 머신 러닝 과정의 중요 변수이므로 반드시 PyTorch 코드에서torch.Tensor 변수로 선언되어야 torch 라이브러리의 지원을 받아 regression 이 가능해짐에 유의하자.

 

선형 회귀법 예제에 필요한 라이브러리는 torch autograd 이다. Matplotlib 는 그래픽 처리를 지원하는 파이선 라이브러리이며 Numpy도 중요 파이선 러이브러리이지만 이 예제에 한해서는 필수적인 것은 아니다. PyTorchTensorFlow 머신 러닝 코드를 다루다 보면 torch Tensor TensorFlow Tensor 또는 Pandas가 읽어 들인 수치 데이타들을 처리는 과정에서 Numpy 어레이로 변환해서 처리해야할 경우가 많으므로 항상 넣어 두는 것이 좋다.

 

이 선형회귀 예제에서 필요한 입력 데이타들은 리스트 형 자료구조로 정의 한다. 웨이트 wtorch.Tensor로 그 값을 0.0 으로 선언한다. 0.0 이외에도 임의 의 상수 값으로 정해도 무방하다. requires_grad 속성은 True로 선언해 두어야 autograd에 의한 자동 미분이 가능해진다. 아울러 autograd 라이브러리 지원 하에 Variable을 선언하게 되면 .data .grad 와 같은 텐서(raw tensor)들을 사용할 수 있게 된다. raw tensor는 별도로 선언한 텐서가 아닌 파생하여 생성된 텐서를 뜻한다.

 


초기 웨이트 값 w가 주어졌으면 다음과 같이 변화되는 웨이트 값과 loss 함수 값을 추적하기 위한 w_list l_list를 리스트형 자료로 선언한다. loss 함수의 최소 값을 찾아내기 위해서 10회의 epoch를 설정하자. epoch 별로 3개의 데이타에 대한 loss 함수 값과 웨이트 w에 대한 미분 기울기 값을 계산한다.

그 중 첫 번째 한해서 다음과 같이 계산을 추적해보자.


미분 기울기 값은 learning rate 값과 곱하여 다음 번 epoch 에서의 새 웨이트 값 w를 계산하고 미분 값을 저장했던 grad.data0.0으로 초기화 시킨다.

참고로 웨이트 wautograd Variable 로 지정했기 때문에 w를 상속한 .dataraw tensor이며 아울러 변수 w에 대한 미분 값은 .grad.data 에 저장됨에 유의하자. 다음 그림에서 requires_grad=True에 상응하는 l.backward()에 의해 back-propagation 계산이 이루어지면 매번 계산 후 w.grad.data 값을 0.0으로 설정해야 한다. 이러한 코드 구조가 필요한 이유는 PyTorch 머신러닝에서 컴퓨팅 부담이 대단히 큰 Transfer Learning 학습 코드 작성 시에 시간 소모가 있을 수 있는 Fine Tuning을 할 것인지 생략할 것인지 여부를 requires_grad를 사용하여 결정할 수 있기 때문에 편리하게 처리할 수 있도록 그러한 가능성을 부여한 듯하다.


#pytorch linear regression

import torch
from torch.autograd import Variable
import numpy as np
import matplotlib.pyplot as plt

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

w = Variable(torch.Tensor([0.0]), requires_grad=True)

def forward(x):
    return x * w
def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) * (y_pred - y)

print("\npredict (before training)",  4, w, forward(4).data[0])

w_list = []
l_list = []

w.data = w

for epoch in range(20):
    for x_val, y_val in zip(x_data, y_data):
        l = loss(x_val, y_val)
        l.backward()
        w.data = w.data - 0.01 * w.grad.data[0]
        print("\tgrad: ", x_val, y_val, w.data[0], w.grad.data[0])
        w_list.append(w.data[0])
        l_list.append(l.data[0])
        w.grad.data.zero_()
    print("progress:", epoch, l.data[0])
plt.plot(w_list, l_list)
plt.ylabel('Loss')
plt.xlabel('w')
plt.show()