暖通控制
本例使用建筑温度、供暖功率、天气与日程数据训练热过程模型,再构建 MPC 或 FFPID 控制器,在人员舒适度与供暖费用之间进行优化。
1. 任务背景与目标
室内空气与墙体共同决定温度响应
建筑供暖需要在舒适度和运行费用之间取得平衡。空气升温较快,墙体和围护结构储热、放热较慢,因此关小供暖后室温仍可能继续变化。本例用室内空气与墙体两个热状态描述这种热惯性。
室外温度决定建筑向外散热的条件,太阳辐射和人员活动提供额外热量,使用日程决定何时需要较高的舒适温度。控制器需要在人员到达前适当预热,并在无人时段降低目标;分时电价则影响提前供暖是否划算。
由此,建模需要把供暖功率与天气、日程分开:前者是可调动作,后两者是外部输入。世界模型学习不同条件下的温度响应,MPC 用它比较未来一段时间的供暖方案;FFPID 则提供结构较简单的对照。
舒适度、控制周期与费用
对象包含区内空气与围护结构两个温度状态;供暖同时受室外温、日射、人员内扰影响。 当前仿真设定如下:
图:任务对象及其作用与反馈关系。实线表示物理作用,虚线表示观测与控制信号。
| 项目 | 任务定义 |
|---|---|
| 状态 | zone = [t_zone, t_wall],区温与墙温 |
| 动作 | 供暖功率 [0, 10] kW |
| 控制周期 | 15 分钟,即 0.25 h |
| 在室日程 | 工作日 8:00~18:00,目标 21°C |
| 无人日程 | 回落目标 16°C |
| 在室舒适带 | 目标温度 ±1 K |
| 外生输入 | 天气 weather、人员/设定值/电价 schedule |
供暖功率增加通常提高温度,因此本例使用正增益控制器配置。迁移到制冷或其他反向作用的任务时,应根据实际过程调整控制方向。
examples/hvac_zone/reward.py 使用执行动作后的区温,当前奖励为:
excess = max(|T_zone_next - setpoint| - 1, 0)
comfort = excess² # 在室
comfort = max(setpoint - T_zone_next, 0) # 无人
energy = price × heat × 0.25
r_t = -comfort - 3 × energy在室时惩罚超出舒适带的幅度平方,无人时只惩罚低于回落目标的温度。 电价为仿真单位价格,电费不是实际账单;总回报提高不一定表示电费下降,必须拆开看。
2. 数据与准备
一条轨迹需要覆盖升温、保持和日程切换,温度、供暖功率、天气与日程必须按同一个 15 分钟时刻对齐。墙温帮助模型表达储热,室外温和日射解释外部换热,在室标记与电价用于控制目标和后续方案比较。
默认 data/hvac_zone.npz 是 30 条轨迹 × 4 天,每条 384 步,共 11520 个转移。 采集控制器为比例恒温器:每条轨迹重抽增益与目标偏置、叠加动作抖动,并插入固定功率阶跃。 它不利用未来天气或电价规划,也不同于无激励的固定基线。
| Key | 标准 Shape | 含义 |
|---|---|---|
zone | [11520, 2] | 当前区温、墙温 |
action | [11520, 1] | 供暖功率 |
weather | [11520, 2] | 室外温、日射系数 |
schedule | [11520, 3] | 在室标记、设定值、电价 |
next_zone | [11520, 2] | 下一步区温、墙温 |
index | [30] | 轨迹结束下标(exclusive) |
天气发生器包含日周期、逐日变化与 AR(1) 残差,这是天气扰动,不是区温仪表测量噪声。 仿真日历包含周末规则,但默认每条轨迹从第 0 天运行 4 天,不能声称这份默认数据已经覆盖周末。
已有文件直接复用,不需另行预处理。只有缺失数据且允许仿真采集时,才从源码仓库根目录运行:
cd examples/hvac_zone
python prepare_data.py采集脚本会与 RC 仿真对象交互,并覆盖输出 NPZ。 纯离线条件下应取得已有数据文件并跳过此步骤。
数据生成参数
| 参数 | 默认值 |
|---|---|
--trajectories | 30 |
--days | 4 |
--seed | 20260822 |
3. 建模与配置
下面先展示 examples/hvac_zone/config.yaml 的配置,再结合本任务逐块解释。训练命令使用同一文件。
name: hvac_zone
version: '2.0'
graph:
nodes:
action:
inputs: [zone, schedule]
network:
backbone: mlp
hidden_dims: [128, 128]
activation: leakyrelu
output_dist: TanhNormal
delta_zone:
inputs: [zone, action, weather, schedule]
network:
backbone: mlp
hidden_dims: [256, 256]
activation: leakyrelu
output_dist: TanhNormal
next_zone:
inputs: [zone, delta_zone]
function: builtin.delta_add
transitions: auto
columns:
zone: [t_zone, t_wall]
action:
- {name: heat, min: 0.0, max: 10.0}
weather: [t_out, solar]
schedule: [occupancy, setpoint, price]
data: {train_ratio: 0.75, batch_size: 256}
training:
device: auto
stages:
- name: venv
algorithm: venv.revive_p
hyperparameters:
epochs: 500
bc:
optimizer: {lr: 0.0003, weight_decay: 1.0e-06}
grad_clip: 50
loss: nll
adversarial:
start_epoch: 0
enabled: true
ood: {d_lr: 0.0006}
rollout: {horizon: 48, batch_size: 512}
validation:
rollout: {enabled: true, interval: 10, horizon: 48, num_trajectories: 8}
selection: {metric: val/rollout/mae, mode: min}
- name: policy
algorithm: controller.mpc
inherit_from: venv
hyperparameters:
method: cem
horizon: 24
num_samples: 128
num_elites: 16
num_iterations: 4
temperature: 1.0
gamma: 0.99
deterministic: true
use_policy_prior: false
warm_start: false
future_exogenous_keys: [weather, schedule]
seed: 0
action_bounds:
action: [0.0, 10.0]
tune: {enabled: true, mode: validate_only, fast_eval_segments: 8, full_eval_segments: 12, eval_horizon: 96,
seed: 42}
policy_nodes: [action]
reward: {path: reward.py, function: get_reward}
output:
save_freq: 20
tensorboard: true
onnx: {required: true, atol: 0.0001}配置入口
| 配置 | 世界模型阶段 | 控制器阶段 | 用途与运行规模 |
|---|---|---|---|
examples/hvac_zone/config.yaml | venv.revive_p | controller.mpc | 默认完整路线;世界模型 500 epoch,MPC 验证与导出 |
examples/hvac_zone/configs/revive_p_ffpid.yaml | venv.revive_p | controller.ffpid | 对照路线;世界模型 500 epoch,最多 36 个增益组合 |
examples/hvac_zone/config.min.yaml | venv.revive_p | controller.mpc | 最小声明,仍有两阶段;未写字段由默认层补齐 |
两份完整配置的图、数据配置和世界模型阶段相同,但分别运行训练不等于已经共享同一模型文件。 控制器结构、搜索方式与可用未来信息都不同,分数差不能直接归因为“前瞻能力”的单独贡献。
config.min.yaml 没有显式保留主配置方案的规划窗、未来天气/日程键和导出容差, 不是完整配置方案的等价缩写,也不是“只训练世界模型”。 本教程完整训练使用 config.yaml;查看生效值可用 revive validate --show-defaults。
配置逐块讲解
graph:状态、动作和未来信息
action ← zone, schedule 使用 [128, 128] MLP; delta_zone ← zone, action, weather, schedule 使用 [256, 256] MLP。 两个节点为 leakyrelu、TanhNormal,next_zone 用 builtin.delta_add 合成, transitions: auto 推断 zone ← next_zone。
weather 与 schedule 是外生列,模型内推演从数据回放。动作节点可拟合历史行为分布, 但默认 MPC 配置的 use_policy_prior: false,不能将其解释为正在使用该网络作 CEM 先验。
data:切分与批量
train_ratio: 0.75、batch_size: 256。保留轨迹边界,并从解析配置和报告核对实际划分。 单一建筑参数和有限天气分布上的验证,不代表跨建筑泛化。
training.stages[venv]:世界模型
venv.revive_p 训练 500 epoch;监督部分学习率 3e-4、nll 损失、梯度裁剪 50。 从第 0 轮启用对抗,训练推演 horizon 48、batch_size 512; 每 10 轮验证 8 个长度 48 的窗口,按 val/rollout/mae 的最小值选模。
48 步等于 12 小时,不是完整的 24 小时昼夜周期。 这一窗口用于观察空气与墙体的热惯性;是否足够支撑控制仍需多步误差和闭环验证。
training.stages[policy]:MPC 与 FFPID
inherit_from: venv 消费选中的世界模型。MPC 使用 CEM、horizon 24(6 小时)、 128 个候选、16 个精英、4 次迭代;warm_start 与 use_policy_prior 均为 false。
future_exogenous_keys: [weather, schedule] 使规划器读取未来天气、人员、设定值和电价。 当前评估器传入的是仿真未来真值,不是带误差的天气预报。 这些结果只能说明该信息假设下的表现,不能直接推断实际预报条件下的收益。
FFPID 对照读取 zone[0] 和 schedule[1],固定 kd: 0; anti_windup: clamp、integral_limit: 100 沿用现有配置。 它的前馈项是 kff × setpoint,不是室外温或天气扰动前馈,也不读取未来序列。 当前网格:kp [3, 6, 12]、ki [0, 0.02, 0.05]、kff [0.1, 0.2, 0.3, 0.4]; 允许 ki=0,不能预先断言效果提升一定来自积分。
控制器评估规模
| 参数 | config.yaml | configs/revive_p_ffpid.yaml |
|---|---|---|
tune.mode | validate_only | two_stage |
tune.max_trials | — | 36 |
tune.top_k | — | 6 |
tune.fast_eval_segments | 8 | 16 |
tune.full_eval_segments | 12 | 24 |
tune.eval_horizon | 96 | 96 |
MPC 只验证并导出,不搜索增益;FFPID 先快速排序,再完整评估前 6 个候选。 96 步对应一天的模型内控制评估。表中 — 表示未显式配置,不表示无限预算。 reward.path 相对 YAML 所在目录解析,变体的 ../reward.py 仍指向同一文件。
output:输出文件与导出
默认 best_only 保留最优模型及同轮续训态,tensorboard: true 记录训练指标;save_freq 仅在 legacy 模式生效。 onnx.required: true 要求导出和一致性校验, onnx.atol: 1e-4 保留当前配置方案。容差是数值一致性要求,不是温控精度或仪表精度的证明。
4. 训练与选模
以下命令在 examples/hvac_zone 目录执行,假定数据已存在:
revive validate --config config.yaml --data data/hvac_zone.npz
revive train --config config.yaml --train-data data/hvac_zone.npz \
--run-id full_mpc --log-dir logs --seed 42选择 FFPID 时使用以下替代路线:
revive train --config configs/revive_p_ffpid.yaml --train-data data/hvac_zone.npz \
--run-id full_ffpid --log-dir logs --seed 42检查 logs/<run_id>/report.md、config.resolved.yaml、世界模型验证指标、 控制器排序结果及 models/policy.pt。世界模型误差小和模型内回报高都不保证外部控制成功。
仅检查流程时可加 --profile smoke 并换新 run ID; 当前 smoke 不压缩控制器的 CEM 采样数、tune 候选数或验证窗口,仍可能耗时。 正式比较控制效果时使用完整训练配置;每次训练使用独立 run ID。
一键路线与文件
bash run_all.sh full_mpc
bash run_all.sh full_ffpid configs/revive_p_ffpid.yaml它是分步操作的替代:默认配置仍为 config.yaml、训练 seed 42。 已有数据则复用,缺失或设置 FORCE_PREPARE 时重新采集;随后评固定基线一次、候选两次, 最后一次写 logs/<run_id>/flagship.json。候选两次使用相同协议,不构成两组独立样本。 一键命令不是纯离线命令;主要脚本为 examples/hvac_zone/prepare_data.py、examples/hvac_zone/evaluate.py、examples/hvac_zone/run_all.sh。
5. 模型使用与评估
固定候选后运行:
python evaluate.py --dataset --json
python evaluate.py --baseline --episodes 12 --days 4 --seed 20260901 --json
python evaluate.py --model logs/full_mpc/models/policy.pt \
--episodes 12 --days 4 --seed 20260901 --jsonFFPID 对应 logs/full_ffpid/models/policy.pt。三种模式 --dataset、--baseline、--model 只能选一个。数据模式只复算已有轨迹、不推进仿真,轨迹数和边界来自 NPZ; 汇总脚本按第一条轨迹长度计算逐步均值,变长轨迹需要另核统计方法。
评估协议
| 参数 | 默认值 |
|---|---|
--episodes | 12 |
--days | 4 |
--seed | 20260901 |
基线与候选使用相同的环境 seeds(起始 seed 加回合序号),保持初态、天气和日程一致。 固定基线使用采集增益/偏置区间中点,不加抖动或阶跃激励。 MPC 还额外读取未来真值;共同工况不意味着控制器获得的信息相同。
| 指标 | 含义 |
|---|---|
real_return_mean/std | 每集奖励求和后的跨集均值/标准差 |
real_reward_mean_per_step | 平均每步奖励 |
real_comfort_excess_k | 在室步的超舒适带幅度均值,带内按 0 计 |
real_comfort_violation_rate | 在室步中超出舒适带的比例 |
real_energy_cost | 每回合仿真电费的均值 |
超标幅度与超标时长必须并排看,它们可能对候选给出不同排序。 框架 val/rollout/reward_mean 是每步量,val/rollout/return_mean 是整段量; 模型内默认控制评估为 96 步、外部为 384 步,不能直接对回报和作差。 使用 --json 会执行所选评估,不是读取上一轮结果。
6. 结果与分析
数据为 30 条、每条 4 天的轨迹。仿真评估使用 12 个相同初态与天气日程,每个回合 4 天、384 步,起始 seed 为 20260901。
| 指标 | 数据行为 | 固定比例基线 | REVIVE-P + FFPID | REVIVE-P + MPC |
|---|---|---|---|---|
| 平均每步奖励 | -1.304 | -0.952 | -0.450 | -0.387 |
| 在室舒适超标幅度(K) | 0.727 | 0.445 | 0.047 | 0.011 |
| 在室越界时长占比 | 71.0% | 85.8% | 4.0% | 8.4% |
| 每回合电费 | 46.95 | 46.39 | 52.75 | 49.38 |
两种学习控制器都显著改善了在室温度。MPC 的平均超标幅度更小,FFPID 的越界时长占比更低,因此需要同时观察偏差大小和持续时间。
FFPID 与 MPC 的电费分别比固定基线高约 13.7% 和 6.4%。本例取得的是舒适度与电费加权目标下的改善,舒适度提高伴随额外供暖费用。调整奖励权重时,应重新比较这两项指标。
MPC 使用给定的未来天气与日程,FFPID 只使用当前输入。实际建筑中的天气预报误差需要作为独立测试条件,分别观察预报偏差对预热时机和舒适度的影响。
7. 迁移到实际业务
本例默认把墙温作为可观测状态,并假定未来天气真值可得。实际业务若缺少墙温测点、 仅有带误差的预报,必须重审观测结构和测试协议,需要重新评估控制效果。 动作上限 10 kW 也不证明任意天气下设定值可达;天气发生器的随机残差并非严格有界, 需按实际设计工况另查热负荷和执行器容量。
先评估热惯性与舒适/能耗指标,再设计预测误差、初态、不同日程与跨建筑测试。 数学仿真检查见 tests/unit/test_hvac_zone_env.py, 工程回归见 tests/perf/baselines.json;它们不是现场验收承诺。
阅读任务页约定,区分数据准备、训练验证和独立评估。