clc; clear; close all;
%% === 1. 读数据 ===
data = readmatrix('数据集.xls'); % Excel 文件
X = data(:,1:25); % 输入:25列
Y = data(:,26:30); % 输出:5列
%% === 2. 划分训练/测试 ===
% rng(1260); % 固定随机种子
N = size(X,1);
idx = randperm(N);
num_train = round(0.8*N);
train_idx = idx(1:num_train);
test_idx = idx(num_train+1:end);
X_train_raw = X(train_idx,:);
Y_train_raw = Y(train_idx,:);
X_test_raw = X(test_idx,:);
Y_test_raw = Y(test_idx,:);
%% === 3. 使用mapminmax归一化训练集 === [^1]
% 转置数据(mapminmax要求每行为一个特征)
[X_train, X_ps] = mapminmax(X_train_raw', 0, 1);
[Y_train, Y_ps] = mapminmax(Y_train_raw', 0, 1);
% 转置回原始维度(样本×特征)
X_train = X_train';
Y_train = Y_train';
%% === 4. 用训练集参数归一化测试集 ===
X_test = mapminmax('apply', X_test_raw', X_ps)';
Y_test = mapminmax('apply', Y_test_raw', Y_ps)';
%% === 5. 网络结构 ===
in_num = 25; hid1_num = 50; hid2_num = 40; out_num = 5;
net_param_num = in_num*hid1_num + hid1_num*hid2_num + ...
hid2_num*out_num + hid1_num + hid2_num + out_num;
%% === 6. GA-PSO参数 ===
pop_size = 90; max_gen = 1000; % 更大群体,更长迭代
w_max = 0.8; w_min = 0.2;
c1_ini = 1.7; c1_end = 0.5; c2_ini = 0.5; c2_end = 1.5;
pm_min = 0.05; pm_max = 0.3;
pop = randn(pop_size, net_param_num) * 0.1; % 初始化权值小点
v = zeros(pop_size, net_param_num);
pbest = pop; pbest_fit = inf(pop_size,1); gbest_fit = inf; gbest = pop(1,:);
fit_hist = zeros(max_gen,1);
loss_weights = [1 1 0.5 4 4]; % 多输出加权
lambda = 0.01; % 正则化系数
%% === 7. 主循环 ===
for gen = 1:max_gen
for i = 1:pop_size
[fit, ~] = BP_fitness_ReLU(pop(i,:), X_train, Y_train, ...
in_num, hid1_num, hid2_num, out_num, lambda, loss_weights);
if fit < pbest_fit(i)
pbest_fit(i) = fit; pbest(i,:) = pop(i,:);
end
if fit < gbest_fit
gbest_fit = fit; gbest = pop(i,:);
end
end
fit_hist(gen) = gbest_fit;
% PSO参数自适应
w = w_max - (w_max-w_min)*gen/max_gen;
c1 = c1_ini - (c1_ini-c1_end)*gen/max_gen;
c2 = c2_ini + (c2_end-c2_ini)*gen/max_gen;
lr = 0.01 * (1 - gen/max_gen); % 线性衰减
% PSO更新
for i = 1:pop_size
v(i,:) = w*v(i,:) + c1*rand*(pbest(i,:)-pop(i,:)) + c2*rand*(gbest-pop(i,:));
pop(i,:) = pop(i,:) + v(i,:);
end
% GA部分
diversity = mean(std(pop));
pm = pm_min + (pm_max-pm_min)*(1 - diversity);
ga_rate = min(0.8, gen/max_gen);
ga_num = round(pop_size * ga_rate);
for k = 1:2:ga_num
idx_cross = randperm(pop_size,2);
cp = randi([1, net_param_num-1]);
child1 = [pop(idx_cross(1),1:cp), pop(idx_cross(2),cp+1:end)];
child2 = [pop(idx_cross(2),1:cp), pop(idx_cross(1),cp+1:end)];
if rand < pm, child1(randi(net_param_num)) = child1(randi(net_param_num)) + randn*0.05; end
if rand < pm, child2(randi(net_param_num)) = child2(randi(net_param_num)) + randn*0.05; end
pop(idx_cross(1),:) = child1; pop(idx_cross(2),:) = child2;
end
% 精英保留
[~, sort_idx] = sort(pbest_fit);
pop(1,:) = pbest(sort_idx(1),:);
if mod(gen,50)==0 || gen==1
fprintf('第 %d 代,最优适应度 %.6f\n', gen, gbest_fit);
end
end
%% === 8. 预测+反归一化 ===
[~, Yp_train] = BP_fitness_ReLU(gbest, X_train, Y_train, ...
in_num, hid1_num, hid2_num, out_num, lambda, loss_weights);
% 反归一化 [^1]
Y_pred_train = mapminmax('reverse', Yp_train', Y_ps)';
[~, Yp_test] = BP_fitness_ReLU(gbest, X_test, Y_test, ...
in_num, hid1_num, hid2_num, out_num, lambda, loss_weights);
% 反归一化 [^1]
Y_pred_test = mapminmax('reverse', Yp_test', Y_ps)';
% === 9. 评估 ===
[RMSE_train, MAE_train, MAPE_train, R2_train] = calc_metrics(Y(train_idx,:), Y_pred_train);
[RMSE_test, MAE_test, MAPE_test, R2_test] = calc_metrics(Y(test_idx,:), Y_pred_test);
fprintf('\n=== 训练集 ===\nRMSE: %.4f, MAE: %.4f, MAPE: %.2f%%, R²: %.4f\n', RMSE_train, MAE_train, MAPE_train, R2_train);
fprintf('=== 测试集 ===\nRMSE: %.4f, MAE: %.4f, MAPE: %.2f%%, R²: %.4f\n', RMSE_test, MAE_test, MAPE_test, R2_test);
[R2v, MAPEv, RMSEv, MAEv] = calc_metrics_each(Y(test_idx,:), Y_pred_test);
for j = 1:out_num
fprintf('输出%d: R²=%.4f, RMSE=%.4f, MAE=%.4f, MAPE=%.2f%%\n', j, R2v(j), RMSEv(j), MAEv(j), MAPEv(j));
end
figure; plot(fit_hist,'LineWidth',2);
xlabel('迭代次数'); ylabel('最优适应度'); title('收敛曲线'); grid on;
for j = 1:out_num
figure;
scatter(Y(test_idx,j), Y_pred_test(:,j),'filled');
hold on; plot(xlim,xlim,'r--','LineWidth',1.2); hold off;
xlabel(['真实 输出',num2str(j)]); ylabel(['预测 输出',num2str(j)]);
title(['输出',num2str(j),' 测试集']); grid on;
end
% === 将评估指标保存到Excel ===
output_metrics = table(...
(1:out_num)', R2v', MAEv', MAPEv', RMSEv', ...
'VariableNames', {'输出编号', 'R2', 'MAE', 'MAPE', 'RMSE'});
filename = '测试集输出评估指标.xlsx';
writetable(output_metrics, filename, 'Sheet', '各输出评估指标');
save('GA_PSO_BP_ReLU_MinMax_NoLog.mat', 'gbest', 'in_num', 'hid1_num', 'hid2_num', 'out_num', ...
'X_ps', 'Y_ps'); % 保存归一化参数
disp('✅ Min-Max 归一化版模型已保存');
%% === === 函数 === ===
function [fit, Yp] = BP_fitness_ReLU(params, X, Y, in_num, hid1_num, hid2_num, out_num, lambda, loss_w)
idx1 = in_num*hid1_num; idx2 = idx1 + hid1_num*hid2_num; idx3 = idx2 + hid2_num*out_num;
W1 = reshape(params(1:idx1), in_num, hid1_num);
W2 = reshape(params(idx1+1:idx2), hid1_num, hid2_num);
W3 = reshape(params(idx2+1:idx3), hid2_num, out_num);
b1 = params(idx3+1:idx3+hid1_num);
b2 = params(idx3+hid1_num+1:idx3+hid1_num+hid2_num);
b3 = params(idx3+hid1_num+hid2_num+1:end);
H1 = max(0, X*W1 + b1);
H2 = max(0, H1*W2 + b2);
Yp = H2*W3 + b3;
mse_each = mean((Y - Yp).^2,1);
mae_each = mean(abs(Y - Yp),1);
mse = sum(loss_w .* mse_each) / sum(loss_w);
mae = sum(loss_w .* mae_each) / sum(loss_w);
reg = lambda * mean(params.^2);
fit = mse * 0.8 + mae * 0.2 + reg;
end
function [RMSE, MAE, MAPE, R2] = calc_metrics(Y, Yp)
RMSE = sqrt(mean((Y(:)-Yp(:)).^2));
MAE = mean(abs(Y(:)-Yp(:)));
MAPE = mean(abs((Y(:)-Yp(:)) ./ (Y(:)+eps))) * 100;
SS_res = sum((Y(:)-Yp(:)).^2);
SS_tot = sum((Y(:)-mean(Y(:))).^2);
R2 = 1 - SS_res/SS_tot;
end
function [R2v, MAPEv, RMSEv, MAEv] = calc_metrics_each(Y, Yp)
[~, m] = size(Y);
R2v = zeros(1,m); MAPEv = zeros(1,m); RMSEv = zeros(1,m); MAEv = zeros(1,m);
for j = 1:m
y = Y(:,j); yp = Yp(:,j);
SS_res = sum((y-yp).^2); SS_tot = sum((y-mean(y)).^2);
R2v(j) = 1 - SS_res/SS_tot;
RMSEv(j) = sqrt(mean((y-yp).^2));
MAEv(j) = mean(abs(y-yp));
yt = y; yt(abs(yt)<1e-4)=1e-4;
MAPEv(j) = mean(abs((y-yp)./yt)) * 100;
end
end=== 测试集 ===
RMSE: 0.0137, MAE: 0.0069, MAPE: 223.61%, R²: 0.9052
输出1: R²=0.9676, RMSE=0.0130, MAE=0.0087, MAPE=78.95%
输出2: R²=0.9544, RMSE=0.0025, MAE=0.0019, MAPE=104.79%
输出3: R²=0.9812, RMSE=0.0000, MAE=0.0000, MAPE=4.65%
输出4: R²=0.1639, RMSE=0.0276, MAE=0.0216, MAPE=353.93%
输出5: R²=0.2119, RMSE=0.0026, MAE=0.0021, MAPE=371.11%
对该代码进行按前面给出的方案进行进行修改,让MAPE的值降低
最新发布