news 2026/10/17 8:30:33

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用DBSCAN优化风电-负荷场景削减,替代K-means的工程实践

场景削减这件事,我在实际项目里被 K-means 折腾过很长时间。当时手头有一组风电出力数据和区域负荷数据,用蒙特卡洛方法生成了 10000 个风-负荷联合场景,要做随机机组组合,必须把它们削减到十几个典型场景。我一开始默认就是 K-means,结果调 k 调到崩溃:k=8 的时候质心曲线明显失真,k=14 又冒出一堆单点簇,换两次随机种子,削减结果就飘得厉害。后来把思路换成 DBSCAN 密度聚类,很多问题才算想明白——场景削减的困难,不在于怎么把某个固定聚类数给凑出来,而在于怎么让数据自己告诉你,这个概率分布里究竟藏着哪些相对独立的形态。这篇文章就把这套方法从原理到流水线,再到工程调参的细节完整梳理一遍,给同样做风电-负荷场景削减的人做个参考。

1. 为什么 K-means 在风-负荷场景削减这件事上让人不踏实

1.1 场景削减的数学本质:用少数几条曲线近似一个概率分布

先明确一下场景削减到底在干什么。给定一个很大的样本集合,每个样本是一条风电时序曲线加一条负荷时序曲线,目标是用很小一个子集,比如 8~20 条典型曲线,配合一组离散概率权重,去逼近原始样本集合所代表的概率分布。这个逼近要进入后续的随机规划模型,比如随机机组组合、随机经济调度,模型里每个典型场景对应一组决策变量和概率,期望成本就是按这些权重算出来的。

所以评价场景削减好坏,不是看聚出来的簇漂不漂亮,而是看两件事:一是典型场景集与原样本集合在分布层面的距离是否足够小;二是用削减后的场景算出的优化目标,是否接近用全场景算出的结果。数学上常用 Wasserstein 距离来量化两个分布之间的差异,工程上则用期望值偏差、方差保留率、调度成本偏差这些更直观的指标。

从这个角度回头看我当时的 K-means 操作,问题立刻就明显了:K-means 的优化目标是簇内平方和最小,它根本不关心你最终那个概率分布的近似质量。它把样本空间机械地切成若干个近似球形的区域,对“分布形状”没有任何概念。风电-负荷联合场景的样本分布远不是球形,它是高度相关的时序曲线集合,形状可能是细长条、弯曲带、带分支的流形结构。用 K-means 去切这种数据,等于拿圆规去切不规则的拼图,怎么切都别扭。

1.2 K-means 的三个“不舒服”之处

第一,k 值没有任何物理含义。做风电-负荷削减时,你真正想问的问题是:这些场景里到底有几种典型天气模式、几种负荷形态?K-means 没法回答,它只接受你给一个整数。实际工程里大家常用肘部法则、轮廓系数去“猜” k,但这些指标对高维时序数据经常失效。我当时用轮廓系数选出 k=15,可仔细看这 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 距离图定 eps

DBSCAN 有两个关键参数: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_components=15) X_pca = pca.fit_transform(X_scaled) # DBSCAN 聚类,eps 由 k 距离图确定 db = DBSCAN(eps=0.5, min_samples=25) 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(axis=1))] # 权重:簇内样本数 / 总样本数 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 个,T=24,拼接后 48 维,标准化后 PCA 降到 15 维。DBSCAN 取 min_samples=25,eps 通过 k 距离图选在 0.5 附近,聚类结果是 12 个密度簇,外加 217 个噪声点。K-means 用轮廓系数选最优 k=15。

对比项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 维标准化数据跑 DBSCAN,k 距离图画出来几乎是一条平滑直线,没有明显拐点。原因是高维空间中每个点的最近邻距离都趋于接近,密度差异被淹没,DBSCAN 引以为傲的“密度对比”失效了。

对策就是降维。但降维也要看数据场景:如果 T=96 甚至 T=168,曲线维度更高,单纯的 PCA 可能不够,可以先用符号聚合近似方法把时序压缩成若干段统计特征,再进 DBSCAN。总之,务必要让聚类发生在密度结构可分辨的低维空间里,这是整套方法能否成立的前提。

5.3 噪声场景不要一删了之

