一、代码
1. 主程序 (main_sfla_regression.m)
matlab
%% 随机蛙跳算法优化最小二乘回归
% 功能:使用SFLA算法寻找最优回归系数,最小化最小二乘误差
clc; clear; close all;
%% 1. 生成测试数据
fprintf('=== 随机蛙跳算法优化最小二乘回归 ===\n\n');
% 设置随机种子
rng(42);
% 生成样本数据
n_samples = 100; % 样本数
n_features = 3; % 特征数(包括偏置项)
% 真实参数(用于生成数据)
true_params = [2.5, -1.8, 3.2, 5.0]'; % [w1, w2, w3, bias]
% 生成输入特征
X = randn(n_samples, n_features-1); % 不包括偏置列
% 添加偏置项
X_with_bias = [ones(n_samples, 1), X]; % 第一列为1(偏置)
% 生成输出(加入噪声)
noise = 0.1 * randn(n_samples, 1);
y = X_with_bias * true_params + noise;
fprintf('数据生成完成:\n');
fprintf(' 样本数: %d\n', n_samples);
fprintf(' 特征数: %d\n', n_features);
fprintf(' 真实参数: [%s]\n\n', strjoin(cellstr(num2str(true_params', '%.2f')), ', '));
%% 2. 设置SFLA参数
params = struct();
params.population_size = 100; % 青蛙总数
params.memeplexes_count = 10; % 族群数量
params.iterations = 200; % 迭代次数
params.max_leaps = 15; % 每个族群的最大跃迁次数
params.damping = 0.5; % 跃迁步长衰减因子
params.dim = n_features; % 问题维度
params.lb = -10 * ones(1, n_features); % 下界
params.ub = 10 * ones(1, n_features); % 上界
fprintf('SFLA参数设置:\n');
fprintf(' 青蛙总数: %d\n', params.population_size);
fprintf(' 族群数量: %d\n', params.memeplexes_count);
fprintf(' 迭代次数: %d\n\n', params.iterations);
%% 3. 运行SFLA优化
fprintf('开始SFLA优化...\n');
tic;
[best_params, best_fitness, convergence_curve] = sfla_optimizer(X_with_bias, y, params);
optimization_time = toc;
fprintf('优化完成!耗时: %.2f 秒\n\n', optimization_time);
%% 4. 使用标准最小二乘法验证
fprintf('标准最小二乘法结果:\n');
standard_params = (X_with_bias' * X_with_bias) \ (X_with_bias' * y);
standard_rmse = sqrt(mean((y - X_with_bias * standard_params).^2));
fprintf(' 参数: [%s]\n', strjoin(cellstr(num2str(standard_params', '%.4f')), ', '));
fprintf(' RMSE: %.6f\n\n', standard_rmse);
%% 5. 输出SFLA优化结果
fprintf('SFLA优化结果:\n');
fprintf(' 最优参数: [%s]\n', strjoin(cellstr(num2str(best_params', '%.4f')), ', '));
fprintf(' 最小RMSE: %.6f\n', best_fitness);
% 计算参数误差
param_errors = abs(best_params - true_params');
relative_errors = param_errors ./ abs(true_params');
fprintf(' 参数误差: [%s]\n', strjoin(cellstr(num2str(param_errors', '%.4f')), ', '));
fprintf(' 相对误差: [%s]\n\n', strjoin(cellstr(num2str(relative_errors', '%.2f%%')), ', '));
%% 6. 预测和评估
y_pred_sfla = X_with_bias * best_params;
y_pred_std = X_with_bias * standard_params;
rmse_sfla = sqrt(mean((y - y_pred_sfla).^2));
mae_sfla = mean(abs(y - y_pred_sfla));
r2_sfla = 1 - sum((y - y_pred_sfla).^2) / sum((y - mean(y)).^2);
fprintf('SFLA模型性能指标:\n');
fprintf(' RMSE: %.6f\n', rmse_sfla);
fprintf(' MAE: %.6f\n', mae_sfla);
fprintf(' R²: %.6f\n\n', r2_sfla);
%% 7. 可视化结果
figure('Position', [100, 100, 1200, 800]);
% 子图1:收敛曲线
subplot(2, 3, 1);
semilogy(convergence_curve, 'b-', 'LineWidth', 2);
grid on;
xlabel('迭代次数');
ylabel('RMSE (log scale)');
title('SFLA收敛曲线');
legend('最佳适应度');
% 子图2:真实值与预测值对比(散点图)
subplot(2, 3, 2);
plot(y, y_pred_sfla, 'bo', 'MarkerSize', 6, 'MarkerFaceColor', 'b');
hold on;
plot([min(y), max(y)], [min(y), max(y)], 'r--', 'LineWidth', 1.5);
grid on;
xlabel('真实值');
ylabel('预测值');
title('SFLA预测 vs 真实值');
legend('预测点', '理想线');
% 子图3:残差分析
subplot(2, 3, 3);
residuals = y - y_pred_sfla;
plot(y_pred_sfla, residuals, 'ro', 'MarkerSize', 6, 'MarkerFaceColor', 'r');
hold on;
plot([min(y_pred_sfla), max(y_pred_sfla)], [0, 0], 'k-', 'LineWidth', 1.5);
grid on;
xlabel('预测值');
ylabel('残差');
title('残差分析');
% 子图4:参数对比
subplot(2, 3, 4);
bar_data = [true_params', standard_params', best_params'];
bar_labels = {'w1', 'w2', 'w3', 'bias'};
bar(bar_data);
set(gca, 'XTickLabel', bar_labels);
grid on;
ylabel('参数值');
title('参数对比');
legend('真实值', '标准LS', 'SFLA优化');
% 子图5:预测误差分布
subplot(2, 3, 5);
histogram(residuals, 20, 'FaceColor', 'g', 'EdgeColor', 'black');
grid on;
xlabel('预测误差');
ylabel('频数');
title('预测误差分布');
% 子图6:SFLA与标准LS对比
subplot(2, 3, 6);
plot(y, 'k-', 'LineWidth', 1.5, 'DisplayName', '真实值');
hold on;
plot(y_pred_std, 'r--', 'LineWidth', 1.5, 'DisplayName', '标准LS');
plot(y_pred_sfla, 'b:', 'LineWidth', 2, 'DisplayName', 'SFLA优化');
grid on;
xlabel('样本序号');
ylabel('输出值');
title('预测结果对比');
legend('Location', 'best');
sgtitle('随机蛙跳算法优化最小二乘回归结果');
%% 8. 保存结果
results = struct();
results.true_params = true_params;
results.standard_params = standard_params;
results.sfla_params = best_params;
results.sfla_rmse = best_fitness;
results.standard_rmse = standard_rmse;
results.convergence_curve = convergence_curve;
results.optimization_time = optimization_time;
save('sfla_regression_results.mat', 'results');
fprintf('结果已保存到: sfla_regression_results.mat\n');
2. 随机蛙跳算法核心函数 (sfla_optimizer.m)
matlab
function [best_params, best_fitness, convergence_curve] = sfla_optimizer(X, y, params)
% 随机蛙跳算法优化器
% 输入:
% X - 输入特征矩阵 [n_samples, n_features]
% y - 输出向量 [n_samples, 1]
% params - 算法参数结构体
% 输出:
% best_params - 最优参数
% best_fitness - 最优适应度(RMSE)
% convergence_curve - 收敛曲线
% 初始化种群
population = initialize_population(params);
% 计算初始适应度
fitness = evaluate_fitness(population, X, y);
% 记录收敛曲线
convergence_curve = zeros(params.iterations, 1);
% 主循环
for iter = 1:params.iterations
% 按适应度排序(从小到大)
[fitness, sort_idx] = sort(fitness);
population = population(sort_idx, :);
% 划分族群
memeplexes = divide_into_memeplexes(population, params.memeplexes_count);
% 对每个族群进行局部搜索
for m = 1:params.memeplexes_count
memeplexes{m} = local_search(memeplexes{m}, X, y, params);
end
% 全局洗牌(重新混合所有青蛙)
population = shuffle_population(memeplexes, params.memeplexes_count);
% 重新计算适应度
fitness = evaluate_fitness(population, X, y);
% 记录最佳适应度
[best_fitness, best_idx] = min(fitness);
convergence_curve(iter) = best_fitness;
% 显示进度
if mod(iter, 20) == 0 || iter == 1
fprintf(' 迭代 %d/%d: 最佳RMSE = %.6f\n', iter, params.iterations, best_fitness);
end
end
% 返回最优解
[~, best_idx] = min(fitness);
best_params = population(best_idx, :)';
end
%% 初始化种群
function population = initialize_population(params)
population = zeros(params.population_size, params.dim);
for i = 1:params.population_size
for j = 1:params.dim
population(i, j) = params.lb(j) + rand() * (params.ub(j) - params.lb(j));
end
end
end
%% 评估适应度(计算RMSE)
function fitness = evaluate_fitness(population, X, y)
[n_frogs, n_params] = size(population);
fitness = zeros(n_frogs, 1);
for i = 1:n_frogs
params = population(i, :)';
predictions = X * params;
errors = y - predictions;
fitness(i) = sqrt(mean(errors.^2)); % RMSE
end
end
%% 划分族群
function memeplexes = divide_into_memeplexes(population, n_memeplexes)
[n_frogs, n_params] = size(population);
frogs_per_memeplex = floor(n_frogs / n_memeplexes);
memeplexes = cell(n_memeplexes, 1);
for m = 1:n_memeplexes
start_idx = (m-1) * frogs_per_memeplex + 1;
end_idx = min(m * frogs_per_memeplex, n_frogs);
memeplexes{m} = population(start_idx:end_idx, :);
end
end
%% 局部搜索(蛙跳)
function memeplex = local_search(memeplex, X, y, params)
[n_frogs, n_params] = size(memeplex);
% 对族群内的每个青蛙进行跃迁
for leap = 1:params.max_leaps
% 找到族群内的最佳和最差青蛙
fitness = evaluate_fitness(memeplex, X, y);
[~, best_idx] = min(fitness);
[~, worst_idx] = max(fitness);
best_frog = memeplex(best_idx, :)';
worst_frog = memeplex(worst_idx, :)';
% 计算跃迁步长
step = params.damping * (best_frog - worst_frog);
% 更新最差青蛙的位置
new_worst = worst_frog + step;
% 边界检查
for j = 1:n_params
if new_worst(j) < params.lb(j)
new_worst(j) = params.lb(j);
elseif new_worst(j) > params.ub(j)
new_worst(j) = params.ub(j);
end
end
% 评估新位置
new_fitness = sqrt(mean((y - X * new_worst).^2));
% 如果新位置更好,则更新
if new_fitness < fitness(worst_idx)
memeplex(worst_idx, :) = new_worst';
end
end
end
%% 全局洗牌(重新混合所有青蛙)
function population = shuffle_population(memeplexes, n_memeplexes)
% 将所有族群合并
population = [];
for m = 1:n_memeplexes
population = [population; memeplexes{m}];
end
% Fisher-Yates洗牌算法
[n_frogs, n_params] = size(population);
for i = n_frogs:-1:2
j = randi(i);
% 交换第i行和第j行
temp = population(i, :);
population(i, :) = population(j, :);
population(j, :) = temp;
end
end
3. 简化版SFLA(快速测试用,simple_sfla.m)
matlab
%% 简化版SFLA(用于快速测试)
function [best_params, best_rmse] = simple_sfla(X, y, dim, pop_size, iterations)
% 简化版随机蛙跳算法
% 输入:
% X - 输入特征矩阵
% y - 输出向量
% dim - 参数维度
% pop_size - 种群大小
% iterations - 迭代次数
% 输出:
% best_params - 最优参数
% best_rmse - 最小RMSE
% 参数边界
lb = -10 * ones(1, dim);
ub = 10 * ones(1, dim);
% 初始化种群
population = lb + rand(pop_size, dim) .* (ub - lb);
% 迭代优化
for iter = 1:iterations
% 评估适应度
fitness = zeros(pop_size, 1);
for i = 1:pop_size
pred = X * population(i, :)';
fitness(i) = sqrt(mean((y - pred).^2));
end
% 排序
[fitness, idx] = sort(fitness);
population = population(idx, :);
% 更新最差个体(向最优个体学习)
best = population(1, :)';
worst = population(end, :)';
% 随机步长
step = 0.5 * (best - worst) .* (2*rand(dim,1)-1);
new_worst = worst + step;
% 边界检查
new_worst = max(new_worst', lb);
new_worst = min(new_worst, ub');
% 贪婪选择
pred_new = X * new_worst';
new_fitness = sqrt(mean((y - pred_new).^2));
if new_fitness < fitness(end)
population(end, :) = new_worst;
end
% 显示进度
if mod(iter, 50) == 0
fprintf('迭代 %d: RMSE = %.6f\n', iter, fitness(1));
end
end
% 返回最优解
best_params = population(1, :)';
best_rmse = fitness(1);
end
二、说明
1. 运行步骤
- 将上述三个
.m文件保存到同一文件夹 - 在 MATLAB 中打开
main_sfla_regression.m - 点击运行或直接输入
main_sfla_regression
2. 参数调整建议
| 参数 | 建议值 | 说明 |
|---|---|---|
population_size |
50-200 | 青蛙总数,越大搜索越全面但越慢 |
memeplexes_count |
5-20 | 族群数量,通常取种群大小的1/10 |
iterations |
100-500 | 迭代次数,根据收敛情况调整 |
max_leaps |
10-20 | 每个族群的最大跃迁次数 |
damping |
0.3-0.7 | 跃迁步长衰减因子 |
参考 随机蛙跳源代码,寻找最优变量,输出最小二乘回归 www.youwenfan.com/contentcsu/63109.html
3. 算法特点
优点:
- 全局寻优能力强,不易陷入局部最优
- 参数少,易于实现
- 收敛速度快
缺点:
- 对参数设置敏感
- 在高维问题上可能收敛较慢