MATLAB 随机蛙跳算法 (SFLA) 优化最小二乘回归

一、代码

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. 运行步骤

  1. 将上述三个 .m 文件保存到同一文件夹
  2. 在 MATLAB 中打开 main_sfla_regression.m
  3. 点击运行或直接输入 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. 算法特点

优点

  • 全局寻优能力强,不易陷入局部最优
  • 参数少,易于实现
  • 收敛速度快

缺点

  • 对参数设置敏感
  • 在高维问题上可能收敛较慢
相关推荐
wuweijianlove1 小时前
算法优化中的缓存层次结构与内存映射的技术7
算法
故事和你911 小时前
洛谷-【数据结构2-2】线段树1
开发语言·javascript·数据结构·算法·动态规划·图论
电科一班林耿超1 小时前
机器学习大师课 第 8 课:端到端项目实战 —— 泰坦尼克号生存预测
人工智能·算法·机器学习
70asunflower1 小时前
7.2 回归 —— 预测一个数字
人工智能·数据挖掘·数据分析·回归
ComputerInBook1 小时前
数字图像处理(4版)——第 12 章——图像模式分类(上)(Rafael C.Gonzalez&Richard E. Woods)
图像处理·人工智能·算法·模式识别·图像模式分类
y = xⁿ1 小时前
20天速通LeetCodeday13:DFS深度优先搜素
算法·深度优先
七牛开发者1 小时前
开源项目观察|ds4:本地 Agent 推理,不只是把模型跑起来
人工智能·redis·算法·开源
影sir1 小时前
OI Wiki--算法竞赛百科
经验分享·算法
吞下星星的少年·-·1 小时前
x*y的所有因数=x的所有因数分别乘以y的所有因数
算法