MCM520 ← 资料站首页 电工杯 2025 A 优秀范文二:调度者视角的光伏功率日前预测误差解剖(段位分解 + 爬坡事件 + 集合自适应区间 + 信息价值) 打开交互阅读器 →

电工杯 2025 A 优秀范文二:调度者视角的光伏功率日前预测误差解剖(段位分解 + 爬坡事件 + 集合自适应区间 + 信息价值)

一、摘要

范文一回答的是建模者的经典问题:「哪个模型平均最准、区间覆盖率多少」。本文换到调度台的视角,回答三个更贴近使用的问题:误差集中在曲线的哪一段?突发的爬坡事件抓不抓得住?区间能不能跟着当日的不确定性伸缩?以及,花钱买的气象云信息到底兑现了多少? 为此在复用范文一 240 天合成面板(SEED=20250501,20 MW 电站,96 点/天)与三模型输出的基础上,构建四个解剖工具:① 按「功率段位」(爬升/平台/回落)拆解误差,替代全天单一 nRMSE;② 以 |ΔP(15 min)|≥0.8 MW(装机的 4%)为事件阈值,统计各模型的命中率、精确率与幅度误差;③ 用相似日集合(k=9)逐点经验分位数构建 P5–P95 自适应区间,并派生中位数预测 M4;④ 将物理链路的晴空指数输入分为气候平均/NWP/完美信息三档,度量 NWP 云信息的价值梯度。核心发现有四条,每一条都对范文一的结论构成重要补充甚至反转:其一,误差高度集中于爬升段(n=768)与回落段(n=783),平台段(n=354)最准(M2 仅 0.0384);而积灰未建模使 M1 恰恰在平台段最差(0.0775)——高功率段的绝对误差被系统性高估放大。其二,综合精度冠军 M2 相似日法是「平滑器也是爬坡杀手」:其 nRMSE 最优的另一面是爬坡命中率崩塌——晴天 38.9%、多云 29.9%、阴雨仅 6.7%(75 个真实事件只命中 5 个);M1/M3 命中率虽达 68%–81%,精确率却只有约 40%–62%,虚报近半。其三,在与范文一严格同口径的名义 90% 下,k=9 集合区间在晴天同时做到更可靠(93.2%)与够锐(宽 1.962 MW,仅比常数区间宽 4%);但在多云天以窄 9.2% 的锐度换来覆盖下滑 3.0 个百分点,在阴雨天更是严重欠覆盖(75.0%,低 15.4 个百分点)——相似日池薄时,经验分位数会系统性低估尾部。其四,多云天的 NWP 云信息仅兑现约 14%(气候平均 0.0706 → NWP 0.0640,完美信息可达 0.0233),而晴天 NWP 甚至劣于气候平均(0.0387 vs 0.0332)——瓶颈根本不在云而在积灰等链路外因素。全文纯标准库、确定性复现,正文、配图、附录与真源四路数字一致。

二、问题重述

电网调度员拿到一份日前预测曲线后,真正要做的决策不是「这份曲线平均差多少」,而是:备用容量该在哪些时段多留?什么时刻可能触发爬坡告警?今天敢不敢把现货敞口开大? 这些问题分别对应误差的时间分布、事件捕捉能力与不确定性刻画,恰恰都是「全天一个 nRMSE + 一条常数宽度区间」无法回答的。具体地,本文在范文一的三模型(M1 物理基线 / M2 相似日加权 / M3 混合修正)框架上追加四问:① 若把一天拆成功率爬升、高位平台与回落三种段位,各模型的误差分布是什么?谁在调度最敏感的时段失准?② 以固定阈值定义爬坡事件后,各模型的命中率(漏报多少)、精确率(虚报多少)与幅度误差(抓到的坡够不够大)如何?这直接决定备用容量与告警策略。③ 范文一的残差分位区间宽度全天恒定;若改用相似日集合的逐点经验分位数,区间能否随当日不确定性自动伸缩?在同名义置信度下与常数区间的覆盖率—锐度权衡如何?④ 日前数值天气预报(NWP)中的云信息值多少误差改善?它的价值上限(完美信息)与当前兑现率之比,指示了改进方向应投向气象观测还是物理链路本身。

