为何我基于MATLAB实现的简易线性回归梯度下降算法不收敛?
梯度下降不收敛的原因及修复方案
你的代码核心逻辑没问题,但几个关键细节导致了收敛失败:
1. 未对特征做归一化/标准化
梯度下降对特征的数值尺度极度敏感。你用到的x和y(事故数据集的第14、4列)数值范围可能差异极大,比如x是千级、y是百级,这会导致w和b的梯度更新幅度失衡,要么震荡要么收敛极慢。
修复方案:在使用数据前添加标准化步骤,比如Z-score标准化:
x = (x - mean(x)) / std(x); y = (y - mean(y)) / std(y);
或者最小-最大归一化:
x = (x - min(x)) / (max(x) - min(x)); y = (y - min(y)) / (max(y) - min(y));
2. 迭代次数过少
仅设置100次迭代远远不够,尤其是当学习率alpha较小时,梯度下降需要大量迭代才能逼近最优解。
修复方案:增加迭代次数,同时记录每次迭代的代价函数值,直观观察收敛趋势:
max_iter = 10000; J_history = zeros(max_iter, 1); % 存储每次迭代的均方误差 for i = 1:max_iter y_est = w*x + b; J_history(i) = mean((y-y_est).^2); temp_w = w + alpha*(mean(x.*(y - w*x - b))); temp_b = b + alpha*(mean(y - w*x - b)); w = temp_w; b = temp_b; end % 绘制代价曲线观察收敛情况 plot(J_history); xlabel('迭代次数'); ylabel('均方误差J');
3. 学习率alpha的选择逻辑错误
你尝试的不同alpha无效,本质是因为未做归一化。归一化后可以重新调整学习率:
- 若代价函数J震荡甚至上升,说明
alpha过大,需缩小(比如从0.1调到0.01) - 若J下降极慢,说明
alpha过小,需增大(比如从0.000001调到0.01)
完整修复代码示例
%% Linear regression close all; clear; clc; dataset = load('accidents'); data = dataset.hwydata; x = data(:,14); y = data(:,4); % 数据标准化 x = (x - mean(x)) / std(x); y = (y - mean(y)) / std(y); %% Gradient descent w = 0; b = 0; alpha = 0.01; % 归一化后可尝试该学习率 max_iter = 10000; J_history = zeros(max_iter, 1); for i = 1:max_iter y_est = w*x + b; J_history(i) = mean((y - y_est).^2); % 参数更新 temp_w = w + alpha * mean(x .* (y - y_est)); temp_b = b + alpha * mean(y - y_est); w = temp_w; b = temp_b; end % 可视化代价变化 figure; plot(J_history); xlabel('迭代次数'); ylabel('均方误差 J'); title('梯度下降代价函数变化'); % 可视化拟合结果 figure; scatter(x, y, 10, 'b', 'filled'); hold on; plot(x, w*x + b, 'r', 'LineWidth', 2); xlabel('标准化后的x'); ylabel('标准化后的y'); title('线性回归拟合结果'); hold off;
内容的提问来源于stack exchange,提问作者wanderer
相关产品推荐
相关产品推荐

