简介:这份资源围绕深度强化学习在主动配电网电压控制中的应用展开,面向计算机、电气工程及相关专业的学习者,尤其适合需要项目实战练习、课程设计或期末大作业参考的同学。内容聚焦如何利用强化学习算法对IEEE33节点配电网进行电压调控,涉及潮流计算与二阶锥规划等关键环节,属于进阶型实战项目。压缩包共4个文件,以m脚本文件为主,另含一个系统隐藏文件,整体约8KB,体积轻量,便于快速查阅与二次开发。目前已有64人学习下载,具备一定参考热度。通过其中的潮流计算与优化脚本,读者可理解主动配电网电压控制的基本建模思路,掌握深度强化学习与电力系统仿真结合的代码组织方式,并据此完成实验复现或课程设计任务,对提升项目实战能力有直接帮助。
1. 主动配电网电压控制为什么值得用深度强化学习重做一遍
分布式光伏在配电网里的渗透率一高,电压就越发不听话。中午光伏满发,末端节点电压往上顶;傍晚光伏一退,负荷一上来,电压又往下掉。传统做法靠电容器组、有载调压变压器和静止无功补偿器,配合一套基于规则的九区图或者离线整定的PID,在源荷波动不大的年代够用。可一旦光伏和储能的出力变成分钟级甚至秒级波动,这套离线策略就开始翻车——调压设备动作次数飙升,寿命掉得比预期快,电压合格率还上不去。
深度强化学习(DRL)之所以被拿来做主动配电网电压控制,核心在于它能把「什么时候动哪台设备、动多少」这件事,从离线规则变成在线序贯决策。智能体观察当前电压、功率、荷电状态,输出调压动作,环境反馈电压偏差和动作代价,策略在反复交互中收敛。它不需要精确的配电网物理模型,能吃掉光伏出力和负荷的不确定性,这是模型预测控制(MPC)和传统最优潮流比较难受的地方。
这篇笔记面向的是已经懂配电网潮流、也写过一点强化学习代码的工程师,或者正在做相关课题、需要一套能跑通的最小闭环的人。我会把「基于深度强化学习的主动配电网电压控制」拆成环境建模、算法选型、训练调参、避坑排查和验证方法五块,中间给可抄的代码和参数表。不吹它能包治百病,只讲我实际搭过一遍之后,哪些地方值得投入,哪些地方是玄学。
2. 把配电网电压控制建模成马尔可夫决策过程:状态、动作、奖励怎么定
2.1 为什么选DDPG/SAC而不是DQN
电压控制的动作空间是连续的——电容器组可以投切,但SVC的无功出力、储能的有功无功、逆变器的无功支撑都是连续量。DQN只能处理离散动作,要把连续无功离散成几十档,动作维度一高就组合爆炸,训练根本收敛不了。所以常见做法是选确定性策略梯度类的DDPG,或者更稳的SAC。SAC的最大熵框架对探索更友好,在配电网这种奖励稀疏、约束多的环境里,比DDPG不容易陷入局部最优。
我一般会先用DDPG跑通流程,确认环境和奖励设计没问题,再换SAC对比。如果动作维度低于10维、状态维度在50以内,DDPG加经验回放和软更新就够。动作维度上到20以上,或者有多个调压设备需要协调,SAC的自动温度调节会省掉很多调alpha的功夫。
2.2 状态空间:别把潮流全塞进去
状态设计是最容易过度工程的地方。有人把整个配电网的节点电压、支路功率、光伏出力全塞进状态向量,维度上百,结果训练慢、泛化差。实际有效的状态应该只包含决策真正需要的信息:
- 关键节点电压幅值(通常是馈线末端和光伏并网点),标幺值
- 各调压设备的当前档位或出力
- 光伏和负荷的短期预测值或当前实测值
- 储能的荷电状态(SOC)
- 时间戳(反映光伏出力的大致时段)
状态维度控制在20到40之间比较合适。归一化必须做,电压用标幺值,功率除以基准容量,SOC本来就在0到1之间。
2.3 动作空间与奖励函数
动作空间按设备类型分。电容器组是离散档位,可以用连续输出加取整,或者用Gumbel-Softmax做离散选择。SVC和逆变器无功是连续量,直接输出无功增量。储能的有功充放也是连续量。所有动作都要做范围裁剪,否则训练早期智能体会输出离谱值导致潮流不收敛。
奖励函数是电压控制的核心。常见设计是:
def compute_reward(voltage_pu, action, prev_action, v_min=0.95, v_max=1.05): # 电压偏差惩罚:越限部分加重惩罚 v_violation = np.sum(np.maximum(0, v_min - voltage_pu)) + \ np.sum(np.maximum(0, voltage_pu - v_max)) # 电压偏差平方和,鼓励电压靠近1.0 v_deviation = np.sum((voltage_pu - 1.0) ** 2) # 动作代价:抑制设备频繁动作 action_cost = 0.01 * np.sum(np.abs(action - prev_action)) # 网损近似:用电压偏差和动作幅度间接反映 reward = -10.0 * v_violation - 1.0 * v_deviation - action_cost return reward逻辑说明:越限惩罚系数给到10,是因为电压合格是硬约束,越限一次的影响远大于电压稍微偏离1.0。动作代价系数0.01是经验值,太大智能体会躺平不动,太小设备会来回抖。参数说明:v_min和v_max按国标取0.95和1.05,如果馈线长、压降大,可以放宽到0.93和1.07做训练,但评估时按0.95和1.05算合格率。
提示:奖励里的网损项不要直接算潮流网损,那会让每步训练慢一个数量级。用电压偏差和动作幅度做代理,效果差不了多少。
3. 用Python搭一套可训练的最小闭环:环境、智能体、回放池
3.1 环境封装:基于pandapower的配电网仿真
环境用pandapower做潮流计算,封装成gym风格。核心是reset和step两个方法。reset时随机化光伏出力和负荷,跑一次潮流得到初始电压。step时把智能体动作映射到设备参数,再跑潮流,返回新状态和奖励。
import pandapower as pp import numpy as np import gym from gym import spaces class VoltageControlEnv(gym.Env): def __init__(self, net, pv_buses, cap_buses, svc_buses): super().__init__() self.net = net self.pv_buses = pv_buses self.cap_buses = cap_buses self.svc_buses = svc_buses # 状态:关键节点电压 + 光伏出力 + SOC + 时间 n_voltage = len(net.bus) n_pv = len(pv_buses) self.obs_dim = n_voltage + n_pv + 1 + 1 self.action_dim = len(cap_buses) + len(svc_buses) self.action_space = spaces.Box( low=-1.0, high=1.0, shape=(self.action_dim,), dtype=np.float32) self.observation_space = spaces.Box( low=-np.inf, high=np.inf, shape=(self.obs_dim,), dtype=np.float32) self.prev_action = np.zeros(self.action_dim) self.step_count = 0 def reset(self): # 随机化光伏出力和负荷 for i, bus in enumerate(self.pv_buses): self.net.sgen.at[i, 'p_mw'] = np.random.uniform(0, 0.5) pp.runpp(self.net) self.prev_action = np.zeros(self.action_dim) self.step_count = 0 return self._get_obs() def step(self, action): action = np.clip(action, -1.0, 1.0) # 映射到电容器档位和SVC无功 for i, bus in enumerate(self.cap_buses): step = int(np.round(action[i] * 5)) # -5到5档 self.net.shunt.at[i, 'step'] = step for j, bus in enumerate(self.svc_buses): idx = len(self.cap_buses) + j self.net.svc.at[j, 'q_mvar'] = action[idx] * 2.0 # -2到2 Mvar try: pp.runpp(self.net) converged = True except pp.LoadflowNotConverged: converged = False if not converged: reward = -100.0 done = True return self._get_obs(), reward, done, {} v_pu = self.net.res_bus.vm_pu.values reward = self._compute_reward(v_pu, action) self.prev_action = action.copy() self.step_count += 1 done = self.step_count >= 24 # 一天24步 return self._get_obs(), reward, done, {} def _get_obs(self): v_pu = self.net.res_bus.vm_pu.values pv_p = self.net.sgen.p_mw.values soc = 0.5 # 简化,实际接储能模型 hour = self.step_count / 24.0 return np.concatenate([v_pu, pv_p, [soc, hour]]).astype(np.float32) def _compute_reward(self, v_pu, action): v_violation = np.sum(np.maximum(0, 0.95 - v_pu)) + \ np.sum(np.maximum(0, v_pu - 1.05)) v_deviation = np.sum((v_pu - 1.0) ** 2) action_cost = 0.01 * np.sum(np.abs(action - self.prev_action)) return -10.0 * v_violation - 1.0 * v_deviation - action_cost逻辑说明:reset随机化光伏和负荷,保证每个回合的初始条件不同,这是DRL泛化的关键。step里动作裁剪到-1到1,再映射到实际设备参数。潮流不收敛时给-100的惩罚并终止,避免智能体学会输出导致发散的离谱动作。参数说明:电容器档位映射系数5表示最大5档,SVC无功范围2 Mvar,这些要按实际设备容量改。done条件设24步代表一天,如果做实时控制可以改成固定步数或电压越限即终止。
3.2 SAC智能体:网络结构、超参数、训练循环
智能体用stable-baselines3的SAC,省去自己写网络和优化器的功夫。策略网络用两层256的全连接,激活函数ReLU。学习率3e-4,回放池大小1e6,batch size 256,gamma 0.99,tau 0.005。这些是SAC在连续控制任务上的常用起点。
from stable_baselines3 import SAC from stable_baselines3.common.callbacks import EvalCallback from stable_baselines3.common.monitor import Monitor env = VoltageControlEnv(net, pv_buses, cap_buses, svc_buses) env = Monitor(env) model = SAC( "MlpPolicy", env, learning_rate=3e-4, buffer_size=1_000_000, batch_size=256, gamma=0.99, tau=0.005, policy_kwargs=dict(net_arch=[256, 256]), verbose=1, tensorboard_log="./sac_voltage_tb/" ) eval_env = Monitor(VoltageControlEnv(net, pv_buses, cap_buses, svc_buses)) eval_callback = EvalCallback( eval_env, best_model_save_path="./best_model/", log_path="./eval_log/", eval_freq=5000, deterministic=True, render=False) model.learn(total_timesteps=500_000, callback=eval_callback) model.save("sac_voltage_final")逻辑说明:Monitor包装环境记录每回合奖励和长度,方便在TensorBoard看训练曲线。EvalCallback每5000步评估一次,保存最优模型,避免训练后期过拟合或崩溃。参数说明:total_timesteps 50万步是起步值,配电网状态简单的话20万步就能看到电压合格率明显提升,复杂馈线可能要100万步以上。buffer_size 1e6占内存约几个G,机器内存小就降到2e5。
3.3 训练过程要看哪些指标
训练时盯三个东西:回合奖励的滑动平均、电压越限次数、设备动作次数。回合奖励上升但越限次数不降,说明奖励函数设计有问题,可能是动作代价系数太大导致智能体不敢动。越限次数降了但动作次数飙升,说明动作代价系数太小,设备在抖。理想情况是奖励稳步上升,越限次数降到接近零,动作次数稳定在一个合理范围。
TensorBoard里重点看eval/mean_reward和rollout/ep_rew_mean的差距。差距大说明过拟合,需要加环境随机化或者减网络容量。如果eval奖励一直不涨,先检查状态归一化和动作范围,这两个地方出错训练基本不会收敛。
4. 训练不收敛、电压越限反复出现:排查清单与参数边界
4.1 现象:训练初期奖励直接崩到-100并频繁终止
原因:智能体随机探索时输出大动作,导致潮流不收敛。这是最常见的第一道坎。
解决:在step里对动作做更严格的裁剪,或者加一个动作平滑项,让相邻两步动作差不要太大。也可以在训练前用专家规则预热回放池,塞一批基于九区图的合理动作,让智能体先学会不把潮流搞崩。
4.2 现象:训练中期奖励震荡,电压合格率忽高忽低
原因:奖励函数里越限惩罚和动作代价的权重比例不对,或者学习率太大导致策略更新步子太猛。
解决:先把学习率降到1e-4试,如果还震荡,检查奖励量级。越限惩罚10、动作代价0.01这个比例在多数馈线上能用,但如果设备容量大、动作幅度大,动作代价要相应调大。另外SAC的target entropy可以手动设成-action_dim,自动调节有时会跑偏。
4.3 现象:训练后期电压合格率上不去,卡在90%左右
原因:状态空间缺少关键信息,智能体看不到导致越限的根源。常见的是没把光伏出力预测或负荷水平放进状态。
解决:把光伏出力的短期预测(比如未来15分钟)加进状态,或者把当前时刻的光伏出力与额定容量的比值放进去。如果馈线有多个光伏,至少要把总出力和最大单点出力放进去。状态里加时间戳也有帮助,智能体能学到中午光伏大发时该提前动作。
4.4 现象:换一条馈线重新训练,效果完全不行
原因:DRL策略过拟合到训练馈线的拓扑和参数上,泛化能力差。
解决:训练时随机化馈线参数,包括线路阻抗、光伏位置和容量、负荷水平。每回合reset时重新采样这些参数,智能体才能学到与拓扑无关的控制逻辑。如果目标就是特定馈线,那不用管泛化,但要知道换馈线必须重新训练。
4.5 现象:仿真里表现很好,上真机或硬件在环就翻车
原因:仿真潮流模型和实际配电网有偏差,或者通信延迟导致状态和动作不同步。
解决:在仿真里加观测噪声和动作延迟,训练时就让智能体适应不完美信息。观测噪声可以加高斯噪声,延迟可以用上一时刻的状态代替当前状态。另外真机上的调压设备有动作死区和响应时间,仿真里要建模,否则策略会频繁发无效指令。
注意:排查顺序永远是先查环境(潮流收敛、状态归一化、动作范围),再查奖励(量级、比例),最后查算法(学习率、网络容量、回放池)。环境问题占训练失败的七成以上。
5. 策略验证与进阶:从仿真合格率到可落地的控制逻辑
5.1 验证不能只看平均奖励
训练完的模型,评估时要看四个指标:电压合格率、电压越限最大深度、设备日均动作次数、网损变化。合格率是硬指标,至少要达到99%以上才谈得上可用。越限最大深度反映极端场景下的风险,如果偶尔出现0.90以下的电压,说明策略在极端光伏出力或负荷下失效,需要针对性加场景训练。
设备动作次数直接关系寿命。电容器组一天动作超过10次就要警惕,SVC和逆变器无功可以频繁调,但也要看设备手册的允许次数。网损变化是附加收益,好的电压控制策略通常能降网损,但如果为了降网损牺牲合格率,那就是本末倒置。
5.2 用规则兜底,别让DRL裸奔
实际部署时,DRL策略外面要包一层安全校验。动作输出后先检查是否会导致电压越限加剧,如果是就回退到规则策略。规则策略不用复杂,九区图或者简单的电压阈值判断就够。这层兜底在仿真里看不出价值,但真机上能避免很多尴尬。
def safe_action(drl_action, current_voltage, v_min=0.95, v_max=1.05): # 如果当前电压已经越限,优先用规则动作 if np.any(current_voltage < v_min) or np.any(current_voltage > v_max): rule_action = rule_based_control(current_voltage) # 混合:DRL动作和规则动作取平均,平滑过渡 return 0.5 * drl_action + 0.5 * rule_action return drl_action逻辑说明:电压越限时不完全信任DRL,用规则动作做修正。取平均是为了避免动作突变,实际可以按越限深度调权重。参数说明:v_min和v_max按运行要求设,rule_based_control可以是一个简单的查表函数。
5.3 进阶方向:多智能体与迁移学习
单智能体控制整条馈线,动作维度一高就难训。进阶做法是按区域拆成多智能体,每个智能体管一片,用MADDPG或QMIX协调。另一个方向是迁移学习,在仿真里预训练,再用少量真机数据微调,减少现场调试时间。
我自己的习惯是,任何DRL控制策略在仿真里跑通之后,先做一轮极端场景测试——光伏出力从0跳到额定、负荷从轻载跳到重载、通信中断几秒——看策略会不会输出危险动作。这一轮测试比看平均奖励有用得多。电压控制这事,平均表现好不代表极端情况安全,而极端情况才是真正考验策略的地方。
希望帮到你。
本文还有配套的精品资源,点击获取