三、模型假设与符号

  • H1(面板复用):完全复用范文一的确定性合成面板与清洗结果(缺失插值 87 点、限电剔除 86 点)、三模型逐点输出及其分天气指标,本文所有新指标均由同一批测试日(40 天,晴 21/多云 13/阴雨 6)重新派生,保证与范文一可比。
  • H2(爬坡事件定义):记相邻 15 min 出力变化 |ΔP|≥0.8 MW(装机的 4%)为一个爬坡事件。阈值取 4% 是工程惯例量级:低于它的事件对备用调用的边际影响有限,高于它则事件稀疏到统计不稳。
  • H3(段位划分):实际出力 p≥60% 装机为平台段;2%≤p<60% 且局部斜率为正为爬升段、为负为回落段;夜间(p<2%)不参与统计。段位标签由真实曲线决定而非预测曲线,确保评估不受模型自身平滑性污染。
  • H4(同名义对比原则):集合区间与范文一常数区间的对比必须在同一名义置信度下进行。范文一采用残差 P5–P95(名义 90%),故集合区间主对比同样取 P5/P95;P10–P90(名义 80%)仅作自适应形态展示,不参与可靠性结论。

主要符号:RAMP_THRAMP\_TH 为爬坡事件阈值(0.8 MW/15 min);Kens=9K_{\mathrm{ens}}=9 为集合相似日数;hithit、precprec、ampamp 分别为事件命中率、精确率与幅度 MAE;q^p(i)\hat{q}_p(i) 为第 ii 时刻相似日集合功率的经验 pp 分位数(线性插值,type 7);Lc/Ln/LoL_c/L_n/L_o 分别为气候平均、NWP、完美 kt 输入下的物理链路 nRMSE。

四、方法:把一个平均数还原成一张调度地图

图1 调度者视角的误差解剖框架

4.1 功率段位分解

全天 nRMSE 把三类性质完全不同的误差混进一个标量:平台段的水平偏差、爬升段的跟踪滞后、回落段的提前衰减。分解方法是逐点打段位标签(按 H3),再在各段内部分别累计 RMSE 并除以装机容量。样本量(爬升 768、平台 354、回落 783 点,合计 1905 个有效点)来自 40 个测试日的全部白天时段,每一段都有足够的统计支撑。

4.2 爬坡事件三指标

以真实曲线定义事件集合 E={i: ∣ΔPact(i)∣≥RAMP_TH}E=\{i:\ |\Delta P_{\mathrm{act}}(i)|\ge RAMP\_TH\},预测事件集合 FF 同理定义于预测曲线。命中率 ∣E∩F∣/∣E∣|E\cap F|/|E| 度量漏报(漏掉的坡意味着备用不足),精确率 ∣E∩F∣/∣F∣|E\cap F|/|F| 度量虚报(频繁误报会透支告警可信度),幅度 MAE 只在命中的事件上累计 ∣ΔPpred−ΔPact∣|\Delta P_{\mathrm{pred}}-\Delta P_{\mathrm{act}}|,度量「抓到的坡够不够大」——三者合起来才是备用容量视角的完整画像,任何一个单一指标都会误导。

4.3 相似日集合分位区间与中位数预测 M4

范文一取 k=5 相似日做点预测平均;本文明知分位数需要更大的样本支撑尾部,故将集合扩至 k=9(与范文一相同的类内余弦相似度口径),对每个时刻把 9 个相似日的实际功率排序后取经验分位数 q^05,q^10,q^50,q^90,q^95\hat q_{05},\hat q_{10},\hat q_{50},\hat q_{90},\hat q_{95}。其中 q^50\hat q_{50} 序列本身就是一个新的点预测 M4 集合中位数——它是鲁棒的「典型相似日」水平估计;P5–P95 带则是随时间伸缩的自适应区间。

4.4 NWP 云信息的价值阶梯

