跳转到内容

冰箱温控 ​

本例使用温度、制冷动作与开门记录学习冰箱热过程,再训练 PPO 策略将箱内温度保持在 −2°C。通过独立温控仿真观察降温过程、扰动恢复和稳态误差。

1. 任务背景与目标 ​

制冷、漏热与开门扰动 ​

冰箱需要把储存空间维持在目标温度附近。制冷执行器从箱内移走热量,箱体同时与外界换热;开门时换热增强,温度会更快回升。制冷动作的效果还取决于当前温度与环境温度之差,所以相同功率在不同温度下不一定产生相同的温降。

控制过程可分为初始降温和稳定保持两个阶段。前者需要尽快接近目标,后者需要补偿漏热,并在开门后恢复。制冷过弱会长期偏暖,制冷过强又会造成过冷和不必要的动作波动。

本例把门状态视为外部扰动:世界模型使用它解释温度变化,策略则只根据当前温度调节制冷。这样的图结构区分了“影响对象的变量”和“控制器实际读取的变量”,也决定了后续数据中必须同时记录温度、动作和门状态。

控温目标与评价 ​

目标是将箱内温度从约 10°C 调到 -2°C 并稳定跟踪。室外温度为 15°C, 开门会增强换热、使箱内温度更快回升。控制量 action 是非负制冷功率,示例配置限定范围为 [0, 10]。 这里的功率尺度和上限是仿真任务约定,不能直接解释成真实压缩机的额定功率。

制冷执行器降低箱内温度,开门和环境换热形成外扰,策略根据温度观测调节制冷动作

图:任务对象及其作用与反馈关系。实线表示物理作用,虚线表示观测与控制信号。

策略只读取温度 temperature;世界模型还读取外生扰动 door_open。 这是本案例的观测接口选择,并不是说实际冰箱一定无法获取门磁信号。

examples/refrigerator/reward.py 的当前奖励为:

text
r_t = -|next_temperature - (-2)|

奖励越接近 0 越好。功率惩罚权重为 0,因此本教程评价的是控温效果,不宣称节能优化。 温度记录和评估返回值含测量噪声;本文的温度 MAE 是观测温度误差,不是隐藏物理温度误差。

2. 数据与准备 ​

为区分主动制冷与开门导致的温变,每一行数据包含动作执行前温度、该步制冷动作、同一步门状态及执行后的温度。开门状态是动力学输入,下一步温度是监督标签;策略使用的观测仍只有当前温度。

data/refrigeration.npz 的标准数据是 1 条轨迹 × 2000 步,不是多条独立轨迹。 采样初温为 10°C,采样间隔为 1 个仿真时间单位。采集策略使用带噪声的比例控制, 其内部设定点为 -3.75°C;开门安排以 200 步为窗口、每次开门持续约 20 步。

Key标准 Shape含义
temperature[2000, 1]当前观测温度,含标准差 0.1°C 的高斯测量噪声
action[2000, 1]历史制冷动作
door_open[2000, 1]门开关,0/1,外生扰动
next_temperature[2000, 1]执行动作后的下一步观测温度
index[1]轨迹结束下标(exclusive),值为 [2000]

已有这份数据时直接复用,无需重新采集或额外预处理。只有缺失数据且允许仿真采集时, 才运行以下可选步骤(从源码仓库根目录进入案例):

bash
cd examples/refrigerator
python prepare_data.py

prepare_data.py 会运行仿真器生成数据。已有数据默认复用;需要重新生成时使用 python prepare_data.py --force。 纯离线条件下不要运行它;缺少数据时应先取得已有数据文件。 之后的世界模型训练和策略优化只消费离线数据及学到的世界模型,不调用该采集仿真器。

train_ratio: 0.5 是本例固定的训练/验证划分。仅有一条轨迹时,框架从跨轨迹划分回退为 轨迹内前后划分:前半段训练、后半段验证。验证段与训练段属于同一次连续运行;独立测试另用不同初温和开门安排。

3. 建模与配置 ​

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

yaml
name: refrigerator
version: '2.0'
graph:
  nodes:
    action:
      inputs: [temperature]
      network:
        backbone: mlp
        hidden_dims: [128, 128]
        activation: leakyrelu
      output_dist: TanhNormal
    delta_temperature:
      inputs: [temperature, action, door_open]
      network:
        backbone: mlp
        hidden_dims: [128, 128]
        activation: leakyrelu
      output_dist: TanhNormal
    next_temperature:
      inputs: [temperature, delta_temperature]
      function: builtin.delta_add
  transitions: auto
  columns:
    temperature: [temp]
    action:
    - {name: power, min: 0.0, max: 10.0}
    door_open: [door]
