资讯动态

蒙特卡罗与同步回代:风光场景生成与约减实战解析

发布时间:2026/10/6 8:52:18 来源:尧图企业网站定制
搞过电力系统调度或者新能源并网分析的人大概都体会过这种尴尬风光出力曲线看着每天都是那么几条可真拿一条典型日曲线去算储能容量、算备用需求、算机组组合结果往往偏乐观关键时刻调度员只能靠人工经验兜底。蒙特卡罗算法、启发式风光场景生成、同步回代场景约减这几个词听起来像论文标题实际上干的活很直白——把无限多种可能的风光出力过程压缩成有限个有代表性的场景并且保留概率信息。我最早接触这套东西是在做风光储联合优化的时候被随机优化模型的求解规模卡到怀疑人生后来把场景从几千个约到十个计算时间从半小时降到几秒结果精度几乎没有下降。这篇文章就按这个完整流程来拆从蒙特卡罗生成、启发式改进到同步回代消除的每一步原理、Python实现和实际调参经验都会讲到适合正在做随机优化、电力规划或储能配置的朋友参考。顺带说一句最近很热的“上传一段视频生成对应的三维场景”本质上也是在用少量关键信息表达复杂世界和场景约减是同一个思路。1. 风光场景生成到底在解决什么1.1 为什么一条“典型出力曲线”不靠谱很多初学者喜欢把历史数据平均一下当作风光出力场景输入优化模型。表面上看省事实际上有两个大问题。第一平均曲线会抹掉时间相关性尤其是风力光伏不同步的时候系统实际需要的旋转备用会被严重低估。第二光伏、风电的极端出力状态比如连续阴天、大风的阵风过程才是电网规划里最要命的场景平均之后这些极端情况彻底消失优化结果自然偏乐观。我在一个光伏加储能项目里试过用典型日曲线做容量配置结果算出来的储能容量比实际需求少了将近30%。后来改成场景法才把方案置信水平补回来。所以场景生成要回答的不只是“平均长什么样”而是“极端情况和中间状态各有多大可能出现”。对运行调度来说你要知道最差工况出现在什么时候对规划来说你要知道概率分布的长尾到底有多厚。单条确定性的出力曲线给不了这些信息必须用一批带概率的场景来逼近真实分布。1.2 蒙特卡罗采样、启发式生成和同步回代约减如何串成一条线整套流程其实是一条流水线。第一步用蒙特卡罗算法按照风速、辐照度等概率模型生成成千上万条风光时序这一步解决“样本够不够”的问题。第二步用启发式策略对采样过程或初始场景做优化解决“样本质量好不好”的问题。第三步用同步回代消除法把场景集合缩减到目标数量同时给每个保留场景重新分配概率解决“下游优化能不能算得动”的问题。三者缺一不可。只蒙特卡罗不约减场景多到随机优化根本没法收敛只约减不好好生成初始样本本身就偏了后面全是白做。我习惯把这套流程叫“先发散、再收敛”先用随机性铺满可能性空间再用距离判据和概率转移做减法。这跟拍视频生成三维场景也很像——先拍大量素材再从中挑选关键帧重建几何结构不是为了保存所有画面而是为了用少量高信息量的画面还原真实空间。2. 核心算法拆解蒙特卡罗、启发式与同步回代2.1 蒙特卡罗场景生成从概率分布到出力时序蒙特卡罗算法本质上就是用重复随机试验来逼近复杂概率分布。对风速来说最常用的两参数Weibull分布概率密度函数是[ f(v;k,c)\frac{k}{c}\left(\frac{v}{c}\right)^{k-1}e^{-(v/c)^k} ]其中 (k) 是形状参数(c) 是尺度参数。得到分布后可以用逆变换采样生成 ([0,1]) 均匀随机数 (u)代入反函数 (v c(-\ln(1-u))^{1/k}) 得到风速样本。这里一定要先做分布拟合再采样不能直接拿原始风速时序去随机抽否则会把测量误差和极端异常值当成自然波动。但直接对全天风速整体采样是不够的因为时序有自相关性白天和晚上的风力是连续演化的不是独立同分布的。我经常用AR(1)模型叠加Weibull边缘分布先按小时相关性生成基础序列再去匹配分布这样得到的风速场景才有时序感。光伏部分类似用Beta分布描述辐照度按日出日落时段削去夜间零值再叠加大气透明度随机波动。最后把风速通过风机功率曲线映射成功率辐照度通过光电转换模型映射成功率就得到一条包含风电光伏两个随机源的场景。这套流程里最常见的错误是只对“单时刻出力”采样忽略24小时之间的关联。调度决策关心的是连续时段的净负荷曲线如果每个时刻独立采样会出现白天风速很大、夜里光伏满发这种物理上几乎不存在的组合下游优化结果就不敢信了。2.2 启发式策略让随机采样少做无用功如果只是无脑蒙特卡罗N取2000甚至5000里面会有一大堆彼此非常接近的场景这就是无效样本。启发式策略的出发点是在采样或初筛阶段就引入“哪些区域更该被照顾”的判断。常见做法有三种。第一种是拉丁超立方抽样。把概率空间分层保证采样点均匀覆盖分布的各分位数特别是让低概率但高影响的风速区间也能采到。同样采500个点普通随机采样的尾部可能只有几个样本拉丁超立方能保证每个分位区间都有样本场景的覆盖度明显提升。第二种是基于距离的贪心初筛。先大致算一遍两两场景之间的距离把完全重复的场景直接合并。这一步不用太精确因为后面还有严格的同步回代但可以先砍掉明显冗余的样本节省后续计算量。第三种是重要性采样思想。对极端出力区间加大采样权重比如连续阴天或者强阵风时段让这些“稀有但危险”的场景在初始集合里出现更多次然后再在概率修正阶段把权重调回来。这样做的目的是防止尾部场景在约减时被过早删掉。我一直强调启发式不是某套固定公式而是一个“减少无效计算”的总原则。同步回代消除本质上也是启发式——它每一步都在做局部最优决策用最短距离找最不值得保留的场景。2.3 同步回代消除法的原理与数学直觉同步回代Backward Reduction也叫同步回代消除这个名字看起来很绕思路其实很简单从大集合一步步往回删每次删掉一个场景把它的概率转给离它最近的保留场景一直删到目标数量。数学上它在最小化约减前后分布之间的Kantorovich距离也就是Wasserstein距离的一种离散版本。每一步要最小化的目标函数通常是[ p_i \cdot d(i,j) ]其中 (d(i,j)) 是场景 (i) 和场景 (j) 之间的距离。为什么乘上 (p_i)因为删掉一个概率大的场景信息损失显然更大而如果两个场景距离很近删掉一个也不会造成太大偏差。直觉上就是“优先删除概率小、又离别的场景最近的样本”。被删场景的概率不能凭空消失要并给最近的保留场景这样整个概率质量守恒。具体流程是计算所有保留场景两两距离找到 (p_i \cdot d(i,j)) 最小的场景对删除其中一个更新概率重复直到数量达标。这个算法每一步都是贪心的但因为Kantorovich距离有良好的连续性工程上效果通常很稳定。这里要注意距离度量的选择。最常用的是欧氏距离但如果你关心的是功率峰值就可以用削峰后的损失函数做距离如果你关心的是全时段总电量可以用曼哈顿距离。场景内如果有风电和光伏两个随机源一定要先做联合场景再算距离否则单独约减风、光再合并会破坏两个随机源之间的相关性。3. 从零实现风光场景生成与约减3.1 模拟数据和功率模型准备下面是一套我在原型验证里常用的Python简化流程。用两参数Weibull拟合风速光伏用Beta分布再配上风机和光伏的功率转化函数。为了演示方便把一天分成24小时风速序列用AR(1)加随机扰动模拟光伏序列用Beta分布乘日照开关。如果你手上有实际数据可以把这里的分布参数替换成历史数据拟合结果流程完全不用改。距离计算之前要把风电功率和光伏功率都归一化到 ([0,1]) 之间不然功率量纲不同距离会被量级更大的那项支配。这步看着小但非常重要我见过不少工程代码栽在这里。import numpy as np def wind_power(v, v_in3.0, v_r12.0, v_out25.0, P1.0): p np.zeros_like(v, dtypefloat) low (v v_in) (v v_r) mid (v v_r) (v v_out) p[low] P * ((v[low] - v_in) / (v_r - v_in)) ** 3 p[mid] P return p def solar_power(g, g_ref1000.0, P1.0): # 简化模型辐照度正比于输出功率P为额定峰值系数 return np.clip(g / g_ref, 0, 1) * P这里功率曲线用了最常见的三次方升段实际风机曲线会有厂商给出的离散值直接用插值更准。光伏模型也没有考虑温度修正工程上可以再加一个温度系数项让输出功率在高温时适当降低。3.2 生成初始场景集合下面这个函数生成N个长度为24小时的风光联合场景每个场景是一个48维向量前24维是风电归一化功率后24维是光伏归一化功率。风速用AR(1)先生成带自相关的序列再映射到风机功率曲线。严格做法是先做逆变换让序列同时满足边缘分布和相关结构这里给出一个工程上够用的版本。def generate_scenarios(N200, T24, seed42): rng np.random.default_rng(seed) scenarios np.zeros((N, T * 2)) for s in range(N): w rng.standard_normal(T) ar np.zeros(T) ar[0] w[0] for t in range(1, T): ar[t] 0.8 * ar[t-1] 0.6 * w[t] v 8.0 ar * 4.0 v np.clip(v, 0, 30) scenarios[s, :T] wind_power(v) g rng.beta(2, 3, T) * rng.uniform(900, 1100) mask np.array([1.0 if (t 6 and t 18) else 0.0 for t in range(T)]) g g * mask scenarios[s, T:] solar_power(g.astype(float)) return scenarios注意AR(1)系数0.8是随手给的实际应该从历史数据估计。如果你有测风塔数据用统计工具拟合AR参数更快。初始场景数N先设成200足够验证逻辑等把所有步骤跑通再按第4章的优化方法往大调。3.3 同步回代约减核心函数这个函数是最核心的部分。我维护一个原始场景索引列表每次计算当前集合的两两距离矩阵把距离矩阵乘以对应场景概率找到最小值位置删掉被选中的场景概率转移到距离它最近的保留场景。工程实现上推荐直接用scipy的cdist它的精度和效率都比手写双重循环好。from scipy.spatial.distance import cdist def backward_reduction(scenarios, probs, target_k): idx list(range(len(scenarios))) p probs.copy().astype(float) while len(idx) target_k: sub scenarios[idx] d cdist(sub, sub) np.fill_diagonal(d, np.inf) weighted d * p[idx][:, None] pos np.argmin(weighted) a, b divmod(pos, len(idx)) p[idx[b]] p[idx[a]] idx.pop(a) return scenarios[idx], p[idx]这段代码有个容易踩的细节a和b是当前索引列表里的位置p数组用原始全局索引访问所以不用担心pop之后索引漂移。调用方式很简单N 200 scen generate_scenarios(N) prob np.ones(N) / N K 10 red_scen, red_prob backward_reduction(scen, prob, K) print(red_prob.sum()) # 概率之和始终为1如果你想验证概率转移是不是对的可以额外打印每轮删除的场景编号和它被并给谁。我自己调试时会把“删除编号-合并编号-概率更新”打出来对着场景图检查比只看最终结果更容易发现问题。3.4 约减效果怎么看只把N减到K不叫成功还要看约减前后的概率分布差异。我最常用的指标有三个一是各时刻出力均值曲线约减前后的均值差应该很小二是分位数尤其是5%和95%分位数如果尾部对不上说明极端场景被删太多三是保留场景的典型性用一个二维散点图横轴是全天总风电出力纵轴是全天总光伏出力点的大小表示概率看看保留场景是否均匀覆盖原始样本云团。如果所有保留场景都挤在中心说明距离度量或者目标K有问题。这时候不要急着加N先检查是不是光伏和风电量纲不匹配或者目标K设得太小。我通常会把K从5开始往上扫看误差下降曲线找到拐点再定K。拐点前误差下降很快拐点后增加K收益很小那个拐点就是合理的场景数。4. 实际项目中的坑与调参经验4.1 约减失真场景留够了但风险仍然偏小场景约减最常见的坑是约减之后期望值不变但分位数误差很大。因为同步回代按“概率乘距离”选删除对象概率小的极端场景很容易被先删掉概率被并到相邻场景尾部风险悄悄消失。我踩过一次比较深的坑做储能容量配置场景约到10个均值曲线看起来和原始2000个场景差不到1%但95%置信水平下的缺电时间少了将近一半。后来我把极端场景设置了保护权重也就是在距离矩阵里给尾部场景加权重强制它们多活几轮才把可靠性指标拉回来。具体做法是先按总出力大小排序把前后5%的场景标记为“受保护”在计算加权距离时给这些场景的概率乘一个大于1的系数让它们更难被选中删除。代价是约减后的均值误差会稍微变大但可靠性指标明显更真实。如果你是做规划目标场景K最好不要低于10做日内调度K可以小到5但还需要额外用鲁棒约束兜底。K太小会让随机优化退化成确定性优化失去场景法的意义。4.2 算力不够用大规模约减的工程优化同步回代的一个痛点是每次迭代都要重算距离矩阵复杂度接近 (O(N^3))。N2000、K10时纯Python版本可能要跑好几分钟内存也容易爆。工程上我一般这样破。第一初始N不要盲目设大先用500到1000跑一次看概率分布检验不行再增量采样。第二用KDTree的最近邻查询来近似找最近场景避免全矩阵计算。KDTree的精度损失通常很小但速度能快一个数量级。第三分批约减先把2000个场景分成4批每批约到250再合并成1000继续约减到10。误差比一步到位大一点但工程上完全可以接受。第四如果下游模型对精度要求很高改成K-means聚类初始化加同步回代微调先用聚类给每个场景打上簇标签再在簇内用回代兼顾速度和精度。我实际跑过的工程里通常用“启发式初筛同步回代精减”的组合。启发式初筛可以用简单的距离聚类把明显重复的场景合并同步回代再在剩下的场景上做概率精修。这样组合下来比单纯堆场景数更稳也更容易解释给不懂算法的业务方听。下面是我常用的方法选择参照表方法速度精度适用场景纯同步回代慢高初始场景数不大精度要求极高KDTree近似回代快较高初始场景数大需要快速出结果K-means聚类约减快中需要先降维再用回代微调分批回代最快中高大规模场景工程快速迭代4.3 和“视频生成三维场景”一句话的联想前几天看到“上传一段视频生成对应的三维场景”这类应用第一反应是它跟风光场景约减在哲学上很像。视频生成三维场景是从连续多帧图像里提取几何结构用网格、点云或3D高斯做紧凑表示场景约减则是从成千上万条风光时序里提取概率代表性场景。两者都在做同一件事用尽量少但有效的离散元素去承载一个连续且充满不确定性的原始空间。区别只在于视频场景追求几何还原度风光场景追求概率分布逼近和下游决策一致性。所以如果你能理解手机拍一圈视频就能重建一个房间的原理再回头看蒙特卡罗加同步回代其实并不难。关键帧的选择逻辑和场景约减里“概率乘距离”的选择逻辑本质上都是一种信息压缩。最后说点个人体会。在风光场景生成与约减这套流程里算法本身早就成熟真正决定项目成败的往往是你对“哪些场景不能丢”的判断。不要只盯着均值和概率要多问自己保留的场景放到调度模型里会不会让极端情况永远不出现多留一两个尾部场景计算量也就增加百分之几可靠性却可能翻倍。我后来做这类项目都会先把极端场景清单单独拉出来无论如何要保住它们然后再让同步回代去处理那些冗余样本。这套思路放到任何不确定性建模场景里都适用。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