๐Ÿ˜Ž ๊ณต๋ถ€ํ•˜๋Š” ์ง•์ง•์•ŒํŒŒ์นด๋Š” ์ฒ˜์Œ์ด์ง€?

TimeSeries DeepLearing [Encoder-Decoder LSTM (=seq2seq)] ๋ณธ๋ฌธ

๐Ÿ‘ฉ‍๐Ÿ’ป ์ธ๊ณต์ง€๋Šฅ (ML & DL)/Serial Data

TimeSeries DeepLearing [Encoder-Decoder LSTM (=seq2seq)]

์ง•์ง•์•ŒํŒŒ์นด 2022. 9. 5. 14:51
728x90
๋ฐ˜์‘ํ˜•

220905 ์ž‘์„ฑ

<๋ณธ ๋ธ”๋กœ๊ทธ๋Š” doheon, codlingual ๋‹˜์˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค :-) >

https://doheon.github.io/%EC%BD%94%EB%93%9C%EA%B5%AC%ED%98%84/time-series/ci-3.lstm-post/#lstm-encoder

 

[์ฝ”๋“œ๊ตฌํ˜„] Time Series Forecasting - LSTM (seq2seq)

Time Series Forecasting ํ”„๋กœ์ ํŠธ

doheon.github.io

https://codlingual.tistory.com/90

 

Intro to Encoder-Decoder LSTM(=seq2seq) ๋ฒˆ์—ญ ๋ฐ ์ •๋ฆฌ

์ถœ์ฒ˜ 1) Encoder-Decoder Long Short-Term Memory Networks 2) A Gentle Introduction to LSTM Autoencoders 3) Step-by-step Understanding LSTM Autoencoder layers Encoder-Decoder LSTM (=seq2seq) - input๋„..

codlingual.tistory.com

 

 

๐Ÿ˜Ž1. Encoder-Decoder LSTM (=seq2seq)

  • ์žฅ๋‹จ๊ธฐ ๊ธฐ์–ต(LSTM) ์‹ ๊ฒฝ๋ง์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋ง
  • ์‹œํ€€์Šค์˜ ๋ฏธ๋ž˜์˜ ์‹œ๊ฐ„ ์Šคํ… ๊ฐ’์„ ์ „๋งํ•˜๊ธฐ ์œ„ํ•ด ์‘๋‹ต ๋ณ€์ˆ˜๊ฐ€ ๊ฐ’์ด ์‹œ๊ฐ„ ์Šคํ… ํ•˜๋‚˜๋งŒํผ ์ด๋™๋œ ํ›ˆ๋ จ ์‹œํ€€์Šค์ธ sequence-to-sequence ํšŒ๊ท€ LSTM ์‹ ๊ฒฝ๋ง์„ ํ›ˆ๋ จ
  • LSTM ์‹ ๊ฒฝ๋ง์€ ์ž…๋ ฅ ์‹œํ€€์Šค์˜ ๊ฐ ์‹œ๊ฐ„ ์Šคํ…๋งˆ๋‹ค ๋‹ค์Œ ์‹œ๊ฐ„ ์Šคํ…์˜ ๊ฐ’์„ ์˜ˆ์ธกํ•˜๋„๋ก ํ•™์Šต

  • input๋„ sequencial ๋ฐ์ดํ„ฐ, output๋„ sequencial ๋ฐ์ดํ„ฐ
  • (๋ฌธ์ œ) input๊ณผ output์˜ sequence ๊ธธ์ด๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ
  • (ํ•ด๊ฒฐ) Encoding : ์—ฌ๋Ÿฌ ๊ธธ์ด์˜ input์„ ๊ณ ์ • ๊ธธ์ด ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ → Decoding : ๊ณ ์ • ๊ธธ์ด ๋ฒกํ„ฐ๋ฅผ ํ•ด๋…ํ•˜์—ฌ ์ถœ๋ ฅ ํ”„๋ฆฐํŠธ
    • Encoder-Decoder LSTM ๋ชจ๋ธ์€ ๋‹ค์–‘ํ•œ ๊ธธ์ด์˜ ์‹œ๊ณ„์—ด ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„, ๋‹ค์–‘ํ•œ ๊ธธ์ด์˜ ์‹œ๊ณ„์—ด ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ
    • LSTM Autoencoder๋Š” ๋‹ค์–‘ํ•œ ๊ธธ์ด์˜ ์‹œ๊ณ„์—ด input ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ ์ • ๊ธธ์ด ๋ฒกํ„ฐ๋กœ ์••์ถ•ํ•ด Decoder์— ์ž…๋ ฅ์œผ๋กœ ์ „๋‹ฌํ•ด์คŒ
    • ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ encoded feature vector๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด ์žˆ์Œ

  • Teacher Forcing
    • ๋‹ค์Œ ๋ฌธ์žฅ์˜ input์œผ๋กœ ์ด์ „ ๊ฐ’์˜ output์ด ์•„๋‹Œ ์›๋ž˜ target ๊ฐ’์ด input์œผ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š” ๊ฒƒ
      • ์žฅ์ 
        • ํ•™์Šต ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ๋Š” ๋ชจ๋ธ์˜ ์˜ˆ์ธก ์„ฑ๋Šฅ์ด ๋‚˜์˜๋‹ค
        • Teacher Forcing์„ ์ด์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ž˜๋ชป๋œ ์˜ˆ์ธก ๊ฐ’์„ ํ† ๋Œ€๋กœ Hidden State ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋˜๊ณ , ์ด ๋•Œ๋ฌธ์— ๋ชจ๋ธ์˜ ํ•™์Šต ์†๋„๋Š” ๋”๋ŽŒ์ง€๊ฒŒ ๋จ
        • ํ•™์Šต์ด ๋น ๋ฅด๋‹ค
      • ๋‹จ์ 
        • ์ถ”๋ก  (Inference) ๊ณผ์ •์—์„œ๋Š” Ground Truth๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋‹ค
        • ๋ชจ๋ธ์€ ์ „ ๋‹จ๊ณ„์˜ ์ž๊ธฐ ์ž์‹ ์˜ ์ถœ๋ ฅ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜ˆ์ธก์„ ์ด์–ด๊ฐ€์•ผํ•จ
        • ๋…ธ์ถœ ํŽธํ–ฅ ๋ฌธ์ œ (Exposure Bias Problem)

 

 

 

