用于求解线性回归的梯度下降和正规方程方法给出了不同的解

时间:2012-06-30 04:08:21

标签: matlab machine-learning linear-regression gradient-descent

我正在研究机器学习问题,并希望使用线性回归作为学习算法。我已经实现了两种不同的方法来查找线性回归模型的参数theta:梯度(最陡)下降和法线方程。在相同的数据上,它们都应该给出大致相等的theta向量。但他们没有。

两个theta向量在所有元素上非常相似,但第一个。这是用于将所有1的向量乘以数据的那个。

以下是theta s的样子(第一列是Gradient descent的输出,是Normal方程的第二输出):

Grad desc Norm eq
-237.7752 -4.6736
-5.8471   -5.8467
9.9174    9.9178
2.1135    2.1134
-1.5001   -1.5003
-37.8558  -37.8505
-1.1024   -1.1116
-19.2969  -19.2956
66.6423   66.6447
297.3666  296.7604
-741.9281 -744.1541
296.4649  296.3494
146.0304  144.4158
-2.9978   -2.9976
-0.8190   -0.8189

与正常方程返回的theta(1, 1)相比,渐变下降返回的theta(1, 1)有什么不同?我的代码中有错误吗?

这是我在Matlab中实现的正规方程式:

function theta = normalEque(X, y)
    [m, n] = size(X);
    X = [ones(m, 1), X];
    theta = pinv(X'*X)*X'*y;
end

这是梯度下降的代码:

function theta = gradientDesc(X, y)
    options = optimset('GradObj', 'on', 'MaxIter',  9999);
    [theta, ~, ~] = fminunc(@(t)(cost(t, X, y)),...
                    zeros(size(X, 2), 1), options);
end

function [J, grad] = cost(theta, X, y)
    m = size(X, 1);
    X = [ones(m, 1), X];
    J = sum((X * theta - y) .^ 2) ./ (2*m);
    for i = 1:size(theta, 1)
        grad(i, 1) = sum((X * theta - y) .* X(:, i)) ./ m;
    end
end

我将完全相同的数据Xy传递给两个函数(我没有规范化X)。

编辑1:

根据答案和评论,我检查了几个代码并运行了一些测试。

首先,我想检查问题是否可能由@user1489497's answer建议的单数附近的X beeing引起。所以我用inv替换了pinv - 当它运行时我真的得到警告Matrix is close to singular or badly scaled.。为了确保这不是问题,我获得了更大的数据集并使用这个新数据集运行测试。此时inv(X)未显示警告,并使用pinvinv给出了相同的结果。所以我希望 X不再接近单数

然后我按照woodchips按照建议更改了normalEque代码,所以现在看起来像:

function theta = normalEque(X, y)
    X = [ones(size(X, 1), 1), X];
    theta = pinv(X)*y;
end

然而问题仍然存在。对于不接近单数的新数据,新的normalEque函数会将thetagradientDesc区分开来。

为了找出哪个算法是错误的,我在相同的数据上运行了数据挖掘软件Weka的线性回归算法。 Weka计算theta与normalEque的输出非常相似,但与gradientDesc的输出不同。所以我猜normalEque是正确的, gradientDesc 中存在错误。

以下是Weka,thetanormalEque计算的GradientDesc s的比较:

Weka(correct) normalEque    gradientDesc
779.8229      779.8163      302.7994
  1.6571        1.6571        1.7064
  1.8430        1.8431        2.3809
 -1.5945       -1.5945       -1.5964
  3.8190        3.8195        5.7486
 -4.8265       -4.8284      -11.1071
 -6.9000       -6.9006      -11.8924
-15.6956      -15.6958      -13.5411
 43.5561       43.5571       31.5036
-44.5380      -44.5386      -26.5137
  0.9935        0.9926        1.2153
 -3.1556       -3.1576       -1.8517
 -0.1927       -0.1919       -0.6583
  2.9207        2.9227        1.5632
  1.1713        1.1710        1.1622
  0.1091        0.1093        0.0084
  1.5768        1.5762        1.6318
 -1.3968       -1.3958       -2.1131
  0.6966        0.6963        0.5630
  0.1990        0.1990       -0.2521
  0.4624        0.4624        0.2921
-12.6013      -12.6014      -12.2014
 -0.1328       -0.1328       -0.1359

我还计算了Justin Peel's answer建议的错误。 normalEque的输出给出了较小的平方误差,但差异很小。当我使用函数theta计算cost的成本梯度时更加(与gradientDesc使用的相同)我得到了接近零的渐变。在gradientDesc的输出上完成同样不会使梯度接近零。这就是我的意思:

>> [J_gd, grad_gd] = cost(theta_gd, X, y, size(X, 1));
>> [J_ne, grad_ne] = cost(theta_ne, X, y, size(X, 1));
>> disp([J_gd, J_ne])
  120.9932  119.1469
>> disp([grad_gd, grad_ne])
  -0.005172856743846  -0.000000000908598
  -0.026126463200876  -0.000000135414602
  -0.008365136595272  -0.000000140327001
  -0.094516503056041  -0.000000169627717
  -0.028805977931093  -0.000000045136985
  -0.004761477661464  -0.000000005065103
  -0.007389474786628  -0.000000005010731
   0.065544198835505  -0.000000046847073
   0.044205371015018  -0.000000046169012
   0.089237705611538  -0.000000046081288
  -0.042549228192766  -0.000000051458654
   0.016339232547159  -0.000000037654965
  -0.043200042729041  -0.000000051748545
   0.013669010209370  -0.000000037399261
  -0.036586854750176  -0.000000027931617
  -0.004761447097231  -0.000000027168798
   0.017311225027280  -0.000000039099380
   0.005650124339593  -0.000000037005759
   0.016225097484138  -0.000000039060168
  -0.009176443862037  -0.000000012831350
   0.055653840638386  -0.000000020855391
  -0.002834810081935  -0.000000006540702
   0.002794661393905  -0.000000032878097

这表明梯度下降根本不会收敛到全局最小值......但是,当我运行数千次迭代时,情况就不是这样了。 那么bug在哪里?

4 个答案:

答案 0 :(得分:6)

我终于有时间回到这里了。没有“错误”。

如果矩阵是单数的,那么有无限多的解。您可以从该组中选择任何解决方案,并获得同样好的答案。 pinv(X)* y解是一个很好的解决方案,因为它是最小的规范解决方案。

使用inv(X)* y绝对没有充分的理由。更糟糕的是,对正规方程使用逆,因此inv(X'* X)* X'* y只是数值废话。我不在乎是谁告诉你使用它,它们会引导你到错误的地方。 (是的,对于条件良好的问题,它可以接受,但大多数时候你不知道什么时候会给你废话。所以为什么要使用它?)

正常方程通常是一件坏事,即使您正在解决正则化问题。有办法做到这一点,避免平方系统的条件号,虽然我不会解释它们,除非被问及这个答案已经足够长了。

X \ y也会产生合理的结果。

绝对没有理由在问题上抛出无约束的优化器,因为这会产生不稳定的结果,完全取决于你的起始值。

作为一个例子,我将从一个单一的问题开始。

X = repmat([1 2],5,1);
y = rand(5,1);

>> X\y
Warning: Rank deficient, rank = 1, tol =  2.220446e-15. 
ans =
                         0
         0.258777984694222

>> pinv(X)*y
ans =
         0.103511193877689
         0.207022387755377

pinv和反斜杠返回略有不同的解决方案。事实证明,有一个基本的解决方案,我们可以为X的行空间添加任意数量的零空间向量。

null(X)
ans =
         0.894427190999916
        -0.447213595499958

pinv生成最小范数解决方案。在可能产生的所有解决方案中,这个解决方案至少有2个标准。

相反,反斜杠生成的解决方案将一个或多个变量设置为零。

但是如果使用无约束优化器,它将生成一个完全取决于起始值的解决方案。同样,可以将任意数量的空向量添加到您的解决方案中,并且您仍然拥有完全有效的解决方案,并且具有相同的误差平方值。

请注意,即使没有返回奇点,也不一定意味着你的矩阵不接近单数。你对这个问题几乎没有什么改变,所以它仍然很接近,只是不足以触发警告。

答案 1 :(得分:2)

正如其他人所提到的,病态的粗麻布矩阵可能是导致问题的原因。

标准梯度下降算法达到局部最优所采用的步数是由粗糙度的最大特征值除以最小值(这被称为Hessian的条件数)的函数。因此,如果您的矩阵是病态的,那么可能需要进行大量的迭代才能使梯度下降收敛到最优。 (对于单一的情况,它当然可以收敛到许多点。)

我建议尝试三种不同的方法来验证无约束的优化算法是否适用于您的问题(应该如此): 1)通过计算随机输入的已知线性函数的结果并添加少量高斯噪声来生成一些合成数据。确保您拥有的数据点多于维度。这应该产生非奇异的粗麻布。 2)向误差函数添加正则化项以增加粗体的条件数。 3)使用二阶方法,如共轭梯度或L-BFGS而不是梯度下降,以减少算法收敛所需的步骤数。 (您可能需要与#2一起完成此操作。)

答案 2 :(得分:1)

你能发布一些关于X的样子吗?你使用的是pinv(),它是Moore-Penrose伪逆。如果矩阵病态,这可能导致获得逆的问题。我敢打赌,梯度下降法更接近标记。

答案 3 :(得分:0)

您应该看到哪种方法实际上给您最小的错误。这将表明哪种方法正在挣扎。我怀疑正规方程方法是困难的解决方案,因为如果X病态,那么你可能会遇到一些问题。

您应该用theta = X\y替换普通方程解决方案,它将使用QR分解方法来解决它。