|
|
il y a 5 mois | |
|---|---|---|
| .. | ||
| 20min_predict.py | il y a 5 mois | |
| README.md | il y a 5 mois | |
| args.py | il y a 5 mois | |
| data_export.py | il y a 5 mois | |
| data_preprocessor.py | il y a 5 mois | |
| data_trainer.py | il y a 5 mois | |
| edge_index.pt | il y a 5 mois | |
| gat_lstm.py | il y a 5 mois | |
| main.py | il y a 5 mois | |
| model.pth | il y a 5 mois | |
| scaler.pkl | il y a 5 mois | |
这是一个用于预测超滤(UF)和反渗透(RO)系统未来20分钟压力和流量变化的时间序列预测模型。
预测目标:16个关键指标
C.M.UF1-4_DB@press_PVC.M.RO1-4_DB@DPT_1 和 C.M.RO1-4_DB@DPT_2RO1-4_CSFlow想象有16个专家,每个专家只负责预测一个指标。虽然他们看到的输入数据相同(79个传感器数据),但各自独立学习预测自己负责的那一个指标。
输入(79个特征) → [专家1预测UF1压力]
→ [专家2预测UF2压力]
→ ...
→ [专家16预测RO4流量]
为什么这样设计?
输入窗口:过去60个时间点(4小时历史数据,每4分钟一个点) 输出窗口:未来5个时间点(20分钟,每4分钟预测一次)
历史:t-60 → t-59 → ... → t-1 → t
↓
[LSTM处理]
↓
未来: t+1 → t+2 → t+3 → t+4 → t+5
每个"专家"内部使用LSTM(长短期记忆网络):
LSTM层(64隐藏单元) → 取最后时刻状态 → 全连接层 → 输出5步预测
LSTM的作用:
data_preprocessor.py)# 多线程读取51个CSV文件,提速明显
read_and_combine_csv_files()
resolution=60)# 把时间转成周期性特征
minute_sin = sin(2π × 分钟数 / 1440) # 一天的周期
day_sin = sin(2π × 天数 / 366) # 一年的周期
为什么这样做?
# 把所有数据缩放到0-1之间
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
joblib.dump(scaler, 'scaler.pkl') # 保存归一化器供预测时使用
作用:让不同量级的特征(压力0.03MPa vs 流量360m³/h)在训练时权重平衡
# 滑动窗口生成样本
输入:t-60到t的所有特征(60×79=4740维)
输出:t+1到t+5的16个目标(5×16=80维)
gat_lstm.py)class SingleGATLSTM:
def __init__(self):
# LSTM层:处理时间序列
self.lstm = nn.LSTM(input_size=79, hidden_size=64, num_layers=1)
# 输出层:LSTM输出 → 5步预测
self.final_linear = nn.Sequential(
nn.Linear(64, 64), # 第一层全连接
nn.LeakyReLU(0.01), # 激活函数
nn.Dropout(0), # Dropout防止过拟合(这里设为0)
nn.Linear(64, 5) # 输出5个时间步
)
class GAT_LSTM:
def __init__(self):
# 创建16个独立的专家
self.models = nn.ModuleList([SingleGATLSTM() for _ in range(16)])
def forward(self, x):
# 每个专家独立预测
outputs = [model(x) for model in self.models]
# 拼接结果:[batch, 5] × 16 → [batch, 80]
return torch.cat(outputs, dim=1)
data_trainer.py)for epoch in range(max_epochs):
for inputs, targets in train_loader:
# 1. 前向传播:所有16个专家并行预测
outputs = model(inputs) # [batch, 80]
# 2. 计算整体损失:MSE(均方误差)
loss = MSELoss(outputs, targets)
# 3. 反向传播:更新所有16个专家的参数
loss.backward()
optimizer.step()
关键设计:
# 如果验证集损失连续500轮不下降,提前停止
if val_loss没有改善 > patience(500轮):
停止训练,加载最优模型权重
防止过拟合,保存泛化能力最强的模型
# 每100轮学习率乘以0.9
scheduler = StepLR(step_size=100, gamma=0.9)
训练后期降低学习率,让模型更稳定地收敛
| 参数 | 值 | 说明 |
|---|---|---|
seq_len |
60 | 输入历史长度(4小时) |
output_size |
5 | 预测未来步数(20分钟) |
feature_num |
79 | 输入特征数 |
labels_num |
16 | 预测目标数 |
hidden_size |
64 | LSTM隐藏层大小 |
batch_size |
1024 | 每批训练样本数 |
lr |
0.01 | 初始学习率 |
epochs |
1000 | 最大训练轮数 |
patience |
500 | 早停耐心值 |
predict.py)模型推理:
model.eval() # 切换到评估模式
with torch.no_grad(): # 不计算梯度
predictions = model(inputs)
反归一化:将0-1范围的预测值还原到真实物理量
可选后处理:
训练完成后,在测试集上计算:
20分钟TMP预测模型源码/
├── args.py # 参数配置(数据集日期、模型超参数)
├── data_preprocessor.py # 数据预处理(读取、归一化、构建样本)
├── gat_lstm.py # 模型定义(16个专家模型架构)
├── data_trainer.py # 训练器(训练循环、早停、评估)
├── main.py # 训练入口(整合所有流程)
├── predict.py # 预测接口(加载模型、实时推理)
├── model.pth # 训练好的模型权重
├── scaler.pkl # 归一化器(保证预测时数据处理一致)
└── edge_index.pt # 图结构索引(如果使用GAT则需要)
python main.py
会自动完成:数据加载 → 预处理 → 训练 → 验证 → 测试 → 保存模型
from predict import Predictor
predictor = Predictor()
predictions = predictor.predict(df) # df是最新的传感器数据
predictor.save_predictions(predictions)
数据量不足时:
hidden_size(比如32)dropout(比如0.2)epochs预测效果不好时:
seq_len(更长历史窗口)resolution(尝试不同采样率)训练太慢时:
batch_sizestart_files - end_files)Q:为什么用16个独立模型而不是一个大模型?
A:每个指标的变化模式不同,独立建模能让每个专家专注于自己的任务,预测更准确。
Q:为什么输入79个特征,只预测16个?
A:79个特征包含系统的全面信息(流量、压力、温度、化学指标等),但我们只关心16个关键指标的未来变化。
Q:如何判断模型训练好了?
A:看验证集R²是否>0.9,MAPE是否<5%,以及预测曲线是否与真实值吻合。
Q:模型能预测多远?
A:设计是20分钟,时间越远精度越低。如果需要更长预测(比如1小时),建议增加output_size并调整模型结构。