把物理链路(与 M1 完全同式)的 kt 输入替换为三档:气候平均 kt(同类天气训练日的逐时刻均值——零气象信息下限)、NWP kt(现状)、完美 kt(当天真值,信息论上限)。三档共用同一功率转换链,误差之差即归因于云信息本身:Lc−LoL_c-L_o 是理论总价值,Lc−LnL_c-L_n 是当前 NWP 已兑现的部分,兑现率 = (Lc−Ln)/(Lc−Lo)(L_c-L_n)/(L_c-L_o)。

五、结果 I:误差的时空解剖

5.1 段位分解:平台段最准,也最能暴露系统偏差

图2 按功率段位分解的 nRMSE

图 2 给出段位分解结果。M2 与 M3 的误差都在平台段最低(0.0384 与 0.0607,低于各自爬升段的 0.0493 与 0.0566),符合直觉——高位平台期出力平稳、易预测。但 M1 恰好相反:平台段是其最差段位(0.0775)。原因正是范文一发现的积灰偏差:物理链路不知道组件脏了约 9%,这个固定比例的高估乘以最高的功率水平,绝对误差在平台段被放大到最大。同一个「全天 nRMSE 冠军归属」的故事,拆到段位层面呈现出完全不同的机理图景:数据驱动方法赢在最难的地方(跟踪变化),物理方法输在水平最高的时候(偏差被放大)。

5.2 多云典型日:相似日平均是一台低通滤波器

图3 多云典型日:M2 把云致爬坡抹成缓坡

图 3 是理解第二条发现的钥匙。多云日的真实功率是云团过境造成的密集锯齿,而 M2 的 k=9 平均曲线把这些锯齿几乎全部抹成一条缓坡——平均操作在压低随机误差的同时,也压掉了所有真实存在的高频结构。这不是 M2 独有的缺陷,而是一切「取历史均值」类方法的宿命:nRMSE 衡量的正是与均值的偏离,所以平滑器天然占优。

5.3 爬坡事件:nRMSE 冠军的致命盲区

图4 爬坡事件命中率对比

图 4 揭示了平滑的代价。以 0.8 MW/15 min 为阈值,40 个测试日共有真实爬坡事件 716 个(晴 303、多云 338、阴雨 75)。M2 的命中率全面崩塌:晴 38.9%、多云 29.9%、阴雨仅 6.7%——阴雨天的 75 个真实事件它只命中 5 个,全天仅报出 13 个候选事件,几乎整体失明。相反,M1/M3 命中率达 68%–81%(多云 81.1%/80.2%),但精确率仅 39.8%–61.7%,即每报两次坡约有一次虚报。更有意思的是幅度维度:M2 在晴天命中事件的幅度 MAE 只有 0.09 MW——它能「命中」的本来就是小坡,真正的陡坡(幅度常达 2 MW 以上,多云天 M1/M3 命中事件幅度 MAE 约 1.9 MW)全部漏网。结论:用全天 nRMSE 选出的冠军模型,恰恰是调度台上最危险的爬坡情报源;反之 M1/M3 的高召回伴随高虚报,直接拿去发告警会迅速透支运行人员的信任。

六、结果 II:自适应区间与云信息的价值

6.1 集合带的形态:宽度跟着不确定性走

图5 相似日集合的自适应区间

图 5 展示多云典型日的 P5–P95 集合带:午间云活动最强处带宽最大,早晚出力爬升期自动收窄。这种「随时段伸缩」的几何形态是常数宽度区间原理上做不到的——后者只能用一个折中宽度覆盖全天,必然在午间过窄、在早晚过宽。

6.2 同名义 90% 对比:锐度与可靠性的天气分化

图6 同名义口径下集合区间 vs 范文一常数区间

