为弹性网络预先计算 Gram 矩阵

Beginner

This tutorial is from open-source community. Access the source code

简介

本实验展示了如何在使用带权重样本的弹性网络(ElasticNet)时预先计算 Gram 矩阵。需要注意的是,如果使用了带权重的样本,在计算 Gram 矩阵之前,设计矩阵必须进行中心化处理,然后通过权重向量的平方根进行重新缩放。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。

加载数据集并创建样本权重

我们首先加载数据集并创建一些样本权重。我们使用 scikit-learn 中的make_regression函数来生成一个包含 100,000 个样本的随机回归数据集。然后,我们生成一个对数正态分布的权重向量,并将其归一化,使其总和等于样本总数。

import numpy as np
from sklearn.datasets import make_regression

rng = np.random.RandomState(0)

n_samples = int(1e5)
X, y = make_regression(n_samples=n_samples, noise=0.5, random_state=rng)

sample_weight = rng.lognormal(size=n_samples)
## normalize the sample weights
normalized_weights = sample_weight * (n_samples / (sample_weight.sum()))

使用加权样本预计算 Gram 矩阵

为了使用precompute选项并结合样本权重来拟合弹性网络(elastic net),我们必须在计算 Gram 矩阵之前,先对设计矩阵进行中心化处理,并通过归一化权重对其进行重新缩放。我们通过从每行中减去每个特征列的加权平均值来对设计矩阵进行中心化。然后,我们将中心化后的设计矩阵的每行乘以相应归一化权重的平方根,从而对其进行重新缩放。最后,我们通过将重新缩放后的设计矩阵与其转置矩阵做点积来计算 Gram 矩阵。

X_offset = np.average(X, axis=0, weights=normalized_weights)
X_centered = X - np.average(X, axis=0, weights=normalized_weights)
X_scaled = X_centered * np.sqrt(normalized_weights)[:, np.newaxis]
gram = np.dot(X_scaled.T, X_scaled)

拟合弹性网络

现在我们可以进行拟合了。我们必须将中心化后的设计矩阵传递给fit,以防止弹性网络估计器检测到它未中心化并丢弃我们传递的 Gram 矩阵。但是,如果我们传递缩放后的设计矩阵,预处理代码会错误地再次对其进行缩放。我们还将归一化权重传递给fit函数的sample_weight参数。

from sklearn.linear_model import ElasticNet

lm = ElasticNet(alpha=0.01, precompute=gram)
lm.fit(X_centered, y, sample_weight=normalized_weights)

总结

本实验展示了如何在使用带权重样本的弹性网络(ElasticNet)时预先计算 Gram 矩阵。我们首先加载了一个回归数据集,并创建了一个对数正态分布的权重向量,该向量经过归一化处理后总和等于样本总数。然后,我们对设计矩阵进行了中心化处理,通过归一化权重对其进行重新缩放,并计算了 Gram 矩阵。最后,我们使用预先计算的 Gram 矩阵和归一化权重来拟合弹性网络。