본문 바로가기
Artificial Intelligence/Deep Learning

[PyTorch] 파이토치로 선형회귀 구현하기 / nn.Module

by EunjiBest 2022. 11. 19.

[PyTorch] 파이토치로 선형회귀 구현하기,nn.Module

 

 

 

Import 

 

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

 

 

torch: 텐서를 생성하는 라이브러리

torch.autograd: 자동미분 기능을 제공하는 라이브러리

torch.nn: 신경망을 생성하는 라이브러리

torch.multiprocessing: 병럴처리 기능을 제공하는 라이브러리

torch.utils: 데이터 조작 등 유틸리티 기능 제공

torch.legacy(./nn/.optim): Torch로부터 포팅해온 코드

torch.onnx: ONNX(Open Neural Network Exchange) 서로 다른 프레임워크 간의 모델을 공유할 때 사용

 

 

 

Train 만들기

 

x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2], [4], [6]])

 

3x1 모양의 tensor를 만들어 x,y train 생성

 

 

 

가중치와 편향 초기화

 

간단히 설명을 하자면,,

직선의 방정식 y = Wx+b 에서 w와 b를 조정하여 최적의 y값(정답)에 가깝도록 해주는 것이 

머신러닝의 목적이다.

 

더 자세한 설명은

↓↓↓↓↓↓↓↓↓↓↓

 

머신러닝(Machine Learing)이란? 오차함수 MAE(mean absolute error)/MSE(mean squared erro)

머신러닝(Machine Learing)이란? 오차함수 MAE(mean absolute error)/MSE(mean squared erro) 블로그를 운영하면서 머신러닝에 대해 글을 쓴 것이 없다느는 것을 알고 놀랬다. 어제 공부한 내용을 토대로, 머신러닝

eunjibest.tistory.com

 

 

W = torch.zeros(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

 

W와 b를 0으로 설정해준다.

따라서 y = 0x + 0 이된다.

 

hypothesis = x_train * W + b
print(hypothesis)

 

W와 b를 조정하기 위해서 가설을 세워준다.

H(x) = Wx+b라고 식을 세울 수 있는데 이때 x_train데이터이다.

 

 

 

loss함수 선언

 

>>> cost = torch.mean((hypothesis - y_train) ** 2) 
>>> print(cost)


tensor(18.6667, grad_fn=<MeanBackward1>)

 

loss함수는 MSE(평균 제곱 오차)를 사용해보자.

정답데이터에서 y_train을 빼고 제곱한 평균이다.

 

 

 

경사하강법(SGD)

 

optimizer = optim.SGD([W, b], lr=0.01)
optimizer.zero_grad() 
cost.backward()
optimizer.step()

 

optim.SGD함수에 W,b를 넣어주고 학습률은 0.01로 설정해준다.

zero_grad()함수는 기울기를 0으로 초기화 시켜준다. 파이토치는 이전 기울기를 값에 누적시키기 때문이다.

cost.backward()함수를 호출하면 기울기 계산이 된다.

optimizer.step()함수는 W와 b에서 리턴되는 변수를 0.01(학습률)을 빼주어 업데이트가 된다. 

 

 

 

최종 학습 코드

 

x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2], [4], [6]])

