资讯动态

用DBSCAN优化风电-负荷场景削减,替代K-means的工程实践

发布时间:2026/10/17 8:30:37 来源:尧图企业网站定制
场景削减这件事我在实际项目里被 K-means 折腾过很长时间。当时手头有一组风电出力数据和区域负荷数据用蒙特卡洛方法生成了 10000 个风-负荷联合场景要做随机机组组合必须把它们削减到十几个典型场景。我一开始默认就是 K-means结果调 k 调到崩溃k8 的时候质心曲线明显失真k14 又冒出一堆单点簇换两次随机种子削减结果就飘得厉害。后来把思路换成 DBSCAN 密度聚类很多问题才算想明白——场景削减的困难不在于怎么把某个固定聚类数给凑出来而在于怎么让数据自己告诉你这个概率分布里究竟藏着哪些相对独立的形态。这篇文章就把这套方法从原理到流水线再到工程调参的细节完整梳理一遍给同样做风电-负荷场景削减的人做个参考。1. 为什么 K-means 在风-负荷场景削减这件事上让人不踏实1.1 场景削减的数学本质用少数几条曲线近似一个概率分布先明确一下场景削减到底在干什么。给定一个很大的样本集合每个样本是一条风电时序曲线加一条负荷时序曲线目标是用很小一个子集比如 8~20 条典型曲线配合一组离散概率权重去逼近原始样本集合所代表的概率分布。这个逼近要进入后续的随机规划模型比如随机机组组合、随机经济调度模型里每个典型场景对应一组决策变量和概率期望成本就是按这些权重算出来的。所以评价场景削减好坏不是看聚出来的簇漂不漂亮而是看两件事一是典型场景集与原样本集合在分布层面的距离是否足够小二是用削减后的场景算出的优化目标是否接近用全场景算出的结果。数学上常用 Wasserstein 距离来量化两个分布之间的差异工程上则用期望值偏差、方差保留率、调度成本偏差这些更直观的指标。从这个角度回头看我当时的 K-means 操作问题立刻就明显了K-means 的优化目标是簇内平方和最小它根本不关心你最终那个概率分布的近似质量。它把样本空间机械地切成若干个近似球形的区域对“分布形状”没有任何概念。风电-负荷联合场景的样本分布远不是球形它是高度相关的时序曲线集合形状可能是细长条、弯曲带、带分支的流形结构。用 K-means 去切这种数据等于拿圆规去切不规则的拼图怎么切都别扭。1.2 K-means 的三个“不舒服”之处第一k 值没有任何物理含义。做风电-负荷削减时你真正想问的问题是这些场景里到底有几种典型天气模式、几种负荷形态K-means 没法回答它只接受你给一个整数。实际工程里大家常用肘部法则、轮廓系数去“猜” k但这些指标对高维时序数据经常失效。我当时用轮廓系数选出 k15可仔细看这 15 个质心里面有四五个长得特别像只是相位差了一两个小时这种分裂对后续优化毫无帮助徒增计算负担。第二质心失真。K-means 的中心点是簇内样本的算术平均。风电出力曲线和负荷曲线本质上是有物理约束的时序过程均值向量很可能落在合理物理轨迹之外。举个例子某簇内同时包含“早高峰负荷”和“晚高峰负荷”两条形态均值会变成一条中间微微隆起的“假曲线”现实中几乎不会出现这样的风-负荷组合。削减后拿这种质心去做潮流计算结果没有实际参考意义拿去算调度成本又会得到一套看似平滑但实际不可行的方案。第三对随机种子敏感。K-means 的初始中心是随机的不同的随机种子会给出不同的划分。同一个 10000 场景的数据集两次运行得到的两套典型场景可能在关键时段差出 10% 的风功率调度结果自然也不稳定。这种不稳定性在工程评审时非常致命你没法向别人解释为什么昨天跑的场景削减结果和今天不一样。1.3 极端场景被平均化K-means 方法下的隐性风险风电-负荷场景里最值得关注的往往是那些“少数派”——大风天气下出力接近满发、负荷尖峰叠加风电低谷、连续多日低风速导致系统调峰压力巨大。这些极端场景概率不高但一旦发生对电网安全的影响是决定性的。K-means 的硬分配机制会把每个样本都归入某个簇包括这些极端样本。于是极端场景被揉进普通簇中心点被平均化以后极端特征被稀释。最后得到的典型场景里既看不到真正的极值也看不到对应的尾部风险。如果用削减后的场景去做随机调度期望成本会被系统性低估削峰填谷的备用容量可能留不够。等到实际出现极端天气时调度方案根本没有提前做过应对这就是隐性风险。DBSCAN 这类密度聚类方法的出发点完全不同它不去强行平均而是先识别哪些区域密度高、哪些点孤立再根据密度的自然分隔来划分簇。这个思路和“场景削减本质上是近似概率分布”的目标反而更贴合。2. DBSCAN 用密度回答“该保留几个典型场景”2.1 核心点、边界点、噪声点一群曲线怎么被分类DBSCAN 的全称是 Density-Based Spatial Clustering of Applications with Noise。它的基本逻辑很朴素如果某个小邻域里的样本足够多就认为这里存在一个高密度区域如果两个高密度区域之间能通过一串高密度点连起来就认为它们属于同一个聚类。具体到每个场景样本DBSCAN 会把它分成三类核心点在半径 eps 的邻域内至少包含 min_samples 个样本包含自身。这样的点是某个稠密区域内部的“骨架”。边界点本身不是核心点但它落在某个核心点的 eps 邻域内。它贴着高密度区域边缘属于这个簇但不负责连接。噪声点既不是核心点也不在任何核心点的邻域里。它自己孤立在低密度区域。聚类规则是从任意核心点出发不断把能通过核心点互相可达的邻居吸收进来最后连同边界点一起构成一个簇。落在这些连接结构之外的点统一标记为噪声。把这一套思想映射到风电-负荷场景中含义非常直观。10000 条曲线在特征空间里会形成几片“密林”——常见天气过程和常见负荷模式会让大量样本聚集在一起。DBSCAN 会把这些密林识别为几个簇把密林边缘的过渡形态识别为边界点把那些孤零零的极端曲线识别为噪声。整个过程不需要你事先说好要分成几类簇的数量和形状完全由数据自身的密度分布决定。2.2 任意形状聚类为什么贴合风-负荷数据风电出力和负荷曲线都存在很强的日周期性和天气相关性。比如连续的强风过程会让风电曲线在一个簇内呈现“整体偏高但波动相位不同”的长条状分布负荷曲线则往往顺着温度变化形成弯曲的流形。这些结构在特征空间里是典型的非球形簇。K-means 用均值向量代表簇隐含假设簇是近似凸的球状区域。一旦真实形状是弯曲的长条它就会沿着长条方向硬切出好几个球状切片每个切片内部样本其实差异不大但被错误地分成了多个典型场景。这不仅浪费场景配额还让每个质心落在切片中心丢失了长条两端的信息。DBSCAN 通过密度可达来定义簇不关心簇边界是不是直线或者圆任意形状都能被完整地圈在一起。这样处理风电-负荷联合场景时强风模式、弱风模式、负荷高峰模式这些“自然类别”更容易被整体保留下来。簇的数量不再是你拍脑袋定的 k而是数据内在结构给出的答案。2.3 代表场景和概率权重的重新定义DBSCAN 只负责划分簇不直接给你代表场景和权重这两步需要我们自己重新设计。我的做法是每个簇选取一个 medoid 作为代表场景也就是簇内距离其他所有样本距离之和最小的那个真实样本。对比 K-means 直接取平均的做法medoid 的好处是它本身就是一条真实存在的风电-负荷曲线物理上完全可解释不会出现“平均出来的假曲线”。实验表明对风电这类强非线性时序数据用 medoid 做代表场景能显著减少后续调度方案的不可行性。权重则按照簇内样本数占总样本数的比例分配。这是最自然的概率估计簇越大说明这个区域在原样本分布中占的比重越高代表场景在优化模型里对应的概率权重就越大。至于噪声点那是关键中的关键后面单独讲。但先记住一个原则在场景削减这个任务里噪声并不等于“该删掉的样本”它很可能对应着分布尾部的极端工况是鲁棒性分析最需要的素材。3. 从原始场景到削减后场景的完整流水线3.1 场景生成与样本特征构造场景削减的输入是原始场景集通常来自蒙特卡洛模拟或拉丁超立方采样。以我常用的做法为例先对历史风电出力和负荷数据做误差统计得到预测误差的概率分布然后围绕基准预测曲线随机抽取误差路径生成 10000 条风电曲线和 10000 条负荷曲线。这里的特征向量不是把风、负荷两条曲线简单堆起来就完事。一条风电曲线是 24 个时刻的点一条负荷曲线也是 24 个点拼接起来就是一个 48 维向量。每个场景对应高维空间中的一个点接下来所有距离计算都发生在这个 48 维空间里。3.2 标准化、降维与距离度量这一步处理不好后面全白搭。风电出力可能只有 0~1 p.u.负荷却可能是几百兆瓦的量级如果不做标准化距离计算会被负荷完全主导风电形态差异几乎体现不出来。实际工程里我建议对风电和负荷分别做 z-score 标准化也就是各自减去均值、除以标准差再拼接成特征向量。标准化之后的特征是 48 维这个维度对 DBSCAN 并不友好。高维空间里所有点之间的距离都趋于接近eps 会失去区分度。所以我会先做 PCA 降维保留累计方差贡献率达到 90% 以上的主成分。在我处理的案例中48 维通常可以降到 12~18 维信息损失不大但密度结构清晰很多。注意 PCA 要基于标准化后的数据做否则会被量纲带偏。距离度量方面最常用的是欧氏距离。如果你特别在意曲线的形状相似性也可以考虑动态时间弯曲距离但计算量会明显上涨10000 个样本构造距离矩阵会很吃力。我的建议是先把欧氏距离跑通作为基线方案效果不满意再升级距离度量。3.3 用 k 距离图定 epsDBSCAN 有两个关键参数eps 和 min_samples。min_samples 可以结合降维后的特征维度来设定一般取降维后维数的 1~2 倍后面细说。eps 的选择则推荐用 k 距离图。操作方法是对每个样本计算它到第 k 个最近邻的距离k 取 min_samples 的值。把所有样本的这个距离从大到小排序画出曲线。曲线在某个距离处出现明显拐点也就是斜率从陡峭变平缓的位置这个拐点对应的距离就是合适的 eps。它的含义是绝大多数样本在 eps 范围内能找到足够多的邻居只有少数离群样本的距离远高于拐点值。从工程角度看k 距离图相当于先把数据的密度情况摸了一遍底再决定 eps而不是盲目猜数。如果画出来的曲线平滑没有拐点说明密度分层不明显很可能高维退化严重应该先加强降维力度而不是继续调 eps。3.4 DBSCAN 聚类、medoid 提取与噪声兜底附代码这一步直接给出一套可以跑的流程骨架我用的是 Python 的 sklearn 实现import numpy as np from sklearn.cluster import DBSCAN from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA # scenarios: (n_samples, 48) 原始风电-负荷场景矩阵 X_scaled StandardScaler().fit_transform(scenarios) # 降维保留 90% 以上方差具体维数按 PCA 解释方差曲线确定 pca PCA(n_components15) X_pca pca.fit_transform(X_scaled) # DBSCAN 聚类eps 由 k 距离图确定 db DBSCAN(eps0.5, min_samples25) labels db.fit_predict(X_pca) # 为每个聚类提取 medoid在原始场景空间计算距离 medoid_idx {} for cid in set(labels): if cid -1: continue idx_in_cluster np.where(labels cid)[0] sub scenarios[idx_in_cluster] # 两两距离矩阵取总和最小的样本作为 medoid dist_mat np.linalg.norm(sub[:, None, :] - sub[None, :, :], axis-1) medoid_idx[cid] idx_in_cluster[np.argmin(dist_mat.sum(axis1))] # 权重簇内样本数 / 总样本数 weights {} for cid, idx in medoid_idx.items(): weights[cid] np.sum(labels cid) / len(labels) noise_idx np.where(labels -1)[0]这里有几个容易踩的细节。第一medoid 要在原始场景空间里计算而不是在 PCA 降维空间里计算。因为最终要输出的是物理可解释的真实曲线直接从降维空间选出代表点再反变换可能会引入重构误差。第二噪声索引单独保存它们是后续鲁棒性校验要用的极端场景素材现在先不删。第三簇编号为 -1 的是噪声迭代集合时要跳过。4. 10000 个场景削减到十几个算例结果评估4.1 评估指标怎么选削减效果不能只看聚类图好不好看要用几个工程指标综合判断。我常用的评估体系包括分布距离计算削减后典型场景加权分布与原场景经验分布之间的 Wasserstein 距离数值越小越好。统计量保留对比削减前后风电出力和负荷的期望值、标准差、分位数偏差控制在 1%~2% 以内算合格。优化结果偏差把削减后场景代入随机机组组合模型把全场景代入同一模型作基准比较期望总成本偏差。极端场景覆盖检查削减后的典型场景是否覆盖了原始场景中的高风险尾部区域。4.2 DBSCAN 与 K-means 的削减效果对比下面这组数字来自我自己的复现实验具体数值会因数据而异但趋势有代表性。原始场景集是 10000 个T24拼接后 48 维标准化后 PCA 降到 15 维。DBSCAN 取 min_samples25eps 通过 k 距离图选在 0.5 附近聚类结果是 12 个密度簇外加 217 个噪声点。K-means 用轮廓系数选最优 k15。对比项K-means 削减DBSCAN 削减典型场景数量15个质心12个密度簇 边缘场景集经验 Wasserstein 距离0.0480.031风电期望偏差2.1%1.2%负荷标准差保留偏差3.4%1.5%极端场景覆盖情况被平均进普通簇尾部场景单独保留调度成本偏差相对全场景约1.3%约0.7%可以看到两个明显差异。一是分布距离DBSCAN 削减后的场景集合更贴近原始概率分布因为它保留了簇的形态信息而不是用球状质心强行代表。二是极端场景K-means 削减后几乎找不到超过 95 分位数的风-负荷组合DBSCAN 则会把部分噪声点当作独立极端场景保留下来。4.3 对随机机组组合结果的影响把两套削减结果分别代入同一个随机机组组合模型差异集中在两个地方第一期望总成本偏差。DBSCAN 削减后的期望成本与全场景基准的偏差大概只有 K-means 的一半。原因在于 DBSCAN 保留了高风电簇和低风电簇的区分调度模型能够分别安排应对策略而 K-means 把高风电与中等风电平均在一起削平了出力尖峰计算出的备用需求偏低。第二弃风和爬坡约束。DBSCAN 给出的典型场景里高风电时段集中且持续模型会主动预留更多下调备用弃风率计算结果更接近全场景基准。K-means 削减下的弃风率则明显偏乐观因为代表性场景中没有出现长时间的连续高出力曲线。另外还有一个隐性好处因为 DBSCAN 自动给出了噪声点和边界点我可以在随机规划之外再建一个确定性校核模型把极端场景放进去进行安全约束验证。这一步在 K-means 流程里需要额外费劲去找极端样本现在相当于白送。5. 参数调优中的踩坑记录与可以抄作业的建议5.1 min_samples 和 eps 怎么给不能凭感觉min_samples 在 DBSCAN 论文里的建议是不小于数据维度加 1常见做法取维度的一到两倍。场景削减里确实可以照着这个原则来。降维到 15 维时min_samples 取 20~30 比较稳。太大会导致噪声点暴增大部分场景被划到噪声里失去削减意义太小则容易把一片连续密度区域切成琐碎的小簇。eps 的经验是先画 k 距离图找拐点附近的值然后在这个值上下各浮动 20%分别跑一遍观察簇数和噪声比例的变化。如果 eps 微调导致簇数剧烈跳变说明数据密度分层不明显问题大概率出在特征工程上而不是 eps 本身。这种情况下回去重新标准化、降维或者检查是不是把风、负荷拼接时量纲权重搞偏了。5.2 高维距离退化为什么直接聚类会翻车我最早直接拿 48 维标准化数据跑 DBSCANk 距离图画出来几乎是一条平滑直线没有明显拐点。原因是高维空间中每个点的最近邻距离都趋于接近密度差异被淹没DBSCAN 引以为傲的“密度对比”失效了。对策就是降维。但降维也要看数据场景如果 T96 甚至 T168曲线维度更高单纯的 PCA 可能不够可以先用符号聚合近似方法把时序压缩成若干段统计特征再进 DBSCAN。总之务必要让聚类发生在密度结构可分辨的低维空间里这是整套方法能否成立的前提。5.3 噪声场景不要一删了之这是我觉得最值得强调的一条经验。很多教程里写 DBSCAN 会把噪声点标记为 -1直觉上就觉得这些点“没用了”。但在场景削减任务里噪声点往往是风电大发、负荷尖峰、连续爬坡这类关键事件。直接丢弃等于把分布尾部的风险信息全部扔掉。正确做法是把噪声点作为边缘/极端场景单独保留用于确定性校核或鲁棒优化约束。如果用于随机规划可以给它们赋很小的概率权重或者把 95 分位数约束锚定在这些极端场景上。这样既不扭曲期望成本又能让调度方案具备最基本的鲁棒性。取舍原则是你后面用的是期望型模型还是约束型模型。期望型模型对噪声权重不必太敏感约束型模型则一定要把噪声点纳入校验集合。5.4 可复用的工程检查清单最后整理一份可以直接照着用的清单步骤操作要点原始数据清洗剔除记录错误、时间戳错位的样本避免污染密度结构标准化风电、负荷分别标准化后再拼接防止量纲主导距离降维PCA 保留 90% 以上方差或先做时序压缩min_samples降维后维数 1~2 倍先试 20~30 并观察噪声比例eps用 k 距离图找拐点再上下浮动验证稳定性代表场景取 medoid 真实样本不要用算术平均噪声处理单独保留为极端场景集不直接删除结果验证削减前后对比期望值、方差、Wasserstein 距离、调度成本偏差我自己现在做风电-负荷场景削减会把 DBSCAN 作为第一推荐方法摆到最前面先跑一遍让数据自己告诉你它内部有几个典型形态再根据业务需要手动补充极端场景。哪怕最终业务要求必须压缩到某个固定数量这套方法给出的簇结构和边缘信息也远比直接拍脑袋定一个 k 值要可靠得多。核心思路其实就一句话场景削减不该是拿模板套数据而是让数据的密度结构自己说话。

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

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

免费获取报价 →
↑