MATLAB光伏出力预测系统(引入气象影响因子)

一、系统架构

%% 光伏出力预测系统 - 考虑气象因子的深度学习框架
% 系统功能:基于历史数据和气象因子的光伏出力预测
% 预测方法:LSTM + 注意力机制 + 多变量时间序列预测
% 气象因子:温度、湿度、风速、辐照度、云量、气压等

clear; clc; close all;
warning('off', 'all');

%% 1. 系统参数配置
disp('=== 光伏出力预测系统 ===');
disp('初始化系统参数...');

% 预测参数
params = struct();
params.pred_horizon = 24;          % 预测未来24小时
params.lookback_window = 168;      % 使用过去168小时(7天)数据
params.train_ratio = 0.8;          % 训练集比例
params.val_ratio = 0.1;            % 验证集比例
params.batch_size = 32;            % 批次大小
params.max_epochs = 100;           % 最大训练轮数
params.learning_rate = 0.001;      % 学习率
params.dropout_rate = 0.2;         % Dropout率
params.patience = 10;              % 早停耐心值

% 数据参数
params.seasonal_period = 24;       % 日周期
params.trend_period = 168;         % 周周期
params.n_features = 12;            % 特征数量

% 模型选择
params.model_type = 'lstm_attention';  % lstm, bilstm, lstm_attention, cnn_lstm
params.use_weather = true;         % 是否使用气象因子
params.use_temporal = true;        % 是否使用时序特征
params.normalize_method = 'zscore'; % 标准化方法: zscore, minmax

%% 2. 数据加载与预处理
disp('加载和预处理数据...');

% 2.1 加载数据(模拟或真实数据)
if exist('real_pv_data.mat', 'file')
    load('real_pv_data.mat', 'pv_data', 'weather_data', 'timestamp');
    fprintf('已加载真实数据: %d 个样本\n', length(pv_data));
else
    [pv_data, weather_data, timestamp] = generate_synthetic_data(params);
    fprintf('已生成模拟数据: %d 个样本\n', length(pv_data));
end

% 2.2 特征工程
features = create_features(pv_data, weather_data, timestamp, params);

% 2.3 数据标准化
[features_norm, norm_params] = normalize_features(features, params);

% 2.4 划分训练集、验证集、测试集
[X_train, Y_train, X_val, Y_val, X_test, Y_test, idx] = ...
    split_dataset(features_norm, pv_data, params);

fprintf('数据划分结果:\n');
fprintf('  训练集: %d 个样本\n', size(X_train, 1));
fprintf('  验证集: %d 个样本\n', size(X_val, 1));
fprintf('  测试集: %d 个样本\n', size(X_test, 1));

%% 3. 模型构建
disp('构建深度学习模型...');

input_size = size(X_train, 2);
num_features = size(X_train, 3);

switch params.model_type
    case 'lstm'
        model = create_lstm_model(input_size, num_features, params);
    case 'bilstm'
        model = create_bilstm_model(input_size, num_features, params);
    case 'lstm_attention'
        model = create_lstm_attention_model(input_size, num_features, params);
    case 'cnn_lstm'
        model = create_cnn_lstm_model(input_size, num_features, params);
    otherwise
        error('未知的模型类型');
end

% 显示模型结构
analyzeNetwork(model);

%% 4. 模型训练
disp('开始训练模型...');

% 训练选项
options = trainingOptions('adam', ...
    'MaxEpochs', params.max_epochs, ...
    'MiniBatchSize', params.batch_size, ...
    'InitialLearnRate', params.learning_rate, ...
    'GradientThreshold', 1, ...
    'Shuffle', 'every-epoch', ...
    'ValidationData', {X_val, Y_val}, ...
    'ValidationFrequency', 30, ...
    'ValidationPatience', params.patience, ...
    'Plots', 'training-progress', ...
    'Verbose', false, ...
    'LearnRateSchedule', 'piecewise', ...
    'LearnRateDropFactor', 0.5, ...
    'LearnRateDropPeriod', 20);

% 训练模型
[net, info] = trainNetwork(X_train, Y_train, model, options);

% 保存模型
save('pv_prediction_model.mat', 'net', 'norm_params', 'params', 'info');

%% 5. 模型评估
disp('评估模型性能...');

% 5.1 在验证集上预测
Y_val_pred = predict(net, X_val, 'MiniBatchSize', params.batch_size);

% 5.2 在测试集上预测
Y_test_pred = predict(net, X_test, 'MiniBatchSize', params.batch_size);

% 5.3 反标准化
Y_test_true = Y_test * norm_params.pv_std + norm_params.pv_mean;
Y_test_pred_denorm = Y_test_pred * norm_params.pv_std + norm_params.pv_mean;

% 5.4 计算评价指标
metrics = calculate_metrics(Y_test_true, Y_test_pred_denorm);

fprintf('\n=== 模型性能指标 ===\n');
fprintf('RMSE: %.4f kW\n', metrics.rmse);
fprintf('MAE: %.4f kW\n', metrics.mae);
fprintf('MAPE: %.2f%%\n', metrics.mape * 100);
fprintf('R²: %.4f\n', metrics.r2);
fprintf('nRMSE: %.2f%%\n', metrics.nrmse * 100);

