# 20分钟TMP预测模型训练逻辑说明 ## 模型概述 这是一个用于预测超滤(UF)和反渗透(RO)系统未来20分钟压力和流量变化的时间序列预测模型。 **预测目标**:16个关键指标 - 4个UF跨膜压差(TMP):`C.M.UF1-4_DB@press_PV` - 8个RO压力差:`C.M.RO1-4_DB@DPT_1` 和 `C.M.RO1-4_DB@DPT_2` - 4个RO浓水流量:`RO1-4_CSFlow` ## 核心思路 ### 1. 模型架构:16个"专家"并行工作 想象有16个专家,每个专家只负责预测一个指标。虽然他们看到的输入数据相同(79个传感器数据),但各自独立学习预测自己负责的那一个指标。 ``` 输入(79个特征) → [专家1预测UF1压力] → [专家2预测UF2压力] → ... → [专家16预测RO4流量] ``` **为什么这样设计?** - 每个指标的变化规律可能不同,独立建模更精准 - 但它们共享输入特征,仍能捕捉系统的整体状态 ### 2. 时间窗口:用过去预测未来 **输入窗口**:过去60个时间点(4小时历史数据,每4分钟一个点) **输出窗口**:未来5个时间点(20分钟,每4分钟预测一次) ``` 历史:t-60 → t-59 → ... → t-1 → t ↓ [LSTM处理] ↓ 未来: t+1 → t+2 → t+3 → t+4 → t+5 ``` ### 3. 网络结构:LSTM捕捉时间依赖 每个"专家"内部使用LSTM(长短期记忆网络): ``` LSTM层(64隐藏单元) → 取最后时刻状态 → 全连接层 → 输出5步预测 ``` **LSTM的作用**: - 记住长期趋势(比如压力缓慢上升) - 捕捉短期波动(比如突然的流量变化) - 自动提取时间序列中的重要模式 ## 训练流程详解 ### 步骤1:数据预处理(`data_preprocessor.py`) #### 1.1 数据读取和采样 ```python # 多线程读取51个CSV文件,提速明显 read_and_combine_csv_files() ``` - 原始数据每4秒一条,采样后每4分钟一条(`resolution=60`) - 这样做减少数据量,同时保留关键变化趋势 #### 1.2 时间特征编码 ```python # 把时间转成周期性特征 minute_sin = sin(2π × 分钟数 / 1440) # 一天的周期 day_sin = sin(2π × 天数 / 366) # 一年的周期 ``` **为什么这样做?** - 模型能理解"早上8点"和"第二天早上8点"是类似的时刻 - 能捕捉季节性变化(比如夏天和冬天的水质差异) #### 1.3 归一化 ```python # 把所有数据缩放到0-1之间 scaler = MinMaxScaler() scaled_data = scaler.fit_transform(data) joblib.dump(scaler, 'scaler.pkl') # 保存归一化器供预测时使用 ``` **作用**:让不同量级的特征(压力0.03MPa vs 流量360m³/h)在训练时权重平衡 #### 1.4 构建监督学习样本 ```python # 滑动窗口生成样本 输入:t-60到t的所有特征(60×79=4740维) 输出:t+1到t+5的16个目标(5×16=80维) ``` ### 步骤2:模型初始化(`gat_lstm.py`) #### 单个专家模型结构 ```python 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个时间步 ) ``` #### 16个专家组合 ```python 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) ``` ### 步骤3:联合训练(`data_trainer.py`) #### 训练循环 ```python 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() ``` **关键设计**: - 虽然有16个专家,但用**一个损失函数**联合优化 - 好处:专家之间能通过共享梯度信息"互相学习" #### 早停机制 ```python # 如果验证集损失连续500轮不下降,提前停止 if val_loss没有改善 > patience(500轮): 停止训练,加载最优模型权重 ``` 防止过拟合,保存泛化能力最强的模型 #### 学习率调度 ```python # 每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`) ### 实时预测步骤 1. **加载最新数据**:读取最近4小时的传感器数据 2. **预处理**: - 按分辨率下采样(每4分钟一个点) - 时间特征编码(正弦/余弦) - 归一化(使用训练时保存的scaler) 3. **模型推理**: ```python model.eval() # 切换到评估模式 with torch.no_grad(): # 不计算梯度 predictions = model(inputs) ``` 4. **反归一化**:将0-1范围的预测值还原到真实物理量 5. **可选后处理**: - 异常值检测(四分位法) - 平滑处理(加权平均) ## 模型性能评估 训练完成后,在测试集上计算: - **R²(决定系数)**:越接近1越好,表示预测值与真实值的拟合程度 - **RMSE(均方根误差)**:越小越好,单位与目标变量相同 - **MAPE(平均绝对百分比误差)**:越小越好,百分比形式更直观 ## 文件结构说明 ``` 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则需要) ``` ## 使用建议 ### 训练新模型 ```bash python main.py ``` 会自动完成:数据加载 → 预处理 → 训练 → 验证 → 测试 → 保存模型 ### 使用模型预测 ```python from predict import Predictor predictor = Predictor() predictions = predictor.predict(df) # df是最新的传感器数据 predictor.save_predictions(predictions) ``` ### 调参建议 1. **数据量不足时**: - 减小 `hidden_size`(比如32) - 增大 `dropout`(比如0.2) - 减少 `epochs` 2. **预测效果不好时**: - 检查数据质量(异常值、缺失值) - 增加 `seq_len`(更长历史窗口) - 调整 `resolution`(尝试不同采样率) 3. **训练太慢时**: - 减小 `batch_size` - 减少数据文件范围(`start_files` - `end_files`) - 使用GPU(自动检测) ## 常见问题 **Q:为什么用16个独立模型而不是一个大模型?** A:每个指标的变化模式不同,独立建模能让每个专家专注于自己的任务,预测更准确。 **Q:为什么输入79个特征,只预测16个?** A:79个特征包含系统的全面信息(流量、压力、温度、化学指标等),但我们只关心16个关键指标的未来变化。 **Q:如何判断模型训练好了?** A:看验证集R²是否>0.9,MAPE是否<5%,以及预测曲线是否与真实值吻合。 **Q:模型能预测多远?** A:设计是20分钟,时间越远精度越低。如果需要更长预测(比如1小时),建议增加`output_size`并调整模型结构。