前言:网上找的代码是keras以tensorflow为后端的,苦于不知道具体版本号,所以各种报错,所以参考网上的代码将其修改为基于pytorch的
参考链接:
https://blog.csdn.net/Muzi_Water/article/details/103921115
https://blog.csdn.net/jejune5/article/details/121673615
最终可用的版本
"Month","Sales"
"1964-01",2815
"1964-02",2672
"1964-03",2755
"1964-04",2721
"1964-05",2946
"1964-06",3036
# %%
import pandas as pd
import numpy as np
import torch
from torch import nn
from torch.nn import functional as F
from torch.utils.data import TensorDataset, DataLoader
import torchkeras
from plotly import graph_objects as go
from sklearn.preprocessing import MinMaxScaler
# %%
# 导入数据
# 数据下载:https://www.kaggle.com/kankanashukla/champagne-data
# 下载地址2:https://gitee.com/jejune/Datasets/blob/master/champagne.csv
df = pd.read_csv('champagne.csv', index_col=0)
df.head()
# %%
# 数据预览
fig = go.Figure()
fig.add_trace(go.Scatter(y=df['Sales'], name='Sales'))
fig.show()
# %%
# 数据处理
# 归一化 [0, 1]
scaler = MinMaxScaler()
predict_field = 'Scaler'
df[predict_field] = scaler.fit_transform(df['Sales'].values.reshape(-1, 1))
df.head()
# %%
def create_dataset(data: list, time_step: int):
arr_x, arr_y = [], []
for i in range(len(data) - time_step - 1):
x = data[i: i + time_step]
y = data[i + time_step]
arr_x.append(x)
arr_y.append(y)
return np.array(arr_x), np.array(arr_y)
time_step = 8
X, Y = create_dataset(df[predict_field].values, time_step)
# %%
# cuda
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 转化成 tensor->(batch_size, seq_len, feature_size)
X = torch.tensor(X.reshape(-1, time_step, 1), dtype=torch.float).to(device)
Y = torch.tensor(Y.reshape(-1, 1, 1), dtype=torch.float).to(device)
print('Total datasets: ', X.shape, '-->', Y.shape)
# 划分数据
split_ratio = 0.8
len_train = int(X.shape[0] * split_ratio)
X_train, Y_train = X[:len_train, :, :], Y[:len_train, :, :]
print('Train datasets: ', X_train.shape, '-->', Y_train.shape)
# %%
# 构建迭代器
batch_size = 10
ds = TensorDataset(X, Y)
dl = DataLoader(ds, batch_size=batch_size, num_workers=0)
ds_train = TensorDataset(X_train, Y_train)
dl_train = DataLoader(ds_train, batch_size=batch_size, num_workers=0)
# 查看第一个batch
x, y = next(iter(dl_train))
print(x.shape)
print(y.shape)
# %%
# 定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.lstm = nn.LSTM(input_size=1, hidden_size=6, num_layers=3, batch_first=True)
self.fc = nn.Linear(in_features=6, out_features=1)
def forward(self, x):
# x is input, size (batch_size, seq_len, input_size)
x, _ = self.lstm(x)
# x is output, size (batch_size, seq_len, hidden_size)
x = x[:, -1, :]
x = self.fc(x)
x = x.view(-1, 1, 1)
return x
# %%
# 自定义训练方式
model = Net().to(device)
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
# 测试一个batch
# features, labels = next(iter(dl_train))
# loss = train_step(model, features, labels)
# print(loss)
def train_step(model, features, labels):
# 正向传播求损失
predictions = model.forward(features)
loss = loss_function(predictions, labels)
# 反向传播求梯度
loss.backward()
# 参数更新
optimizer.step()
optimizer.zero_grad()
return loss.item()
# 测试一个batch
# features, labels = next(iter(dl_train))
# loss = train_step(model, features, labels)
# %%
# 训练模型
def train_model(model, epochs):
for epoch in range(1, epochs + 1):
list_loss = []
for features, labels in dl_train:
lossi = train_step(model, features, labels)
list_loss.append(lossi)
loss = np.mean(list_loss)
if epoch % 10 == 0:
print('epoch={} | loss={} '.format(epoch, loss))
print("finish training")
save_path = './myLstm_learn.pth'
torch.save(model.state_dict(), save_path)
# %%
# 自定义训练方式
# 训练-----
# train_model(model, 150)
# model = Net().to(device)
# loss_function = nn.MSELoss()
# optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
# 测试---------
model = Net().to(device)
model.load_state_dict(torch.load('myLstm_learn.pth'))
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
# %%
# 预测验证预览
y_true = Y.cpu().numpy().squeeze()
print('Y[0:10]:{0} shape:{1}'.format(Y[0:10], Y.shape))
print(y_true[0:10])
y_pred = model.forward(X).detach().cpu().numpy().squeeze()
print('y_pred[0:10]:{0} shape:{1}'.format(y_pred[0:10], y_pred.shape))
fig = go.Figure()
fig.add_trace(go.Scatter(y=y_true, name='y_true'))
fig.add_trace(go.Scatter(y=y_pred, name='y_pred'))
fig.show()
下图是没有归一化过的原数据