W = torch.zeros(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

optimizer = optim.SGD([W, b], lr=0.01)

nb_epochs = 1999
for epoch in range(nb_epochs + 1):


    hypothesis = x_train * W + b

    cost = torch.mean((hypothesis - y_train) ** 2)


    optimizer.zero_grad()
    cost.backward()
    optimizer.step()


    if epoch % 100 == 0:
        print('Epoch {:4d}/{} W: {:.3f}, b: {:.3f} Cost: {:.6f}'.format(
            epoch, nb_epochs, W.item(), b.item(), cost.item()
        ))

 

1. x_train, y_train 지정.

2. W,b 0으로 초기화.

3. Optimizer를 SGD로 설정.

4. epochs는 원하는 학습 횟수

5. epochs의 수만큼 for문 돌리기

5-1. 가설식 H(x) 세우기

5-2. loss함수 만들기

5-3. loss함수로 H(x) 업데이트 시켜주기

5-4. 로그 출력하는  if문 써주기

 

 

 

 

nn.Module로 구현하기

 

모듈이 있다면 더 쉽게 구현이 가능하다.

이번에는 다중 선형 회귀 모델을 구현해보자.

 

import torch
import torch.nn as nn
import torch.nn.functional as F

 

필요한 모듈을 import시켜준다.

 

torch.manual_seed(1)

 

다음에 모델을 돌릴 때에도 같은 값이 나오게 하기 위해서 random_seed 설정을 해준다.

 

x_train = torch.FloatTensor([[73, 80, 75],
                             [93, 88, 93],
                             [89, 91, 90],
                             [96, 98, 100],
                             [73, 66, 70]])
y_train = torch.FloatTensor([[152], [185], [180], [196], [142]])

 

데이터셋을 간단하게 만들어 준 후

 

model = nn.Linear(3,1)

 

nn.Linear모델 안에 (3,1) 인자를 넣어준다.

3개의 입력 x에 대해서 1개의 출력 y를 가진다는 뜻이다.

 

optimizer = torch.optim.SGD(model.parameters(), lr=1e-5)

 

optimizer도 SGD로 설정해주면 된다.

 

위 모든 코드를 다 합치면 다음과 같이 된다.

 

nb_epochs = 2000
for epoch in range(nb_epochs+1):


    prediction = model(x_train)
    cost = F.mse_loss(prediction, y_train) 
    
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    if epoch % 100 == 0:
      print('Epoch {:4d}/{} Cost: {:.6f}'.format(
          epoch, nb_epochs, cost.item()
      ))

 

epochs만큼 도는 for문을 만든다.

nn.Module로 만든 model변수안에 x_train을 넣어주어 가설식을 세운다.

F.mse_loss는 파이토치에서 제공하는 MSE 함수이다.

zero_grad()로  gradient를 0 초기화 해준다.

backward()로 그라디언트 계산한다.

step()으로 미분간을 업데이트한다.

if문으로 출력 로그를 만든다.

 

 

 

class로 모델 구현하기

 

파이토치는 대부분 모델 생성을 할 때 class를 사용하고 있다고 한다.

같은 모델인데도 파이토치 코드가 괜히 어렵게 보인다고 느끼는 이유가 있었나보다.

 

model = nn.Linear(1,1)

 

input = 1, output = 1인 Linear모델을 선언했다.

이를 클래스로 구현한다면 아래와 같다.

 

class LinearRegressionModel(nn.Module):
    def __init__(self): 
        super().__init__()
        self.linear = nn.Linear(1, 1) 

    def forward(self, x):
        return self.linear(x)
        
model = LinearRegressionModel()

 

 LinearRegressionModel은 nn.Module을 상속받는다.

__init__()에서는 모델의 구조와 동작을 정의하는 생성자를 정의한다.

super()함수를 부르면 nn.Module 클래스의 속성들을 가지고 초기화 된다.

 LinearRegressionModel()을 model변수에 넣고

model()에 넣으면 자동으로 forward 함수의 연산이 진행된다.

 

위 class의 형식은 파이토치 모델 사용에서 대부분 사용하고 있으므로 외우는 것이 좋겠다.,

 

그럼 본격적으로 학습을 시켜보자.

 

x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2], [4], [6]])

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

 

train데이터를 만들고 optimizer도 SGD로 설정해주었다.

 

nb_epochs = 2000
for epoch in range(nb_epochs+1):

    prediction = model(x_train)
    cost = F.mse_loss(prediction, y_train)
    optimizer.zero_grad()
    cost.backward() 
    optimizer.step()

    if epoch % 100 == 0:
      print('Epoch {:4d}/{} Cost: {:.6f}'.format(
          epoch, nb_epochs, cost.item()
      ))

 

나머지 코드는 위의 for문과 동일하다.

prediction으로 가설식을 만들 때 model()안에 x_train을 넣으면 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

댓글