这是我觉得最值得强调的一条经验。很多教程里写 DBSCAN 会把噪声点标记为 -1,直觉上就觉得这些点“没用了”。但在场景削减任务里,噪声点往往是风电大发、负荷尖峰、连续爬坡这类关键事件。直接丢弃,等于把分布尾部的风险信息全部扔掉。

正确做法是把噪声点作为边缘/极端场景单独保留,用于确定性校核或鲁棒优化约束。如果用于随机规划,可以给它们赋很小的概率权重,或者把 95 分位数约束锚定在这些极端场景上。这样既不扭曲期望成本,又能让调度方案具备最基本的鲁棒性。取舍原则是:你后面用的是期望型模型还是约束型模型。期望型模型对噪声权重不必太敏感,约束型模型则一定要把噪声点纳入校验集合。

5.4 可复用的工程检查清单

最后整理一份可以直接照着用的清单:

步骤操作要点
原始数据清洗剔除记录错误、时间戳错位的样本,避免污染密度结构
标准化风电、负荷分别标准化后再拼接,防止量纲主导距离
降维PCA 保留 90% 以上方差,或先做时序压缩
min_samples降维后维数 1~2 倍,先试 20~30 并观察噪声比例
eps用 k 距离图找拐点,再上下浮动验证稳定性
代表场景取 medoid 真实样本,不要用算术平均
噪声处理单独保留为极端场景集,不直接删除
结果验证削减前后对比期望值、方差、Wasserstein 距离、调度成本偏差

我自己现在做风电-负荷场景削减,会把 DBSCAN 作为第一推荐方法摆到最前面:先跑一遍,让数据自己告诉你它内部有几个典型形态,再根据业务需要手动补充极端场景。哪怕最终业务要求必须压缩到某个固定数量,这套方法给出的簇结构和边缘信息,也远比直接拍脑袋定一个 k 值要可靠得多。核心思路其实就一句话:场景削减不该是拿模板套数据,而是让数据的密度结构自己说话。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 8:30:19

用Git管理Agent技能库:目录契约、版本策略与评审闸门

半年多前,我所在团队的 Agent 技能库还处于一种极度随意的状态:技能包散落在共享文档和各人本地文件夹里,谁想加技能就加一份,谁想改就改一份,“最新版本”“最终修订版”这类文件名累积了几十个。表面上大家一直在扩充…

作者头像 李华
网站建设 2026/10/17 8:29:52

SPSS非参数检验全指南:从原理到论文报告与AMOS衔接

刚接触问卷数据分析那会儿,我犯过一个特别典型的错误:拿到一份满意度量表,想看性别差异,直接“分析→比较均值→独立样本t检验”,结果显著,心里还挺美。直到有一次数据明明偏态得厉害,被一位前辈…

作者头像 李华
网站建设 2026/10/17 8:29:29

金融领域元学习实战:破解小样本学习难题

这两年做金融AI落地,最常被问的一个问题是:“我们不是有上亿条交易数据吗,为什么一个新模型从立项到上线要折腾好几个月?”问题就出在“干净、可标注、事件就绪”的数据上——数据总量看着多,特定场景下的有效样本可能…

作者头像 李华
网站建设 2026/10/17 8:29:26

Unity原生Text文字渐显:用状态机替代协程的完整方案

最近在做一套对话框展示逻辑时,遇到一个很典型的 UI 需求:一行提示文字要在指定时机淡入,淡入完成后停留一段时间,再根据剧情或玩家操作淡出。听起来很简单,第一反应自然是开个协程,从 0 把 alpha 跑到 1。…

作者头像 李华
网站建设 2026/10/17 8:28:46

2024商用AI视频生成选型指南:稳定性、可控性与成本全解析

做商用AI视频生成选型,2024年是个特别拧巴的年份。一方面模型能力肉眼可见地往上蹿,几乎每个月都有“新效果炸裂”的方案放出来;另一方面,真正敢把AI视频接进生产线的团队,反而比去年更谨慎了。我最近大半年一直在做AI…

作者头像 李华
网站建设 2026/10/17 8:27:38

STM32F1平台MPU9250九轴传感器移植:从F4例程到稳定出数

简介:MPU9250从STM32F4移植到F1源码例程,是一份面向嵌入式开发者的完整移植工程,重点解决在资源更有限的STM32F1平台上驱动九轴传感器MPU9250的问题。资料涵盖GPIO映射、中断向量调整、时钟配置、内存优化等关键环节,适合需要将现…

作者头像 李华