PCA 中特征重要性的度量
Measure of Feature Importance in PCA
我正在进行主成分分析 (PCA),我想找出对结果贡献最大的特征。
我的直觉是总结特征对各个组件的各个贡献的所有绝对值。
import numpy as np
from sklearn.decomposition import PCA
X = np.array([[-1, -1, 4, 1], [-2, -1, 4, 2], [-3, -2, 4, 3], [1, 1, 4, 4], [2, 1, 4, 5], [3, 2, 4, 6]])
pca = PCA(n_components=0.95, whiten=True, svd_solver='full').fit(X)
pca.components_
array([[ 0.71417303, 0.46711713, 0. , 0.52130459],
[-0.46602418, -0.23839061, -0. , 0.85205128]])
np.sum(np.abs(pca.components_), axis=0)
array([1.18019721, 0.70550774, 0. , 1.37335586])
在我看来,这可以衡量每个原始特征的重要性。请注意,第三个特征的重要性为零,因为我有意创建了一个只是常量值的列。
是否有更好的 PCA“重要性度量”?
PCA 的重要性度量在 explained_variance_ratio_
中。此数组提供每个组件解释的方差百分比。它按组件的重要性降序排列,当所有组件都被使用时总和为 1,或者超过请求阈值的最小可能值。在您的示例中,您将阈值设置为 95%(应解释的方差),因此数组总和将为 0.9949522861608583,因为第一个组件解释了 92.021143% 和第二个 7.474085% 的方差,因此您收到了 2 个组件。
components_
是存储特征space中最大方差方向的数组。它的尺寸是 n_components_
乘 n_features_
。这是您在应用 transform()
以获得数据的降维投影时乘以数据点的值。
更新
为了获得原始特征对每个主成分的贡献百分比,您只需要归一化components_
,因为它们设置了原始向量对投影的贡献量。
r = np.abs(pca.components_.T)
r/r.sum(axis=0)
array([[0.41946155, 0.29941172],
[0.27435603, 0.15316146],
[0. , 0. ],
[0.30618242, 0.54742682]])
如您所见,第三个功能对 PC 没有贡献。
如果您需要原始特征对解释方差的总贡献,则需要考虑每个 PC 贡献(即 explained_variance_ratio_
):
ev = np.abs(pca.components_.T).dot(pca.explained_variance_ratio_)
ttl_ev = pca.explained_variance_ratio_.sum()*ev/ev.sum()
print(ttl_ev)
[0.40908847 0.26463667 0. 0.32122715]
如果您只是将 PC 与 np.sum(np.abs(pca.components_), axis=0)
相加,即假定所有 PC 都同等重要,但这种情况很少见。要使用 PCA 进行粗略的特征选择,在根据相对贡献缩放 PC 后丢弃低贡献 PC 后求和 and/or。
这是一个直观示例,突出显示了为什么普通总和无法按预期工作。
给定 20 个特征的 3 个观察值(可视化为三个 5x4 热图):
>>> print(X.T)
[[2 1 1 1 1 1 1 1 1 4 1 1 1 4 1 1 1 1 1 2]
[1 1 1 1 1 1 1 1 1 4 1 1 1 6 3 1 1 1 1 2]
[1 1 1 2 1 1 1 1 1 5 2 1 1 5 1 1 1 1 1 2]]
这些是生成的 PC:
>>> pca = PCA(n_components=None, whiten=True, svd_solver='full').fit(X.T)
请注意,PC3 在 (2,1)
处具有很高的震级,但如果我们检查其解释的方差,它提供 ~0 贡献:
>>> print(pca.explained_variance_ratio_)
array([0.6638886943392722, 0.3361113056607279, 2.2971091700327738e-32])
这会导致在对未缩放的 PC 求和(左)与对按解释的方差比缩放的 PC 求和(右)时出现特征选择差异:
>>> unscaled = np.sum(np.abs(pca.components_), axis=0)
>>> scaled = np.sum(pca.explained_variance_ratio_[:, None] * np.abs(pca.components_), axis=0)
加上未缩放的总和(左),无意义的PC3仍然被赋予了33%的权重。这导致 (2,1)
被认为是最重要的特征,但如果我们回顾原始数据,(2,1)
对观察结果的区分度很低。
通过缩放和(右),PC1 和 PC2 分别具有 66% 和 33% 的权重。现在 (3,1)
和 (3,2)
是实际跟踪原始数据的最重要的特征。
我正在进行主成分分析 (PCA),我想找出对结果贡献最大的特征。
我的直觉是总结特征对各个组件的各个贡献的所有绝对值。
import numpy as np
from sklearn.decomposition import PCA
X = np.array([[-1, -1, 4, 1], [-2, -1, 4, 2], [-3, -2, 4, 3], [1, 1, 4, 4], [2, 1, 4, 5], [3, 2, 4, 6]])
pca = PCA(n_components=0.95, whiten=True, svd_solver='full').fit(X)
pca.components_
array([[ 0.71417303, 0.46711713, 0. , 0.52130459],
[-0.46602418, -0.23839061, -0. , 0.85205128]])
np.sum(np.abs(pca.components_), axis=0)
array([1.18019721, 0.70550774, 0. , 1.37335586])
在我看来,这可以衡量每个原始特征的重要性。请注意,第三个特征的重要性为零,因为我有意创建了一个只是常量值的列。
是否有更好的 PCA“重要性度量”?
PCA 的重要性度量在 explained_variance_ratio_
中。此数组提供每个组件解释的方差百分比。它按组件的重要性降序排列,当所有组件都被使用时总和为 1,或者超过请求阈值的最小可能值。在您的示例中,您将阈值设置为 95%(应解释的方差),因此数组总和将为 0.9949522861608583,因为第一个组件解释了 92.021143% 和第二个 7.474085% 的方差,因此您收到了 2 个组件。
components_
是存储特征space中最大方差方向的数组。它的尺寸是 n_components_
乘 n_features_
。这是您在应用 transform()
以获得数据的降维投影时乘以数据点的值。
更新
为了获得原始特征对每个主成分的贡献百分比,您只需要归一化components_
,因为它们设置了原始向量对投影的贡献量。
r = np.abs(pca.components_.T)
r/r.sum(axis=0)
array([[0.41946155, 0.29941172],
[0.27435603, 0.15316146],
[0. , 0. ],
[0.30618242, 0.54742682]])
如您所见,第三个功能对 PC 没有贡献。
如果您需要原始特征对解释方差的总贡献,则需要考虑每个 PC 贡献(即 explained_variance_ratio_
):
ev = np.abs(pca.components_.T).dot(pca.explained_variance_ratio_)
ttl_ev = pca.explained_variance_ratio_.sum()*ev/ev.sum()
print(ttl_ev)
[0.40908847 0.26463667 0. 0.32122715]
如果您只是将 PC 与 np.sum(np.abs(pca.components_), axis=0)
相加,即假定所有 PC 都同等重要,但这种情况很少见。要使用 PCA 进行粗略的特征选择,在根据相对贡献缩放 PC 后丢弃低贡献 PC 后求和 and/or。
这是一个直观示例,突出显示了为什么普通总和无法按预期工作。
给定 20 个特征的 3 个观察值(可视化为三个 5x4 热图):
>>> print(X.T)
[[2 1 1 1 1 1 1 1 1 4 1 1 1 4 1 1 1 1 1 2]
[1 1 1 1 1 1 1 1 1 4 1 1 1 6 3 1 1 1 1 2]
[1 1 1 2 1 1 1 1 1 5 2 1 1 5 1 1 1 1 1 2]]
这些是生成的 PC:
>>> pca = PCA(n_components=None, whiten=True, svd_solver='full').fit(X.T)
请注意,PC3 在 (2,1)
处具有很高的震级,但如果我们检查其解释的方差,它提供 ~0 贡献:
>>> print(pca.explained_variance_ratio_)
array([0.6638886943392722, 0.3361113056607279, 2.2971091700327738e-32])
这会导致在对未缩放的 PC 求和(左)与对按解释的方差比缩放的 PC 求和(右)时出现特征选择差异:
>>> unscaled = np.sum(np.abs(pca.components_), axis=0)
>>> scaled = np.sum(pca.explained_variance_ratio_[:, None] * np.abs(pca.components_), axis=0)
加上未缩放的总和(左),无意义的PC3仍然被赋予了33%的权重。这导致 (2,1)
被认为是最重要的特征,但如果我们回顾原始数据,(2,1)
对观察结果的区分度很低。
通过缩放和(右),PC1 和 PC2 分别具有 66% 和 33% 的权重。现在 (3,1)
和 (3,2)
是实际跟踪原始数据的最重要的特征。