๐Ÿ˜Ž2. ์ฝ”๋“œ๊ตฌํ˜„

  • ํ•œ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์œผ๋กœ ์ธก์ • ๋˜์–ด ์žˆ๋Š” ํ•œ ๋‹ฌ์น˜ ํŠน์ • ๊ตฌ๊ฐ„์˜ ํ‰๊ท  ์†๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋งˆ์ง€๋ง‰ ์ผ์ฃผ์ผ ๊ฐ„์˜ ํ‰๊ท  ์†๋„๋ฅผ ์˜ˆ์ธก

1๏ธโƒฃ Load Data

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt

from tqdm import trange     #  ์ž‘์—…์ง„ํ–‰๋ฅ  ํ‘œ์‹œ
import random
data = pd.read_csv("์„œ์ธ์ฒœIC-๋ถ€ํ‰IC ํ‰๊ท ์†๋„.csv", encoding='CP949')
plt.figure(figsize=(20,5))
plt.plot(range(len(data)), data["ํ‰๊ท ์†๋„"])
data.head()         # ๋…„, ์›”, ์ผ, ์‹œ ๊ฐ€ ์žˆ๋Š” column๊ณผ ํ‰๊ท ์†๋„์˜ ๊ฐ’์ด ์žˆ๋Š” column

 

2๏ธโƒฃ Data Preprocessing

data = data.drop(columns='Unnamed: 0')
data

from sklearn.preprocessing import MinMaxScaler

# sklearn์˜ MinMaxScaler๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์˜ ๋ฒ”์œ„๋ฅผ 0~1๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.
min_max_scaler = MinMaxScaler()             

# ์Šค์ผ€์ผ์„ ์กฐ์ •ํ•˜๋Š” ์ •๊ทœํ™” ํ•จ์ˆ˜
data["ํ‰๊ท ์†๋„"] = min_max_scaler.fit_transform(data["ํ‰๊ท ์†๋„"].to_numpy().reshape(-1,1))
  • ๋งˆ์ง€๋ง‰ ์ผ์ฃผ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ˆ์ธกํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์ด๋ฏ€๋กœ train, test set์„ ๋งˆ์ง€๋ง‰ ์ผ์ฃผ์ผ์„ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋ˆ ์คŒ
train = data[:-24*7]
train = train["ํ‰๊ท ์†๋„"].to_numpy()

test = data[-24*7:]
test = test["ํ‰๊ท ์†๋„"].to_numpy()

train

 