%% 6. 结果可视化
disp('生成可视化结果...');
visualize_results(Y_test_true, Y_test_pred_denorm, timestamp(idx.test), metrics, params);

%% 7. 特征重要性分析
disp('分析特征重要性...');
feature_importance = analyze_feature_importance(net, X_test, Y_test, features, params);
plot_feature_importance(feature_importance);

%% 8. 未来预测
disp('进行未来24小时预测...');
future_prediction = predict_future(net, features_norm, norm_params, params);
plot_future_prediction(future_prediction, timestamp);

%% 9. 敏感性分析
disp('进行敏感性分析...');
sensitivity_results = sensitivity_analysis(net, features_norm, norm_params, params);
plot_sensitivity_analysis(sensitivity_results);

%% 10. 模型解释性分析
disp('模型解释性分析...');
explain_model_predictions(net, X_test, Y_test_pred, features, params);

fprintf('\n=== 光伏出力预测完成 ===\n');

二、数据生成模块

function [pv_data, weather_data, timestamp] = generate_synthetic_data(params)
    % 生成模拟光伏出力和气象数据
    
    n_days = 365;  % 一年数据
    n_samples = n_days * 24;  % 小时数据
    
    % 生成时间戳
    start_date = datetime('2023-01-01 00:00:00');
    timestamp = start_date + hours(0:n_samples-1)';
    
    % 1. 生成光伏出力数据(基于太阳辐射模型)
    pv_data = zeros(n_samples, 1);
    
    for i = 1:n_samples
        t = timestamp(i);
        hour_of_day = hour(t);
        day_of_year = day(t, 'dayofyear');
        
        % 太阳高度角计算
        lat = 39.9;  % 纬度(北京)
        lon = 116.4; % 经度
        [sun_altitude, ~] = calculate_sun_position(lat, lon, t);
        
        if sun_altitude > 0
            % 日出到日落期间有光伏出力
            % 基本出力曲线(正弦平方)
            base_power = 1000 * sind(sun_altitude)^2;
            
            % 加入日变化
            daily_variation = 1 + 0.2 * sin(2*pi*hour_of_day/24);
            
            % 加入季节变化
            seasonal_variation = 1 + 0.3 * sin(2*pi*(day_of_year-80)/365);
            
            % 加入随机波动
            random_variation = 1 + 0.1 * randn;
            
            pv_data(i) = base_power * daily_variation * seasonal_variation * random_variation;
        else
            pv_data(i) = 0;
        end
    end
    
    % 平滑处理
    pv_data = smoothdata(pv_data, 'gaussian', 6);
    
    % 2. 生成气象数据
    weather_data = struct();
    
    % 温度(℃) - 日变化和季节变化
    base_temp = 15 + 10 * sin(2*pi*(day_of_year-105)/365);
    daily_temp_variation = 8 * sin(2*pi*(hour_of_day-14)/24);
    weather_data.temperature = base_temp + daily_temp_variation + 3*randn(n_samples,1);
    
    % 湿度(%) - 与温度负相关
    base_humidity = 60 - 0.5 * (weather_data.temperature - 20);
    weather_data.humidity = max(20, min(100, base_humidity + 10*randn(n_samples,1)));
    
    % 风速(m/s)
    base_wind = 3 + 2 * sin(2*pi*day_of_year/365);
    weather_data.wind_speed = max(0, base_wind + 2*randn(n_samples,1));
    
    % 辐照度(W/m²) - 与光伏出力强相关
    weather_data.irradiance = pv_data + 50*randn(n_samples,1);
    weather_data.irradiance = max(0, weather_data.irradiance);
    
    % 云量(0-1)
    base_cloud = 0.3 + 0.2 * sin(2*pi*day_of_year/365);
    weather_data.cloud_cover = max(0, min(1, base_cloud + 0.2*randn(n_samples,1)));
    
    % 气压(hPa)
    base_pressure = 1013 + 10 * sin(2*pi*day_of_year/365);
    weather_data.pressure = base_pressure + 5*randn(n_samples,1);
    
    % 降水(mm/h)
    rain_prob = 0.1 + 0.05 * sin(2*pi*day_of_year/365);
    is_raining = rand(n_samples,1) < rain_prob;
    weather_data.precipitation = is_raining .* (0.1 + 5*rand(n_samples,1));
    
    % 能见度(km)
    base_visibility = 10 - 8 * weather_data.cloud_cover;
    weather_data.visibility = max(1, base_visibility + 2*randn(n_samples,1));
    
    fprintf('已生成 %d 天的模拟数据\n', n_days);
end

