跳转到内容

暖通控制 ​

本例使用建筑温度、供暖功率、天气与日程数据训练热过程模型,再构建 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 使用执行动作后的区温,当前奖励为:

text
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 天,不能声称这份默认数据已经覆盖周末。

已有文件直接复用,不需另行预处理。只有缺失数据且允许仿真采集时,才从源码仓库根目录运行:

bash
cd examples/hvac_zone
python prepare_data.py

采集脚本会与 RC 仿真对象交互,并覆盖输出 NPZ。 纯离线条件下应取得已有数据文件并跳过此步骤。

数据生成参数 ​

参数默认值
--trajectories30
--days4
--seed20260822

3. 建模与配置 ​

下面先展示 examples/hvac_zone/config.yaml 的配置,再结合本任务逐块解释。训练命令使用同一文件。

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.yamlvenv.revive_pcontroller.mpc默认完整路线;世界模型 500 epoch,MPC 验证与导出
examples/hvac_zone/configs/revive_p_ffpid.yamlvenv.revive_pcontroller.ffpid对照路线;世界模型 500 epoch,最多 36 个增益组合
examples/hvac_zone/config.min.yamlvenv.revive_pcontroller.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.yamlconfigs/revive_p_ffpid.yaml
tune.modevalidate_onlytwo_stage
tune.max_trials—36
tune.top_k—6
tune.fast_eval_segments816
tune.full_eval_segments1224
tune.eval_horizon9696

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 目录执行,假定数据已存在:

bash
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 时使用以下替代路线:

bash
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
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. 模型使用与评估 ​

固定候选后运行:

bash
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 --json

FFPID 对应 logs/full_ffpid/models/policy.pt。三种模式 --dataset、--baseline、--model 只能选一个。数据模式只复算已有轨迹、不推进仿真,轨迹数和边界来自 NPZ; 汇总脚本按第一条轨迹长度计算逐步均值,变长轨迹需要另核统计方法。

评估协议 ​

参数默认值
--episodes12
--days4
--seed20260901

基线与候选使用相同的环境 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 + FFPIDREVIVE-P + MPC
平均每步奖励-1.304-0.952-0.450-0.387
在室舒适超标幅度(K)0.7270.4450.0470.011
在室越界时长占比71.0%85.8%4.0%8.4%
每回合电费46.9546.3952.7549.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;它们不是现场验收承诺。

阅读任务页约定,区分数据准备、训练验证和独立评估。