3๏ธโƒฃ Sliding Window Dataset

  • ํ•™์Šต์„ ์œ„ํ•ด์„œ๋Š” ์ธํ’‹ ๋ฐ์ดํ„ฐ์™€ ์•„์›ƒํ’‹ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”
  • ์‹œ๊ณ„์—ด ์˜ˆ์ธก์„ ์œ„ํ•ด ๋ฐ์ดํ„ฐ์˜ ์ผ์ •ํ•œ ๊ธธ์ด์˜ input window, output window๋ฅผ ์„ค์ •ํ•˜๊ณ , ๋ฐ์ดํ„ฐ์˜ ์ฒ˜์Œ ๋ถ€๋ถ„๋ถ€ํ„ฐ ๋๋ถ€๋ถ„๊นŒ์ง€ sliding ์‹œ์ผœ์„œ ๋ฐ์ดํ„ฐ์…‹์„ ์ƒ์„ฑ
    • input window, output window, stride๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ  iw+ow๋งŒํผ์˜ ๊ธธ์ด๋ฅผ stride๊ฐ„๊ฒฉ์œผ๋กœ slidingํ•˜๋ฉด์„œ ๋ฐ์ดํ„ฐ์…‹์„ ์ƒ์„ฑ
    • ๊ฒฐ๊ณผ์˜ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์œผ๋กœ๋Š” input, ๋‘ ๋ฒˆ์งธ ๊ฐ’์œผ๋กœ๋Š” output์ด ์ถœ๋ ฅ๋˜๋„๋ก ์„ ์–ธ
# torch์˜ Dataset ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ window dataset์„ ์ƒ์„ฑํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์„ ์–ธ
from torch.utils.data import DataLoader, Dataset

class windowDataset(Dataset):           # Sliding ํ•จ์ˆ˜
    
    def __init__(self, y, input_window, output_window, stride=1):
        #์ด ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜
        L = y.shape[0]
        #stride์”ฉ ์›€์ง์ผ ๋•Œ ์ƒ๊ธฐ๋Š” ์ด sample์˜ ๊ฐœ์ˆ˜
        num_samples = (L - input_window - output_window) // stride + 1

        #input๊ณผ output : shape = (window ํฌ๊ธฐ, sample ๊ฐœ์ˆ˜)
        X = np.zeros([input_window, num_samples])
        Y = np.zeros([output_window, num_samples])

        for i in np.arange(num_samples):
            start_x = stride*i
            end_x = start_x + input_window
            X[:,i] = y[start_x:end_x]

            start_y = stride*i + input_window
            end_y = start_y + output_window
            Y[:,i] = y[start_y:end_y]

        X = X.reshape(X.shape[0], X.shape[1], 1).transpose((1,0,2))
        Y = Y.reshape(Y.shape[0], Y.shape[1], 1).transpose((1,0,2))
        self.x = X
        self.y = Y
        
        self.len = len(X)
    def __getitem__(self, i):
        return self.x[i], self.y[i]
    def __len__(self):
        return self.len
  • ์ผ์ฃผ์ผ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ˆ์ธกํ•ด์•ผ ํ•˜๋ฏ€๋กœ output window์˜ ํฌ๊ธฐ๋Š” 24*7๋กœ ์„ค์ •ํ–ˆ๊ณ  input window์˜ ํฌ๊ธฐ๋Š” ๊ทธ ๋‘๋ฐฐ๋กœ ์„ค์ •
  • dataset์„ ์ด์šฉํ•˜์—ฌ torch ์˜ DataLoader๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐฐ์น˜ ํ•™์Šต์„ ์ง„ํ–‰
๋”๋ณด๊ธฐ
from torch.utils.data import DataLoader

dataloader = DataLoader(
            dataset, # ์œ„์—์„œ ์ƒ์„ฑํ•œ ๋ฐ์ดํ„ฐ ์…‹
            batch_size = 32, # 1ํšŒ ๋‹น 32๊ฐœ์˜ ๋ฐ์ดํ„ฐ์”ฉ ๋ถ„ํ• 
            shuffle = True # ๋ฐ์ดํ„ฐ๋“ค์˜ ์ˆœ์„œ๋Š” ์„ž์–ด์„œ ๋ถ„ํ• 
) 
iw = 24*14
ow = 24*7

train_dataset = windowDataset(train, input_window=iw, output_window=ow, stride=1)

# ๋ชจ๋ธ ํ•™์Šต ๊ณผ์ • ์‹œ ๊ฐ step ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ batch size ํฌ๊ธฐ๋กœ ๋ถ„ํ• 
train_loader = DataLoader(train_dataset, batch_size=64)

 

 

