冰箱温控
本例使用温度、制冷动作与开门记录学习冰箱热过程,再训练 PPO 策略将箱内温度保持在 −2°C。通过独立温控仿真观察降温过程、扰动恢复和稳态误差。
1. 任务背景与目标
制冷、漏热与开门扰动
冰箱需要把储存空间维持在目标温度附近。制冷执行器从箱内移走热量,箱体同时与外界换热;开门时换热增强,温度会更快回升。制冷动作的效果还取决于当前温度与环境温度之差,所以相同功率在不同温度下不一定产生相同的温降。
控制过程可分为初始降温和稳定保持两个阶段。前者需要尽快接近目标,后者需要补偿漏热,并在开门后恢复。制冷过弱会长期偏暖,制冷过强又会造成过冷和不必要的动作波动。
本例把门状态视为外部扰动:世界模型使用它解释温度变化,策略则只根据当前温度调节制冷。这样的图结构区分了“影响对象的变量”和“控制器实际读取的变量”,也决定了后续数据中必须同时记录温度、动作和门状态。
控温目标与评价
目标是将箱内温度从约 10°C 调到 -2°C 并稳定跟踪。室外温度为 15°C, 开门会增强换热、使箱内温度更快回升。控制量 action 是非负制冷功率,示例配置限定范围为 [0, 10]。 这里的功率尺度和上限是仿真任务约定,不能直接解释成真实压缩机的额定功率。
图:任务对象及其作用与反馈关系。实线表示物理作用,虚线表示观测与控制信号。
策略只读取温度 temperature;世界模型还读取外生扰动 door_open。 这是本案例的观测接口选择,并不是说实际冰箱一定无法获取门磁信号。
examples/refrigerator/reward.py 的当前奖励为:
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] |
已有这份数据时直接复用,无需重新采集或额外预处理。只有缺失数据且允许仿真采集时, 才运行以下可选步骤(从源码仓库根目录进入案例):
cd examples/refrigerator
python prepare_data.pyprepare_data.py 会运行仿真器生成数据。已有数据默认复用;需要重新生成时使用 python prepare_data.py --force。 纯离线条件下不要运行它;缺少数据时应先取得已有数据文件。 之后的世界模型训练和策略优化只消费离线数据及学到的世界模型,不调用该采集仿真器。
train_ratio: 0.5 是本例固定的训练/验证划分。仅有一条轨迹时,框架从跨轨迹划分回退为 轨迹内前后划分:前半段训练、后半段验证。验证段与训练段属于同一次连续运行;独立测试另用不同初温和开门安排。
3. 建模与配置
下面先展示 examples/refrigerator/config.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.yaml | venv.revive_p | policy.ppo | 默认训练方案;500 + 1000 epoch |
examples/refrigerator/config.bc.yaml | venv.bc | policy.ppo | 纯监督世界模型对照;500 + 1000 epoch |
examples/refrigerator/config.min.yaml | venv.revive_p | policy.ppo | 精简声明,保留对抗和两阶段;未写的参数使用默认值 |
config.min.yaml 的“最小”指配置写法精简,不表示只有世界模型,也不表示默认训练规模很小。 需要检查流程时使用 --profile smoke;正式训练使用对应完整配置。 config.bc.yaml 将世界模型算法改为 venv.bc,并使用该算法的监督学习参数结构, 不是仅把一个 adversarial.enabled 开关改成 false。它与默认配置保持相同图结构、主要训练参数和 PPO 设置,适合作为监督训练对照。
图结构与外生输入
action ← temperature (策略:制冷动作)
delta_temperature ← temperature, action, door_open (学习温度增量)
next_temperature ← temperature, delta_temperature (builtin.delta_add)
transition: temperature ← next_temperaturedoor_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 / epochs | venv.revive_p / 500 |
bc.loss / bc.optimizer.lr | nll / 1e-4,监督学习部分 |
adversarial.enabled / adversarial.start_epoch | true / 0,从首轮使用对抗训练 |
adversarial.rollout.horizon | 50,训练时的多步窗口 |
validation.rollout | 每 10 轮验证,horizon 50、5 条验证轨迹窗口 |
validation.selection.metric / mode | val/rollout/mae / min,按多步误差选世界模型 |
training.stages[policy]:PPO 策略
algorithm: policy.ppo,inherit_from: venv 消费前一阶段选出的世界模型;策略训练不需要原采集控制器。
| 参数 | 当前值与作用 |
|---|---|
epochs / rollout_horizon | 1000 / 100,在模型内优化 100 步控制过程 |
optimizer.lr / num_rollout_trajs | 4e-5 / 256 |
epsilon / gamma / gae_lambda | 0.2 / 0.99 / 0.95 |
reward.path / reward.function | reward.py / get_reward;路径相对 YAML 所在目录 |
validation.rollout | 每轮验证并强制最终验证,horizon 100 |
validation.selection.metric / mode | val/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 目录执行,并假定数据已经存在。 先验证配置与数据接口,再启动完整配置的训练:
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若只需检查流程,可单独运行以下替代命令。该模式的结果仅用于流程验证:
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 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. 模型使用与评估
固定策略后执行:
python evaluate.py --model logs/repro/models/policy.pt --episodes 100 --steps 100 --seed 0评估协议
| 参数 | 默认值 |
|---|---|
--episodes | 100 |
--steps | 100 |
--seed | 0 |
每集初温从 [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 + PPO | BC + PPO |
|---|---|---|
| 回合回报均值 | -35.2746 | -35.4019 |
| 回合回报标准差 | 5.9659 | 5.9753 |
| 稳态温度 MAE(°C) | 0.17301 | 0.17456 |
| 世界模型多步 MAE | 0.053764 | 0.053774 |
| 世界模型多步 MSE | 0.005122 | 0.005132 |
两条路线的预测误差和控制效果接近,稳态温度 MAE 约为 0.17°C。回报衡量整个降温和保持过程,稳态 MAE 只统计末 20% 步数,因此二者反映不同阶段的控制质量。
数据行为与学习策略
| 指标 | 采集数据 | REVIVE-P + PPO 仿真评估 |
|---|---|---|
| 平均每步奖励 | -0.5182 | -0.3527 |
| 温度跟踪 MAE(°C) | 0.5182 | 0.3527 |
采集数据是连续长轨迹,评估是多次独立重置,初温与开门安排不同。数据列用于理解训练样本中的控温水平;比较两种学习方案时,以相同仿真条件下的结果为准。
由于奖励仅惩罚温度误差,本结果说明控温表现。若业务同时关注用电量,需要在奖励与评估中另加功率或能耗指标。
7. 迁移到实际业务
迁移时先确认数据单位、观测关系和动作边界,再修改图结构、训练与验证,最后调整奖励和业务验收标准。 PID/MPC 等控制器是可选扩展,本例主线使用 PPO,不能当作这些控制器已验证的成绩。
阅读任务页约定,区分数据准备、训练验证和独立评估。