본문 바로가기

Deep Learning/Fxxkin Easy Pytorch

[Fxxkin Easy Pytorch - 01] - 비선형 회귀를 Pytorch로 돌려보자

반응형

비선형회귀를 Pytorch로 돌려보자 

지난번에는 선형회귀를 Pytorch로 돌려봤으니 이번에는 비선형회귀를 돌려보자. 데이터는 역시 기상청이 운영하는 기상자료개방포털에서 얻어왔다. 

지난번포스팅참조

 

[Fxxkin Easy Pytorch - 00] 기온을 이용한 지면온도 예측

기온 데이터를 통한 지면온도 예측 Linear Regression(선형회귀)를 적용한 간단한 예측 Pytorch에서 linear Regression을 사용해 분석하는 법을 알아보자 분석을 하는 개개인에 따라, 분석 데이터에 따라 다

kd1658.tistory.com

선형회귀랑 전체적인 구조는 비슷하지만 이번에는 시각화를 통해서 어떤 방식으로 찾아가는지도 gif로 만들었다.

나는 원주 ASOS의 2020년 1월 1일 ~ 2020년 12월 31일 습도, 풍속 시간자료를 학습데이터로 사용했다.

 

 

import torch
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
import torch.nn.functional as F

import matplotlib.pyplot as plt

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns

from sklearn import linear_model
from sklearn.model_selection import train_test_split

import glob

비선형회귀에 사용할 패키지들, 지난번과 크게 다르지 않다.

stn_number = "114"

dir_path = "dataset/ASOS/" + stn_number
filename = glob.glob(dir_path + "/*.csv") 

df = pd.read_csv(filename[0], encoding="cp949")

df.columns = ["stn_no","stn_name","date","temperature","RI","WS","humidity"]

df = df.drop(columns=["stn_no","stn_name","date","temperature","RI"])

csv 데이터 불러오고 컬럼명을 영어로 바꾸어주었다. 그리고나서 필요없는 데이터 삭제

print(df.isnull().sum())

# WS          1
# humidity    0
# dtype: int64

결측값이 있는지 확인해보았다.

풍속에서 결측값이 확인되었다. 시계열 데이터가 아니니까 그냥 데이터를 하나 날리기로 하자

 

df = df.dropna()

print(df.isnull().sum())

# WS          0
# humidity    0
# dtype: int64

데이터를 날린 후 잘 날아갔나 다시 확인

 

sns.jointplot(x=df["WS"], y=df["humidity"])

plt.show()

데이터를 그래프로 뿌려서 확인해보자

 

데이터 밀도를 확인해보려고 jointplot으로 뿌려보았다. 풍속이 0인 데이터가 많고 습도는 60~80이 많아보인다.

데이터 모양이 회귀로 뿌려봤자 좋은 데이터가 나올 것 같지는 않지만 그래도 pytorch로 돌려본다는 의의가 있으니 함 해보자

 

# 데이터를 tensor로 변경
X_train = torch.Tensor([[x] for x in list(df.humidity)])
y_train = torch.torch.FloatTensor([[x] for x in list(df.WS)])

# TensorDataset으로 변경
train_data = TensorDataset(X_train, y_train)

# 배치사이즈를 설정하고 Dataloader 세팅
batch_size = len(X_train)
train_dl = DataLoader(train_data, batch_size, shuffle=True)

# 임의의 모델 설정
model = net = torch.nn.Sequential(
        torch.nn.Linear(1, 250),
        torch.nn.LeakyReLU(),
        torch.nn.Linear(250, 125),
        torch.nn.LeakyReLU(),
        torch.nn.Linear(125, 1),
    )
    
# 비용함수 설정 : MSE
loss_fn = torch.nn.MSELoss()

# 활성화함수 설정 : Adam
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

pandas dataframe 형태인 데이터를 tensor로 변환해주고 tensordataset으로 변환한다. 배치사이즈는 데이터 크기로 세팅했다. 나의 titan v는 강력하니까. DataLoader에 데이터를 넣어준다.

임의의 모델을 만들어서 넣었다. 클래스를 만들 수도 있지만 클래스 만들기를 싫어하는 나는 Sequential을 이용해서 순서대로 연결했다.

비용함수는 MSE로 활성화 함수는 Adam으로 정했다.

 

num_epochs = 500

for epoch in range(num_epochs):
    for step, (xb, yb) in enumerate(train_dl):
        pred = model(xb)

        loss = loss_fn(pred, yb)

        optimizer.zero_grad()   
        loss.backward()         
        optimizer.step()
        
    print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))

epoch은 넉넉하게 500으로 잡고 for문을 돌려보았다. 이 구조는 지난번 포스팅과 같은 구조이다. 이렇게 돌리면 epoch마다 loss를 확인해 볼 수 있다.

이번학습은 loss가 0.6537 정도에서 거의 고정되었다. 어썸!

 

이런식으로 시각화 할 수 있다.

이번에는 마지막 모델만 시각화 해보는게 아니라 gif 파일로 학습과정을 시각화 해보았다 이게 꽤 재밌다.

 

 

이런식으로 gif로 만들어보았다. 

터미널에서 loss만 확인하는 것보다는 이렇게 변화하는 과정을 살펴보니 확실히 더 재미있다.

비선형 회귀 또한 사실 scikit-learn으로 돌리는 게 훨씬 빠르고 최적값을 뽑아줄 것이다. 언제나 그렇듯 pytorch를 이용했다는 것에 의의를 두겠다.

 

반응형