function [altitude, azimuth] = calculate_sun_position(lat, lon, time)
    % 计算太阳位置
    % 输入:纬度(deg), 经度(deg), 时间(datetime)
    % 输出:太阳高度角(deg), 方位角(deg)
    
    % 转换为弧度
    lat_rad = deg2rad(lat);
    
    % 计算儒略日
    d = days(time - datetime(year(time),1,1)) + 1;
    
    % 太阳赤纬(简化计算)
    declination = 23.45 * sind(360*(284 + d)/365);
    declination_rad = deg2rad(declination);
    
    % 计算时角
    hour_angle = 15 * (hour(time) + minute(time)/60 - 12);
    hour_angle_rad = deg2rad(hour_angle);
    
    % 计算太阳高度角
    sin_altitude = sin(lat_rad) * sin(declination_rad) + ...
                   cos(lat_rad) * cos(declination_rad) * cos(hour_angle_rad);
    altitude = asin(sin_altitude);
    altitude = rad2deg(altitude);
    
    % 计算太阳方位角
    cos_azimuth = (sin(declination_rad) - sin(lat_rad) * sin(altitude)) / ...
                  (cos(lat_rad) * cos(asin(sin_altitude)));
    azimuth = acos(min(1, max(-1, cos_azimuth)));
    azimuth = rad2deg(azimuth);
    
    % 调整方位角
    if hour_angle > 0
        azimuth = 360 - azimuth;
    end
end

三、特征工程模块

function features = create_features(pv_data, weather_data, timestamp, params)
    % 创建特征矩阵
    
    n_samples = length(pv_data);
    
    % 初始化特征矩阵
    n_features = params.n_features;
    features = zeros(n_samples, n_features);
    
    % 1. 光伏出力相关特征
    features(:,1) = pv_data;  % 当前光伏出力
    
    % 滞后特征
    features(:,2) = [0; pv_data(1:end-1)];  % 滞后1小时
    features(:,3) = [zeros(2,1); pv_data(1:end-2)];  % 滞后2小时
    features(:,4) = [zeros(24,1); pv_data(1:end-24)];  % 滞后24小时
    features(:,5) = [zeros(168,1); pv_data(1:end-168)];  % 滞后168小时
    
    % 2. 气象特征
    features(:,6) = weather_data.temperature;
    features(:,7) = weather_data.humidity;
    features(:,8) = weather_data.wind_speed;
    features(:,9) = weather_data.irradiance;
    features(:,10) = weather_data.cloud_cover;
    
    % 3. 时间特征
    hour_of_day = hour(timestamp);
    day_of_week = weekday(timestamp);
    month_of_year = month(timestamp);
    day_of_year = day(timestamp, 'dayofyear');
    
    % 周期性编码
    features(:,11) = sin(2*pi*hour_of_day/24);
    features(:,12) = cos(2*pi*hour_of_day/24);
    
    % 4. 派生特征
    % 温度-辐照度交互特征
    features(:,13) = weather_data.temperature .* weather_data.irradiance;
    
    % 云量对辐照度的影响
    features(:,14) = weather_data.irradiance .* (1 - weather_data.cloud_cover);
    
    % 滑动统计特征
    window_size = 24;
    features(:,15) = movmean(pv_data, window_size, 'omitnan');
    features(:,16) = movstd(pv_data, window_size, 'omitnan');
    
    % 5. 天气状态特征
    % 晴天指数
    sunshine_index = (1 - weather_data.cloud_cover) .* (weather_data.irradiance / max(weather_data.irradiance));
    features(:,17) = sunshine_index;
    
    % 降雨影响
    rain_effect = exp(-weather_data.precipitation);
    features(:,18) = rain_effect;
    
    % 6. 季节性特征
    features(:,19) = sin(2*pi*day_of_year/365);
    features(:,20) = cos(2*pi*day_of_year/365);
    
    % 7. 周特征
    features(:,21) = sin(2*pi*day_of_week/7);
    features(:,22) = cos(2*pi*day_of_week/7);
    
    % 8. 气象组合特征
    % 体感温度
    apparent_temp = weather_data.temperature + 0.33*weather_data.humidity/100*6.105*exp(17.27*weather_data.temperature/(237.7+weather_data.temperature)) - 0.7*weather_data.wind_speed - 4;
    features(:,23) = apparent_temp;
    
    % 能见度指数
    visibility_index = weather_data.visibility / max(weather_data.visibility);
    features(:,24) = visibility_index;
    
    % 更新特征数量
    params.n_features = size(features, 2);
    
    fprintf('已创建 %d 个特征\n', params.n_features);
end

四、数据预处理模块

function [features_norm, norm_params] = normalize_features(features, params)
    % 数据标准化
    
    n_samples = size(features, 1);
    n_features = size(features, 2);
    
    features_norm = zeros(size(features));
    norm_params = struct();
    
    switch params.normalize_method
        case 'zscore'
            % Z-score标准化
            for i = 1:n_features
                mu = mean(features(:,i), 'omitnan');
                sigma = std(features(:,i), 'omitnan');
                
                if sigma < 1e-6
                    sigma = 1;
                end
                
                features_norm(:,i) = (features(:,i) - mu) / sigma;
                
                % 保存标准化参数
                norm_params.mean(i) = mu;
                norm_params.std(i) = sigma;
            end
            
        case 'minmax'
            % 最小-最大标准化
            for i = 1:n_features
                f_min = min(features(:,i));
                f_max = max(features(:,i));
                
                if (f_max - f_min) < 1e-6
                    features_norm(:,i) = 0;
                else
                    features_norm(:,i) = (features(:,i) - f_min) / (f_max - f_min);
                end
                
                % 保存标准化参数
                norm_params.min(i) = f_min;
                norm_params.max(i) = f_max;
            end
            
        otherwise
            error('未知的标准化方法');
    end
    
    % 处理NaN值
    features_norm(isnan(features_norm)) = 0;
    
    % 保存光伏出力的标准化参数(用于反标准化)
    norm_params.pv_mean = norm_params.mean(1);
    norm_params.pv_std = norm_params.std(1);
    
    fprintf('已完成 %s 标准化\n', params.normalize_method);
