|
|
5 meses atrás | |
|---|---|---|
| .. | ||
| README.md | 5 meses atrás | |
| args.py | 5 meses atrás | |
| data_preprocessor.py | 5 meses atrás | |
| data_trainer.py | 5 meses atrás | |
| gat_lstm.py | 5 meses atrás | |
| main.py | 5 meses atrás | |
| model.pth | 5 meses atrás | |
| predict.py | 5 meses atrás | |
| scaler.pkl | 5 meses atrás | |
这是一个用于预测反渗透(RO)系统未来90天压力差变化的长期趋势预测模型。与20分钟模型不同,这个模型关注的是长期的膜污染趋势。
预测目标:8个RO压力差指标
C.M.RO1-4_DB@DPT_1C.M.RO1-4_DB@DPT_2| 特性 | 20分钟模型 | 90天模型 |
|---|---|---|
| 预测时长 | 20分钟(5步) | 90天(2160步) |
| 时间分辨率 | 4分钟/点 | 1小时/点 |
| 输入历史 | 4小时(60点) | 180天(4320点) |
| 预测目标 | 16个指标 | 8个指标 |
| 输入特征 | 79个 | 16个 |
| 应用场景 | 实时监控、短期调度 | 长期趋势、维护计划 |
膜污染是一个缓慢累积的过程:
模型目标:预测未来90天内,每个RO膜组的压力差如何演变,从而:
过去180天 → [LSTM处理] → 未来90天
(4320小时) (2160小时)
为什么这么长?
不同于20分钟模型的79个特征,这里只用16个:
C.M.RO1-4_FT_JS@outC.M.RO_TT_ZJS@out、电导率 C.M.RO_Cond_ZJS@outC.M.RO1-4_DB@DPT_1/2(输入也是输出,捕捉自相关)为什么减少特征?
data_preprocessor.py)resolution = 60 # 每60条原始数据取1条
chunk = all_data.iloc[::60, :] # 从4秒一条变成4分钟一条
之后再在训练时按小时聚合
# 只编码年周期,不编码日周期(长期趋势不关心一天内变化)
day_year_sin = sin(2π × 天数 / 366)
day_year_cos = cos(2π × 天数 / 366)
# 超长窗口需要特殊处理
window_time_span = 1小时 × (4320 + 314) # 额外314小时buffer
# 训练样本生成:step_size=1(密集采样)
# 测试样本生成:step_size=2160(跳跃采样,节省计算)
为什么测试集跳跃采样?
gat_lstm.py)# 8个独立专家(对应8个压差指标)
class GAT_LSTM:
def __init__(self):
self.models = nn.ModuleList([SingleGATLSTM() for _ in range(8)])
class SingleGATLSTM:
# LSTM层
self.lstm = nn.LSTM(
input_size=16, # 输入16个特征
hidden_size=64, # 隐藏层64单元
num_layers=1, # 单层LSTM
batch_first=True
)
# 输出层
self.final_linear = nn.Sequential(
nn.Linear(64, 64),
nn.LeakyReLU(0.01),
nn.Dropout(0),
nn.Linear(64, 2160) # 输出2160步(90天)
)
注意:虽然输入序列长达4320,但LSTM的隐藏层只有64维:
data_trainer.py)for epoch in range(1000):
# 前向传播
outputs = model(inputs) # [batch, 2160×8]
# 计算MSE损失
loss = MSELoss(outputs, targets)
# 反向传播
loss.backward()
optimizer.step()
# 验证
val_loss = validate(val_loader)
# 早停
if val_loss没有改善超过500轮:
break
batch_size = 128 # 比20分钟模型小(1024 vs 128)
# 因为每个样本更长,内存占用大
learning_rate = 0.01 # 学习率相同
scheduler_step = 100 # 每100轮衰减0.9
data_trainer.py)# 模型输出:[样本数, 2160×8]
# 需要重塑为:[样本数, 2160步, 8个指标]
predictions = predictions.reshape(n_samples, 2160, 8)
# 再展平为:[样本数×2160, 8]用于反归一化
predictions = predictions.reshape(-1, 8)
# 只反归一化最后8列(压差指标)
column_scaler = MinMaxScaler()
column_scaler.min_ = scaler.min_[-8:]
column_scaler.scale_ = scaler.scale_[-8:]
predictions = column_scaler.inverse_transform(predictions)
predict.py)class Predictor:
# 参数设置
seq_len = 4320 # 需要180天历史数据
output_size = 2160 # 预测90天
feature_num = 16 # 16个输入特征
labels_num = 8 # 8个预测目标
历史数据准备:
预测起始时间:
# 预测起点 = 最新数据时间 + 3小时
test_start_date = max_date + timedelta(hours=3)
多重平滑处理:
# 对预测结果进行3层平滑(减少噪声)
predictions = moving_average_smooth(predictions)
predictions = exponential_smooth(predictions)
predictions = savitzky_golay_smooth(predictions) # 可选
为什么需要平滑?
window = 30 # 30小时窗口
smoothed = convolve(data, window)
简单有效,适合去除高频噪声
EMA[t] = α × data[t] + (1-α) × EMA[t-1]
近期数据权重更高,适合捕捉趋势变化
# 用多项式拟合窗口内的数据
savgol_filter(data, window=25, polyorder=2)
保留趋势的同时降噪,适合平滑的长期曲线
| 参数 | 值 | 说明 |
|---|---|---|
seq_len |
4320 | 输入历史长度(180天) |
output_size |
2160 | 预测未来步数(90天) |
feature_num |
16 | 输入特征数 |
labels_num |
8 | 预测目标数 |
hidden_size |
64 | LSTM隐藏层大小 |
batch_size |
128 | 每批训练样本数 |
lr |
0.01 | 初始学习率 |
epochs |
1000 | 最大训练轮数 |
patience |
500 | 早停耐心值 |
90天TMP预测模型源码/
├── args.py # 参数配置(长期预测专用参数)
├── data_preprocessor.py # 数据预处理(年周期编码、长序列处理)
├── gat_lstm.py # 模型定义(8个专家模型)
├── data_trainer.py # 训练器(与20分钟版本类似)
├── main.py # 训练入口
├── predict.py # 预测接口(包含多重平滑)
├── model.pth # 训练好的模型权重
└── scaler.pkl # 归一化器
# 预测90天后的压差
predictions = predictor.predict(historical_data)
# 找出何时需要CEB
threshold = 0.20 # 压差超过0.20 MPa需要清洗
ceb_dates = find_dates_above_threshold(predictions, threshold)
# 分析压差上升速率
rate = (predictions[-1] - predictions[0]) / 90 # 平均每天增速
expected_lifetime = (max_TMP - current_TMP) / rate
# 对比不同运行参数下的长期压差
scenario_A = predict_with_params(flow=300)
scenario_B = predict_with_params(flow=360)
增加外部因素:
改进模型结构:
集成多模型:
# 使用更小的batch_size
batch_size = 64
# 减少训练数据量(只用近期数据)
start_files = 5 # 从第5个文件开始
# 降低采样率
step_size = 10 # 训练时每10步取1个样本
Q:为什么用4320步输入,而不是更短?
A:膜污染是周期性+趋势性的复合过程,需要看足够长的历史才能区分周期波动和长期趋势。
Q:预测90天会不会太长?
A:对于膜污染这种缓慢过程,90天只是一个CEB周期。实际应用中可以每周重新预测,不断修正。
Q:如何判断模型是否学到了长期趋势?
A:绘制预测曲线,看是否捕捉到压差的缓慢上升。如果曲线波动剧烈,可能只学到了短期噪声。
Q:能否用这个模型做短期预测?
A:不建议。这个模型牺牲了短期精度换取长期趋势,用于短期预测反而不如20分钟模型。