LSTM(+GRU)์ ์ด์ฉํ ์ผ์ฑ์ ์(+NAVER) ์ฃผ๊ฐ ์์ธกํ๊ธฐ
220922 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋ coding-yoon ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค :-) >
https://coding-yoon.tistory.com/131
[Pytorch] LSTM์ ์ด์ฉํ ์ผ์ฑ์ ์ ์ฃผ๊ฐ ์์ธกํ๊ธฐ
์๋ ํ์ธ์. ์ค๋์ LSTM์ ์ด์ฉํด์ ์ผ์ฑ์ ์ ์ฃผ๊ฐ๋ฅผ ์์ธกํด๋ณด๊ฒ ์ต๋๋ค. ํฐ Dataset์ ๋ฐ๋ก ํ์ํ์ง ์์ผ๋ ๋ถ๋ด ๊ฐ์ง ์๊ณ ํ์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์๋๋ ๋ณธ๋ฌธ ๊ธ์ ๋๋ค. cnvrg.io/pytorch-lstm/?gclid=C
coding-yoon.tistory.com
1๏ธโฃ library load
- pandas_datareader
- Yahoo Finance์์ ์ฆ์ ์๋ฃ๋ฅผ ๋ฐ์์ฌ ์ ์
- ์น ์์ ๋ฐ์ดํฐ๋ฅผ DataFrame ๊ฐ์ฒด๋ก ๋ง๋๋ ๊ธฐ๋ฅ์ ์ ๊ณต
import numpy as np
import pandas as pd
import pandas_datareader.data as pdr
import matplotlib.pyplot as plt
import datetime
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
2๏ธโฃ ์ผ์ฑ ์ ์ ์ฃผ์ ๋ถ๋ฌ์ค๊ธฐ
- ์ผ์ฑ์ ์์ ์ข ๋ชฉ์ฝ๋๋ 005930
start = (2000, 1, 1) # 2020๋
01๋
01์
start = datetime.datetime(*start)
end = datetime.date.today() # ํ์ฌ
# yahoo ์์ ์ผ์ฑ ์ ์ ๋ถ๋ฌ์ค๊ธฐ
df = pdr.DataReader('005930.KS', 'yahoo', start, end)
df.Close.plot(grid=True)
3๏ธโฃ ๋ชจ๋ธ ์ฑ๋ฅ ํ์ตํ๊ธฐ์ํด ๋ฐ์ดํฐ ๋ถ๋ฅํ๊ธฐ
- open ์๊ฐ
- high ๊ณ ๊ฐ
- low ์ ๊ฐ
- close ์ข ๊ฐ
- volume ๊ฑฐ๋๋ (ํ์ ์์ด์ DROP)
- Adj Close ์ฃผ์์ ๋ถํ , ๋ฐฐ๋น, ๋ฐฐ๋ถ ๋ฑ์ ๊ณ ๋ คํด ์กฐ์ ํ ์ข ๊ฐ (์์ธกํ๊ณ ์ ํ๋ TARGET)
X = df.drop(columns='Volume')
y = df.iloc[:, 5:6]
print(X)
print(y)
4๏ธโฃ ํ์ต์ด ์๋๊ธฐ ์ํด ๋ฐ์ดํฐ ์ ๊ทํ ๋ฐ split
- StandardScaler : ๊ฐ ํน์ง์ ํ๊ท ์ 0, ๋ถ์ฐ์ 1์ด ๋๋๋ก ๋ณ๊ฒฝ
- MinMaxScaler : ์ต๋/์ต์๊ฐ์ด ๊ฐ๊ฐ 1, 0์ด ๋๋๋ก ๋ณ๊ฒฝ
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.model_selection import train_test_split
mm = MinMaxScaler()
ss = StandardScaler()
X_ss = ss.fit_transform(X)
y_mm = mm.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X_ss, y_mm, test_size=0.2, shuffle=True, random_state=34)
print("Training Shape", X_train.shape, y_train.shape)
print("Testing Shape", X_test.shape, y_test.shape)
- ํ์ตํ ์ ์๋ ํํ๋ก ๋ณํํ๊ธฐ ์ํด Torch๋ก ๋ณํ
- Torch์ Variable
- data : a์ tensor ํํ์ ๋ฐ์ดํฐ๊ฐ ๋ด๊น
- grad : data๊ฐ ๊ฑฐ์ณ์จ layer์ ๋ํ ๋ฏธ๋ถ๊ฐ์ด ์ถ์
- grad_fn : ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํ ํจ์์ ๋ํ ์ ๋ณด
- Torch์ Variable
X_train_tensors = Variable(torch.Tensor(X_train))
X_test_tensors = Variable(torch.Tensor(X_test))
y_train_tensors = Variable(torch.Tensor(y_train))
y_test_tensors = Variable(torch.Tensor(y_test))
X_train_tensors_final = torch.reshape(X_train_tensors, (X_train_tensors.shape[0], 1, X_train_tensors.shape[1]))
X_test_tensors_final = torch.reshape(X_test_tensors, (X_test_tensors.shape[0], 1, X_test_tensors.shape[1]))
print("Training Shape", X_train_tensors_final.shape, y_train_tensors.shape)
print("Testing Shape", X_test_tensors_final.shape, y_test_tensors.shape)
5๏ธโฃ LSTM ๋คํธ์ํฌ
- RNN (default)
- RNN์ ์ ๋ ฅ : [sequence, batch_size, input_size]
- nn.RNN : ๊ธฐ๋ณธ ์ธ์ ๊ฐ์ผ๋ก input_size, hidden_size (nn.RNN์ ๊ฑธ์น๋ฉด ๋์ค๋ Output), num_layer (์ธต)
- output
- output[-1] : [sequence, batch_size, hidden_size] ์์ Sequence์ ๊ฐ์ฅ ๋
- hidden[-1] : [num_layer, batch_size, hidden_size] ์์ num_layer์ ๊ฐ์ฅ ๋
- output
- GPU ์์ด์ CPU
device = torch.device('cpu')
class LSTM1(nn.Module):
def __init__(self, num_classes, input_size, hidden_size, num_layers, seq_length):
super(LSTM1, self).__init__()
self.num_classes = num_classes #number of classes
self.num_layers = num_layers #number of layers
self.input_size = input_size #input size
self.hidden_size = hidden_size #hidden state
self.seq_length = seq_length #sequence length
self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size,
num_layers=num_layers, batch_first=True) #lstm
self.fc_1 = nn.Linear(hidden_size, 128) #fully connected 1
self.fc = nn.Linear(128, num_classes) #fully connected last layer
self.relu = nn.ReLU()
def forward(self,x):
h_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)).to(device) #hidden state
c_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)).to(device) #internal state
# Propagate input through LSTM
output, (hn, cn) = self.lstm(x, (h_0, c_0)) #lstm with input, hidden, and internal state
hn = hn.view(-1, self.hidden_size) #reshaping the data for Dense layer next
out = self.relu(hn)
out = self.fc_1(out) #first Dense
out = self.relu(out) #relu
out = self.fc(out) #Final Output
return out
- ๋คํธ์ํฌ ํ๋ผ๋ฏธํฐ ๊ตฌ์ฑ
num_epochs = 30000 #1000 epochs
learning_rate = 0.00001 #0.001 lr
input_size = 5 #number of features
hidden_size = 2 #number of features in hidden state
num_layers = 1 #number of stacked lstm layers
num_classes = 1 #number of output classes
lstm1 = LSTM1(num_classes, input_size, hidden_size, num_layers, X_train_tensors_final.shape[1]).to(device)
loss_function = torch.nn.MSELoss() # mean-squared error for regression
optimizer = torch.optim.Adam(lstm1.parameters(), lr=learning_rate) # adam optimizer
6๏ธโฃ ํ์ต
for epoch in range(num_epochs):
outputs = lstm1.forward(X_train_tensors_final.to(device)) # forward pass
optimizer.zero_grad() # caluclate the gradient, manually setting to 0
# obtain the loss function
loss = loss_function(outputs, y_train_tensors.to(device))
loss.backward() #calculates the loss of the loss function
optimizer.step() #improve from loss, i.e backprop
if epoch % 100 == 0:
print("Epoch: %d, loss: %1.5f" % (epoch, loss.item()))
num_epochs = 10000 #1000 epochs ์ผ๋ก ํ๋ฉด
7๏ธโฃ ์์ธก
- ์ ์ฒ๋ผ ๋ณํ~
df_X_ss = ss.transform(df.drop(columns='Volume'))
df_y_mm = mm.transform(df.iloc[:, 5:6])
df_X_ss = Variable(torch.Tensor(df_X_ss)) #converting to Tensors
df_y_mm = Variable(torch.Tensor(df_y_mm))
#reshaping the dataset
df_X_ss = torch.reshape(df_X_ss, (df_X_ss.shape[0], 1, df_X_ss.shape[1]))
- ๋นจ๊ฐ ์ ์ดํ๊ฐ ์์ธกํ ๊ฒ...
train_predict = lstm1(df_X_ss.to(device))#forward pass
data_predict = train_predict.data.detach().cpu().numpy() #numpy conversion
dataY_plot = df_y_mm.data.numpy()
data_predict = mm.inverse_transform(data_predict) #reverse transformation
dataY_plot = mm.inverse_transform(dataY_plot)
plt.figure(figsize=(10,6)) #plotting
plt.axvline(x=4563, c='r', linestyle='--') #size of the training set
plt.plot(dataY_plot, label='Actuall Data') #actual plot
plt.plot(data_predict, label='Predicted Data') #predicted plot
plt.title('Time-Series Prediction')
plt.legend()
plt.show()
+ GRU Model
class GRU(nn.Module) :
def __init__(self, num_classes, input_size, hidden_size, num_layers, seq_length) :
super(GRU, self).__init__()
self.num_classes = num_classes
self.num_layers = num_layers
self.input_size = input_size
self.hidden_size = hidden_size
self.seq_length = seq_length
self.gru = nn.GRU(input_size=input_size,hidden_size=hidden_size,
num_layers=num_layers,batch_first=True)
self.fc_1 = nn.Linear(hidden_size, 128)
self.fc = nn.Linear(128, num_classes)
self.relu = nn.ReLU()
def forward(self, x) :
h_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))
output, (hn) = self.gru(x, (h_0))
hn = hn.view(-1, self.hidden_size)
out = self.relu(hn)
out = self.fc_1(out)
out = self.relu(out)
out = self.fc(out)
return out
num_epochs = 1000
learning_rate = 0.0001
input_size=5
hidden_size=2
num_layers=1
num_classes=1
model=GRU(num_classes,input_size,hidden_size,num_layers,X_train_tensors_final.shape[1]).to(device)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for epoch in range(num_epochs) :
outputs = model.forward(X_train_tensors_final)
optimizer.zero_grad()
loss = criterion(outputs, y_train_tensors)
loss.backward()
optimizer.step()
if epoch % 100 == 0 :
print(f'Epoch : {epoch}, loss : {loss.item():1.5f}')
df_X_ss = ss.transform(df.drop(columns='Volume'))
df_y_mm = mm.transform(df.iloc[:, 5:6])
df_X_ss = Variable(torch.Tensor(df_X_ss)) #converting to Tensors
df_y_mm = Variable(torch.Tensor(df_y_mm))
#reshaping the dataset
df_X_ss = torch.reshape(df_X_ss, (df_X_ss.shape[0], 1, df_X_ss.shape[1]))
train_predict = model(df_X_ss.to(device)) #forward pass
data_predict = train_predict.data.detach().cpu().numpy() #numpy conversion
dataY_plot = df_y_mm.data.numpy()
# Undo the scaling of X according to feature_range
data_predict = mm.inverse_transform(data_predict) #reverse transformation
dataY_plot = mm.inverse_transform(dataY_plot)
plt.figure(figsize=(10,6)) #plotting
plt.axvline(x=4563, c='r', linestyle='--') #size of the training set
plt.plot(dataY_plot, label='Actuall Data') #actual plot
plt.plot(data_predict, label='Predicted Data') #predicted plot
plt.title('Time-Series Prediction')
plt.legend()
plt.show()
ํ ............
epoch๊ฐ ํด์๋ก loss ๊ฐ์ด 0์ ๊ฐ๊น์์ ธ์
actual ๊ณผ predict ๊ทธ๋ํ๊ฐ ๋งค์ฐ ์ ์ฌํ๋ค
์ ํด์๋ก ์์ ์ ์ฌํ๊ฒ ์ ์์ธก๋๋๊ฑฐ์ง.........???
์ผ๋จ ๋ด๊ฐ epoch ์๊ฒ ํด์ ์ด์ํ ๊ทธ๋ํ ์์ธก๊ฐ์ด ๋์์ง๋ง.......
์๊ทธ๋ด๊น์?
๊ถ๊ธใ ํด์
๋ต์ข...
- NAVER ์ฃผ๊ฐ ^^
- ์๋ ์ด๋ ๊ฒ ์์ธก์ ์ํ๋ค๊ณ ์?
- layer๋ ์์๋ฐ..;;?
start = (2000, 1, 1) # 2020๋
01๋
01์
start = datetime.datetime(*start)
end = datetime.date.today() # ํ์ฌ
# yahoo ์์ NAVER ๋ถ๋ฌ์ค๊ธฐ
df = pdr.DataReader('035420.KS', 'yahoo', start, end)
df.Close.plot(grid=True)