按 H4 的同名义原则(双方都取 P5–P95),图 6 给出主对比。晴天:集合区间覆盖率 93.2%(范文一 90.2%),平均宽度 1.962 MW 对 1.887 MW,只多 4%——可靠性与锐度双赢,因为晴天的不确定性小而稳定,历史相似日几乎就是当日的复刻。多云天:集合区间以窄 9.2%(4.841 对 5.331 MW)换来覆盖率下滑 3.0 个百分点(87.2% 对 90.2%)——锐度的改善不足以抵偿可靠性的损失,属于不划算的交易。阴雨天:集合区间严重欠覆盖,实测仅 75.0%,比名义低 15 个百分点、比范文一同口径实测低 15.4 个百分点。根因是相似日池薄:训练集中阴雨日本就稀缺,k=9 几乎取走整个池子,「最相似」的九天彼此差异很大,其经验离散度仍不足以覆盖测试日可能出现的极端雨带。分段宽度(图 7)进一步显示不确定性的内部结构:两类天气下平台段带宽最大(晴 2.780、多云 5.864 MW),爬升/回落段明显收窄(多云 4.669/4.940 MW)——即便同为「宽」,宽的位置也有讲究。

图7 集合区间宽度按段位分布

作为点估计的补充,M4 集合中位数在晴天拿下全场最优 nRMSE=0.0176,优于 M2 的 0.0193——中位数对集合内离群日的抗性使其成为低不确定天气下的理想水平估计;但在多云(0.0571)与阴雨(0.0306)不占优,此时形状与水平信息仍需物理/混合模型补足。

6.3 云信息的价值阶梯:14% 的兑现率与晴天的反直觉

图8 NWP 云信息价值梯度

图 8 的三档梯度给出本文最具行动指导性的结论。多云天:气候平均 0.0706 → NWP 0.0640 → 完美信息 0.0233。理论总价值高达 −64%,而当前 NWP 仅兑现 (0.0706−0.0640)/(0.0706−0.0233)≈14%(0.0706-0.0640)/(0.0706-0.0233)\approx 14\%——绝大多数潜在改善仍躺在未来更好的云观测里(更高分辨率的云图、地基全天空成像仪),这是明确值得投入的方向。晴天出现反直觉结果:NWP 的 0.0387 不仅远不及完美信息的 0.0338,反而劣于什么都不给的气候平均 0.0332——晴天的 kt 本该是一条平直带,NWP 施加的扰动纯属注入噪声;而完美信息也只把误差从 0.0332 降到 0.0338 的量级,说明晴天瓶颈根本不在云信息,而在积灰等链路外因素,买再好的气象源也无济于事,正确动作是给物理链路加 soiling 项。阴雨天:气候平均与 NWP 几乎持平(0.0295 对 0.0297),完美信息却低至 0.0106——NWP 目前对雨带强度几乎没有提供有效信息,改进空间同样巨大。

七、结论与调度建议

  1. 备用容量分段配置:误差集中于爬升段(M2 达 0.0493)与回落段(0.0504),平台段最准(0.0384)。灵活调节资源应向日出后与日落前的过渡时段倾斜,全天均一备用既在平台段浪费、又在爬坡时刻不足。
  2. 爬坡告警需要组合策略:不要用 nRMSE 选「告警模型」。可行方案是以 M1/M3 作高召回探测器(命中率 68%–81%)、M2 作水平参考,第二判据(如辐照实测突变)过滤虚报;或对 M2 输出叠加高频残差扰动生成爬坡情景。阴雨天 M2 的 6.7% 命中率意味着任何依赖相似日均值的告警体系在该天气下形同虚设。
  3. 区间策略分天气启用:晴天推荐切换到集合自适应区间(覆盖 93.2%、宽度代价仅 4%,且带宽随时段伸缩给出「几点最难测」的额外信息);多云与阴雨天集合带不可单独信赖(覆盖 87.2%/75.0%),应予扩宽或与残差常数区间取并集,并把「相似日池是否足够厚」作为启用前提。
  4. 信息投入的优先级排序:预算应优先投向多云/阴雨场景的云观测能力——完美信息的改进上限达 64%,而当前兑现率仅 14%(多云);晴天则应先修物理链路(纳入 soiling 项收回约 9% 的系统性高估),气象投入在该场景下不仅无益(NWP 劣于气候平均)而且方向错误。

八、模型验证(四路一致)

