我目前正在Coursera平台上学习机器学习课程,并且尝试实现逻辑回归。为了实现逻辑回归,我使用梯度下降法来最小化成本函数,并且需要编写一个名为costFunctionReg.m
的函数,该函数返回当前参数集下每个参数的成本和梯度。
问题描述如下:
我的成本函数工作正常,但梯度函数不行。请注意,我更倾向于使用循环来实现,而不是逐元素操作。
我单独计算theta[0]
(在MATLAB中为theta(1)
),因为它不被正则化,即我们不使用第一个项(带有lambda
的项)。
function [J, grad] = costFunctionReg(theta, X, y, lambda) %COSTFUNCTIONREG 计算带正则化的逻辑回归的成本和梯度 % J = COSTFUNCTIONREG(theta, X, y, lambda) 计算使用 % theta作为正则化逻辑回归参数的成本和 % 相对于参数的成本梯度。 % 初始化一些有用的值 m = length(y); % 训练样本的数量 n = length(theta); % 参数(特征)的数量 % 你需要正确返回以下变量 J = 0; grad = zeros(size(theta)); % ====================== 你的代码在这里 ====================== % 说明:计算特定theta选择的成本。 % 你应该将J设置为成本。 % 计算偏导数并将grad设置为成本相对于theta中每个参数的偏导数 % ----------------------1. 计算成本------------------- % 假设 h = sigmoid(X * theta); for i = 1 : m % 第i项的成本在正则化之前 J = J - ( y(i) * log(h(i)) ) - ( (1 - y(i)) * log(1 - h(i)) ); % 添加正则化项 for j = 2 : n J = J + (lambda / (2*m) ) * ( theta(j) )^2; end end J = J/m; % ----------------------2. 计算梯度------------------- % 不正则化theta[0],即MATLAB中的theta(1) j = 1; for i = 1 : m grad(j) = grad(j) + ( h(i) - y(i) ) * X(i,j); end for j = 2 : n for i = 1 : m grad(j) = grad(j) + ( h(i) - y(i) ) * X(i,j) + lambda * theta(j); end end grad = (1/m) * grad; % =============================================================end
我哪里做错了?
回答:
你应用正则化的方式是错误的。你应该在对所有训练样本求和之后添加正则化项,但你却在每个样本之后添加正则化项。如果你保持代码在修正前的状态,你会无意中使梯度步长变大,最终会超过解。这种超调会累积,最终会使梯度向量的各个分量(除了偏置项外)变成Inf
或-Inf
。
简单来说,将你的lambda*theta(j)
语句放在第二个for
循环结束之后:
for j = 2 : n for i = 1 : m grad(j) = grad(j) + ( h(i) - y(i) ) * X(i,j); % 修改 end grad(j) = grad(j) + lambda * theta(j); % 修改end