3.1 数据处理

```def nn_seq(B, pred_step_size):
train = data[:int(len(data) * 0.7)]
test = data[int(len(data) * 0.7):len(data)]
# 归一化
train.drop([train.columns[0]], axis=1, inplace=True)
test.drop([test.columns[0]], axis=1, inplace=True)
scalar = MinMaxScaler()
train = scalar.fit_transform(train.values)
test = scalar.transform(test.values)
def process(dataset, batch_size):
dataset = dataset.tolist()
seq = []
for i in range(0, len(dataset) - 24 - pred_step_size, pred_step_size):
train_seq = []
for j in range(i, i + 24):
x = []
for c in range(len(dataset[0])):  # 前24个时刻的所有变量
x.append(dataset[j][c])
train_seq.append(x)
# 下几个时刻的所有变量
train_labels = []
for j in range(len(dataset[0])):
train_label = []
for k in range(i + 24, i + 24 + pred_step_size):
train_label.append(dataset[k][j])
train_labels.append(train_label)
# tensor
train_seq = torch.FloatTensor(train_seq)
train_labels = torch.FloatTensor(train_labels)
seq.append((train_seq, train_labels))
seq = MyDataset(seq)
seq = DataLoader(dataset=seq, batch_size=batch_size, shuffle=False, num_workers=0, drop_last=True)
return seq
Dtr = process(train, B)
Dte = process(test, B)
return Dtr, Dte, scalar```

3.2 模型搭建

```class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size, n_outputs):
super().__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.num_layers = num_layers
self.output_size = output_size
self.num_directions = 1
self.n_outputs = n_outputs
self.batch_size = batch_size
self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
# self.fcs = [nn.Linear(self.hidden_size, self.output_size).to(device) for i in range(self.n_outputs)]
self.fc1 = nn.Linear(self.hidden_size, self.output_size)
self.fc2 = nn.Linear(self.hidden_size, self.output_size)
self.fc3 = nn.Linear(self.hidden_size, self.output_size)
def forward(self, input_seq):
# print(input_seq.shape)
batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]
h_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device)
c_0 = torch.randn(self.num_directions * self.num_layers, batch_size, self.hidden_size).to(device)
# print(input_seq.size())
# input(batch_size, seq_len, input_size)
# output(batch_size, seq_len, num_directions * hidden_size)
output, _ = self.lstm(input_seq, (h_0, c_0))
preds = []
pred1, pred2, pred3 = self.fc1(output), self.fc2(output), self.fc3(output)
pred1, pred2, pred3 = pred1[:, -1, :], pred2[:, -1, :], pred3[:, -1, :]
# pred = torch.cat([pred1, pred2], dim=0)
pred = torch.stack([pred1, pred2, pred3], dim=0)
# print(pred.shape)
return pred```

`predict(n_outputs, batch_size, output_size)`

3.3 模型训练/测试

```def train(args, Dtr, path):
input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
output_size = args.output_size
model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size,
n_outputs=args.n_outputs).to(device)
loss_function = nn.MSELoss().to(device)
if args.optimizer == 'adam':
optimizer = torch.optim.Adam(model.parameters(), lr=args.lr,
weight_decay=args.weight_decay)
else:
optimizer = torch.optim.SGD(model.parameters(), lr=args.lr,
momentum=0.9, weight_decay=args.weight_decay)
scheduler = StepLR(optimizer, step_size=args.step_size, gamma=args.gamma)
# training
for i in tqdm(range(args.epochs)):
cnt = 0
for (seq, labels) in Dtr:
cnt += 1
seq = seq.to(device)
labels = labels.to(device)  # (batch_size, n_outputs, pred_step_size)
preds = model(seq)  # (n_outputs, batch_size, pred_step_size)
# print(labels.shape)
# print(preds.shape)
# 计算多个损失函数
total_loss = 0
for k in range(args.n_outputs):
total_loss = total_loss + loss_function(preds[k, :, :], labels[:, k, :])
total_loss /= preds.shape[0]

total_loss.backward()
optimizer.step()
print('epoch', i, ':', total_loss.item())
scheduler.step()
state = {
'models': model.state_dict(), 'optimizer': optimizer.state_dict()}
torch.save(state, path)```

```label(batch_size, n_outputs, pred_step_size)
pred((n_outputs, batch_size, pred_step_size))```

```total_loss = 0
for k in range(args.n_outputs):
total_loss = total_loss + loss_function(preds[k, :, :], labels[:, k, :])
total_loss /= preds.shape[0]```

```def test(args, Dte, scalar, path):
input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
output_size = args.output_size
model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size,
n_outputs=args.n_outputs).to(device)
# models = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
model.eval()
print('predicting...')
ys = [[] for i in range(args.n_outputs)]
preds = [[] for i in range(args.n_outputs)]
for (seq, targets) in tqdm(Dte):
targets = np.array(targets.data.tolist())  # (batch_size, n_outputs, pred_step_size)
for i in range(args.n_outputs):
target = targets[:, i, :]
target = list(chain.from_iterable(target))
ys[i].extend(target)
seq = seq.to(device)
_pred = model(seq)
for i in range(_pred.shape[0]):
pred = _pred[i]
pred = list(chain.from_iterable(pred.data.tolist()))
preds[i].extend(pred)
# ys, preds = [np.array(y) for y in ys], [np.array(pred) for pred in preds]
ys, preds = np.array(ys).T, np.array(preds).T
ys = scalar.inverse_transform(ys).T
preds = scalar.inverse_transform(preds).T
for ind, (y, pred) in enumerate(zip(ys, preds), 0):
print(get_mape(y, pred))
plot(y, pred, ind)
plt.show()```

3.4 实验结果

MAPE12.83%3.88%19.61%

MAPE6.01%12.45%7.50%