data: {train_ratio: 0.5, batch_size: 256}
training:
  device: auto
  stages:
  - name: venv
    algorithm: venv.revive_p
    hyperparameters:
      epochs: 500
      bc:
        optimizer: {lr: 0.0001, weight_decay: 1.0e-06}
        grad_clip: 50
        loss: nll
      adversarial:
        start_epoch: 0
        enabled: true
        ood: {d_lr: 0.0006}
        rollout: {horizon: 50, batch_size: 512}
    validation:
      rollout: {enabled: true, interval: 10, horizon: 50, num_trajectories: 5}
      selection: {metric: val/rollout/mae, mode: min}
  - name: policy
    algorithm: policy.ppo
    inherit_from: venv
    hyperparameters:
      policy_nodes: [action]
      epochs: 1000
      rollout_horizon: 100
      optimizer: {lr: 4.0e-05}
      grad_clip: 50
      epsilon: 0.2
      gamma: 0.99
      gae_lambda: 0.95
      num_rollout_trajs: 256
      value_hidden_dims: [128, 128]
      reward: {path: reward.py, function: get_reward}
    validation:
      rollout:
        enabled: true
        interval: 1
        force_final: true
        horizon: 100
        metrics: [reward_mean]
      selection: {metric: val/rollout/reward_mean, mode: max}
output:
  save_freq: 10
  tensorboard: true
  onnx: {required: true}

配置入口 ​

配置世界模型阶段策略阶段用途与运行规模
examples/refrigerator/config.yamlvenv.revive_ppolicy.ppo默认训练方案;500 + 1000 epoch
examples/refrigerator/config.bc.yamlvenv.bcpolicy.ppo纯监督世界模型对照;500 + 1000 epoch
examples/refrigerator/config.min.yamlvenv.revive_ppolicy.ppo精简声明,保留对抗和两阶段;未写的参数使用默认值

config.min.yaml 的“最小”指配置写法精简,不表示只有世界模型,也不表示默认训练规模很小。 需要检查流程时使用 --profile smoke;正式训练使用对应完整配置。 config.bc.yaml 将世界模型算法改为 venv.bc,并使用该算法的监督学习参数结构, 不是仅把一个 adversarial.enabled 开关改成 false。它与默认配置保持相同图结构、主要训练参数和 PPO 设置,适合作为监督训练对照。

图结构与外生输入 ​

text
action            ← temperature                         (策略:制冷动作)
delta_temperature ← temperature, action, door_open      (学习温度增量)
next_temperature  ← temperature, delta_temperature      (builtin.delta_add)
transition: temperature ← next_temperature

door_open 没有生成节点,是外生输入。训练和模型内 rollout 使用数据中的开门序列; 独立仿真测试则由评估器生成开门安排。应核对三处变量的物理含义是否一致,并分别评估不同开门安排下的数据分布。

模型调用端door_open 如何进入策略是否直接观测
世界模型训练/验证从数据取值,rollout 自动推断并回放外生列否
PPO 模型内推演逐步回放数据的外生序列否
独立仿真评估评估器生成门状态并传给仿真器否,仅向策略提供温度

不输入门状态的模型可能把开门导致的温变混入未解释误差,影响多步预测;误差方向和幅度仍需验证,不能预设。 外部输入和真实前缀的使用方法见历史窗口。

配置逐块讲解 ​

graph:观测、动作与动力学 ​

action 只输入 temperature;delta_temperature 输入温度、动作和开门状态。 两个学习节点均为两层 [128, 128] MLP、leakyrelu、TanhNormal。 next_temperature 通过 builtin.delta_add 将当前温度与预测增量相加。 动作列的 min: 0.0、max: 10.0 声明本例允许的制冷范围;迁移到设备时必须重新确认范围和单位。

data:数据划分与批量 ​

train_ratio: 0.5、batch_size: 256。单轨迹划分的限制见前面的数据说明; 验证集误差仅反映当前评估条件;其他开门安排或初始温度下的精度需要单独验证。

training.stages[venv]:世界模型 ​

参数当前值与作用
algorithm / epochsvenv.revive_p / 500
bc.loss / bc.optimizer.lrnll / 1e-4,监督学习部分
adversarial.enabled / adversarial.start_epochtrue / 0,从首轮使用对抗训练
adversarial.rollout.horizon50,训练时的多步窗口
validation.rollout每 10 轮验证,horizon 50、5 条验证轨迹窗口
validation.selection.metric / modeval/rollout/mae / min,按多步误差选世界模型

training.stages[policy]:PPO 策略 ​

algorithm: policy.ppo,inherit_from: venv 消费前一阶段选出的世界模型;策略训练不需要原采集控制器。

参数当前值与作用
epochs / rollout_horizon1000 / 100,在模型内优化 100 步控制过程
optimizer.lr / num_rollout_trajs4e-5 / 256
epsilon / gamma / gae_lambda0.2 / 0.99 / 0.95
reward.path / reward.functionreward.py / get_reward;路径相对 YAML 所在目录
validation.rollout每轮验证并强制最终验证,horizon 100
validation.selection.metric / modeval/rollout/reward_mean / max,按模型内回报选策略

output:模型保存与导出 ​

默认 best_only 保留最优模型及同轮续训态,tensorboard: true 启用日志;save_freq 仅在 legacy 模式生效。 onnx.required: true 要求完成 ONNX 导出及一致性校验。 models/env.pt 用于预测,models/policy.pt 用于输出制冷动作;控温效果由下一节的仿真评估。

