训练数据是一个9列(含有9个特征量),包括炉膛温度,炉膛压力等数据,label数据是主蒸汽流量,其中9个特征量进行了归一化处理,使用的是sklearn里的 StandardScaler。导入的库和包,如下所示:
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
import numpy as np
import torch
from torch import nn
import pandas as pd
from tqdm import tqdm
from tqdm.std import trange
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import QuantileTransformer
import seaborn as sns
from sklearn.metrics import r2_score
DAYS_FOR_TRAIN = 5
EPOCHS = 200
#调参日记
#(1)200 trainloss=0.054
#(2)400 不加学习率降低 效果可以 R20.76
#(3)400不加学习率降低多加入线性层 R20.66 #加激活函数
#(4)400 不加学习率降低多加入线性层 不加激活函数 层数 64 R2-800?
#(5)400 加入学习率降低 加入多层学习率下降效果不好
#(6)400 加入梯级学习率 R2 0.7656
#(7)100 加入梯级学习率 0.78 将hidden_size = 10变为
#(8)300 用Quantile归一化 0.84 400 0.79 300步效果好
#(9)100 LR=0.05 Quantile MinMaxscaler 0.86
#(10)测试850℃2s模型
class LSTM_Regression(nn.Module):
def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):
super().__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, _x, h_state,c_state):
x, (h_state,c_state) = self.lstm(_x , (h_state,c_state)) # _x is input, size (seq_len, batch, input_size)
s, b, h = x.shape # x is output, size (seq_len, batch, hidden_size)
x = x.view(s * b, h)
x = self.fc(x)
x = x.view(s, b, -1) # 把形状改回来
return x,h_state
def InitHidden(self):
h_state=torch.zeros(2, 1, 10)
c_state=torch.zeros(2, 1, 10)# hidden_size =16
# h_state = torch.randn(2, 2, 8)#初始化 hidden_size=8
return h_state,c_state
def create_dataset(dataX,dataY, days_for_train=5) -> (np.array, np.array):
dataset_x, dataset_y = [], []
for i in range(len(dataX) - days_for_train):
_x = dataX[i:(i + days_for_train)]
dataset_x.append(_x)
dataset_y.append(dataY[i + days_for_train])
return (np.array(dataset_x), np.array(dataset_y))
随后开始训练:
if __name__ == '__main__':
train = pd.read_csv('./loader_data2.csv')
train_data = np.array(train.loc[:, 'sep_rst':'sep_sobelsum'], dtype=np.float32) # 转化为numpy数据
label_train_data = np.array(train.sep_sobelart, dtype=np.float32)
scaler = QuantileTransformer() #新的归一化方法
#scaler = StandardScaler() #Standardscaler的归一化方法
train_data = scaler.fit_transform(train_data)
# label_train_data = scaler.fit_transform(label_train_data)
scaler_label = StandardScaler() #Standardscaler的归一化方法
# scaler_label = MinMaxScaler(feature_range=(0, 1)) # minmax归一化
label_train_data = scaler_label.fit_transform(label_train_data.reshape(-1,1))
#train_data = scaler.fit_transform(train_data)
# 数据集序列化,进行标签分离
dataset_x, dataset_y = create_dataset(train_data,label_train_data,DAYS_FOR_TRAIN)
# 划分训练集和测试集,80%作为训练集,20%作为测试集
train_size = int(len(dataset_x) * 0.8)
train_x = dataset_x[:train_size]
train_y = dataset_y[:train_size]
test_x = dataset_x[train_size:]
test_y = dataset_y[train_size:]
# 改变数据集形状,RNN 读入的数据维度是 (seq_size, batch_size, feature_size)
train_x = train_x.reshape(-1, 1, train_x.shape[2]*train_x.shape[1])
train_y = train_y.reshape(-1, 1, 1)
# 数据集转为pytorch的tensor对象
train_x = torch.from_numpy(train_x)
train_y = torch.from_numpy(train_y)
# train model
netdim = train_x.shape[2]*train_x.shape[1]
model = LSTM_Regression(netdim,hidden_size=10,output_size=1, num_layers=2) # 网络初始化
h_state,c_state = model.InitHidden()
loss_function = nn.MSELoss() # 损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # 优化器 Adam 0.05加学习率降低
#scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9) #log学习率下降
#scheduler= torch.optim.lr_scheduler.StepLR(optimizer, step_size=200, gamma=0.3) #有序学习率下降
#scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,milestones=[200,250], gamma=0.1) #多步学习率下降
for step in trange(EPOCHS):
out,h_state = model(train_x,h_state,c_state)
loss = loss_function(out, train_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
h_state = h_state.detach()
#scheduler.step()
if step % 10 == 0:
print('Epoch: {}, Loss:{:.5f}'.format(step, loss.item()))
#torch.save(model.state_dict(), 'model_twosecond_test.pkl') # 用以保存2s的模型
# predict
model = model.eval() # 转换成测试模式
# model.load_state_dict(torch.load('model_params.pkl')) # 读取参数
# 使用全部数据集dataset_x,模型的输出长度会比dataset_x少 DAYS_FOR_TRAIN
dataset_x = dataset_x.reshape(-1, 1, train_x.shape[2]*train_x.shape[1]) # (seq_size, batch_size, feature_size)
dataset_x = torch.from_numpy(dataset_x) # 转为pytorch的tensor对象
pred_y,_ = model(dataset_x,h_state,c_state) # 全量数据集的模型输出 (seq_size, batch_size, output_size)
pred_y = pred_y.view(-1).data.numpy()
# 对标准化数据进行还原
actual_pred_y = scaler_label.inverse_transform(pred_y.reshape(-1,1))
actual_pred_y = actual_pred_y.reshape(-1, 1).flatten()
test_y = scaler_label.inverse_transform(test_y.reshape(-1, 1))
test_y = test_y.reshape(-1, 1).flatten()
actual_pred_y = actual_pred_y[-len(test_y):]
test_y = test_y.reshape(-1, 1)
assert len(actual_pred_y) == len(test_y)
#(1)学习率 0.01可以预测趋势 0.9/0.1 测试集分割
#(2)学习率
import matplotlib.pyplot as plt
# 初始结果 - 预测结果
plt.plot(test_y, 'b', label='real')
plt.plot(actual_pred_y, 'r', label='prediction')
plt.legend(loc='best')
plt.savefig('result.png', format='png', dpi=200)
plt.show()
import seaborn as sns
sns.scatterplot(df["jy"], df["jy_"])
#plt.plot(x,df["jy_"])
#plt.plot(x,df["jy"])
sns.lineplot(np.linspace(50,80, 100),np.linspace(50,80, 100))
评估指标2:——R2决定系数:
from sklearn.metrics import r2_score
loss_sss=r2_score(test_y,actual_pred_y)
print(loss_sss) #R2决定系数