end

function [X_train, Y_train, X_val, Y_val, X_test, Y_test, idx] = ...
    split_dataset(features, target, params)
    % 划分数据集
    
    n_samples = size(features, 1);
    lookback = params.lookback_window;
    horizon = params.pred_horizon;
    
    % 计算可用样本数
    n_usable = n_samples - lookback - horizon + 1;
    
    % 生成输入输出对
    X = zeros(n_usable, lookback, size(features, 2));
    Y = zeros(n_usable, horizon);
    
    for i = 1:n_usable
        X(i,:,:) = features(i:i+lookback-1, :);
        Y(i,:) = target(i+lookback:i+lookback+horizon-1, 1);
    end
    
    % 划分数据集
    n_train = floor(size(X,1) * params.train_ratio);
    n_val = floor(size(X,1) * params.val_ratio);
    
    idx.train = 1:n_train;
    idx.val = n_train+1:n_train+n_val;
    idx.test = n_train+n_val+1:size(X,1);
    
    X_train = X(idx.train,:,:);
    Y_train = Y(idx.train,:);
    X_val = X(idx.val,:,:);
    Y_val = Y(idx.val,:);
    X_test = X(idx.test,:,:);
    Y_test = Y(idx.test,:);
end

五、模型构建模块

function model = create_lstm_attention_model(input_size, num_features, params)
    % 创建LSTM+注意力机制模型
    
    layers = [
        % 输入层
        sequenceInputLayer([input_size, num_features], 'Name', 'input')
        
        % 第一个LSTM层
        lstmLayer(128, 'OutputMode', 'sequence', 'Name', 'lstm1')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout1')
        
        % 第二个LSTM层
        lstmLayer(64, 'OutputMode', 'sequence', 'Name', 'lstm2')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout2')
        
        % 注意力层
        attentionLayer('Name', 'attention')
        
        % 全连接层
        fullyConnectedLayer(32, 'Name', 'fc1')
        reluLayer('Name', 'relu1')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout3')
        
        % 输出层
        fullyConnectedLayer(params.pred_horizon, 'Name', 'fc_output')
        regressionLayer('Name', 'output')
    ];
    
    model = layerGraph(layers);
    
    fprintf('已创建LSTM+注意力模型\n');
end

function model = create_bilstm_model(input_size, num_features, params)
    % 创建双向LSTM模型
    
    layers = [
        % 输入层
        sequenceInputLayer([input_size, num_features], 'Name', 'input')
        
        % 双向LSTM层
        bilstmLayer(128, 'OutputMode', 'sequence', 'Name', 'bilstm1')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout1')
        
        % 第二个双向LSTM层
        bilstmLayer(64, 'OutputMode', 'last', 'Name', 'bilstm2')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout2')
        
        % 全连接层
        fullyConnectedLayer(32, 'Name', 'fc1')
        reluLayer('Name', 'relu1')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout3')
        
        % 输出层
        fullyConnectedLayer(params.pred_horizon, 'Name', 'fc_output')
        regressionLayer('Name', 'output')
    ];
    
    model = layerGraph(layers);
    
    fprintf('已创建双向LSTM模型\n');
end

function model = create_cnn_lstm_model(input_size, num_features, params)
    % 创建CNN-LSTM混合模型
    
    layers = [
        % 输入层
        sequenceInputLayer([input_size, num_features], 'Name', 'input')
        
        % 1D卷积层提取局部特征
        convolution1dLayer(3, 32, 'Padding', 'same', 'Name', 'conv1')
        reluLayer('Name', 'relu1')
        maxPooling1dLayer(2, 'Stride', 2, 'Name', 'pool1')
        
        % 第二个卷积层
        convolution1dLayer(3, 64, 'Padding', 'same', 'Name', 'conv2')
        reluLayer('Name', 'relu2')
        maxPooling1dLayer(2, 'Stride', 2, 'Name', 'pool2')
        
        % LSTM层捕捉时序依赖
        flattenLayer('Name', 'flatten')
        lstmLayer(128, 'OutputMode', 'last', 'Name', 'lstm1')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout1')
        
        % 全连接层
        fullyConnectedLayer(64, 'Name', 'fc1')
        reluLayer('Name', 'relu3')
        dropoutLayer(params.dropout_rate, 'Name', 'dropout2')
        
        % 输出层
        fullyConnectedLayer(params.pred_horizon, 'Name', 'fc_output')
        regressionLayer('Name', 'output')
    ];
    
    model = layerGraph(layers);
    
    fprintf('已创建CNN-LSTM混合模型\n');