4. 训练与选模 ​

以下命令均在 examples/refrigerator 目录执行,并假定数据已经存在。 先验证配置与数据接口,再启动完整配置的训练:

bash
revive validate --config config.yaml --data data/refrigeration.npz
revive train --config config.yaml --train-data data/refrigeration.npz \
  --run-id repro --log-dir logs --seed 42

若只需检查流程,可单独运行以下替代命令。该模式的结果仅用于流程验证:

bash
revive train --config config.min.yaml --train-data data/refrigeration.npz \
  --run-id refrigerator-case-smoke --log-dir logs --seed 42 --profile smoke

训练按 YAML 的两个 stage 顺序执行;无需另传阶段列表。查看 logs/repro/report.md、 阶段验证指标和 logs/repro/models/,确认选模依据和导出状态。 最终控制测试加载 logs/repro/models/policy.pt,不是根据训练损失手工挑出的任意 checkpoint。 每次训练使用独立 run ID。

一键运行与输出文件 ​

以下是一键替代路线,不要在分步训练后无意中再次运行同名训练:

bash
bash run_all.sh repro
bash run_all.sh repro_bc config.bc.yaml

默认配置仍是 config.yaml,训练种子仍是 42。脚本复用已有数据;缺失数据或设置 FORCE_PREPARE 时会调用采集脚本。训练后会调用评估器两次:一次打印,另一次写入 logs/<run_id>/flagship.json。 两次使用相同默认协议,不能计作两组新增的独立测试样本。 因此它不是纯离线命令;需要隔离仿真步数时,使用上面的分步路线。

核心文件为 examples/refrigerator/prepare_data.py、examples/refrigerator/reward.py、examples/refrigerator/evaluate.py 和 examples/refrigerator/run_all.sh;数据、训练日志和模型位于本目录的 data/、logs/<run_id>/。

5. 模型使用与评估 ​

固定策略后执行:

bash
python evaluate.py --model logs/repro/models/policy.pt --episodes 100 --steps 100 --seed 0

评估协议 ​

参数默认值
--episodes100
--steps100
--seed0

每集初温从 [6, 12] 均匀采样,开门安排为随机短时段,与原数据的开门窗口不同。 动作执行前裁剪到 [0, 10]。这里的独立仿真器不是训练得到的世界模型,也不是现场设备。

输出解读
real_reward_mean / real_reward_std每集未折扣奖励求和后,跨集计算均值/标准差
real_reward_mean_per_step平均每步奖励,消除求和的步数倍数,但不消除状态分布差异
real_tracking_mae全程观测温度相对 -2°C 的 MAE,越小越好
real_settle_mae每集末 20% 步数的观测温度 MAE
real_final_temp_mean末态观测温度均值,不能单独反映过程波动

需要机器可读结果时,在同一评估命令末尾添加 --json,结果输出到标准输出。 它会重新执行评估,不是读取上一次结果。当前脚本不自动保存完整温度曲线。

当前框架的 val/rollout/reward_mean 是平均每步奖励,对应这里的 real_reward_mean_per_step;val/rollout/return_mean 才是整段回报均值,对应这里的 real_reward_mean。比较结果时先核对字段对应的统计窗口和计算方式。 训练与测试使用同一奖励函数,但只有同时核对初态、扰动、步数和汇总方式后, 才能合理比较模型内回报与独立仿真回报;同一公式不意味着同分布的两次测量。

6. 结果与分析 ​

训练 seed 为 42,策略在 100 集、每集 100 步的温控仿真中评估。初温从 [6, 12]°C 采样,并加入随机开门扰动。

指标REVIVE-P + PPOBC + PPO
回合回报均值-35.2746-35.4019
回合回报标准差5.96595.9753
稳态温度 MAE(°C)0.173010.17456
世界模型多步 MAE0.0537640.053774
世界模型多步 MSE0.0051220.005132

两条路线的预测误差和控制效果接近,稳态温度 MAE 约为 0.17°C。回报衡量整个降温和保持过程,稳态 MAE 只统计末 20% 步数,因此二者反映不同阶段的控制质量。

数据行为与学习策略 ​

指标采集数据REVIVE-P + PPO 仿真评估
平均每步奖励-0.5182-0.3527
温度跟踪 MAE(°C)0.51820.3527

采集数据是连续长轨迹,评估是多次独立重置,初温与开门安排不同。数据列用于理解训练样本中的控温水平;比较两种学习方案时,以相同仿真条件下的结果为准。

由于奖励仅惩罚温度误差,本结果说明控温表现。若业务同时关注用电量,需要在奖励与评估中另加功率或能耗指标。

7. 迁移到实际业务 ​

迁移时先确认数据单位、观测关系和动作边界,再修改图结构、训练与验证,最后调整奖励和业务验收标准。 PID/MPC 等控制器是可选扩展,本例主线使用 PPO,不能当作这些控制器已验证的成绩。

  • 多控制节点:协调多个执行器,并在共享奖励中表达业务目标。
  • 算法怎么选:世界模型、策略与控制器的选择。
  • 倒立摆:摆起与稳定控制的两阶段任务。

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