当 p > n 时,sklearn 如何进行线性回归?

4

众所周知,当变量的数量(p)大于样本数(n)时,最小二乘估计器未定义。

在sklearn中,我收到以下值:

In [30]: lm = LinearRegression().fit(xx,y_train)

In [31]: lm.coef_
Out[31]: 
array([[ 0.20092363, -0.14378298, -0.33504391, ..., -0.40695124,
         0.08619906, -0.08108713]])

In [32]: xx.shape
Out[32]: (1097, 3419)

调用[30]应该返回错误。当p>n时,例如在这种情况下,sklearn如何工作?

编辑: 看起来矩阵填充了一些值

if n > m:
        # need to extend b matrix as it will be filled with
        # a larger solution matrix
        if len(b1.shape) == 2:
            b2 = np.zeros((n, nrhs), dtype=gelss.dtype)
            b2[:m,:] = b1
        else:
            b2 = np.zeros(n, dtype=gelss.dtype)
            b2[:m] = b1
        b1 = b2
1个回答

8
当线性系统未确定时,sklearn.linear_model.LinearRegression会找到最小的L2范数解。
argmin_w l2_norm(w) subject to Xw = y

通过将伪逆矩阵X应用于向量y,可以始终明确定义并获得结果。

w = np.linalg.pinv(X).dot(y)

scipy.linalg.lstsq 的具体实现被 LinearRegression 使用,使用了 get_lapack_funcs(('gelss',), ...,这是一种通过奇异值分解(由 LAPACK 提供)找到最小范数解的求解器。

可以参考以下示例:

import numpy as np
rng = np.random.RandomState(42)
X = rng.randn(5, 10)
y = rng.randn(5)

from sklearn.linear_model import LinearRegression
lr = LinearRegression(fit_intercept=False)
coef1 = lr.fit(X, y).coef_
coef2 = np.linalg.pinv(X).dot(y)

print(coef1)
print(coef2)

您会发现coef1 == coef2。(请注意,在sklearn估算器的构造函数中指定了fit_intercept=False,因为否则它将在拟合模型之前减去每个特征的平均值,从而产生不同的系数)


这个解决方案是否与岭回归得到的解决方案相同?这种方法只在新版本的sklearn中实现吗?我很确定在某些版本中它会返回一个错误。 - Donbeo
1
不,岭回归会增加额外的L2 惩罚,从而改变目标函数和结果解。在欠定情况下,最小L2范数解只是所有解的仿射空间中的(明智的)选择。然而,如果您将岭回归解作为正则化参数的函数,并让该参数趋近于0,您将找到确切的最小范数解。 - eickenberg
好的,那么获得的解决方案应该与LARS算法路径的最终结果几乎相同,这是有道理的,因为在p > n时这是LSE的标准定义。 (对吗?)你知道sklearn-scipy的先前版本中是否也实现了这一点吗? - Donbeo
当惩罚项趋近于0时,“LARS-Lasso”将收敛于所有解中最小“L1”范数的解。至于LARS,由于它不会丢弃变量,所以您可能是正确的,但我无法给出确凿的证据。 - eickenberg
请注意,在实践中,当你面对 n < p 时,最好使用带有小惩罚项的 sklearn.linear_model.Ridge 而不是最小范数解决方案。 - eickenberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接