我正在构建一个LSTM模型,想要用变量q_max
来预测s_max
,但网络似乎只是对输入数据进行了一些修改,然后将其作为输出。我尝试增加隐藏层大小和训练轮数,但没有成功。我认为可能是数据结构方式或者网络设置方面存在问题。
这是我的模型预测结果图:
我只是希望模型能拟合训练数据,这样我就能知道它可以学习一个简单的问题。
这是我的模型代码:
class LSTM(nn.Module):def __init__(self, num_classes, input_size, hidden_size, num_layers): super(LSTM, self).__init__() self.num_classes = num_classes self.num_layers = num_layers self.input_size = input_size self.hidden_size = hidden_size self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers, batch_first=True) self.fc = nn.Linear(hidden_size, num_classes)def forward(self, x): h_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)) c_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size)) ula, (h_out, _) = self.lstm(x, (h_0, c_0)) h_out = h_out.view(-1, self.hidden_size) out = self.fc(h_out) return out
数据预处理:
def data_manipulator(data): df = pd.read_hdf(data) df = df.iloc[:, [1, 4]] scaler = MinMaxScaler() scaler = scaler.fit_transform(df) df = scaler return pd.DataFrame(df)def sliding_windows(data, seq_length): y = np.ones([len(data)-seq_length-1,1]) x = np.ones([len(data)-seq_length-1,seq_length,1]) for i in range(len(data)-seq_length-1): x[i] = np.array(data.iloc[i:i + seq_length,0]).reshape(-1,1) # ex. [1406, 5, 1] y[i] = data.iloc[i + seq_length, 1] # ex. [1406, 1] return torch.tensor(x, dtype=torch.float), torch.tensor(y, dtype=torch.float)
设置、训练和绘图:
data_files = glob.glob('data/*.hdf')seq_length = 5df = data_manipulator(data_files[0])x, y = sliding_windows(df, seq_length)lstm = LSTM(num_classes= 1,input_size=1, hidden_size = 1, num_layers = 1)criterion = torch.nn.MSELoss()optimizer = torch.optim.Adam(lstm.parameters(), lr=0.001)num_epochs = 2000for epoch in range(num_epochs): optimizer.zero_grad() outputs = lstm(x) loss = criterion(outputs, y) loss.backward() optimizer.step() if epoch % 100 == 0: print("Epoch: %d, loss: %1.5f" % (epoch, loss.item()))lstm.eval()output2 = lstm(x).detach().numpy()plt.plot(df[0], label='q_max 训练数据')plt.plot(df[1], label='s_max 训练数据')plt.plot(output2, label='使用 q_max 训练数据作为输入的 s_max 输出')plt.legend()plt.show()
训练输出:
Epoch: 0, loss: 0.52164Epoch: 100, loss: 0.10143Epoch: 200, loss: 0.04956Epoch: 300, loss: 0.02736Epoch: 400, loss: 0.02732Epoch: 500, loss: 0.02727Epoch: 600, loss: 0.02722Epoch: 700, loss: 0.02714Epoch: 800, loss: 0.02704Epoch: 900, loss: 0.02689Epoch: 1000, loss: 0.02663
回答:
与我的项目导师讨论后,我发现有几点我之前没有考虑到。首先,前向传播返回的是h_out
而不是预测值ula
。其次,我的函数def sliding_windows(data, seq_length):
是一个“多对一”网络,而他希望的是一个更适合此应用的“多对多”网络,我将努力更改数据输入和输出架构。