1) 지난 시간에 이어서 시계열 데이터 예측을 다른 모델과 다른 방법으로 진행해보려 한다.
2) RNN에 대한 기본적인 개념과 지식은 어느 정도 알고 있다고 가정하고 시작하겠다.
class RNNModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 100,
num_layers= 3,
sequence_length = sl,
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# RNN 레이어
# https://pytorch.org/docs/stable/generated/torch.nn.RNN.html
self.rnn = nn.RNN(input_size = input_size,
hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True,
bidirectional = False)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, hidden_size]
# output_h = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
k = self.sequence_length * self.hidden_size
# 2) Use output's Last Sequence Length
# k = 1 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256),
nn.LeakyReLU(),
nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [num_layers, bs, hidden_size]
output, h_n = self.rnn(x, h0)
# output's shape: [bs, sl, hidden_size]
# h_n = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
output = output.reshape(bs, -1) # [bs, sl, hidden_size] -> [bs, sl * hidden_size]
# 2) Use output's Last Sequence Length
# output = output[:, -1] # [bs, hidden_size]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
class BiRNNModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 100,
num_layers= 3,
sequence_length = sl,
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# RNN 레이어
self.rnn = nn.RNN(input_size = input_size, hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True, bidirectional = True)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [2*num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, 2*hidden_size]
# output_h = [2*num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
k = self.sequence_length * 2 * self.hidden_size
# 2) Use output's Last Sequence
# k = 1 * 2 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256), nn.LeakyReLU(), nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(2 * self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [2*num_layers, bs, hidden_size]
output, h_n = self.rnn(x, h0)
# output's shape: [bs, sl, 2*hidden_size]
# h_n = [2*num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
output = output.reshape(bs, -1)
# 2) Use output's Last Sequence
# output = output[:, -1]
# output's shape: [bs, 2*hid_dim]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
class LSTMModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 80,
num_layers= 3,
sequence_length = sl, # sl = 7
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# LSTM 레이어
# https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html
self.rnn = nn.LSTM(input_size = input_size, hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True, bidirectional = False)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [num_layers, bs, hidden_size]
# input_c0 = [num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, hidden_size]
# output_h = [num_layers, bs, hidden_size]
# output_c = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
k = self.sequence_length * self.hidden_size
# 2) Use output's Last Sequence
# k = 1 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256), nn.LeakyReLU(), nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [num_layers, bs, hidden_size]
c0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# c0: [num_layers, bs, hidden_size]
output, (h_n, c_n) = self.rnn(x, (h0, c0))
# output's shape: [bs, sl, hidden_size]
# h_n = [num_layers, bs, hidden_size]
# c_n = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
output = output.reshape(bs, -1)
# 2) Use output's Last Sequence
# output = output[:, -1]
# output's shape: [bs, hid_dim]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
class LSTMModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 80,
num_layers= 3,
sequence_length = sl, # sl = 3
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# LSTM 레이어
# https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html
self.rnn = nn.LSTM(input_size = input_size, hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True, bidirectional = False)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [num_layers, bs, hidden_size]
# input_c0 = [num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, hidden_size]
# output_h = [num_layers, bs, hidden_size]
# output_c = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
# k = self.sequence_length * self.hidden_size
# 2) Use output's Last Sequence
k = 1 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256), nn.LeakyReLU(), nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [num_layers, bs, hidden_size]
c0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# c0: [num_layers, bs, hidden_size]
output, (h_n, c_n) = self.rnn(x, (h0, c0))
# output's shape: [bs, sl, hidden_size]
# h_n = [num_layers, bs, hidden_size]
# c_n = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
# output = output.reshape(bs, -1)
# 2) Use output's Last Sequence
output = output[:, -1]
# output's shape: [bs, hid_dim]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
: GRU 모델은 LSTM 모델을 경량화시킨 모델이고, 한국인 조경현 박사님으로부터 제안된 모델이다. (참고)
class RNNModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 100,
num_layers= 3,
sequence_length = sl,
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# RNN 레이어
# https://pytorch.org/docs/stable/generated/torch.nn.RNN.html
self.rnn = nn.RNN(input_size = input_size,
hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True,
bidirectional = False)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, hidden_size]
# output_h = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
k = self.sequence_length * self.hidden_size
# 2) Use output's Last Sequence Length
# k = 1 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256),
nn.LeakyReLU(),
nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [num_layers, bs, hidden_size]
output, h_n = self.rnn(x, h0)
# output's shape: [bs, sl, hidden_size]
# h_n = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
output = output.reshape(bs, -1) # [bs, sl, hidden_size] -> [bs, sl * hidden_size]
# 2) Use output's Last Sequence Length
# output = output[:, -1] # [bs, hidden_size]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
class LSTMModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 80,
num_layers= 3,
sequence_length = sl, # sl = 7
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# LSTM 레이어
# https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html
self.rnn = nn.LSTM(input_size = input_size, hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True, bidirectional = False)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [num_layers, bs, hidden_size]
# input_c0 = [num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, hidden_size]
# output_h = [num_layers, bs, hidden_size]
# output_c = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
k = self.sequence_length * self.hidden_size
# 2) Use output's Last Sequence
# k = 1 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256), nn.LeakyReLU(), nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [num_layers, bs, hidden_size]
c0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# c0: [num_layers, bs, hidden_size]
output, (h_n, c_n) = self.rnn(x, (h0, c0))
# output's shape: [bs, sl, hidden_size]
# h_n = [num_layers, bs, hidden_size]
# c_n = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
output = output.reshape(bs, -1)
# 2) Use output's Last Sequence
# output = output[:, -1]
# output's shape: [bs, hid_dim]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
class GRUModel(nn.Module):
def __init__(self,
input_size = 3, # open, high, low
hidden_size = 100,
num_layers= 2,
sequence_length = sl,
device = device
):
super().__init__()
self.num_layers = num_layers
self.sequence_length = sequence_length
self.hidden_size = hidden_size
self.device = device
# GRU 레이어
# https://pytorch.org/docs/stable/generated/torch.nn.GRU.html
self.rnn = nn.GRU(input_size = input_size, hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True, bidirectional = False)
# input(=x)'s shape: [bs, sl, input_size]
# input_h0 = [num_layers, bs, hidden_size]
# output(=y)'s shape: [bs, sl, hidden_size]
# output_h = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
k = self.sequence_length * self.hidden_size
# 2) Use output's Last Sequence
# k = 1 * self.hidden_size
# Fully Connected Layer
self.seq = nn.Sequential(
# [bs, sl, hidden_size] -> [bs, sl * hidden_size]
nn.Linear(k, 256), nn.LeakyReLU(), nn.Linear(256, 1)
# [bs, k] -> [bs, 256] -> [bs, 1]
)
def forward(self, x):
# x: [bs, sl, input_size]
bs = x.shape[0]
h0 = torch.zeros(self.num_layers, bs, self.hidden_size).to(self.device)
# h0: [num_layers, bs, hidden_size]
output, h_n = self.rnn(x, h0)
# output's shape: [bs, sl, hidden_size]
# h_n = [num_layers, bs, hidden_size]
# 1) 3차원 -> 2차원
output = output.reshape(bs, -1)
# 2) Use output's Last Sequence
# output = output[:, -1]
# output's shape: [bs, hid_dim]
# [bs, k] -> [bs, 256] ->[bs, 1]
y_pred = self.seq(output)
# y_pred: [bs, 1]
return y_pred
: 이로써 여기까지 RNN과 다른 모델들 그리고 예측 방법을 소개하였다. 이것들을 토대로 다양하게 실험을 진행해보고 공부해보는 것 또한 방법이다. 나머지는 여러분께 맡기겠다.