4๏ธโƒฃ 4. Modeling

  • torch์˜ nn.Module์„ ์ด์šฉํ•˜์—ฌ encoder, decoder ๋ชจ๋ธ์„ ๋งŒ๋“ค๊ณ  ์ด ๋‘˜์„ ํ•ฉ์ณ์„œ encoder decoder ๋ชจ๋ธ
  • encoder : input์„ ํ†ตํ•ด decoder์— ์ „๋‹ฌํ•  hidden state ์ƒ์„ฑ
  • decoder : intput์˜ ๋งˆ์ง€๋ง‰ ๊ฐ’๊ณผ encoder์—์„œ ๋ฐ›์€ hidden state๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•œ ๊ฐœ์˜ ๊ฐ’์„ ์˜ˆ์ธก
  • encoder decoder : ์œ„์˜ ๋‘ ๋ชจ๋ธ์„ ํ•ฉ์ณ์คŒ
    • ์›ํ•˜๋Š” ๊ธธ์ด์˜ ์•„์›ƒํ’‹์ด ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ decoder๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์‹คํ–‰์‹œ์ผœ์„œ ์ตœ์ข… output์„ ์ƒ์„ฑ
    • ์›ํ™œํ•œ ํ•™์Šต์„ ์œ„ํ•ด ๋””์ฝ”๋”์˜ ์ธํ’‹์œผ๋กœ ์‹ค์ œ ๊ฐ’์„ ๋„ฃ๋Š” teach forcing์„ ๊ตฌํ˜„

 

โ–ถ lstm encoder
  • input ์œผ๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ์„ ๋ฐ›๊ณ  lstm์„ ์ด์šฉํ•˜์—ฌ ๋””์ฝ”๋”์— ์ „๋‹ฌํ•  hidden state๋ฅผ ์ƒ์„ฑ
# ๋ชจ๋“  ๋‰ด๋Ÿด ๋„คํŠธ์›Œํฌ ๋ชจ๋“ˆ์˜ ๊ธฐ๋ณธ ํด๋ž˜์Šค
import torch.nn as nn       

