【问题标题】:what does the option normalize = True in Lasso sklearn do?Lasso sklearn 中的选项 normalize = True 有什么作用?
【发布时间】:2014-07-28 16:34:49
【问题描述】:

我有一个矩阵,其中每列的平均值为 0,标准值为 1

In [67]: x_val.std(axis=0).min()
Out[70]: 0.99999999999999922

In [71]: x_val.std(axis=0).max()
Out[71]: 1.0000000000000007

In [72]: x_val.mean(axis=0).max()
Out[72]: 1.1990408665951691e-16

In [73]: x_val.mean(axis=0).min()
Out[73]: -9.7144514654701197e-17

如果我使用归一化选项,非 0 系数的数量会发生变化

In [74]: l = Lasso(alpha=alpha_perc70).fit(x_val, y_val)

In [81]: sum(l.coef_!=0)
Out[83]: 47

In [84]: l2 = Lasso(alpha=alpha_perc70, normalize=True).fit(x_val, y_val)

In [93]: sum(l2.coef_!=0)
Out[95]: 3

在我看来,规范化只是将每列的方差设置为 1。结果变化如此之大,这很奇怪。我的数据已经方差= 1。

那么 normalize=T 实际上做了什么?

【问题讨论】:

  • 使用== 比较浮点数不是一个好主意。最好检查从 0 到非常小的数字的绝对差,例如 1e-10。你能用abs做同样的实验吗?
  • 问题是真实存在的,请参见下面的示例。不过,我不完全确定它的确切来源。这很有趣 - 特别是因为我刚刚发现某处必须进行一些额外的重新缩放,因为alpha_max = np.abs(X.T.dot(y)).max() 不是零解惩罚集的严格下限。
  • @eickenberg 如果我设置 normalize=False,你能确认套索工作正常吗?
  • 我更新了我的答案 - 这是一个缩放问题。我稍后会详细说明。
  • 是的,套索很好用。坚持normalize=False 并在Pipeline 中使用StandardScaler,如下所述。请注意,最大惩罚公式还包含一个缩放项(在下面的注释中描述)。

标签: python machine-learning scikit-learn lasso-regression


【解决方案1】:

这是由于sklearn.linear_model.base.center_data 中缩放概念的一个(或潜在的[1])不一致:如果normalize=True,那么它将除以每一列的norm设计矩阵,而不是 标准差 。无论如何,关键字 normalize=True 将从 sklearn 版本 0.17 中弃用。

解决方案:不要不要使用standardize=True。相反,构建一个sklearn.pipeline.Pipeline 并将sklearn.preprocessing.StandardScaler 添加到您的Lasso 对象。这样您甚至不需要执行初始缩放。

请注意,Lasso 的 sklearn 实现中的数据丢失项按n_samples 缩放。因此产生零解的最小惩罚是alpha_max = np.abs(X.T.dot(y)).max() / n_samples(对于normalize=False)。

[1] 我说潜在的不一致,因为normalizenorm这个词相关联,因此至少在语言上是一致的:)

[如果您不想了解详细信息,请在此处停止阅读]

这里有一些复制和粘贴代码来重现问题

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_

【讨论】:

    【解决方案2】:

    我认为上面的答案是错误的......

    在 Lasso 中,如果您设置 normalize=True,则在拟合 lasso 回归之前,每列都将除以其 L2 范数(即 sd*sqrt(n))。设计矩阵的量级因此减小,“预期”系数将增大。系数越大,L1 惩罚越强。所以函数要更加注意L1的惩罚,让更多的特征为0。结果你会看到更多的稀疏特征(β=0)。

    【讨论】:

      猜你喜欢
      • 2022-01-02
      • 2021-06-03
      • 2011-01-28
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 2012-09-26
      • 2019-05-23
      • 2013-09-02
      相关资源
      最近更新 更多