逻辑回归中的成本函数给出 NaN 结果

2024-03-18

我正在使用批量梯度下降来实现逻辑回归。输入样本要分为两类。类别为 1 和 0。在训练数据时,我使用以下 sigmoid 函数:

t = 1 ./ (1 + exp(-z));

where

z = x*theta

我正在使用以下成本函数来计算成本,以确定何时停止训练。

function cost = computeCost(x, y, theta)
    htheta = sigmoid(x*theta);
    cost = sum(-y .* log(htheta) - (1-y) .* log(1-htheta));
end

我将每一步的成本设为 NaN 作为以下值htheta大多数情况下为 1 或 0。我应该如何确定每次迭代的成本值?

这是逻辑回归的梯度下降代码:

function [theta,cost_history] = batchGD(x,y,theta,alpha)

cost_history = zeros(1000,1);

for iter=1:1000
  htheta = sigmoid(x*theta);
  new_theta = zeros(size(theta,1),1);
  for feature=1:size(theta,1)
    new_theta(feature) = theta(feature) - alpha * sum((htheta - y) .*x(:,feature))                         
  end
  theta = new_theta;
  cost_history(iter) = computeCost(x,y,theta);
end
end

您发生这种情况的可能原因有两个。

数据未标准化

这是因为当您将 sigmoid / logit 函数应用于您的假设时,输出概率几乎全部约为 0 或全部 1,并且使用您的成本函数,log(1 - 1) or log(0)将产生-Inf。成本函数中所有这些单独项的累积最终将导致NaN.

具体来说,如果y = 0对于训练示例,如果您的假设的输出是log(x) where x是一个非常小的数字,接近于 0,检查成本函数的第一部分会给我们0*log(x)并且实际上会产生NaN。同样,如果y = 1对于训练示例,如果您的假设的输出也是log(x) where x是一个非常小的数字,这又会给我们0*log(x)并将产生NaN。简而言之,假设的输出要么非常接近 0,要么非常接近 1。

这很可能是由于每个特征的动态范围差异很大,因此是你的假设的一部分,特别是加权和x*theta对于每个训练示例,您都会给出非常大的负值或正值,如果您将 sigmoid 函数应用于这些值,您将非常接近 0 或 1。

解决这个问题的一种方法是正常化在使用梯度下降进行训练之前矩阵中的数据。典型的方法是用零均值和单位方差进行标准化。给定一个输入特征x_k where k = 1, 2, ... n你在哪里n特征,新的标准化特征x_k^{new}可以通过以下方式找到:

m_k是特征的均值k and s_k是特征的标准差k。这也称为标准化数据。您可以在我在这里给出的另一个答案中阅读有关此内容的更多详细信息:这段用于标准化数据的代码是如何工作的? https://stackoverflow.com/questions/28689807/how-does-this-code-for-standardizing-data-work/28690441#28690441

因为您使用线性代数方法进行梯度下降,所以我假设您已经在数据矩阵前面添加了一列全数。知道了这一点,我们可以像这样标准化你的数据:

mX = mean(x,1); 
mX(1) = 0; 
sX = std(x,[],1); 
sX(1) = 1; 
xnew = bsxfun(@rdivide, bsxfun(@minus, x, mX), sX);

每个特征的平均值和标准差存储在mX and sX分别。您可以通过阅读我上面链接到您的帖子来了解此代码的工作原理。我不会在这里重复这些内容,因为这不是本文的范围。为了确保正确的标准化,我将第一列的平均值和标准差分别设置为 0 和 1。xnew包含新的标准化数据矩阵。使用xnew用你的梯度下降算法代替。现在,一旦找到参数,就可以执行任何预测must使用与测试实例的平均值和标准差对任何新测试实例进行归一化训练集。由于学习的参数与训练集的统计数据有关,因此您还必须对要提交给预测模型的任何测试数据应用相同的转换。

假设您有新的数据点存储在名为的矩阵中xx,您将进行标准化,然后执行预测:

xxnew = bsxfun(@rdivide, bsxfun(@minus, xx, mX), sX);

现在您已经有了这个,您可以执行您的预测:

pred = sigmoid(xxnew*theta) >= 0.5;

您可以将阈值 0.5 更改为您认为最好的值,以确定示例属于正类还是负类。

学习率太大

正如您在评论中提到的,一旦对数据进行标准化,成本似乎是有限的,但经过几次迭代后突然变为 NaN。标准化只能让你走到这一步。如果你的学习率或alpha太大,每次迭代都会朝着最小值的方向超调,从而使每次迭代的成本振荡甚至发散,这就是正在发生的情况。在您的情况下,成本在每次迭代时都会发散或增加,以至于它太大以至于无法使用浮点精度表示。

因此,另一种选择是降低学习率alpha直到您看到成本函数在每次迭代中都在减小。确定最佳学习率的一种流行方法是对一系列对数间隔值执行梯度下降alpha看看最终的成本函数值是多少,然后选择导致最小成本的学习率。


假设成本函数是凸的,结合使用上面的两个事实应该可以让梯度下降很好地收敛。对于逻辑回归来说,它肯定是这样的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

逻辑回归中的成本函数给出 NaN 结果 的相关文章

随机推荐