이것저것 기록

[DL, PyTorch] 클래스로 선형회귀 (linear regression) 구현하기 본문

Data Science/ML & DL

[DL, PyTorch] 클래스로 선형회귀 (linear regression) 구현하기

anweh 2020. 10. 14. 14:54

선형회귀는 지도학습 중 예측 문제에 사용하는 알고리즘 중 하나다.

기존 데이터를 기반으로 생성된 모델 (회귀 모델)을 이용하여 새로운 데이터가 들어왔을 때 어떤 값이 될 지 예측하는 문제이다. 

선형회귀 분석은 주어진 데이터를 대표하는 하나의 '직선'을 찾는 것이다. 

이 직선을 '회귀선'이라고 부르고 이 선을 함수로 표현한 것이 '회귀식'이다.

단순선형회귀 분석은 중학교 때 배웠던 1차함수의 그래프 모양이다.

 

 

y= ax+b라는 회귀식이 있을 때 x의 개수가 1개이므로 단순선형회귀 분석이 되는 거고, 

input으로 사용될 설명 변수는 1개가 된다는 말이다. 

 

 

 

 

 

 


1. 선형회귀 분석을 한다는 것은

y = ax + b라는 식에서 a와 b를 구하는 과정을 뜻한다. 

머신러닝의 관점에서 a는 weight값이 되고, b는 bias가 된다. 

선형 회귀식을 예측하기 위해선 우리가 만든 모델인 y = ax + b 직선과 실제 데이터를 찍어놓은 점들의 y값 차이 (error)를 구하고, 이를 좁혀 나가는 방식으로 모델을 학습시킨다. 

나는 단순히 error로 학습시키지 않고, MSE를 사용하였다. (실제 데이터의 y값과 y-pred값의 차이를 제곱해서 넓이로 학습)

 

 

2. Class, DataLoader, Dataset으로 구현한 이유

사실 단순선형회귀는 Class, DataLoader, Dataset 같은 도구를 쓰지 않아도 충분히 구현이 가능한 심플한 모델에 속한다. 

그럼에도 이들을 사용하여 모델을 구현한 이유는 그냥 내가 이것들을 실전에 한 번 적용해보고 싶었다.

간단한 문제에 적용하여 익숙해진 뒤 복잡한 모델에도 사용하기 용이하도록! 

 

 

3. 구현

3.1 사용한 라이브러리

import torch 
import numpy as np
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from torch.autograd import Variable
import pandas as pd

3.2 Data Load

# Dataset
class MyDataset(Dataset):
 
    # Initialize your data, download, etc.
    def __init__(self, file_path):
    	# download, read data
        data = pd.read_csv(file_path)
        
        self.y_data = torch.from_numpy(data['y'].values).unsqueeze(dim=1).float()
        self.x_data = torch.from_numpy(data['x'].values).unsqueeze(dim=1).float()
        
    def __len__(self):
        # return the data length
        return len(self.x_data)
    

    def __getitem__(self, idx):
        # return one item on the index
        x = self.x_data[idx]
        y = self.y_data[idx]
        return x, y

단순선형회귀 분석을 위한 데이터셋은 다음 링크의 train.csv 파일을 사용했다. 

3.3 클래스로 모델 설계

# Model
class LinearRegressionModel(nn.Module): # torch.nn.Module을 상속받는 파이썬 클래스
    def __init__(self): #
        super().__init__()
        self.linear = nn.Linear(1, 1) # 단순선형회귀이므로 input_dim=1, output_dim=1.

    def forward(self, x):
        return self.linear(x)

굳이 클래스로 설계하지 않아도 간단히 nn.Module을 이용해 단순선형회귀를 구현할 수 있다. 

이렇게 설계하는 방법은 다음 링크를 참고!

3.4 학습 

def main(): 
    
    # Hyperparameters 
    batch_size = 1
    lr = 0.00001
    epochs = 500
    num_workers = 0
    dataset = MyDataset('C:/Users/user/Desktop/train.csv')
    train_loader = DataLoader(dataset = dataset,
                              batch_size = batch_size,
                              shuffle = True,
                              num_workers = num_workers)
    model = LinearRegressionModel()
    optimizer = torch.optim.SGD(model.parameters(), lr = lr)
    criterion = nn.MSELoss()
    

    for epoch in range(epochs):
     
        for i, data in enumerate(train_loader): 
            
            # get data
            x, y = data 
            x, y = Variable(x), Variable(y)
            
            # forward pass
            y_pred = model(x)
            
            # compute loss
            loss = criterion(y_pred, y)
            
            if epoch % 10 == 0:
            # 100번마다 로그 출력
              print('Epoch: {:4d}/{}    loss: {:.6f}'.format(
                  epoch, epochs, loss.item()
              ))

            # Zero gradients, perform a backward pass, and update the weights.
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()


# =====================================================================================================================================================

if __name__ == '__main__': 
    main()
    

 

 

4. 결과

에폭을 500까지 갔는데도 로스가 일정하게 떨어지지 않았다.

그러나 로스를 줄이는 것이 목적이 아니라, 그저 클래스, 데이터 로더등을 활용해 구현하는 것이 목적이었기 때문에 추가적인 파라미터 튜닝은 하지 않았다. 

 

 

Comments