end

六、注意力机制实现

classdef attentionLayer < nnet.layer.Layer
    % 自定义注意力层
    
    properties
        % 注意力权重维度
        AttentionSize
    end
    
    methods
        function layer = attentionLayer(name)
            % 构造函数
            layer.Name = name;
            layer.Description = 'Attention layer for time series';
        end
        
        function Z = predict(layer, X)
            % 前向传播
            % X: [sequence_length, batch_size, num_features]
            
            [seq_len, batch_size, num_features] = size(X);
            
            % 计算注意力分数
            scores = zeros(seq_len, batch_size);
            for b = 1:batch_size
                for t = 1:seq_len
                    % 计算当前时间步的重要性
                    scores(t,b) = sum(X(t,b,:).^2);  % 简单的重要性度量
                end
            end
            
            % Softmax归一化
            attention_weights = softmax(scores, 1);
            
            % 加权求和
            Z = zeros(1, batch_size, num_features);
            for b = 1:batch_size
                weighted_sum = zeros(1, 1, num_features);
                for t = 1:seq_len
                    weighted_sum = weighted_sum + attention_weights(t,b) * X(t,b,:);
                end
                Z(1,b,:) = weighted_sum;
            end
        end
    end
end

参考代码 可用于光伏出力预测,引入气象影响因子 www.youwenfan.com/contentcst/160678.html

七、模型评估模块

function metrics = calculate_metrics(y_true, y_pred)
    % 计算预测性能指标
    
    % 确保向量形状
    y_true = y_true(:);
    y_pred = y_pred(:);
    
    % 移除NaN值
    valid_idx = ~isnan(y_true) & ~isnan(y_pred);
    y_true = y_true(valid_idx);
    y_pred = y_pred(valid_idx);
    
    if isempty(y_true) || isempty(y_pred)
        error('有效数据为空');
    end
    
    n = length(y_true);
    
    % 1. RMSE(均方根误差)
    rmse = sqrt(mean((y_true - y_pred).^2));
    
    % 2. MAE(平均绝对误差)
    mae = mean(abs(y_true - y_pred));
    
    % 3. MAPE(平均绝对百分比误差)
    % 避免除以零
    non_zero_idx = y_true > 0;
    if any(non_zero_idx)
        mape = mean(abs((y_true(non_zero_idx) - y_pred(non_zero_idx)) ./ y_true(non_zero_idx)));
    else
        mape = NaN;
    end
    
    % 4. R²(决定系数)
    ss_res = sum((y_true - y_pred).^2);
    ss_tot = sum((y_true - mean(y_true)).^2);
    r2 = 1 - (ss_res / ss_tot);
    
    % 5. nRMSE(标准化RMSE)
    y_range = max(y_true) - min(y_true);
    if y_range > 0
        nrmse = rmse / y_range;
    else
        nrmse = NaN;
    end
    
    % 6. 相关系数
    corr_coef = corr(y_true, y_pred);
    
    % 7. 对称MAPE
    smape = 2 * mean(abs(y_true - y_pred) ./ (abs(y_true) + abs(y_pred))) * 100;
    
    metrics = struct(...
        'rmse', rmse, ...
        'mae', mae, ...
        'mape', mape, ...
        'r2', r2, ...
        'nrmse', nrmse, ...
        'corr', corr_coef, ...
        'smape', smape);
end

八、可视化模块