三重交叉验证:① 附录脚本在论文目录独立导入真源模块重跑全部实验,段位样本量(768/354/783)、三模型段位 nRMSE、多云/阴雨爬坡命中率(29.9%/6.7%)、集合区间覆盖率与宽度(93.2%/87.2%/75.0%;1.962/4.841/1.891 MW)、M4 晴天 0.0176 及三档信息梯度共 20 余项数字逐一吻合;② 同名义对比原则经专项核查:集合 P5–P95 与范文一 P5–P95 名义置信度严格一致,P10–P90 仅作展示不入结论;③ 抽取图 5 所示多云典型日,逐点核对 P50 曲线与 9 个相似日实际功率中位数的对应关系,偏差均在浮点舍入量级。正文、配图、附录、真源四路数字一致。

参考文献

[1] 2025 年电工杯数学建模竞赛 A 题:光伏电站发电功率日前预测问题(赛题原文,官方数据未公开)。

[2] 本站范文一:光伏电站发电功率日前预测——清洗 + 晴空指数 + 物理/相似日/混合三模型 + 区间(assets/problems/papers/dgcup2025a-1.md)。

[3] Antonanzas J. et al. Review of photovoltaic power forecasting[J]. Solar Energy, 2016, 136: 78–111.

[4] Lazer D. et al. The parable of Google Flu: traps in big data analysis[J]. Science, 2014, 343(6176): 1203–1205.(「大数据平滑器陷阱」的方法论警示:高频结构可能在求平均中无声消失)

附录:核心 Python 实现(可独立运行复现上述数字)

import sys, os
_HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.abspath(os.path.join(_HERE, "..", "..", "..", "tools")))
import gen_dgcup2025a_2 as H


def _f(x):
    return "NA" if x is None else "%.4f" % x


R = H.gen_dgcup2025a_2()
print("SEED=%d 装机=%.0fMW 爬坡阈值=%.2fMW/15min 集合k=%d"
      % (R["seed"], R["cap"], R["ramp_th"], R["k_ens"]))

print("--- ① 功率段位分解(nRMSE) ---")
for seg, row in R["segments"].items():
    print("%s(n=%d): M1=%s M2=%s M3=%s"
          % (seg, row["n"], _f(row["m1"]["nrmse"]),
             _f(row["m2"]["nrmse"]), _f(row["m3"]["nrmse"])))

print("--- ② 爬坡事件(多云/阴雨) ---")
for w in ("多云", "阴雨"):
    for m in ("m1", "m2", "m3"):
        r = R["ramp"][w][m]
        print("[%s]%s: 真实=%d 预测=%d 命中=%d 命中率=%s 精确率=%s"
              % (w, m, r["events_true"], r["events_pred"], r["hits"],
                 ("%.3f" % r["hit_rate"]) if r["hit_rate"] is not None else "NA",
                 ("%.3f" % r["precision"]) if r["precision"] is not None else "NA"))

print("--- ③ 集合区间(k=9) vs 范文一(同名义90%%: P5-P95) ---")
for w in ("晴", "多云", "阴雨"):
    print("[%s] 集合: 覆盖=%.3f 宽=%.3fMW | 范文一: 覆盖=%.3f 宽=%.3fMW"
          % (w, R["ensemble"]["cover"][w], R["ensemble"]["width_avg"][w],
             R["p1_cover"][w], R["p1_width"][w]))
m4 = R["ensemble"]["m4_metrics"]
print("M4(集合中位数)nRMSE:",
      {w: round(m4[w]["nrmse"], 4) for w in ("晴", "多云", "阴雨")})

print("--- ④ NWP 云信息价值(M1 nRMSE) ---")
for w in ("晴", "多云", "阴雨"):
    r = R["ladder"][w]
    lc, ln, lo = r["climatology"], r["nwp"], r["oracle"]
    rate = (lc - ln) / (lc - lo) if w == "多云" else None
    print("[%s] climatology=%.4f nwp=%.4f oracle=%.4f 兑现率=%s"
          % (w, lc, ln, lo, _f(rate)))