【发布时间】:2015-09-25 17:11:35
【问题描述】:
我正在尝试实现一个Logistic Regression算法,部分Matlab代码如下。
for i = 1 : MAX_ITR
% Calculate mu
mu = 1.0 ./ (1.0 + exp(-(X * w)));
% Calculate h to check for convergence
h(i) = sum(-y .* log(mu) - (1 - y) .* log(1 - mu)) + (lambda / 2) * norm(w([2:end]))^2;
% Calculate gradient and hessian.
G = lambda .* w;
G(1) = 0; % Set extra term for gradient to 0
L = lambda .* eye(D + 1);
L(1) = 0; % Set extra term for Hessian to 0
grad = (X' * (mu - y)) + G;
S = diag((mu .* (1 - mu)));
H = (X' * S * X) + L;
% Update w
w = w - H\grad;
end
显然mu 的值不能为 1,因为指数不能为 0。但是,在某些值中,指数的计算结果非常小,例如 1.6629e-05。这会导致该实例的 mu 值非常接近 1,即 0.999983371689452。
我已经逐次运行代码迭代,前 4 次迭代很好,因为 mu 不包含任何这样的“接近 1”值。但是,第五次迭代确实如此,因此,我的h 得到了一个NaN,算法不会收敛。
我已经运行了digits 命令,它的值是32,所以我不知道是什么导致了这个问题。
预计到达时间:
在@rayryeng 的建议之后更新了代码:
D是X中的特征个数,m是训练样本个数X
for i = 1 : MAX_ITR
% Initialize arrays
grad = zeros(D+1,1);
h(i) = 0;
H = zeros(D+1,D+1);
for j = 1 : m
% Calculate mu
mu = sigmoid(X(j,:) * w);
% Calculate h (to check for convergence)
h(i) = h(i) - (1/m)*(y(j) * log(mu) + (1 - y(j)) * log(1 - mu)) + (lambda / (2 * m)) * norm(w(2:end))^2;
% Calculate gradient and Hessian
G = lambda * w;
G(1) = 0; % Set extra term for gradient to 0
L = lambda * eye(numFeatures + 1);
L(1) = 0; % Set extra term for Hessian to 0
grad = grad - (1/m) * ((X(j,:)' * (mu - y(j))) + G);
S = diag((mu .* (1 - mu)));
H = H - (1/m) * ((X(j,:)' * S * X(j,:)) + L);
end
%fprintf('h(%d) = %0.5f\n', i, h(i));
% Update w
w = w - H\grad;
end
我不再收到NaN 错误,并且h 值似乎在几次迭代后收敛。
【问题讨论】:
-
我假设
w(1)是偏置项....但是在计算 sigmoid 时,您又将它包含在X*w中? -
我猜
NaN是因为(1-y).*log(1-mu)类似于0*inf。不能把mu的表达式写成log(1-mu)并化简,避免精度损失问题吗? -
您可以尝试使用
log1p处理较小的mu值:... -(1-y).*log1p(-mu) ...。您还应该查看y的变化情况。digits用于可变精度算术 - 如果您以标准双精度执行此操作,则无关紧要。 -
@rayryeng 是的,w(1) 是偏差项。我已经删除了。
-
@Rayne - 我稍后会调试你的代码,但与此同时,看看这个:dropbox.com/s/sitgpmu6oe2cfyt/ps1sol.pdf?dl=1 - 这是 Andrew Ng 从 2014 年秋季开始的 CS 229 课程的第一个问题分配,第 2-4 页显示了如何为 LR 实现牛顿法的代码。将其与您的实现进行比较,看看是否匹配。
标签: matlab precision logistic-regression