这是由于(或潜在的 [1])在缩放概念中的不一致sklearn.linear_model.base.center_data
:如果normalize=True
,那么它将除以设计矩阵的每一列的范数,而不是除以标准偏差。对于它的价值,该关键字normalize=True
将从 sklearn 版本 0.17 中弃用。
解决方法:不要使用standardize=True
。相反,构建 asklearn.pipeline.Pipeline
并将 asklearn.preprocessing.StandardScaler
添加到您的Lasso
对象。这样,您甚至不需要执行初始缩放。
请注意,Lasso 的 sklearn 实现中的数据丢失项按比例缩放n_samples
。因此,产生零解的最小惩罚是alpha_max = np.abs(X.T.dot(y)).max() / n_samples
(for normalize=False
)。
[1] 我说潜在的不一致,因为normalize与单词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_