Lesson 02 · 环境
可练手的环境:EnergyPlus + Sinergym
真实楼宇没法拿来"试错训练 RL"——你需要一个高保真沙盒。这一课把它搭起来。
BrainBox 在 14,000 栋楼上跑,你不可能。但你可以用一个被全球学者用了十几年的建筑物理仿真器 EnergyPlus,加上把它包装成强化学习 gym 的 Sinergym,得到一个和真楼行为足够像、又能无限次试错的实验台。
整门课后面所有的预测模型、RL 策略、安全门控,都会跑在这个环境里。所以这一课的动手做,是"通关前置条件"——跑不通,后面都免谈。
一、三个角色,一张图看懂
┌─────────────────────────────────────────────────────────────┐
│ 你的 RL / 预测训练循环 │
│ (Gymnasium 标准接口:reset/step) │
└───────────────────────────┬─────────────────────────────────┘
│ 观测 obs / 动作 action / 奖励 reward
▼
┌─────────────────────────────────────────────────────────────┐
│ Sinergym 把 EnergyPlus 包成 Gymnasium env │
│ 提供 5-zone office 等现成建筑 + 随机天气 │
└───────────────────────────┬─────────────────────────────────┘
│ 回调里读传感器 / 写执行器
▼
┌─────────────────────────────────────────────────────────────┐
│ EnergyPlus 美国能源部建筑能耗仿真引擎(C 库) │
│ 真正算热平衡、冷机 COP、管网……一栋楼一个 episode │
└─────────────────────────────────────────────────────────────┘
| 组件 | 是什么 | 本课用到哪 |
|---|---|---|
| EnergyPlus | 物理仿真引擎,算一栋楼的热 / 能耗演化 | 被 Sinergym 调用,你不直接碰 |
| Sinergym | 把 EnergyPlus 包成 Gymnasium env | 主力,gym.make('Eplus-…') |
| Gymnasium | RL 环境接口标准(Farama 维护) | 你和 RL 库之间的"插头标准" |
二、版本必须钉死(最大的坑)
Sinergym、EnergyPlus、Python 三者版本互相钉死,错一个就跑不起来。这是新手 90% 的卡点。
| Sinergym | Python | EnergyPlus | 状态 |
|---|---|---|---|
| 3.12.x | 3.12.3 | 25.1.0 | 最新(2026-07,本课用这列) |
| 3.11.0 | 3.12.3 | 25.1.0 | 稳定 |
| 3.10.0 | 3.12.3 | 24.2.0 | 旧 |
| 3.5.8 | 3.12.3 | 24.1.0 | 旧 |
三、动手做:用 Docker 起一个能跑的环境
这条路径不碰本地 EnergyPlus 安装,最省心。确认你装了 Docker Desktop(macOS / Windows / Linux 都行)。
动手做 2.1 · 拉镜像并进容器(约 5 分钟)
Sinergym 官方提供多阶段镜像(builder / dev / runtime)。教学用 runtime 就够——里面已装好 OS + EnergyPlus 25.1 + Python 3.12 + Sinergym。
# 1. 拉取 Sinergym 官方镜像(runtime 变体) docker pull jajimer/sinergym:latest # 2. 起一个交互式容器,并把本地工作目录挂进去(方便存脚本) docker run -it --name sinergym-lab \ -v "$PWD/workspace":/workspace \ jajimer/sinergym:latest bash # 3. 进容器后,确认版本钉死无误 python --version # 应输出 Python 3.12.3 pip show sinergym | grep Version energyplus --version # 应输出 EnergyPlus, Version 25.1.0
Python 3.12.3、Version: 3.12.x(或 3.11.0)、EnergyPlus, Version 25.1.0。对上就说明三件套版本一致,可以往下走。
之后每次想继续,只需 docker start -ai sinergym-lab 重新进入同一个容器,环境不丢。
动手做 2.2 · 跑通 5-zone office gym(约 5 分钟)
容器里创建 hello_sinergym.py,注册环境并随机跑几步,看观测/动作/奖励长什么样。
import gymnasium as gym import sinergym # 注册 Eplus-* 系列 env id(副作用导入) import numpy as np # 5 区域办公楼 + 炎热气候 + 连续动作 + 随机天气扰动 env = gym.make("Eplus-5zone-hot-continuous-stochastic-v1") obs, info = env.reset() print("观测维度 =", obs.shape) print("动作空间 =", env.action_space) for step in range(5): action = env.action_space.sample() # 先用随机动作探探路 obs, reward, terminated, truncated, info = env.step(action) print(f"step {step} reward={reward:+.3f} terminated={terminated} info keys={list(info)}") if terminated or truncated: obs, info = env.reset() env.close()
python hello_sinergym.py
total_power、comfort_violation、energy 等)。能跑完 5 步不报错,环境就通了。
如果第一步特别久别慌——Sinergym 每个 episode 是一次全年 EnergyPlus 仿真,逐时间步推进。这正是后面 RL 训练慢的根源(第 6 课会讲怎么提速)。
四、读懂这个 env:观测、动作、奖励
跑通只是第一步。要复刻 BrainBox,你得清楚这个 MDP 的三要素——它们对应到 BrainBox 的预测输入(obs)和控制输出(action)。
观测空间(obs)——对应"感知 + 预测输入"
Sinergym 自动从 EnergyPlus 的 Output:Variable / Output:Meter 生成观测。5-zone office 典型包含:
- 时间:month / day_of_month / hour
- 各 zone 状态:zone air temperature、relative humidity(这正是支柱 A 要预测的目标)
- 全楼表计:facility total HVAC electricity、cooling energy、heating energy(对应奖励里的"能耗")
- 室外扰动:outdoor drybulb temp、direct/diffuse solar radiation
动作空间(action)——对应"设定值优化"
连续 Box,默认是加热/制冷设定点温度(heating/cooling setpoint)。这恰好对上 BrainBox"优化 setpoints"的描述——你不直接动阀门,你改"目标温度",让既有 BMS 控制环去追。
# action 是 [-1, 1] 的归一化值,Sinergym 会映射回真实 setpoint print(env.action_space) # Box(low=-1, high=1, shape=(2,)) # 第 0 维 → heating setpoint;第 1 维 → cooling setpoint(°C) # 真实范围在 env 的 variables.yaml 里定义(通常 15–30°C 区间)
奖励(reward)——能耗 vs 舒适的权衡
Sinergym 默认奖励是 −(能耗项 + 舒适违规惩罚项)。这跟 BrainBox"能耗 + 舒适度 + 设备磨损"的多目标是同一个思路,第 6 课我们会把它改得更贴近 BrainBox。
| 项 | Sinergym 默认 | BrainBox 目标 |
|---|---|---|
| 能耗 | 归一化 kWh | 电费(可加权) |
| 舒适 | 超出 18–26°C 的时长 | 同(+ CO₂、PMV 可选) |
| 设备磨损 | 无 | 有(动作变化惩罚) |
五、关键陷阱清单
| 坑 | 现象 | 解法 |
|---|---|---|
| 版本错配 | ImportError: pyenergyplus 或段错误 | 严格按上面矩阵,优先 Docker |
| 忘导入 sinergym | env id not found | import sinergym 必须有(注册副作用) |
| episode 很慢 | 一步几秒,全年 episode 极慢 | 正常;第 6 课用并行 VecEnv 提速 |
| 观测量纲悬殊 | 温度 ~20、能耗 ~1e6,梯度爆炸 | 务必用 NormalizeObservation 包一层 |
用旧 gym | step 返回 4 元组报错 | 用 gymnasium(5 元组),别用旧 gym |
1. 你有了一个高保真、可无限试错的建筑物理沙盒(EnergyPlus),以及把它变成 RL gym 的 Sinergym。
2. 三者分工:EnergyPlus 算物理 / Sinergym 包接口 / Gymnasium 当插头标准。
3. 版本钉死(Sinergym 3.12 ↔ EnergyPlus 25.1 ↔ Python 3.12.3),优先 Docker 跑。
4. MDP 三要素已摸清:obs(zone 温湿度 + 表计 + 天气)、action(加热/制冷设定点)、reward(能耗 + 舒适违规)。后面所有课都在这上面玩。
Gymnasium 的 step() 返回的 5 元组里,terminated 和 truncated 的区别是什么?
对了。这个区分对值函数 bootstrapping 至关重要:只在 terminated(真终态)时才停止 bootstrap;truncated(如一年仿真跑完)只是人为截断,下一状态的值仍应被估计。混了会让 RL 学到错误的"末日"信号。
- Sinergym 仓库与文档:github.com/ugr-sail/sinergym · ugr-sail.github.io/sinergym
- Sinergym 论文:e-Energy 2021 doi/10.1145/3486611.3488729;arXiv 2412.08293 arxiv.org/abs/2412.08293
- EnergyPlus Python API:energyplus.readthedocs.io/…/api;下载:energyplus.net/downloads
- Gymnasium:gymnasium.farama.org/api/env