使用Python与Julia进行线性回归的解析解

时间:2015-06-15 21:56:55

标签: python matrix julia

使用Andrew Ng的类中的示例(使用正规方程找出线性回归的参数):

使用Python:

X = np.array([[1, 2104, 5, 1, 45], [1, 1416, 3, 2, 40], [1, 1534, 3, 2, 30], [1, 852, 2, 1, 36]])
y = np.array([[460], [232], [315], [178]])
θ = ((np.linalg.inv(X.T.dot(X))).dot(X.T)).dot(y)
print(θ)

结果:

[[  7.49398438e+02]
 [  1.65405273e-01]
 [ -4.68750000e+00]
 [ -4.79453125e+01]
 [ -5.34570312e+00]]

朱莉娅:

X = [1 2104 5 1 45; 1 1416 3 2 40; 1 1534 3 2 30; 1 852 2 1 36]
y = [460; 232; 315; 178]

θ = ((X' * X)^-1) * X' * y

结果:

5-element Array{Float64,1}:
 207.867    
   0.0693359
 134.906    
 -77.0156   
  -7.81836  

此外,当我多次使用Julia's - 而不是Python's - θ时,我得到的数字接近于y。

我无法弄清楚我做错了什么。谢谢!

3 个答案:

答案 0 :(得分:11)

使用X ^ -1与伪逆

对应于the pseudo inverse

pinv (X)比 inv (X)更广泛地适用,X ^ -1等于。朱莉娅和Python都没有使用 inv 做得很好,但在这种情况下,朱莉娅显然做得更好。

但是如果将表达式更改为

julia> z=pinv(X'*X)*X'*y
5-element Array{Float64,1}:
 188.4     
   0.386625
 -56.1382  
 -92.9673  
  -3.73782 

您可以验证X * z = y

julia> X*z
4-element Array{Float64,1}:
 460.0
 232.0
 315.0
 178.0

答案 1 :(得分:9)

Python中更加数字化的方法,无需自己进行矩阵代数就是使用numpy.linalg.lstsq进行回归:

In [29]: np.linalg.lstsq(X, y)
Out[29]: 
(array([[ 188.40031942],
        [   0.3866255 ],
        [ -56.13824955],
        [ -92.9672536 ],
        [  -3.73781915]]),
 array([], dtype=float64),
 4,
 array([  3.08487554e+03,   1.88409728e+01,   1.37100414e+00,
          1.97618336e-01]))

(将解决方案矢量与@ waTeim在Julia中的答案进行比较)。

您可以通过打印矩阵反向来查看病态调节的来源:

In [30]: np.linalg.inv(X.T.dot(X))
Out[30]: 
array([[ -4.12181049e+13,   1.93633440e+11,  -8.76643127e+13,
         -3.06844458e+13,   2.28487459e+12],
       [  1.93633440e+11,  -9.09646601e+08,   4.11827338e+11,
          1.44148665e+11,  -1.07338299e+10],
       [ -8.76643127e+13,   4.11827338e+11,  -1.86447963e+14,
         -6.52609055e+13,   4.85956259e+12],
       [ -3.06844458e+13,   1.44148665e+11,  -6.52609055e+13,
         -2.28427584e+13,   1.70095424e+12],
       [  2.28487459e+12,  -1.07338299e+10,   4.85956259e+12,
          1.70095424e+12,  -1.26659193e+11]])

机房工程!

将此点积与X.T一起导致精确度的灾难性损失。

答案 2 :(得分:3)

请注意,X是一个4x5矩阵,或者统计表示您观察的参数少于估算的参数。因此,最小二乘问题具有无限多个解,其中平方误差的总和恰好等于零。在这种情况下,正规方程对你没有多大帮助,因为矩阵X'X是单数的。相反,您应该找到X*b=y的解决方案。

大多数数值线性代数系统都是基于FORTRAN包LAPACK,它使用一个可旋转的QR因子分解来解决问题X*b=y。由于存在无限多的解决方案,LAPACK选择具有最小规范的解决方案。在朱莉娅,只需编写

即可获得此解决方案

float(X)\y

(不幸的是,float部分现在是必要的,但这会改变。)

在精确算术中,您应该使用所提出的方法获得与上述方法相同的解决方案,但是您的问题的浮点表示会引入小的舍入误差,这些错误将影响计算的解决方案。与直接在X上使用QR分解相比,使用正规方程时,舍入误差对解的影响要大得多。

X行数多于列数的常见情况下也是如此,因此建议您在求解最小二乘问题时避免使用正规方程。但是,当X的行数多于列数时,矩阵X'X相对较小。在这种情况下,使用正规方程而不是使用QR分解来解决问题要快得多。在许多统计问题中,与静态误差相比,额外的数值误差非常小,因此可以简单地忽略由于正规方程引起的精度损失。