class lstm_encoder(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers = 1):
        super(lstm_encoder, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.lstm = nn.LSTM(input_size = input_size, hidden_size = hidden_size, num_layers = num_layers, batch_first=True)

    def forward(self, x_input):
        lstm_out, self.hidden = self.lstm(x_input)
        return lstm_out, self.hidden

โ–ถ lstm decoder

  • sequence์˜ ์ด์ „๊ฐ’ ํ•˜๋‚˜์™€, ์ด์ „ ๊ฒฐ๊ณผ์˜ hidden state๋ฅผ ์ž…๋ ฅ ๋ฐ›์•„์„œ ๋‹ค์Œ ๊ฐ’ ํ•˜๋‚˜๋ฅผ ์˜ˆ์ธก
    • ๋งˆ์ง€๋ง‰์— fc layer๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ input size์™€ ๋™์ผํ•˜๊ฒŒ ํฌ๊ธฐ๋ฅผ ๋งž์ถฐ์คŒ
class lstm_decoder(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers = 1):
        super(lstm_decoder, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.lstm = nn.LSTM(input_size = input_size, hidden_size = hidden_size,num_layers = num_layers, batch_first=True)
        self.linear = nn.Linear(hidden_size, input_size)           

    def forward(self, x_input, encoder_hidden_states):
        lstm_out, self.hidden = self.lstm(x_input.unsqueeze(-1), encoder_hidden_states)
        output = self.linear(lstm_out)
        
        return output, self.hidden

โ–ถ encoder decoder

  • ์œ„ ๋‘ ๋ชจ๋ธ์„ ํ•ฉ์น˜๊ธฐ
  • ์ธ์ฝ”๋”๋ฅผ ํ•œ๋ฒˆ ์‹คํ–‰์‹œํ‚ค๊ณ  ์ธ์ฝ”๋”์—์„œ ์ „๋‹ฌ๋ฐ›์€ hidden state์™€ input์˜ ๋งˆ์ง€๋ง‰๊ฐ’์„ decoder์— ์ „๋‹ฌํ•ด์„œ ๋‹ค์Œ ์˜ˆ์ธก๊ฐ’์„ ๊ตฌํ•จ
    • ์—ฌ๊ธฐ์„œ ๋‚˜์˜จ ๊ฐ’๊ณผ hidden state๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ์›ํ•˜๋Š” ๊ธธ์ด๊ฐ€ ๋ ๋•Œ ๊นŒ์ง€ decoder๋ฅผ ์‹คํ–‰
  • decoder์˜ ์ธํ’‹์œผ๋กœ ์ด์ „ ์˜ˆ์ธก๊ฐ’์ด ์•„๋‹Œ ์‹ค์ œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” teacher forcing๋„ ๊ตฌํ˜„
    • Teacher Forcing : ๋‹ค์Œ ๋ฌธ์žฅ์˜ input์œผ๋กœ ์ด์ „ ๊ฐ’์˜ output์ด ์•„๋‹Œ ์›๋ž˜ target ๊ฐ’์ด input์œผ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š” ๊ฒƒ
class lstm_encoder_decoder(nn.Module):
    def __init__(self, input_size, hidden_size):
        super(lstm_encoder_decoder, self).__init__()

        self.input_size = input_size
        self.hidden_size = hidden_size

        self.encoder = lstm_encoder(input_size = input_size, hidden_size = hidden_size)
        self.decoder = lstm_decoder(input_size = input_size, hidden_size = hidden_size)

    def forward(self, inputs, targets, target_len, teacher_forcing_ratio):
        batch_size = inputs.shape[0]
        input_size = inputs.shape[2]

        outputs = torch.zeros(batch_size, target_len, input_size)

        _, hidden = self.encoder(inputs)
        decoder_input = inputs[:,-1, :]
        
        #์›ํ•˜๋Š” ๊ธธ์ด๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ decoder๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
        for t in range(target_len): 
            out, hidden = self.decoder(decoder_input, hidden)
            out =  out.squeeze(1)           # squeezeํ•จ์ˆ˜๋Š” ์ฐจ์›์ด 1์ธ ์ฐจ์›์„ ์ œ๊ฑฐ
            
            # teacher forcing์„ ๊ตฌํ˜„ํ•œ๋‹ค.
            # teacher forcing์— ํ•ด๋‹นํ•˜๋ฉด ๋‹ค์Œ ์ธํ’‹๊ฐ’์œผ๋กœ๋Š” ์˜ˆ์ธกํ•œ ๊ฐ’์ด ์•„๋‹ˆ๋ผ ์‹ค์ œ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค.
            if random.random() < teacher_forcing_ratio:
                decoder_input = targets[:, t, :]
            else:
                decoder_input = out
            outputs[:,t,:] = out

        return outputs
	
    # ํŽธ์˜์„ฑ์„ ์œ„ํ•ด ์˜ˆ์ธกํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋„ ์ƒ์„ฑํ•œ๋‹ค.
    def predict(self, inputs, target_len):
        self.eval()
        inputs = inputs.unsqueeze(0)        # unsqueezeํ•จ์ˆ˜๋Š” 1์ธ ์ฐจ์›์„ ์ƒ์„ฑ
        batch_size = inputs.shape[0]
        input_size = inputs.shape[2]
        outputs = torch.zeros(batch_size, target_len, input_size)
        _, hidden = self.encoder(inputs)
        decoder_input = inputs[:,-1, :]
        for t in range(target_len): 
            out, hidden = self.decoder(decoder_input, hidden)
            out =  out.squeeze(1)
            decoder_input = out
            outputs[:,t,:] = out
        return outputs.detach().numpy()[0,:,0]

 

 

5๏ธโƒฃ Train

  • ์ƒ์„ฑํ•œ ๋ชจ๋ธ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ›ˆ๋ จ ์‹œ์ž‘
import torch
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = lstm_encoder_decoder(input_size=1, hidden_size=16).to(device)

 

  • ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ
    • ์—ํญ(epoch) ์ˆ˜ : ๋ฐ์ดํ„ฐ์…‹์„ ๋ฐ˜๋ณตํ•˜๋Š” ํšŸ์ˆ˜
    • ๋ฐฐ์น˜ ํฌ๊ธฐ(batch size) : ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๊ฐฑ์‹ ๋˜๊ธฐ ์ „ ์‹ ๊ฒฝ๋ง์„ ํ†ตํ•ด ์ „ํŒŒ๋œ ๋ฐ์ดํ„ฐ ์ƒ˜ํ”Œ์˜ ์ˆ˜
    • ํ•™์Šต๋ฅ (learning rate) : ๊ฐ ๋ฐฐ์น˜/์—ํญ์—์„œ ๋ชจ๋ธ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์กฐ์ ˆํ•˜๋Š” ๋น„์œจ
      • ๊ฐ’์ด ์ž‘์„์ˆ˜๋ก ํ•™์Šต ์†๋„๊ฐ€ ๋Š๋ ค์ง
      • ๊ฐ’์ด ํฌ๋ฉด ํ•™์Šต ์ค‘ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ
# ๋‹ค์–‘ํ•œ ์ตœ์ ํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•˜๋Š” ํŒจํ‚ค์ง€
import torch.optim as optim

learning_rate=0.01
epoch = 3000
optimizer = optim.Adam(model.parameters(), lr = learning_rate)
criterion = nn.MSELoss()
from tqdm import tqdm

model.train()
with tqdm(range(epoch)) as tr:
    for i in tr:
        total_loss = 0.0
        for x,y in train_loader:
            optimizer.zero_grad()
            x = x.to(device).float()
            y = y.to(device).float()
            output = model(x, y, ow, 0.6).to(device)
            loss = criterion(output, y)
            loss.backward()
            optimizer.step()
            total_loss += loss.cpu().item()
        tr.set_postfix(loss="{0:.5f}".format(total_loss/len(train_loader)))

12๋ถ„ 49์ดˆ ๊ฑธ๋ ธ๋‹ค...

 

 

 

6๏ธโƒฃ Evaluate

  • ํ•™์Šต๋œ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์„œ ํ›ˆ๋ จ์ง‘ํ•ฉ์—๋Š” ํฌํ•จ๋˜์ง€ ์•Š์•˜๋˜ ๋งˆ์ง€๋ง‰ ์ผ์ฃผ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ˆ์ธก
predict = model.predict(torch.tensor(train[-24*7*2:]).reshape(-1,1).to(device).float(), target_len=ow)
real = data["ํ‰๊ท ์†๋„"].to_numpy()

# inverse_transform ์ด์šฉํ•˜๋ฉด ์ด๋ฆ„์œผ๋กœ ๋ณ€ํ™˜, transform ์ด์šฉํ•˜๋ฉด ์ˆซ์ž๋กœ ๋ณ€ํ™˜
predict = min_max_scaler.inverse_transform(predict.reshape(-1,1))       
real = min_max_scaler.inverse_transform(real.reshape(-1,1))
plt.figure(figsize=(20,5))
plt.plot(range(400,744), real[400:], label="real")
plt.plot(range(744-24*7,744), predict[-24*7:], label="predict")

plt.title("Test Set")
plt.legend()
plt.show()

๋งˆ์ง€๋ง‰ ์ผ์ฃผ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ˆ์ธก ํ•ด๋ดค๋Š”๋ฐ.. ์–ผ์ถ” ๋น„์Šท..ํ•œ๊ฐ€..? 

 

  • MAPE(mean absolute percentage error)
    • ๊ฒฐ์ธก ๊ตฌ๊ฐ„์˜ MAPE๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ์ •ํ™•ํžˆ ์–ด๋Š์ •๋„ ์ˆ˜์น˜๋กœ ์ •ํ™•ํ•œ์ง€ ๊ณ„์‚ฐ
    • MAPE๊ฐ’๋„ ๊ฒฐ์ธก์น˜์˜ ๊ธธ์ด์— ์ƒ๊ด€์—†์ด ๋Œ€๋ถ€๋ถ„ ์ข‹์€ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
    • ํผ์„ผํŠธ ๊ฐ’์„ ๊ฐ€์ง€๋ฉฐ 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ํšŒ๊ท€ ๋ชจํ˜•์˜ ์„ฑ๋Šฅ์ด ์ข‹๋‹ค๊ณ  ํ•ด์„ํ•  ์ˆ˜ ์žˆ์Œ
    • 0~100% ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ€์ ธ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šฐ๋ฏ€๋กœ ์„ฑ๋Šฅ ๋น„๊ต ํ•ด์„์ด ๊ฐ€๋Šฅ
def MAPEval(y_pred, y_true):
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
MAPEval(predict[-24*7:],real[-24*7:])

 

๊ต‰์žฅํžˆ.. ๋†’๋‹ค.. ์ „ํ˜€ ์ข‹์ง€ ์•Š๋‹ค...

ํ•˜์ดํผ ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐ์ ˆํ•ด์„œ ๋‹ค์‹œ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค..


learning_rate = 0.001
epoch = 3000
์—์„œ๋Š” 8.40561601931441 ๋‚˜์™”์Šค๋‹ˆ๋‹น
 
728x90
๋ฐ˜์‘ํ˜•
Comments