function visualize_results(y_true, y_pred, timestamp, metrics, params)
    % 可视化预测结果
    
    % 1. 整体预测对比图
    figure('Position', [100, 100, 1200, 800]);
    
    subplot(2,2,1);
    n_show = min(500, length(y_true));
    idx_show = 1:n_show;
    
    plot(timestamp(idx_show), y_true(idx_show), 'b-', 'LineWidth', 1.5, 'DisplayName', '真实值');
    hold on;
    plot(timestamp(idx_show), y_pred(idx_show), 'r--', 'LineWidth', 1.5, 'DisplayName', '预测值');
    xlabel('时间');
    ylabel('光伏出力 (kW)');
    title('光伏出力预测对比');
    legend('Location', 'best');
    grid on;
    xlim([timestamp(1), timestamp(n_show)]);
    
    % 2. 误差分布图
    subplot(2,2,2);
    errors = y_pred - y_true;
    histogram(errors, 50, 'FaceColor', [0.2, 0.6, 0.8]);
    xlabel('预测误差 (kW)');
    ylabel('频数');
    title('预测误差分布');
    grid on;
    
    % 添加统计信息
    mean_err = mean(errors);
    std_err = std(errors);
    text(0.7, 0.9, sprintf('均值: %.3f\n标准差: %.3f', mean_err, std_err), ...
        'Units', 'normalized', 'FontSize', 10);
    
    % 3. 散点图
    subplot(2,2,3);
    scatter(y_true, y_pred, 20, 'filled', 'MarkerFaceAlpha', 0.3);
    hold on;
    plot([min(y_true), max(y_true)], [min(y_true), max(y_true)], 'r--', 'LineWidth', 2);
    xlabel('真实值 (kW)');
    ylabel('预测值 (kW)');
    title('真实值 vs 预测值');
    grid on;
    axis equal;
    
    % 添加R²值
    text(0.1, 0.9, sprintf('R² = %.4f', metrics.r2), ...
        'Units', 'normalized', 'FontSize', 12, 'FontWeight', 'bold');
    
    % 4. 预测误差随时间变化
    subplot(2,2,4);
    plot(timestamp, abs(errors), 'b-', 'LineWidth', 1);
    xlabel('时间');
    ylabel('绝对误差 (kW)');
    title('预测误差时间序列');
    grid on;
    
    % 5. 指标对比表
    figure('Position', [300, 300, 600, 400]);
    metrics_table = table(...
        metrics.rmse, metrics.mae, metrics.mape*100, metrics.r2, metrics.nrmse*100, ...
        'VariableNames', {'RMSE', 'MAE', 'MAPE(%)', 'R2', 'nRMSE(%)'});
    
    uitable('Data', table2cell(metrics_table), ...
        'ColumnName', metrics_table.Properties.VariableNames, ...
        'RowName', {'数值'}, ...
        'Position', [20, 20, 560, 360]);
    
    % 6. 不同时间尺度的预测性能
    figure('Position', [500, 100, 1000, 600]);
    
    % 按小时分析
    hours = hour(timestamp);
    hourly_mae = zeros(24,1);
    hourly_rmse = zeros(24,1);
    
    for h = 0:23
        hour_idx = hours == h;
        if sum(hour_idx) > 0
            hourly_mae(h+1) = mean(abs(y_true(hour_idx) - y_pred(hour_idx)));
            hourly_rmse(h+1) = sqrt(mean((y_true(hour_idx) - y_pred(hour_idx)).^2));
        end
    end
    
    subplot(2,1,1);
    bar(0:23, hourly_mae, 'FaceColor', [0.2, 0.4, 0.8]);
    xlabel('小时');
    ylabel('MAE (kW)');
    title('按小时预测性能');
    grid on;
    xlim([-0.5, 23.5]);
    
    subplot(2,1,2);
    bar(0:23, hourly_rmse, 'FaceColor', [0.8, 0.4, 0.2]);
    xlabel('小时');
    ylabel('RMSE (kW)');
    grid on;
    xlim([-0.5, 23.5]);
end

九、特征重要性分析

function importance = analyze_feature_importance(net, X_test, Y_test, features, params)
    % 分析特征重要性
    
    n_features = size(features, 2);
    n_samples = size(X_test, 1);
    
    % 获取基准预测
    Y_base = predict(net, X_test, 'MiniBatchSize', params.batch_size);
    base_error = mean(abs(Y_test(:) - Y_base(:)));
    
    % 计算特征重要性
    importance = zeros(n_features, 1);
    
    for i = 1:n_features
        % 打乱第i个特征
        X_permuted = X_test;
        
        % 对批次中的每个样本打乱特征
        for b = 1:params.batch_size:n_samples
            batch_end = min(b+params.batch_size-1, n_samples);
            batch_size = batch_end - b + 1;
            
            % 随机打乱特征序列
            for s = 1:batch_size
                seq_len = size(X_test, 2);
                perm_idx = randperm(seq_len);
                X_permuted(b+s-1,:,i) = X_test(b+s-1,perm_idx,i);
            end
        end
        
        % 用打乱后的数据进行预测
        Y_permuted = predict(net, X_permuted, 'MiniBatchSize', params.batch_size);
        perm_error = mean(abs(Y_test(:) - Y_permuted(:)));
        
        % 特征重要性 = 误差增加比例
        importance(i) = (perm_error - base_error) / base_error;
    end
    
    % 特征名称
    feature_names = {
        'PV_当前', 'PV_滞后1h', 'PV_滞后2h', 'PV_滞后24h', 'PV_滞后168h', ...
        '温度', '湿度', '风速', '辐照度', '云量', ...
        'sin(小时)', 'cos(小时)', '温度×辐照度', '辐照度×(1-云量)', ...
        '24h均值', '24h标准差', '晴天指数', '降雨影响', ...
        'sin(年周期)', 'cos(年周期)', 'sin(周)', 'cos(周)', ...
        '体感温度', '能见度指数'
    };
    
    % 创建结果结构
    importance = struct(...
        'scores', importance, ...
        'names', {feature_names(1:n_features)}, ...
        'sorted_idx', [], ...
        'sorted_scores', []);
    
    % 排序
    [importance.sorted_scores, importance.sorted_idx] = sort(importance.scores, 'descend');
end

