这是由于缩放概念中的(或潜在的[1])不一致造成的。sklearn.linear_model.base.center_data
: If normalize=True
,然后它将除以norm设计矩阵的每一列,而不是由标准差。对于它的价值,关键字normalize=True
将从 sklearn 0.17 版开始弃用。
Solution: Do not use standardize=True
。相反,建立一个sklearn.pipeline.Pipeline
并在前面添加一个sklearn.preprocessing.StandardScaler
给你的Lasso
目的。这样您甚至不需要执行初始缩放。
请注意,Lasso 的 sklearn 实现中的数据丢失项按比例缩放n_samples
。因此,产生零解的最小惩罚是alpha_max = np.abs(X.T.dot(y)).max() / n_samples
(for normalize=False
).
[1] 我说潜在的不一致,因为正常化与该词相关联norm因此至少在语言上是一致的:)
[如果您不想了解详细信息,请停止阅读]
这是一些复制和粘贴的代码,重现了问题
import numpy as np
rng = np.random.RandomState(42)
n_samples, n_features, n_active_vars = 20, 10, 5
X = rng.randn(n_samples, n_features)
X = ((X - X.mean(0)) / X.std(0))
beta = rng.randn(n_features)
beta[rng.permutation(n_features)[:n_active_vars]] = 0.
y = X.dot(beta)
print X.std(0)
print X.mean(0)
from sklearn.linear_model import Lasso
lasso1 = Lasso(alpha=.1)
print lasso1.fit(X, y).coef_
lasso2 = Lasso(alpha=.1, normalize=True)
print lasso2.fit(X, y).coef_
为了了解发生了什么,现在观察一下
lasso1.fit(X / np.sqrt(n_samples), y).coef_ / np.sqrt(n_samples)
等于
lasso2.fit(X, y).coef_
因此,缩放设计矩阵并适当地重新缩放系数np.sqrt(n_samples)
将一种模型转换为另一种模型。这也可以通过对惩罚进行操作来实现:套索估计器normalize=True
其处罚缩小了np.sqrt(n_samples)
其作用类似于套索估计器normalize=False
(关于您的数据类型,即已经标准化为std=1
).
lasso3 = Lasso(alpha=.1 / np.sqrt(n_samples), normalize=True)
print lasso3.fit(X, y).coef_ # yields the same coefficients as lasso1.fit(X, y).coef_