1. 微网优化调度与深度强化学习的碰撞
微电网调度一直是个让人又爱又恨的领域。去年我在参与一个工业园区微网项目时,深刻体会到了传统优化算法的局限性——那些基于精确数学模型的MPC(模型预测控制)方法,在面对风机出力的随机性和用户负荷的不可预测性时,常常显得力不从心。直到我开始尝试将深度强化学习(DRL)引入这个领域,才真正找到了突破口。
微网系统的复杂性主要体现在这几个方面:
- 电源侧:风力发电的间歇性和波动性
- 储能侧:电池充放电效率的非线性特性
- 负荷侧:恒温负载的惯性特性和价格敏感型负荷的弹性需求
- 电网交互:分时电价带来的经济性约束
这些因素交织在一起,形成了一个高维度、强耦合、非线性的优化问题。传统方法需要为每个子系统建立精确的数学模型,而DRL的优势在于它可以通过与环境的交互学习最优策略,无需完整的系统建模。
2. 微网环境建模与状态空间设计
2.1 微网系统组成建模
我们构建的微网环境包含以下核心组件:
- 风力发电机:采用Weibull分布模拟风速变化
- 储能系统:锂电池模型,考虑充放电效率和循环寿命
- 恒温控制负载:建筑热力学模型,包含温度死区控制
- 价格响应负载:基于电价弹性的需求响应模型
- 主电网连接:考虑分时电价和功率交换限制
python复制class MicrogridEnv(gym.Env):
def __init__(self):
# 状态空间:23个维度
self.observation_space = Box(low=0, high=1, shape=(23,))
# 动作空间:5个维度(储能充放电+4类负载控制)
self.action_space = Box(low=-1, high=1, shape=(5,))
def step(self, action):
# 环境状态转移逻辑
self._update_battery(action[0]) # 储能控制
self._update_thermostatic_loads(action[1:3]) # 恒温负载
self._update_price_sensitive_loads(action[3:]) # 价格敏感负载
next_state = self._get_state()
reward = self._calculate_reward()
done = self._check_done()
return next_state, reward, done, {}
2.2 状态空间的关键特征设计
状态空间的设计直接影响算法的学习效率。我们的23维状态向量包含:
- 时间特征:小时、星期、节假日标志
- 电源侧:风机预测出力、实际出力
- 储能侧:SOC(荷电状态)、充放电功率限制
- 负荷侧:室内温度、设定温度、基线负荷
- 电网侧:当前电价、预测电价
- 历史数据:过去4小时的负荷和发电趋势
关键点:状态归一化到[0,1]区间非常重要,不同量纲的特征会导致训练不稳定
3. 深度强化学习算法选型与改进
3.1 算法对比实验
我们首先对比了三种主流DRL算法:
- DQN(深度Q网络):适合离散动作空间,但在连续控制中表现欠佳
- PPO(近端策略优化):策略稳定性好,但收敛速度慢
- A3C(异步优势演员-评论家):并行探索效率高,适合复杂环境
实验结果表明,在微网调度场景下:
- DQN无法处理连续动作空间(如精确的充放电功率控制)
- PPO容易陷入局部最优,策略更新不够灵活
- A3C展现出最好的综合性能,但仍有改进空间
3.2 A3C算法的核心改进
3.2.1 经验回放机制
原生A3C的每个worker独立探索,经验未被充分利用。我们为每个worker添加了循环经验池:
python复制class CyclicBuffer:
def __init__(self, capacity=10000):
self.buffer = deque(maxlen=capacity) # 自动淘汰旧数据
def add(self, transition):
self.buffer.append(transition)
def sample(self, batch_size):
indices = np.random.choice(len(self.buffer),
size=min(batch_size, len(self.buffer)),
replace=False)
return [self.buffer[i] for i in indices]
经验回放带来两个好处:
- 打破样本间相关性,提高训练稳定性
- 重复利用有价值经验,提升样本效率
3.2.2 半确定性训练策略
在训练不同阶段采用不同的探索策略:
python复制def select_action(self, state):
mu, sigma = self.policy_net(state)
if self.global_step < 1e5: # 探索阶段
action = mu + torch.randn_like(mu) * 0.3
else: # 微调阶段
noise_scale = 0.1 / (1 + self.epoch)
action = mu + torch.randn_like(mu) * noise_scale
return action.clamp(-1, 1)
这种自适应噪声机制使得:
- 早期充分探索状态空间
- 后期精细调整策略参数
- 避免过早收敛到次优解
4. 网络架构与训练技巧
4.1 共享底层的Actor-Critic网络
我们采用共享特征提取层的网络设计:
python复制class SharedACNetwork(nn.Module):
def __init__(self):
super().__init__()
# 共享特征提取层
self.lstm = nn.LSTM(input_size=23, hidden_size=128, num_layers=2)
# 策略头
self.policy_head = nn.Sequential(
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 5),
nn.Tanh() # 输出[-1,1]范围内的动作
)
# 值函数头
self.value_head = nn.Sequential(
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 1)
)
def forward(self, x):
lstm_out, _ = self.lstm(x)
return self.policy_head(lstm_out), self.value_head(lstm_out)
共享LSTM层的优势:
- 时序特征提取能力更强
- 减少网络参数量,加快训练速度
- 策略和价值估计共享特征表示,提高一致性
4.2 奖励函数设计艺术
奖励函数是DRL的灵魂,我们的设计包含三个关键部分:
python复制def calculate_reward(self):
# 1. 经济性指标
energy_cost = self.grid_power * self.electricity_price
# 2. 设备寿命考虑
battery_penalty = 0.02 * abs(self.battery_action)**1.5 # 非线性惩罚
# 3. 用户舒适度
temp_diff = abs(self.indoor_temp - self.set_temp)
comfort_reward = 10 * torch.sigmoid(2 - 5*temp_diff)
# 4. 电网交互约束
grid_penalty = 100 * max(0, abs(self.grid_power) - self.grid_limit)
return -(energy_cost + battery_penalty + grid_penalty) + comfort_reward
设计要点:
- 多目标权衡:经济性、设备寿命、用户舒适度
- 尺度平衡:确保各项奖励在同一数量级
- 非线性处理:对关键指标使用非线性变换
5. 实战部署与性能优化
5.1 训练过程监控
我们实现了全面的训练监控:
python复制class TrainingMonitor:
def __init__(self):
self.episode_rewards = []
self.loss_history = []
def log_episode(self, reward, length):
self.episode_rewards.append(reward)
def log_loss(self, policy_loss, value_loss):
self.loss_history.append((policy_loss, value_loss))
def plot_progress(self):
# 绘制奖励曲线和损失曲线
plt.figure(figsize=(12,5))
plt.subplot(121)
plt.plot(smooth(self.episode_rewards))
plt.subplot(122)
plt.plot([x[0] for x in self.loss_history], label='Policy')
plt.plot([x[1] for x in self.loss_history], label='Value')
plt.legend()
监控指标包括:
- 回合累计奖励
- 策略损失和值函数损失
- 关键动作的统计分布
- 电池SOC变化轨迹
5.2 模型部署优化
生产环境部署的关键步骤:
- 模型导出为ONNX格式:
python复制dummy_input = torch.randn(1, 23)
torch.onnx.export(model, dummy_input, "mg_scheduler.onnx")
- C++加速推理:
cpp复制Ort::Session session(env, "mg_scheduler.onnx", session_options);
auto input_tensor = Ort::Value::CreateTensor<float>(
memory_info, input_data.data(), input_data.size(), input_shape.data(), input_shape.size());
auto outputs = session.Run(Ort::RunOptions{nullptr},
input_names.data(), &input_tensor, 1,
output_names.data(), output_names.size());
性能对比:
- Python推理:~50ms/step
- ONNX+C++推理:<5ms/step
- 传统MPC求解器:2000-5000ms/step
6. 避坑指南与经验分享
6.1 常见问题排查
- 训练不收敛:
- 检查状态归一化是否合理
- 调整奖励函数各项权重
- 降低学习率(通常从3e-4开始尝试)
- 策略过于保守:
- 增加探索噪声
- 检查是否有过大的惩罚项
- 确保动作空间范围设置合理
- 训练波动大:
- 减小并行worker数量
- 增加经验回放池大小
- 使用梯度裁剪(norm=0.5)
6.2 实战经验总结
- 数据预处理比算法更重要:
- 确保所有状态特征在相似尺度
- 对周期性特征(如小时、星期)使用正弦/余弦编码
- 对风机出力等波动大的数据做滑动平均
- 网络结构选择:
- LSTM比Transformer更适合时序建模
- 网络宽度比深度更重要(2-3层足够)
- 激活函数优选ReLU/SiLU
- 超参数调优顺序:
- 先调奖励函数权重
- 再调学习率和batch size
- 最后调网络结构参数
在真实园区微网中的部署效果显示,相比传统MPC方法,我们的A3C++方案实现了:
- 运行成本降低17.3%
- 计算耗时减少两个数量级
- 对预测误差的鲁棒性显著提升
特别是在应对极端天气事件时,DRL策略展现出令人惊喜的适应性——在台风过境导致风机停机的场景下,系统自动触发了需求响应机制,并优化了储能调度节奏,将停电影响降到了最低。