风电的Weibull分布及光电的Beta分布组合研究(Matlab代码实现)
做微电网容量配置或者风光储系统评估的时候,如果直接把风电和光伏的出力当成固定值来处理,最后算出来的结果十有八九是偏乐观的。为什么?因为风电和光伏本质上是间歇性电源,你用一个确定性的数字去描述它,丢掉了最关键的波动信息。比如同一个风电场,年平均风速可能都是6m/s,但一个地方的6m/s是常年稳定吹,另一个地方是时而狂风时而静风,两者的发电特性天差地别。这就需要概率模型登场了。
在新能源资源描述这块,两件事几乎绕不开:风电出力/风速一般用Weibull分布来拟合,光伏出力的标幺值一般用Beta分布来描述,两个分布组合在一起,就能刻画一个风光互补系统的联合出力特性。这篇东西我不打算给你堆公式,而是直接从工程角度讲清楚:为什么是这两个分布、Matlab里怎么把分布参数拟合出来、两个分布怎么组合起来用,以及我在实际项目里踩过的坑。
先说明一下,这篇内容的代码运行环境是Matlab R2021a及以上版本,工具箱只需要基础的Statistics and Machine Learning Toolbox,不需要额外装别的。下面按我实际做项目时的推进顺序来写。
1. 为什么风用Weibull、光用Beta:两个分布背后的物理逻辑
1.1 风速的偏态特性与Weibull分布的适配性
风速数据有几个很明显的统计特征:非负、右偏、存在大量小风速样本,偶尔有极大风速。正态分布是对称的,而且理论上负无穷到正无穷都有概率密度,拿来拟合风速,且不说物理上说不通,实际拟合效果也差得离谱——风速的直方图往往是左高右低的长尾形态,这正是Weibull分布能天然刻画的东西。
Weibull分布的概率密度函数长这样:
f(v) = (k/c) * (v/c)^(k-1) * exp(-(v/c)^k),v ≥ 0
其中k是形状参数,c是尺度参数。k参数特别有意思:k < 1时分布呈单调递减,k = 1时退化为指数分布,k > 1时出现单峰,k在2到3之间时非常接近风速的典型形态。工程上一般风速的k值落在1.5到3之间,c值大致对应年平均风速的1.1倍左右。这也是为什么这么多年来Weibull分布几乎成了风资源评估的行业标准——国际电工委员会IEC 61400系列标准里也推荐用两参数Weibull来拟合风速概率分布。
真正的风电机组出力不是风速本身,而是经过功率曲线转换后的结果。通常风机有一条三段式功率曲线:切入风速以下不出力,切入到额定风速之间近似线性爬升,额定风速以上封顶到额定功率,切出风速以上为了保护风机直接停机。所以你在做风电出力概率建模时,可以直接对风速做Weibull拟合,再经过功率曲线折算到出力;也可以直接对归一化出力做分布拟合。前者更通用,因为功率曲线是风机厂家给定的,可移植性好;后者更省事,但换了机型就得重新拟合。
1.2 Beta分布为什么适合光伏出力
光伏出力的物理过程是光照辐照度经过光伏组件转换而来,而辐照度受云层遮挡、大气衰减、太阳高度角等因素影响,呈现出明显的日内规律性和随机波动性。如果只看白天时段、把光伏出力归一化到[0,1]区间,它的概率密度形态通常不是单峰对称的,往往是低出力区间和高出力区间概率密度比较高,中间出力区间反而偏低——这种"U形"或者"J形"的分布形态,Beta分布是最拿手的。
Beta分布的概率密度函数写成:
f(x) = [Γ(α+β)/(Γ(α)Γ(β))] * x^(α-1) * (1-x)^(β-1),0 < x < 1
它的厉害之处在于形状极其灵活:α和β两个参数组合起来,可以让密度函数呈现均匀、单峰、U形、J形、钟形等各种形态。α < β时密度偏向低值区,α > β时偏向高值区,α = β = 1时就是均匀分布。光伏出力数据在不同天气类型下形态差异很大——晴天出力集中在额定功率附近,Beta分布的α会明显大于β;阴天出力集中在低值区,α小于β;多云天则可能接近均匀。一个分布族能覆盖这么多场景,这是Beta分布被广泛用在光资源描述上的根本原因。
这里有个关键点:Beta分布的支撑集是开区间(0,1),也就是说严格大于0、严格小于1。但实际光伏数据里,辐照度为零的夜间时段出力就是0,多云天气下瞬时出力也可能冲到接近额定值。这就引出后面要说的数据预处理问题。
2. 风速实测数据的Weibull拟合完整流程(Matlab实现)
2.1 参数估计的三种思路:极大似然、矩估计、最小二乘
Weibull参数估计在Matlab里最省事的方式是直接用wblfit函数,它内部用的是极大似然估计(MLE)。但我不建议你无脑调用函数,最好理解一下背后的计算逻辑,这样遇到拟合失败或者结果异常时才知道怎么排查。
极大似然估计的核心思路:找到一组(k, c),使得当前风速样本出现的联合概率最大。对Weibull分布取对数似然函数后求偏导,会得到一个关于k的非线性方程:
Σ(v_i^k * ln(v_i)) / Σ(v_i^k) - (1/k) - (1/n) * Σ(ln(v_i)) = 0
这个方程没有解析解,需要用牛顿-拉弗森迭代或者Matlab的fzero/fminsearch来解。wblfit内部就是做这个迭代的。矩估计则简单得多:已知Weibull分布的均值μ = c * Γ(1+1/k),方差σ² = c² * [Γ(1+2/k) - Γ²(1+1/k)],用样本均值和样本方差去反解k和c,但需要查Γ函数表或者数值求解,实际精度比MLE差一些。
最小二乘法的原理更有意思:Weibull累积分布函数F(v) = 1 - exp(-(v/c)^k),变形得到ln(-ln(1-F(v))) = kln(v) - kln(c),这是一个关于ln(v)的线性方程。把风速排序后计算经验累积频率,做一元线性回归,斜率就是k,截距可以算出c。这种方法实现简单且稳健,不需要迭代,工程上用得很多。
我在实际项目中偏好这么操作:先用最小二乘算一组初值,再用MLE做精细迭代,两者结果偏差超过5%就说明数据质量可能有问题,需要回头查原始数据。下面给出这个组合估计的实现代码。
2.2 Matlab拟合代码与拟合优度检验
% 风速数据导入,假设为列向量 wind_speed,单位m/s % wind_speed = xlsread('wind_data.xlsx', 'A1:A8760'); % 全年小时级数据 %% 第一步:最小二乘初值估计 % 按升序排列风速数据 v_sorted = sort(wind_speed); n = length(v_sorted); % 经验累积频率(Gringorten公式修正,避免0和1的极端值) F_emp = (1:n)' - 0.44) / (n + 0.12); % 线性化变换 x = log(v_sorted); y = log(-log(1 - F_emp)); % 一元线性回归 y = k*x + b p = polyfit(x, y, 1); k_init = p(1); b = p(2); c_init = exp(-b / k_init); %% 第二步:极大似然精细估计 % 用stats工具箱的wblfit,传入初值可减少迭代次数 [param_hat, param_ci] = wblfit(wind_speed, 'Alpha', 0.05, ... 'Options', statset('MaxIter', 1000, 'TolX', 1e-8)); k_hat = param_hat(1); c_hat = param_hat(2); fprintf('最小二乘初值: k = %.4f, c = %.4f\n', k_init, c_init); fprintf('MLE最终结果: k = %.4f, c = %.4f\n', k_hat, c_hat); fprintf('95%%置信区间: k = [%.4f, %.4f], c = [%.4f, %.4f]\n', ... param_ci(1,1), param_ci(2,1), param_ci(1,2), param_ci(2,2));拟合做完之后,很多人就停了,这不对。你还需要回答一个问题:拟合出来的Weibull分布和原始数据到底像不像?最常用的两个检验是卡方检验chi2gof和K-S检验kstest。卡方检验对分组方式敏感,样本量少的时候不建议用;K-S检验基于经验分布函数和理论分布函数的最大差值,更适合风速这种连续型数据。
%% 第三步:拟合优度检验 % K-S检验 [h_ks, p_ks, ksstat] = kstest(wind_speed, 'CDF', ... makedist('Weibull', 'a', c_hat, 'b', k_hat)); fprintf('K-S检验: h = %d, p值 = %.4f, KS统计量 = %.4f\n', ... h_ks, p_ks, ksstat); % 画图对比:频率直方图 vs 理论密度曲线 figure('Color', 'w'); histogram(wind_speed, 30, 'Normalization', 'pdf', 'FaceColor', ... [0.7 0.8 0.9], 'EdgeColor', 'none'); hold on; v_range = linspace(min(wind_speed), max(wind_speed), 500); pdf_theory = wblpdf(v_range, c_hat, k_hat); plot(v_range, pdf_theory, 'r-', 'LineWidth', 2); xlabel('风速 (m/s)'); ylabel('概率密度'); legend('实测风速频率', 'Weibull拟合密度'); grid on;这里有个小细节值得注意:直方图分组数不是随便定的。分组太少,直方图形状失真,拟合曲线看起来怎么都比不上;分组太多,每个bin里的样本太少,频率波动很大。我一般按Sturges公式取bin数 = ceil(1 + log2(n)),n=8760个全年小时风速数据时大概是15~16组,但上面代码里我写30组,因为那是为了展示密度曲线细节,实际检验时还是建议按公式来。
风速数据里有一个容易翻车的地方:零风速和极低风速(<0.1m/s)在气象站数据里经常出现,但测风塔数据里的静风记录往往已经经过仪器噪声处理。如果原始数据里静风比例超过10%,单峰Weibull的拟合质量会明显下降,曲线为了迁就零风速附近的峰值,会把整体形状拉偏。这种情况可以考虑双参数混合Weibull或者直接把静风时段单独建模,但这是另一个话题了,后面我稍微提一下。
3. Beta分布拟合光伏出力的工况与完整实现
3.1 光伏数据预处理:归一化、时段筛选、极端值处理
Beta分布的输入数据要求很简单也很苛刻:必须在(0,1)开区间内。但真实光伏功率数据几乎不可能天然满足这个条件——夜间出力为0,正午晴天出力可能等于额定值,这样数据里就会出现大量的0和1。如果不做处理直接扔给betafit函数,轻则参数估计不收敛,重则直接报错。
我的标准处理流程分三步:
时段筛选:只保留日照时段。这个时段的选取不是拍脑袋定一个"6点到18点",而是根据太阳高度角或者实际辐照度数据来判定。最简单的做法是取辐照度 > 20 W/m²的时刻作为有效日照时段。如果手里只有功率数据没有辐照度数据,可以用出力 > 装机容量1%的时刻反推。
归一化:将筛选出的功率数据除以额定功率,得到标幺值序列,范围天然在[0,1]之间。
边界处理:把归一化结果中等于0的值替换为一个小正数(比如0.001),等于1的值替换为0.999,然后做区间缩放:x_scaled = (x_raw * (len-1) + 0.5) / len,这是工程上常用的"光滑化"处理,避免Beta分布的边界奇异性。
为什么要这么做?Beta分布的密度函数在x趋近0或1时有奇异性——当α<1时x^(α-1)在0附近趋于无穷,当β<1时(1-x)^(β-1)在1附近趋于无穷。如果数据里有大量精确的0或1,极大似然估计会在这个过程中出问题。当然,你可以用混合模型(一个离散概率质量在0点+一个Beta连续部分)来精确建模,但这在微电网规划场景里通常不是必需,边界光滑化已经够用了。
3.2 参数估计的Matlab实现与不同天气类型的差异性
Beta参数估计最常用的是矩估计法,因为公式简单且直观。设样本均值为μ_hat,样本方差为σ²_hat,则:
α = μ_hat * (μ_hat * (1-μ_hat) / σ²_hat - 1) β = (1-μ_hat) * (μ_hat * (1-μ_hat) / σ²_hat - 1)
这个公式的前提是σ²_hat < μ_hat * (1-μ_hat),否则算出来α和β是负的。在实际数据中这个前提基本都能满足,但样本量太小或者天气极端(比如连续晴天的正午时段,出力全在0.98附近,方差趋近于0)时,σ²_hat可能被估得偏小,导致α和β膨胀到几百上千,这时Beta分布几乎退化成一个单点分布,后面做蒙特卡洛抽样时意义就不大了。
Matlab里也可以直接用betafit函数做极大似然估计,它内部采用牛顿迭代法,对初值有一定要求,建议先用矩估计算初值,再传给betafit。
% 光伏出力数据导入,假设为列向量 pv_power,单位kW,装机容量为pv_capacity % pv_power = xlsread('pv_data.xlsx', 'A1:A8760'); %% 第一步:时段筛选与归一化 irradiance_threshold = 20; % W/m2,阈值可根据实际数据调整 % 如果有辐照度数据,用辐照度来筛选;否则用功率阈值 active_idx = find(pv_power > 0.01 * pv_capacity); pv_active = pv_power(active_idx) / pv_capacity; %% 第二步:边界光滑化 n_active = length(pv_active); pv_smooth = (pv_active * (n_active - 1) + 0.5) / n_active; %% 第三步:参数估计(矩估计 + MLE) mu_hat = mean(pv_smooth); var_hat = var(pv_smooth); % 矩估计公式 alpha_moment = mu_hat * (mu_hat * (1-mu_hat) / var_hat - 1); beta_moment = (1-mu_hat) * (mu_hat * (1-mu_hat) / var_hat - 1); % 或者直接用MLE [alpha_mle, beta_mle] = betafit(pv_smooth); fprintf('矩估计: alpha = %.4f, beta = %.4f\n', alpha_moment, beta_moment); fprintf('MLE: alpha = %.4f, beta = %.4f\n', alpha_mle, beta_mle);这里我强烈建议把数据按天气类型拆分后再做拟合。同一个光伏电站在晴天和阴天的Beta参数可能差出一个量级——晴天可能α=6、β=2,阴天可能α=0.8、β=3。如果混在一起拟合,得到的参数描述的是一个"平均状态",既不是晴天也不是阴天,后面用它做容量配置会产生系统性偏差。工程上常见的做法是先用K-means或者基于辐照度均值把历史数据聚成三类:晴天、多云、阴天,然后分别拟合,做蒙特卡洛时按各类天气的出现频率加权抽样。
%% 第四步:按天气类型分场景拟合(示意) % 假设active辐照度均值已经算好,放在数组 irrad_daily_mean 中 % 简单三分类:低/中/高辐照度 low_idx = find(irrad_daily_mean < 250); mid_idx = find(irrad_daily_mean >= 250 & irrad_daily_mean < 500); high_idx = find(irrad_daily_mean >= 500); % 对每一类做Beta拟合 scenarios = {low_idx, mid_idx, high_idx}; alpha_set = zeros(3,1); beta_set = zeros(3,1); prob_set = zeros(3,1); for i = 1:3 idx = scenarios{i}; % 取出该场景下所有时刻的归一化出力 pv_scene = pv_smooth(ismember(floor(((1:n_active)-1)/24)+1, idx)); % 这里简化处理,实际应按日期索引匹配 [alpha_set(i), beta_set(i)] = betafit(pv_scene); prob_set(i) = length(idx) / length(unique_days); end这段代码我做了简化,实际项目中日期索引匹配要仔细处理,但核心思想就是:分场景拟合,场景概率归一化,最后抽样时按概率混合调用。这样得到的联合出力模型比单场景拟合精细得多。
4. 风光出力组合模型的搭建思路与仿真验证
4.1 从"各自拟合"到"组合研究":两种组合层次的实现
"组合"这个词在不同项目里含义差别很大。我把它拆成两个层次大家就清楚了:
第一层是独立组合:风速Weibull分布和光伏Beta分布各自拟合好了之后,在同一个时间框架内(比如8760小时)分别抽样,叠加得到系统总出力。这个做法隐含的假设是风速和辐照度相互独立。在规划阶段简单估算时,这个假设可以接受,因为风速和辐照度之间的相关性本来就不强,虽然两者都在白天或某些天气过程下有耦合,但相关系数一般也就0.3以下。
第二层是相关性组合:引入Copula函数把两个边缘分布连接起来,构建联合分布。风-光之间的相关性虽然不强,但极端天气下存在明显的尾部相关——比如大风天气往往伴随云层增厚,风电出力大时光伏出力反而小,这种负相关如果被忽略,会高估风光联合出力的稳定性,低估系统备用需求。所以从严谨的角度说,做容量配置必须考虑相关性。
Matlab里的Copula实现很成熟,核心是先把各自的边缘分布变成均匀分布(用各自的CDF做概率积分变换),然后拟合一个合适的Copula函数,最常用的是Gaussian Copula和t-Copula,再从这个Copula里抽样,反变换回原始分布空间。
%% 构建风-光联合分布:t-Copula方法 % 前提:wind_speed和pv_smooth已经完成各自的分布拟合 % 步骤1:把原始数据变换到均匀分布空间 u_wind = wblcdf(wind_speed, c_hat, k_hat); % Weibull CDF变换 u_pv = betacdf(pv_smooth, alpha_mle, beta_mle); % Beta CDF变换 % 步骤2:把均匀分布变换到t分布空间(自由度nu,默认用经验估计) % 这里用正态变换近似,因为t-Copula在Matlab中通过copulafit的'T'类型实现 [rho_t, nu_t] = copulafit('t', [u_wind, u_pv]); fprintf('t-Copula相关矩阵: rho = %.4f, 自由度 nu = %.2f\n', ... rho_t(1,2), nu_t); % 步骤3:从拟合好的Copula中生成联合样本 n_sim = 10000; U_sim = copularnd('t', rho_t, nu_t, n_sim); % 在均匀分布空间的联合样本 % 步骤4:反变换回原始物理空间 wind_sim = wblinv(U_sim(:,1), c_hat, k_hat); % 采样风速 pv_sim = betainv(U_sim(:,2), alpha_mle, beta_mle); % 归一化光伏出力抽样 pv_sim_real = pv_sim * pv_capacity; % 还原为功率用Copula的好处是,边缘分布可以各自选择最合适的分布族(风速用Weibull,光伏用Beta),相关性结构由Copula单独刻画,两者互不干扰。这比简单假设一个二元正态分布要严谨得多——二元正态要求边缘分布也是正态的,但风速和光伏出力哪个都不是正态。
4.2 组合模型的验证:Copula抽样结果的统计一致性检验
拟合完Copula不是终点,你得验证抽出来的联合样本是否保留了原始数据的统计特征。我通常做三件事:
- 边缘分布验证:分别对比模拟风速和原始风速的均值、标准差、中位数、P90/P10分位数,偏差控制在2%以内算合格。
- 相关性验证:对比模拟样本的Kendall秩相关系数(copulafit用的是秩相关)和原始数据的秩相关系数,误差应该在0.05以内。
- 极端场景验证:统计原始数据和模拟数据中"风光同时高出力"和"风光同时低出力"的概率,看Copula是否忠实保留了尾部相关。这一步最容易被忽略,但对微电网可靠性分析恰恰最重要。
%% 抽样结果与原始数据的统计对比 stats_names = {'均值'; '标准差'; '中位数'; 'P90'; 'P10'}; wind_stats_orig = [mean(wind_speed); std(wind_speed); median(wind_speed); ... prctile(wind_speed, 90); prctile(wind_speed, 10)]; wind_stats_sim = [mean(wind_sim); std(wind_sim); median(wind_sim); ... prctile(wind_sim, 90); prctile(wind_sim, 10)]; table_wind = table(stats_names, wind_stats_orig, wind_stats_sim, ... 'VariableNames', {'统计量', '原始数据', 'Copula模拟'}); % 秩相关对比 tau_orig = corr(u_wind, u_pv, 'Type', 'Kendall'); tau_sim = corr(U_sim(:,1), U_sim(:,2), 'Type', 'Kendall'); fprintf('Kendall秩相关 原始: %.4f, 模拟: %.4f\n', tau_orig, tau_sim); % 尾部一致概率对比(示例:两者都超过各自P80的事件概率) p_both_orig = mean(wind_speed > prctile(wind_speed, 80) & ... pv_smooth > prctile(pv_smooth, 80)); p_both_sim = mean(wind_sim > prctile(wind_speed, 80) & ... pv_sim > prctile(pv_smooth, 80)); fprintf('联合高出力概率 原始: %.4f, 模拟: %.4f\n', p_both_orig, p_both_sim);如果在这些指标上模拟结果和原始数据对不上,优先怀疑数据预处理阶段的问题——比如风速数据和光伏数据在时间轴上没对齐、光伏数据的0值处理方式影响了Beta参数等。我有一次排查了很久,最后发现是风速数据和光伏数据来自不同年份,时间戳对不上,相关性天然被拉低了。
4.3 组合分布的应用示例:风光互补系统的容量配置
组合模型搭好之后最直接的应用,就是评估某个装机配比下系统的电力缺口概率。假设负荷为恒定的P_load,风电装机为W,光伏装机为S,则每个时刻的总出力为P_total = wind_power * W + pv_power * S,电力缺口概率就是P(P_total < P_load)。
用上面生成的联合样本,这个概率可以直接统计出来:
%% 容量配置方案评估 W_capacity = 50; % 风电装机 MW S_capacity = 30; % 光伏装机 MW P_load = 40; % 负荷 MW(简化恒定负荷假设) % wind_sim的单位是m/s,需要先经过功率曲线换算 wind_power_pu = zeros(size(wind_sim)); v_in = 3; v_r = 12; v_out = 25; % 典型风机参数 wind_power_pu(wind_sim < v_in | wind_sim >= v_out) = 0; idx_ramp = wind_sim >= v_in & wind_sim < v_r; wind_power_pu(idx_ramp) = (wind_sim(idx_ramp) - v_in) / (v_r - v_in); idx_full = wind_sim >= v_r & wind_sim < v_out; wind_power_pu(idx_full) = 1; % 联合出力与缺口概率 P_total = wind_power_pu * W_capacity + pv_sim * S_capacity; loss_prob = mean(P_total < P_load); fprintf('配置风电%.0fMW + 光伏%.0fMW,负荷%.0fMW时的缺口概率 = %.4f\n', ... W_capacity, S_capacity, P_load, loss_prob);这就是组合分布最直接的工程价值:你可以通过这个模型去调整W和S的比例,画出缺口概率的等高线图,找到满足可靠性要求的最小配置组合。比单纯用"年发电量"作为优化目标要靠谱得多,因为年发电量只告诉你总量够不够,不告诉你波动性怎么影响可靠性。
5. 实际项目中容易踩的坑和几条工程建议
5.1 数据层面的坑:零值处理、时间对齐、样本量
第一个坑是静风数据的处理。如果目标风电场的静风时段占比超过15%,单Weibull拟合效果必然差,我建议改用混合Weibull:f(v) = ω * f1(v) + (1-ω) * f2(v),其中f1描述静风/微风段,f2描述中风段,ω是混合权重。参数估计可以用EM算法或者直接在Matlab里用fitgmdist配合自定义分布做,但复杂度会上一个台阶。规划阶段先看看静风占比,占比不高就用单Weibull,省心。
第二个坑是光伏Beta拟合时的边界值处理。前面提到了光滑化方法,但我见过有些论文直接把这部分数据删掉,这也不对——极端出力状态(接近0和接近1)恰恰是光伏系统最重要的运行状态,你把它删了,分布密度在这两个区间会严重失真。边界光滑化是保留样本量的前提下最稳妥的办法。
第三个坑是时间对齐。风速数据和辐照度数据的采样频率如果不同(比如风速是10分钟平均,辐照度是小时平均),做Copula拟合之前必须先统一到同一个时间尺度。这个错误很隐蔽,因为均值看不太出来差异,但相关性分析会明显失真。
5.2 参数估计层面的坑:初值敏感性和不收敛处理
Weibull的MLE在某些样本形态下容易迭代发散,尤其是样本里有极端离群点的时候。wblfit函数虽然内部有迭代保护,但你最好像前面代码里那样先做一次最小二乘得到合理初值,再传给MLE迭代。如果wblfit还是不收敛,把离群点找出来看看是不是测风塔故障导致的异常记录,正常风速数据的极大值不太可能超过40m/s,如果出现60m/s这种数,大概率是传感器出问题了。
Beta分布的矩估计有一个隐含风险:当数据方差很小(比如晴天正午的标准化出力都在0.9附近),σ²_hat远小于μ(1-μ),α、β会变成很大的值(比如α=50、β=8),这时的Beta分布密度曲线极度尖锐,抽样时一旦样本落在尖峰之外,物理意义就很奇怪。我的建议是,如果α或β超过20,考虑是不是数据本身太单一了,可以扩大数据的时间范围(比如把季节性变化也包含进来),或者改成分场景拟合。
5.3 模型层面的坑:Copula的适用性边界
Copula不是万能的。对于风-光这种相关性本来就弱的情形,Gaussian Copula通常够用了,自由度nu很高的t-Copula也会退化成Gaussian。真正需要谨慎的是极端气象事件,比如台风过境时风速和云量同步变化,此时尾部相关性会显著增强,t-Copula的低自由度版本才能捕获这种结构。但低自由度t-Copula对样本量的要求很高,如果历史数据只有一两年,硬拟合低自由度t-Copula反而会过拟合。
我的建议是:先用Gaussian Copula做基准,然后比较t-Copula(让自由度作为自由参数)的拟合优度,用AIC或BIC判断是否值得增加复杂度。如果AIC差异不大,就选参数更少的Gaussian Copula。这个道理和机器学习里奥卡姆剃刀原则是一样的。
5.4 一条经验法则:永远先画直方图再看拟合曲线
不管你的参数估计做得多么精细,我都会先画一张频率直方图+理论密度曲线的对比图,肉眼先看一遍。这不是形式主义——有时候检验统计量全过,但曲线形态在某个区间明显不贴合,原因可能是数据里有分段特征(比如两座不同地形的风电场数据混在一起),这种问题数值检验很难发现,但图上一眼就看出来了。先看图,再做检验,这个顺序不要反过来。
6. 给初学者的快速上手建议与扩展方向
如果这篇内容你只看结论,那么记住三条:风速数据先清洗再拟合,静风占比高就上混合Weibull;光伏出力先筛选日照时段再归一化,Beta拟合务必处理边界值;要做风光联合出力建模,Copula是比独立抽样更严谨的选择,但前提是先把各自的边缘分布拟合扎实。
手头暂时没有实测数据的话,可以用Matlab的makedist生成一组服从Weibull或Beta的仿真数据来跑通流程。比如用wblrnd(8, 2, 8760, 1)生成一组全年小时风速序列,用betarnd(3, 2, 8760, 1)生成一组光伏出力标幺值序列,然后把上面所有代码走一遍,跑通了再换真实数据。这个"先仿真后实测"的思路,我建议所有初学者都养成习惯——因为排错的时候你可以先确定数据没问题,把变量控制在代码和参数这一层,出问题更好定位。
在这个方向继续往下扩展的话,还有几件事值得做:把风速的混合Weibull建模做扎实、给Beta分布引入天气状态转移的马尔可夫链,以及在Copula基础上引入时间序列相关性(因为风速和辐照度本身都有强自相关性)。这些都是从"能做出来"走向"做得专业"的必经之路。
我自己做下来的最大体会是,概率建模这活,七分在数据处理,三分在模型选型。很多人一上来就盯着Copula、混合模型这些高级概念,结果数据预处理没做干净,后面全是徒劳。先把数据的零值、边界、时间对齐、异常值这些基本功做扎实了,再用Weibull和Beta把单机出力模型拟合好,最后才是组合建模——这个顺序走下来,每一步的坑都可以定位到具体环节,不会出现"模型跑出来结果不对但不知道哪里出了问题"的尴尬局面。