案例:梯度计算的矩阵乘法(Example: matrix multiplication in gradient computations )
在线性回归的梯度计算中,其形式可概括为:
当有通过单个索引(公式中的 )与其它几个固定索引(公式中的 )的求和操作时,经常将这个计算改写成矩阵乘法 $[A B]{jk} = \sum_i A{ji} B_{ik}
y \hat{y} y_i \equiv y^{(i)}$),那么可将上面这样的求和模式重新写成下面这样:
因此,由于矩阵的整体计算思想,不需要逐个 索引依次计算,实际只需计算 就可以了。在 MATLAB 中的实现如下:
% X(j,i) = j'th coordinate of i'th example.
% y(i) = i'th value to be predicted; y is a column vector.
% theta = vector of parameters
y_hat = theta'*X; % so y_hat(i) = theta' * X(:,i). Note that y_hat is a *row-vector*.
g = X*(y_hat' - y);
进一步优化练习 1A 和 1B(Exercise 1A and 1B Redux )
返回您练习的 1A 和 1B 代码中,在
ex1a_linreg.m 和 ex1b_logreg.m 文件中,您将发现调用 minFunc 时分别使用的是文件 linear_regression_vec.m 和
logistic_regression_vec.m ,但却是被注释掉的,而不是用 linear_regression.m 和 logistic_regression.m 文件。在本次练习中,请您将
linear_regression_vec.m 和 logistic_regression_vec.m 里的代码以(前文所讲过的)向量化的方式实现并补充完整。将 ex1a_linreg.m 和 ex1b_logreg.m 文
件中的注释取消掉,并比较二者代码的运行时间,检验(现在的代码)是否和先前原本的代码得到的结果是一样的。
调试:梯度检查(Debugging: Gradient Checking)
迄今为止,在 MATLAB 中已经实现了通过计算目标函数的导数来计算梯度的算法(这种求梯度的方法叫做解析解)。在后续章节中,将看到更复杂的模型
(例如神经网络的反向传播算法)。对于这些模型,梯度的计算会变得难以调试,并难以得到正确结果。有时,代码中的微小错误也可以使模型学习到东
西,尽管表现稍稍不如完全正确的代码。因此,即使代码中微小的错误,也难说对最终结果有不好的影响。在本节中,将描述一种在数值层面(这种求梯度
的方法叫做数值解)上检查你的代码在导数计算部分的正确性。通过用数值解来验证导数求得的梯度结果,可以增加您在代码正确性上的信心。
译者注:
解析解指能够根据题意,得出在一定条件下的能够以数学表达式直接表达出来的的解。而数值解指在题中所给出的条件下难以用数学表达式表
达出来,或者能够表达出来但需要每个给定自变量值下的数字结果,而通过计算(手算或计算机计算)的出来的以表格或图形表示的结果。
数值解一般
是近似结果,它与微分方程的真实结果有偏差(参考: 百度知道 )。
假设想要最小化带有参数 的函数 。在这个例子中,假设有 , 。如果使用
minFunc 或其它优化算法,在此之前已实现了某个
函数的代码,函数 是计算 的导数,即 (解析解)。
怎样检查 的代码实现是正确的呢?
再来回顾一下导数的数学定义:
因此,对任何特定的 参数值,可以用下面这个方法(数值解)检查与导数值(解析解)是否接近:
在实践中,设置 为一小常量,通常设置为 。 ( 的值域范围尽管很大,但不设置 “非常”小,比如 ,因为
这会产生计算机的舍入误差。)
译者注:
舍入误差,由于计算机的字长有限,进行数值计算的过程中,对计算得到的中间结果数据要使用“四舍五入”或其他规则取近似值,因而使计算
过程有误差。这种误差称为舍入误差(参考: 百度百科 )。
因此,对给定目标函数的导数 ,它计算的是 (即解析解),可以通过下面这个式子从数值角度(即数值解)来验证导数求得的解(即解析
解)的正确性
以这两个值彼此的接近程度将取决于 。假设 。通常,你会发现的上面这个约等式中的左手边和右手边两个计算出的结果,一致的位
数至少4位(但也经常更多)。
现在,考虑一下参数 是一个向量,而非单个实数的情况(为了想要学到的 个参数),并且有 。现在,概括了导数检查过程,其中参数
可能是一个向量(如在线性回归和逻辑回归的例子中的)。如果正在通过几个向量或者矩阵来做优化,可以将这些参数“打包”进一个“长”的向量中去。在这
里,可以用同样的方法来检查导数。(这也可以使用现成的优化包来完成)。
假设有目标函数 的导数 的计算并化简出的结果: ;想要检查通过导数算出的梯度 是否输出了正确的导数值(即梯度值)。有
,其中