光伏发电作为可再生能源的主力军,其出力特性具有显著的随机性和波动性。在电力系统调度中,我们需要考虑各种可能的光伏出力场景,但直接使用海量原始数据会导致计算复杂度爆炸式增长。这就引出了光伏时间序列聚类的核心需求——如何在保留原始数据统计特征的前提下,将数千条光伏出力曲线压缩到可管理的数量级。
传统方法通常采用蒙特卡洛模拟生成大量场景,但这对后续优化计算造成了巨大负担。我在参与某省级电网调度系统升级时,就遇到过这样的困境:系统需要处理超过5000个光伏场景,导致优化求解时间超过12小时,根本无法满足实时调度需求。这也是为什么场景削减技术(Scenario Reduction)在新能源领域变得越来越重要。
光伏出力受多种因素影响,包括日照强度、云层变化、温度等。经过多次实测数据对比,我发现Beta分布特别适合描述光伏出力的概率特性:
matlab复制a = 2; b = 5; % Beta分布形状参数
daily_max = betarnd(a, b, num_scenes, 1); % 每日最大出力水平
这里a=2, b=5的参数设置是基于我国中部地区春季光伏电站的实测数据拟合结果。实际应用中,建议根据当地气候特点调整这两个参数:
光伏出力在一天内呈现明显的周期性变化,我采用正弦函数叠加噪声的方式来模拟:
matlab复制hours = 24;
time_points = linspace(0, pi, hours);
base_pattern = sin(time_points); % 基本日内模式
% 添加场景特异性波动
for i = 1:num_scenes
noise = 0.1 * randn(1, hours);
pv_scenes(i,:) = daily_max(i) * (base_pattern + noise + abs(min(noise)));
end
关键技巧:在噪声项后添加abs(min(noise))是为了确保出力不为负值,这是实际物理系统的硬性约束。
与传统数据聚类不同,时间序列聚类需要特别注意两点:
我的解决方案是:
matlab复制% 数据预处理
pv_normalized = (pv_scenes - min(pv_scenes,[],2)) ./ ...
(max(pv_scenes,[],2) - min(pv_scenes,[],2)); % 行归一化
% 添加移动平均滤波
window_size = 3;
pv_smoothed = movmean(pv_normalized, window_size, 2);
经过多次实验,我总结出以下参数组合效果最佳:
matlab复制k = 10; % 初始聚类数
options = statset('UseParallel', true); % 启用并行计算
[cluster_idx, centroids] = kmeans(pv_smoothed, k, ...
'Distance', 'cityblock', ... % 曼哈顿距离对异常值更鲁棒
'Replicates', 10, ... % 重复次数
'MaxIter', 200, ...
'Options', options);
参数选择背后的考量:
单独使用轮廓系数有时会误导,我推荐双指标验证法:
matlab复制% 轮廓系数计算
silh_values = silhouette(pv_smoothed, cluster_idx);
avg_silh = mean(silh_values);
% 肘部法则实现
wcss = zeros(1,15); % 测试k=1到15
for k = 1:15
[~, ~, sumd] = kmeans(pv_smoothed, k);
wcss(k) = sum(sumd);
end
% 可视化
figure;
subplot(1,2,1);
plot(1:15, wcss, '-o');
xlabel('聚类数k');
ylabel('组内平方和');
subplot(1,2,2);
plot(centroids');
title(['典型场景 k=',num2str(k),' 轮廓系数=',num2str(avg_silh)]);
每个簇的权重不应简单按样本数计算,我改进的方法考虑了簇内距离:
matlab复制[~, dist_to_centroid] = pdist2(centroids, pv_smoothed, 'cityblock', 'Smallest', 1);
cluster_quality = exp(-dist_to_centroid'); % 转化距离为质量指标
weights = accumarray(cluster_idx, cluster_quality) / sum(cluster_quality);
这种方法赋予紧凑簇更高的权重,更符合物理实际。
在三个省级电网项目中,我遇到的主要问题及解决方案:
天气突变场景处理:
冬季/夏季模式差异:
小样本量问题:
将聚类结果应用于调度系统的具体步骤:
matlab复制typical_scenes = centroids .* (max(pv_scenes,[],2) - min(pv_scenes,[],2))' + min(pv_scenes,[],2)';
matlab复制% 考虑预测误差的权重调整
forecast_error = 0.15; % 典型预测误差率
adjusted_weights = weights .* (1 + forecast_error * randn(size(weights)));
adjusted_weights = adjusted_weights / sum(adjusted_weights);
matlab复制scenario_data = struct(...
'scenes', typical_scenes, ...
'weights', adjusted_weights, ...
'probability', weights);
当处理超大规模场景(>10万条)时,我采用的优化策略:
matlab复制% 第一阶段:子采样5%
sample_idx = randperm(size(pv_scenes,1), ceil(0.05*size(pv_scenes,1)));
[~, coarse_centers] = kmeans(pv_scenes(sample_idx,:), 50);
% 第二阶段:全数据精细聚类
[cluster_idx, centroids] = kmeans(pv_scenes, k, ...
'Start', coarse_centers(1:k,:));
对于分布式光伏场站,我开发了时空联合聚类方法:
matlab复制% 三维数据矩阵构建
pv_tensor = reshape(pv_scenes, [num_stations, hours, num_days]);
% Tucker分解
[core, ~] = tucker_als(pv_tensor, [3 3 3]); % 自定义函数
% 核心张量聚类
[cluster_idx, ~] = kmeans(core(:,:), k);
我总结的最有效可视化方案:
matlab复制figure('Position', [100,100,1200,600]);
subplot(1,2,1);
hold on;
arrayfun(@(i) plot(pv_scenes(cluster_idx==i,:)', 'Color',[0.8 0.8 0.8]), 1:k);
plot(centroids', 'LineWidth', 2);
title('聚类结果展示');
subplot(1,2,2);
pie(weights);
title('场景权重分布');
legend(arrayfun(@(i) sprintf('场景%d',i),1:k,'UniformOutput',false));
除了轮廓系数,我建立的完整评估体系:
matlab复制original_mean = mean(pv_scenes);
reduced_mean = weights' * centroids;
feature_preservation = 1 - norm(original_mean - reduced_mean)/norm(original_mean);
matlab复制[~, extreme_idx] = max(pv_scenes * [1:24]'); % 识别最极端场景
coverage = any(cluster_idx == cluster_idx(extreme_idx));
matlab复制% 模拟调度结果差异
original_cost = mean(dispatch_simulation(pv_scenes));
reduced_cost = dispatch_simulation(centroids) * weights;
error_percent = abs(original_cost - reduced_cost)/original_cost * 100;