解决问题的背景:现有五个属性列,前四个属性列作为特征输入,第五个属性列作为标签值,第五个属性列的意义是类别;先需要通过前50步的数据特征预测后10步的类别(即:51-60步)。
1.直接多输出的方式:直接多输出的方式就是在神经网络的最后加上几个(对应的是需要预测步长是几步,这里是10)一样的全连接神经网络,在这一层之后进行对每个全连接神经网络输出的值的拼接得到一个10步长的结果,用于后面计算损失进行训练。
简单的网络结构如下图:
模型网络的代码如下:
# GRU
class GRURNN(torch.nn.Module):
def __init__(self, input_size, hidden_size, num_layers):
super().__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.num_layers = num_layers
self.gru = torch.nn.GRU(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
self.fc1 = torch.nn.Linear(self.hidden_size, 4)
self.fc2 = torch.nn.Linear(self.hidden_size, 4)
self.fc3 = torch.nn.Linear(self.hidden_size, 4)
self.fc4 = torch.nn.Linear(self.hidden_size, 4)
self.fc5 = torch.nn.Linear(self.hidden_size, 4)
self.fc6 = torch.nn.Linear(self.hidden_size, 4)
self.fc7 = torch.nn.Linear(self.hidden_size, 4)
self.fc8 = torch.nn.Linear(self.hidden_size, 4)
self.fc9 = torch.nn.Linear(self.hidden_size, 4)
self.fc10 = torch.nn.Linear(self.hidden_size, 4)
self.softmax = torch.nn.Softmax(dim=1)
def forward(self, input_seq):
batch_size = input_seq.shape[0]
h_0 = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)
output, _ = self.gru(input_seq,h_0)
pred1 = self.fc1(output)
pred2 = self.fc2(output)
pred3 = self.fc3(output)
pred4 = self.fc4(output)
pred5 = self.fc5(output)
pred6 = self.fc6(output)
pred7 = self.fc7(output)
pred8 = self.fc8(output)
pred9 = self.fc9(output)
pred10 = self.fc10(output)
pred1, pred2, pred3, pred4, pred5, pred6, pred7, pred8, pred9, pred10 = pred1[:, -1, :], pred2[:, -1, :], pred3[:, -1, :], pred4[:, -1, :], pred5[:, -1, :], pred6[:, -1, :], pred7[:, -1, :], pred8[:, -1, :], pred9[:, -1, :], pred10[:, -1, :]
pred1, pred2, pred3, pred4, pred5, pred6, pred7, pred8, pred9, pred10 = self.softmax(pred1), self.softmax(pred2), self.softmax(pred3), self.softmax(pred4), self.softmax(pred5), self.softmax(pred6), self.softmax(pred7), self.softmax(pred8), self.softmax(pred9), self.softmax(pred10)
pred = torch.stack([pred1, pred2, pred3, pred4, pred5, pred6, pred7, pred8, pred9, pred10], dim=1)
return pred
2.滚动数据集输出的方式:滚动数据集的方式就是单步预测的一个整合的版本,具体就是先用前50步预测第51步然后用2-51步作为50步的值进行下一次的输入预测第52步,以此类推;这里后面预测完加入到输入数据中的新值可以就是刚刚预测出来的新值,也可以是数据标签集值的对应到这一步的值。滚动预测的效果会比直接多输出的方式的效果好,但是时间是较长的,对于需要一个较好性能模型的需求来说,时间久一点不是什么问题。
简单的预测步骤如下图(简单表示:5步预测3步):
模型网络的代码如下:
# GRU
class GRURNN(torch.nn.Module):
def __init__(self, input_size, hidden_size, num_layers):
super().__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.num_layers = num_layers
self.gru = torch.nn.GRU(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
self.mlp = torch.nn.Sequential(
torch.nn.Linear(self.hidden_size, 32),
torch.nn.LeakyReLU(),
torch.nn.Linear(32, 16),
torch.nn.LeakyReLU(),
torch.nn.Linear(16, 4)
)
self.softmax = torch.nn.Softmax(dim=1)
def forward(self, input_seq):
batch_size = input_seq.shape[0]
h_0 = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)
output, _ = self.gru(input_seq,h_0)
output = output[:, -1, :]
pred = self.mlp(output)
pred = self.softmax(pred)
return pred
# 直接单步滚动,预测未来多步的预测
class GRURNN_PRO_MORE(torch.nn.Module):
def __init__(self,gru,device):
super(GRURNN_PRO_MORE, self).__init__()
self.gru = gru
self.device = device
def forward(self, src, trg):
batch_size = src.shape[0]
src_len = src.shape[1]
trg_len = trg.shape[1]
output_size = 4
outputs = torch.zeros(batch_size, trg_len, output_size).to(self.device)
for i in range(trg_len):
src = src.float()
output = self.gru(src)
outputs[:, i, :] = output
trg_input = trg[:, i, :4].reshape([batch_size, 1, output_size])
src = torch.cat((src[:, 1:, :], trg_input),dim=1)
return outputs
数据处理:对于数据的处理用到了常用的一些库,像pandas,numpy等。
作者处于学习阶段,如有错误,欢迎批评指正。