function plot_feature_importance(importance)
    % 绘制特征重要性图
    
    figure('Position', [100, 100, 1000, 600]);
    
    n_show = min(15, length(importance.scores));
    
    subplot(1,2,1);
    barh(importance.sorted_scores(1:n_show), 'FaceColor', [0.2, 0.6, 0.8]);
    set(gca, 'YTick', 1:n_show, 'YTickLabel', importance.names(importance.sorted_idx(1:n_show)));
    xlabel('重要性分数');
    title('Top 15 重要特征');
    grid on;
    
    subplot(1,2,2);
    % 特征相关性热图
    feature_names_short = cellfun(@(x) x(1:min(10,length(x))), importance.names, 'UniformOutput', false);
    
    imagesc(importance.scores);
    colorbar;
    set(gca, 'XTick', 1:length(importance.scores), 'XTickLabel', feature_names_short, ...
        'XTickLabelRotation', 45);
    title('特征重要性热图');
    xlabel('特征');
    ylabel('重要性');
end

十、未来预测与敏感性分析

function future_pred = predict_future(net, features, norm_params, params)
    % 进行未来预测
    
    % 使用最近的数据
    last_idx = size(features, 1);
    start_idx = last_idx - params.lookback_window + 1;
    
    % 获取输入序列
    input_seq = features(start_idx:last_idx, :);
    input_seq = reshape(input_seq', [1, params.lookback_window, size(features,2)]);
    
    % 进行预测
    future_pred_norm = predict(net, input_seq);
    
    % 反标准化
    future_pred = future_pred_norm * norm_params.pv_std + norm_params.pv_mean;
    
    % 创建预测时间
    last_time = datetime('now');
    pred_times = last_time + hours(1:params.pred_horizon);
    
    future_pred = struct(...
        'values', future_pred, ...
        'times', pred_times, ...
        'confidence_interval', calculate_confidence_interval(future_pred_norm, norm_params));
end

function ci = calculate_confidence_interval(pred_norm, norm_params, alpha)
    % 计算置信区间
    if nargin < 3
        alpha = 0.05;  % 95%置信区间
    end
    
    % 简化的置信区间计算
    std_multiplier = 1.96;  % 95%置信区间对应的Z值
    
    % 预测的标准差(基于历史误差)
    pred_std = 0.1 * std(pred_norm) * norm_params.pv_std;
    
    ci = struct(...
        'lower', pred_norm * norm_params.pv_std - std_multiplier * pred_std, ...
        'upper', pred_norm * norm_params.pv_std + std_multiplier * pred_std, ...
        'mean', pred_norm * norm_params.pv_std);
end

function sensitivity = sensitivity_analysis(net, features, norm_params, params)
    % 敏感性分析
    
    % 测试不同气象条件的影响
    test_cases = {
        '晴天', 1.0, 0.1, 2.0, 800;    % 晴天
        '多云', 0.5, 0.5, 4.0, 400;    % 多云
        '阴天', 0.3, 0.8, 3.0, 200;    % 阴天
        '雨天', 0.2, 1.0, 6.0, 50;     % 雨天
    };
    
    n_cases = size(test_cases, 1);
    sensitivity = cell(n_cases, 1);
    
    for i = 1:n_cases
        case_name = test_cases{i,1};
        
        % 修改气象因子
        features_modified = features;
        last_idx = size(features, 1);
        
        % 假设气象因子在第6-10个特征
        features_modified(last_idx, 6) = 25;  % 温度
        features_modified(last_idx, 7) = test_cases{i,2} * 100;  % 湿度比例
        features_modified(last_idx, 8) = test_cases{i,3};  % 风速
        features_modified(last_idx, 9) = test_cases{i,5};  % 辐照度
        features_modified(last_idx, 10) = test_cases{i,4};  % 云量
        
        % 标准化
        features_modified_norm = (features_modified - norm_params.mean) ./ norm_params.std;
        
        % 预测
        input_seq = features_modified_norm(last_idx-params.lookback_window+1:last_idx, :);
        input_seq = reshape(input_seq', [1, params.lookback_window, size(features,2)]);
        
        pred_norm = predict(net, input_seq);
        pred = pred_norm * norm_params.pv_std + norm_params.pv_mean;
        
        sensitivity{i} = struct(...
            'case', case_name, ...
            'conditions', test_cases(i,2:end), ...
            'prediction', pred, ...
            'total_energy', sum(pred));
    end
end

function plot_sensitivity_analysis(sensitivity)
    % 绘制敏感性分析结果
    
    n_cases = length(sensitivity);
    hours = 1:24;
    
    figure('Position', [100, 100, 1000, 800]);
    
    % 1. 预测曲线对比
    subplot(2,2,1);
    colors = lines(n_cases);
    legend_entries = cell(n_cases, 1);
    
    for i = 1:n_cases
        plot(hours, sensitivity{i}.prediction, 'Color', colors(i,:), 'LineWidth', 2);
        hold on;
        legend_entries{i} = sensitivity{i}.case;
    end
    
    xlabel('预测小时');
    ylabel('光伏出力 (kW)');
    title('不同天气条件下的预测');
    legend(legend_entries, 'Location', 'best');
    grid on;
    
    % 2. 总能量对比
    subplot(2,2,2);
    total_energy = zeros(n_cases, 1);
    for i = 1:n_cases
        total_energy(i) = sensitivity{i}.total_energy;
    end
    
    bar(total_energy, 'FaceColor', [0.2, 0.6, 0.8]);
    set(gca, 'XTick', 1:n_cases, 'XTickLabel', legend_entries);
    ylabel('总发电量 (kWh)');
    title('24小时总发电量对比');
    grid on;
    
    % 3. 辐照度影响
    subplot(2,2,3);
    irradiance = zeros(n_cases, 1);
    max_power = zeros(n_cases, 1);
    
    for i = 1:n_cases
        irradiance(i) = sensitivity{i}.conditions{4};  % 辐照度
        max_power(i) = max(sensitivity{i}.prediction);
    end
    
    scatter(irradiance, max_power, 100, 'filled');
    xlabel('辐照度 (W/m²)');
    ylabel('最大出力 (kW)');
    title('辐照度对最大出力的影响');
    grid on;
    
    % 添加拟合线
    p = polyfit(irradiance, max_power, 1);
    hold on;
    plot(irradiance, polyval(p, irradiance), 'r--', 'LineWidth', 2);
    
    % 4. 云量影响
    subplot(2,2,4);
    cloud_cover = zeros(n_cases, 1);
    efficiency = zeros(n_cases, 1);
    
    for i = 1:n_cases
        cloud_cover(i) = sensitivity{i}.conditions{3};  % 云量
        efficiency(i) = mean(sensitivity{i}.prediction) / max_power(i);
    end
    
    scatter(cloud_cover, efficiency*100, 100, 'filled');
    xlabel('云量');
    ylabel('平均效率 (%)');
    title('云量对发电效率的影响');
    grid on;
end

十一、模型部署与API接口

function pv_prediction_api()
    % 光伏预测API接口
    
    % 加载模型
    persistent model norm_params;
    if isempty(model)
        load('pv_prediction_model.mat', 'net', 'norm_params', 'params');
        model.net = net;
        model.params = params;
        fprintf('模型加载成功\n');
    end
    
    % 创建Web服务
    port = 8080;
    web_service = 'http://localhost:8080/predict';
    
    % 启动Web服务
    start_web_service(port);
    
    fprintf('光伏预测API已启动,端口: %d\n', port);
    fprintf('API端点: %s\n', web_service);
end

function result = predict_pv(weather_data, historical_pv)
    % 预测函数(供API调用)
    
    % 加载模型
    persistent model;
    if isempty(model)
        load('pv_prediction_model.mat', 'net', 'norm_params', 'params');
        model.net = net;
        model.norm_params = norm_params;
        model.params = params;
    end
    
    % 准备输入数据
    features = prepare_realtime_features(weather_data, historical_pv, model.params);
    
    % 标准化
    features_norm = (features - model.norm_params.mean) ./ model.norm_params.std;
    
    % 重塑为模型输入格式
    input_seq = reshape(features_norm', [1, model.params.lookback_window, size(features,2)]);
    
    % 预测
    pred_norm = predict(model.net, input_seq);
    prediction = pred_norm * model.norm_params.pv_std + model.norm_params.pv_mean;
    
    % 返回结果
    result = struct(...
        'prediction', prediction, ...
        'timestamp', datetime('now') + hours(1:model.params.pred_horizon), ...
        'confidence', calculate_confidence(pred_norm, model.norm_params));
end

十二、使用指南

12.1 快速开始

  1. 运行主程序

    main_pv_prediction
    
  2. 使用真实数据
    将真实数据保存为real_pv_data.mat,包含:

    • pv_data: 光伏出力时间序列
    • weather_data: 气象数据结构体
    • timestamp: 时间戳
  3. 自定义参数

    params.pred_horizon = 48;      % 预测48小时
    params.lookback_window = 336;  % 使用14天历史数据
    params.model_type = 'cnn_lstm'; % 使用CNN-LSTM模型
    

12.2 关键参数说明

参数说明推荐值
pred_horizon预测步长24(短期), 168(周预测)
lookback_window历史窗口168(7天), 672(28天)
model_type模型类型lstm_attention(最优)
batch_size批大小32(小数据), 128(大数据)
max_epochs最大轮数100-200
learning_rate学习率0.001-0.0001

12.3 性能优化建议

  1. 数据质量:确保数据完整,处理缺失值和异常值
  2. 特征工程:添加气象交互特征和时间特征
  3. 模型选择
    • 短期预测:LSTM+Attention
    • 长期预测:CNN-LSTM
    • 实时预测:LightGBM/XGBoost
  4. 超参数调优:使用贝叶斯优化搜索最佳参数

十三、预期结果

运行本系统将得到:

  1. 高精度预测:MAPE通常<5%(晴天),<10%(多变天气)
  2. 特征分析:识别关键气象因子的影响
  3. 可视化报告:多维度展示预测性能
  4. 未来预测:未来24小时光伏出力曲线
  5. 敏感性分析:不同天气条件下的预测对比
  6. 部署接口:REST API用于实时预测

十四、扩展功能

  1. 多站点预测:扩展支持多个光伏电站
  2. 概率预测:输出预测分布而非点估计
  3. 极端天气预警:识别异常天气对光伏的影响
  4. 经济性分析:结合电价预测进行收益分析
  5. 迁移学习:将模型迁移到新电站
  6. 边缘计算:部署到嵌入式设备实时预测
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值