下图是归一化后的原数据和预测数据
我的疑问,time_step = 8,意味着每8个数据预测下一个数据,为什么预测后的图画出来和原始数据的形状一直呢?
后来想明白了,除了前八个数没有,其他数经过迭代,Y里面都包含了,所以观察上面两个图,会发现第二幅图比第一幅图少了前面一截数据图
"x","y"
323.0,253.0
323.0,253.0
323.0,253.0
323.0,253.0
323.0,253.0
323.0,253.0
323.5,253.0
323.5,253.0
323.5,253.0
323.5,253.0
324.0,253.0
324.0,252.5
324.0,252.5
import numpy as np
from torch import nn
import pandas as pd
import os
import torch
from torch.utils.data import TensorDataset, DataLoader
from plotly import graph_objects as go
import matplotlib.pyplot as plt
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
def create_dataset(data, n_predictions, n_next):
'''
对数据进行处理
'''
dim = data.shape[1]
train_X, train_Y = [], []
for i in range(data.shape[0] - n_predictions - n_next - 1):
a = data[i:(i + n_predictions), :]
train_X.append(a)
tempb = data[(i + n_predictions):(i + n_predictions + n_next), :]
b = []
for j in range(len(tempb)):
for k in range(dim):
b.append(tempb[j, k])
train_Y.append(b)
train_X = np.array(train_X, dtype='float64')
train_Y = np.array(train_Y, dtype='float64')
test_X, test_Y = [], []
i = data.shape[0] - n_predictions - n_next - 1
a = data[i:(i + n_predictions), :]
test_X.append(a)
tempb = data[(i + n_predictions):(i + n_predictions + n_next), :]
b = []
for j in range(len(tempb)):
for k in range(dim):
b.append(tempb[j, k])
test_Y.append(b)
test_X = np.array(test_X, dtype='float64')
test_Y = np.array(test_Y, dtype='float64')
return train_X, train_Y, test_X, test_Y
def NormalizeMult(data, set_range):
'''
返回归一化后的数据和最大最小值
'''
normalize = np.arange(2 * data.shape[1], dtype='float64')
normalize = normalize.reshape(data.shape[1], 2)
for i in range(0, data.shape[1]):
if set_range == True:
list = data[:, i]
listlow, listhigh = np.percentile(list, [0, 100])
else:
if i == 0:
listlow = -90
listhigh = 90
else:
listlow = -180
listhigh = 180
normalize[i, 0] = listlow
normalize[i, 1] = listhigh
delta = listhigh - listlow
if delta != 0:
for j in range(0, data.shape[0]):
data[j, i] = (data[j, i] - listlow) / delta
return data, normalize
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.lstm = nn.LSTM(input_size=2, hidden_size=6, num_layers=3, batch_first=True) # 特征是x,y两个坐标,此处修改为2
self.fc = nn.Linear(in_features=6, out_features=2) # 预测结果是x,y两个坐标,此处修改为2
def forward(self, x):
# x is input, size (batch_size, seq_len, input_size)
x, _ = self.lstm(x)
# x is output, size (batch_size, seq_len, hidden_size)
x = x[:, -1, :]
x = self.fc(x)
x = x.view(-1, 1, 2) # 此处修改为2
return x
def train_step(model, features, labels):
# 正向传播求损失
predictions = model.forward(features)
print('predictions:', predictions)
print('labels:', labels)
loss = loss_function(predictions, labels)
# 反向传播求梯度
loss.backward()
# 参数更新
optimizer.step()
optimizer.zero_grad()
return loss.item()
# %%
# 训练模型
def train_model(model, epochs):
for epoch in range(1, epochs + 1):
list_loss = []
for features, labels in dl_train:
lossi = train_step(model, features, labels)
list_loss.append(lossi)
loss = np.mean(list_loss)
if epoch % 10 == 0:
print('epoch={} | loss={} '.format(epoch, loss))
print("finish training")
save_path = './myLstm1.pth'
torch.save(model.state_dict(), save_path)
if __name__ == "__main__":
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
train_num = 9
per_num = 1
# set_range = False
set_range = True
# 读入时间序列的文件数据
data = pd.read_csv('0809.txt', sep=',').iloc[:, 0:2].values
print('data shape:',data.shape)
print("样本数:{0},维度:{1}".format(data.shape[0], data.shape[1]))
# print(data)
# # 画样本数据库
# plt.scatter(data[:, 1], data[:, 0], c='b', marker='o', label='traj_A')
# plt.legend(loc='upper left')
# plt.grid()
# plt.show()
# 归一化
data, normalize = NormalizeMult(data, set_range)
# # 生成训练数据
X_train, Y_train, test_X, test_Y = create_dataset(data, train_num, per_num)
model = Net().to(device)
model.load_state_dict(torch.load('myLstm1.pth'))
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
X_train = torch.tensor(X_train.reshape(-1, train_num, 2), dtype=torch.float).to(device)
Y_train = torch.tensor(Y_train.reshape(-1, 1, 2), dtype=torch.float).to(device)
print('X_train.shape: ', X_train.shape, 'Y_train.shape:', Y_train.shape)
# 构建迭代器
batch_size = 10
# ds = TensorDataset(X, Y)
# dl = DataLoader(ds, batch_size=batch_size, num_workers=0)
ds_train = TensorDataset(X_train, Y_train)
dl_train = DataLoader(ds_train, batch_size=batch_size, num_workers=0)
# # 查看第一个batch
# x, y = next(iter(dl_train))
# print(x.shape)
# print(y.shape)
# 下面三行的作用:开启训练前,调通一个前向传播
# features, labels = next(iter(dl_train))
# loss = train_step(model, features, labels)
# print(loss)
# 开启训练
# train_model(model, 100)
# %%
# 预测验证预览
y_true = Y_train.squeeze().cpu().numpy()
print("y_true.shape:",y_true.shape)
y_pred = model.forward(X_train).detach().squeeze().cpu().numpy()
print("y_pred.shape:", y_pred.shape)
# 画样本数据库
plt.scatter(y_true[:, 1], y_true[:, 0], c='b', marker='o', label='y_true')
plt.scatter(y_pred[:, 1], y_pred[:, 0], c='r', marker='o', label='y_pred')
plt.legend(loc='upper left')
plt.grid()
plt.show()
# fig = go.Figure()
# fig.add_trace(go.Scatter(y=y_true, name='y_true'))
# fig.add_trace(go.Scatter(y=y_pred, name='y_pred'))
# fig.show()
#
# print("x\n", train_X.shape)#(176, 10, 2)
# print("train_X.shape[1], train_X.shape[2]",train_X.shape[1], train_X.shape[2])#10 2
# train_X.shape[1], train_X.shape[2]
# print("y\n", train_Y.shape)
#
# # 训练模型
# model = trainModel(train_X, train_Y)
# loss, acc = model.evaluate(train_X, train_Y, verbose=2)
# print('Loss : {}, Accuracy: {}'.format(loss, acc * 100))
#
# # 保存模型
# np.save("./traj_model_trueNorm.npy", normalize)
# model.save("./traj_model_120.h5")

参考https://blog.csdn.net/qq_40728805/article/details/103959254
我的理解是,对于离线训练来讲,貌似可以双向,那对于在线监测那种,我无法先知道后续的数据,如何反向再来一遍呢?
是不是因为,训练过程我们是有后面数据的,所以训练过程双向没有问题,训练过程确定下来的权重,会用于测试过程的计算而已,可是,网络是双向的,是不是以为着预测的时候也会双向啊,此时又该如何双向呢?
而且,双向的时候,反向时候的数据怎么弄呢?
参考https://blog.csdn.net/aliceyangxi1987/article/details/77094970

下面是调试过程中遇到的问题记录
1,报错https://blog.csdn.net/m0_50736744/article/details/121799432
解决OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.报错问题
解决办法:
在pycharm里调试程序时可以直接通过在程序前添加这两个语句解决
import os
os.environ[“KMP_DUPLICATE_LIB_OK”]=“TRUE”
2,torchkeras安装,pip install torchkeras
3,data[:,0] data[1,:]的含义
data[ a , b ] a的位置限制第几行,b的位置限制第几列
“ : ”表示全部数据
例如:
data[:,0]表示第1列所有数据
data[1,:]表示第2行所有数据
data[:, 1:]表示从第2列开始所有数据