恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
梯度下降法Matlab程序及利用Excel做详细说明:从一行公式到能跑通的代码
首页
资讯中心
/
梯度下降法Matlab程序及利用Excel做详细说明:从一行公式到能跑通的代码
梯度下降法Matlab程序及利用Excel做详细说明:从一行公式到能跑通的代码
发布时间:2026/10/13 19:27:14
简介这份资源围绕梯度下降法这一数据科学中最常用的优化算法展开面向机器学习入门者与需要动手实现优化算法的同学用住宅价格预测作为案例帮助读者从原理到代码建立直观理解。压缩包共4个文件约221KB包含Matlab程序源文件.m、配套数据文件.mat、原理讲解PDF以及一张示意图其中脚本可直接运行复现实验PDF则用Excel表格逐步演示梯度下降的迭代过程把抽象的公式转化为可观察的数值变化。资源已有270人学习下载适合课堂实验、自学练手或作为教学演示素材。读者可借此掌握梯度下降的更新规则、学习率影响与收敛判断并对照Excel推导过程排查代码实现中的常见问题形成从理论到编程的完整闭环。1. 梯度下降法Matlab程序及利用excel做详细说明从一行公式到能跑通的代码很多做算法落地的朋友第一次接触优化算法都是从梯度下降法开始的。标题里这个「梯度下降法Matlab程序及利用excel做详细说明」说白了就是两件事一是用Matlab把梯度下降的迭代过程写成能跑的程序二是用Excel把每一步的数值变化摊开给你看让你知道程序里那个循环到底在算什么。我见过太多人Matlab代码能跑但问他第3次迭代的梯度是多少、学习率调大调小会发生什么答不上来。Excel在这里不是配角它是把黑匣子拆开的工具。这篇适合刚入门数值优化、需要交课程设计、或者想给团队做内部培训的工程师跟着走一遍你能自己改目标函数、调学习率、看收敛曲线也能把Excel表格当成调试面板用。2. 梯度下降法的数学骨架与Matlab实现选型2.1 从一元二次函数看迭代公式到底在做什么梯度下降法的核心就一句话沿着当前点梯度的反方向走一小步步子大小由学习率决定。用数学写出来是 θ_{k1} θ_k - α * ∇J(θ_k)。别小看这个式子里面有三个东西决定了你能不能收敛初始点θ_0、学习率α、梯度∇J。我一般拿一个最简单的目标函数 J(θ) θ^2 2θ 1 来演示它的梯度是 2θ 2最小值在 θ -1 处。为什么选这个因为它的梯度是线性的Excel里手算几步就能看出规律Matlab里跑出来也不会因为数值问题干扰你对算法本身的理解。在Matlab里实现时常见做法是把目标函数和梯度函数分开写成两个匿名函数或者独立的.m文件。匿名函数适合快速验证独立函数适合复杂场景。我一般会先写匿名函数版本因为改起来快不用来回切文件。下面这段代码就是最小可运行版本目标函数和梯度都写在一起迭代过程全部记录下来方便后面和Excel对账。% 梯度下降法最小示例J(theta) theta^2 2*theta 1 % 梯度 dJ/dtheta 2*theta 2 clear; clc; J (theta) theta.^2 2*theta 1; % 目标函数 gradJ (theta) 2*theta 2; % 梯度函数 alpha 0.1; % 学习率 theta 3.0; % 初始点 maxIter 20; % 最大迭代次数 tol 1e-6; % 收敛容差 history zeros(maxIter, 4); % 记录 [迭代次数, theta, J值, 梯度值] for k 1:maxIter g gradJ(theta); jVal J(theta); history(k, :) [k, theta, jVal, g]; if abs(g) tol history history(1:k, :); fprintf(在第 %d 次迭代收敛theta %.6f\n, k, theta); break; end theta theta - alpha * g; % 核心更新步骤 end % 打印迭代记录 fprintf(迭代次数\t theta\t\t J值\t\t 梯度\n); for i 1:size(history, 1) fprintf(%d\t\t %.6f\t %.6f\t %.6f\n, history(i,1), history(i,2), history(i,3), history(i,4)); end这段代码里history矩阵是给Excel做对照用的每一行对应一次迭代。alpha设成0.1是因为对于这个函数学习率超过1就会发散0.1能稳定收敛且步数适中。tol设1e-6是工程上常用的精度再小意义不大浮点误差会干扰判断。maxIter设20是因为这个函数从3.0出发0.1的学习率大约15步就能到-1附近。你如果换成alpha0.5收敛会更快但可能震荡换成alpha1.5直接发散theta会飞到无穷大。这些边界后面在Excel里会看得更清楚。2.2 学习率、初始点、迭代终止条件怎么选学习率α是梯度下降法里最玄学的参数。选大了震荡甚至发散选小了收敛慢到你想砸键盘。对于上面那个二次函数理论上的稳定条件是 α 2/L其中L是梯度的最大变化率这里L2所以α必须小于1。我一般会先用0.1试然后根据收敛曲线调整。如果你不确定有个土办法从0.01开始每次乘以3看什么时候开始震荡然后取那个值的三分之一。初始点θ_0的选择也有讲究。对于凸函数初始点随便选都能收敛到全局最小但步数会差很多。从3.0出发和从100出发前者十几步后者可能要几百步。实际工程里如果目标函数不是凸的初始点就决定了你最终掉进哪个局部最小。我一般会跑多次随机初始化取目标函数值最小的那个结果。迭代终止条件通常用梯度范数小于某个阈值或者相邻两次目标函数值的变化小于阈值。前者更直接后者更实用。Matlab里还可以用optimset设置MaxIter和TolFun但自己写循环的好处是每一步都能记录方便和Excel对照。如果你用Matlab自带的fminunc它内部用的不是纯梯度下降而是拟牛顿法收敛更快但中间过程不透明。做教学和调试时我坚持手写循环。2.3 向量化写法与逐元素写法的取舍上面的例子是一维的实际数据往往是多维的。Matlab的强项是矩阵运算梯度下降的向量化写法能把循环压成一行。假设目标函数是 J(θ) (1/2) * ||Xθ - y||^2梯度是 X^T(Xθ - y)。向量化写法如下% 多元线性回归的梯度下降向量化实现 % X: m x n 特征矩阵y: m x 1 标签向量 % theta: n x 1 参数向量 m size(X, 1); alpha 0.01; theta zeros(size(X, 2), 1); maxIter 1000; for k 1:maxIter grad (1/m) * X * (X * theta - y); % 梯度向量 theta theta - alpha * grad; % 同时更新所有参数 end这里除以m是为了让梯度不受样本量影响学习率可以设得稳定一些。向量化写法比逐元素循环快几十倍尤其是特征维度高的时候。但向量化也有坑X * (X * theta - y) 这个表达式会临时生成一个m x 1的中间向量如果m是百万级内存会爆。这时候要分块计算或者用Matlab的tall array。我一般会在数据量小于10万时用向量化超过就分块。3. 用Excel把每一次迭代摊开从公式到表格的完整映射3.1 搭建Excel迭代表列设计与公式填写Excel在这里的作用是把Matlab循环里的每一步都可视化。我一般建四列迭代次数k、当前θ值、目标函数J(θ)、梯度∇J(θ)。第一行填初始值第二行开始用公式引用上一行的结果。具体操作A2填1B2填3初始θC2填 B2^22B21D2填 2B22。然后A3填 A21B3填 B2-0.1*D2C3和D3分别复制C2和D2的公式往下拉。这样你改B2的初始值或者把0.1改成其他学习率整张表会自动重算。这里的关键是B3的公式B2-0.1D2。0.1就是学习率αD2是当前梯度。这个公式和Matlab里的 theta theta - alpha * g 完全对应。你可以在Excel里单独设一个单元格放学习率比如E1填0.1然后B3写成 B2-$E$1D2这样调学习率不用改公式。我习惯把学习率、初始点、迭代次数都做成参数单元格整张表变成可交互的。3.2 用Excel图表看收敛J值和梯度的双轴曲线光看数字不够直观Excel的图表能把收敛过程画出来。选中C列J值插入折线图横轴用A列迭代次数。你会看到J值一开始下降很快后面越来越平这就是收敛。如果J值先下降然后上升说明学习率太大震荡发散了。再把D列梯度加到次坐标轴能看到梯度绝对值单调减小到接近零。这两条曲线一对照你就知道程序里那个tol到底在卡什么。我一般会做三张图对比α0.1、α0.5、α1.5。α0.1的J值平滑下降α0.5的J值会上下震荡但最终收敛α1.5的J值直接飞出去。这三张图放在一起比任何文字解释都管用。Excel里改一个单元格三张图同时变这种即时反馈是Matlab命令行给不了的。3.3 把Matlab输出导入Excel做逐行对账Matlab跑完后的history矩阵可以导出成CSV然后用Excel打开和手算的表格逐行对比。如果第5行的θ值差在小数点后六位以外说明你的Matlab代码和Excel公式有一处不一致。常见的不一致点Matlab里梯度是2theta2Excel里写成2B21少了个2或者Matlab里更新用的是旧梯度Excel里用了新梯度。这种对账能帮你抓出代码里的低级错误。导出命令很简单writematrix(history, gd_history.csv)。然后在Excel里用「数据」→「从文本/CSV」导入。我一般会在Excel里加一列「Matlab θ」和「Excel θ」的差值用条件格式标出大于1e-6的单元格。这样一眼就能看到哪一步开始分叉。4. 避坑与排查梯度下降法在Matlab和Excel里最容易翻车的5个地方4.1 现象Matlab跑着跑着theta变成NaN原因学习率太大导致数值溢出或者目标函数里有log(0)之类的未定义运算。解决先把学习率降到0.001试如果还NaN就检查目标函数定义域。在循环里加一句 if any(isnan(theta)), break; end 能防止死循环。4.2 现象Excel表格拉了几百行J值一直不降原因公式引用错了行比如B3引用了D3而不是D2导致用了当前梯度而不是上一步梯度。解决检查B3的公式确保减的是上一行的梯度。另一个可能是学习率太小比如1e-6那确实降得慢改成0.01试试。4.3 现象Matlab和Excel结果对不上差在小数点后几位原因Matlab默认双精度Excel也是双精度但Excel显示的时候可能截断了。解决在Excel里把单元格格式改成显示15位小数或者用 ROUND(B2,10) 统一精度。如果还差检查Matlab里是不是用了单精度变量。4.4 现象梯度下降在多元函数上震荡不收敛原因不同维度的特征尺度差异太大导致梯度方向被大尺度特征主导。解决先做特征归一化把每列特征减均值除标准差。Matlab里用 zscore(X)Excel里用 (B2-AVERAGE(B:B))/STDEV(B:B)。归一化之后学习率可以设得更大收敛更快。4.5 现象迭代次数到了maxIter还没收敛原因可能是目标函数本身没有最小值或者学习率太小。解决先画J值的曲线如果还在下降就加大maxIter或者调大学习率。如果J值已经平了但梯度还很大说明你的tol设得太严放宽到1e-4试试。5. 进阶技巧用Excel做参数扫描和Matlab的收敛验证5.1 在Excel里做学习率扫描表Excel的数据表功能可以一次性算多个学习率的结果。建一个两列的表左列是学习率0.01、0.05、0.1、0.5、1.0、1.5右列用公式算20步之后的θ值。具体做法在F2填0.01G2填 3-20F2(2*32) 这种近似不行得老老实实迭代。更实用的办法是用Excel的「模拟分析」→「数据表」把学习率作为输入输出最终θ值。这样你能一眼看到哪个学习率收敛最快且稳定。我一般会做一个二维表行是学习率列是初始点单元格里填最终J值。条件格式标红发散的区域标绿收敛到最小值的区域。这张表就是你的参数安全区地图。对于J(θ)θ^22θ1安全区大概是α在0.01到0.9之间初始点在-10到10之间。5.2 用Matlab验证Excel的收敛边界Excel里看到α1.0时J值震荡但没发散α1.1时发散。Matlab里可以精确找到临界点。写一个循环让α从0.9到1.1步长0.001跑100步看最终θ是否在-1附近。代码如下% 寻找学习率的收敛边界 alphaList 0.9:0.001:1.1; finalTheta zeros(size(alphaList)); for i 1:length(alphaList) alpha alphaList(i); theta 3.0; for k 1:100 theta theta - alpha * (2*theta 2); end finalTheta(i) theta; end % 找到第一个发散的alpha idx find(abs(finalTheta) 100, 1); if ~isempty(idx) fprintf(临界学习率约为 %.3f\n, alphaList(idx)); end这段代码跑出来临界α在1.0附近。和Excel的扫描结果对一下如果一致说明你对算法的理解到位了。如果不一致回去检查Excel的迭代步数是不是和Matlab一样。5.3 把收敛过程录成GIF的土办法Matlab里可以用drawnow和getframe把每一步的θ位置画出来存成GIF。Excel里做不到动画但可以用条件格式做「热力图」把每一步的θ值映射成颜色从红到蓝表示从初始点到最小值。我一般用Excel的色阶功能选中θ列条件格式→色阶→红白蓝。这样你滚动表格的时候能看到颜色从红渐变到蓝直观感受收敛过程。最后说个我自己的习惯每次写完梯度下降代码我一定会在Excel里手算前5步和Matlab输出对一遍。这个习惯帮我抓过至少三次梯度符号写反的错误。符号一错程序跑得再顺也是往反方向跑。希望帮到你。本文还有配套的精品资源点击获取