[英]Randomized PCA .explained_variance_ratio_ sums to greater than one in sklearn 0.15.0
[英]Recovering features names of explained_variance_ratio_ in PCA with sklearn
我正在尝试从使用 scikit-learn 完成的 PCA 中恢复,哪些特征被选为相关的。
IRIS 数据集的经典示例。
import pandas as pd
import pylab as pl
from sklearn import datasets
from sklearn.decomposition import PCA
# load dataset
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# normalize data
df_norm = (df - df.mean()) / df.std()
# PCA
pca = PCA(n_components=2)
pca.fit_transform(df_norm.values)
print pca.explained_variance_ratio_
这返回
In [42]: pca.explained_variance_ratio_
Out[42]: array([ 0.72770452, 0.23030523])
我怎样才能恢复哪两个特征允许这两个数据集之间的解释差异? 换个说法,我如何在 iris.feature_names 中获取此功能的索引?
In [47]: print iris.feature_names
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
在此先感谢您的帮助。
此信息包含在pca
属性中: components_
。 如文档中所述, pca.components_
输出一个[n_components, n_features]
数组,因此要了解组件与不同功能的线性关系,您必须:
注意:每个系数代表特定对组件和特征之间的相关性
import pandas as pd
import pylab as pl
from sklearn import datasets
from sklearn.decomposition import PCA
# load dataset
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# normalize data
from sklearn import preprocessing
data_scaled = pd.DataFrame(preprocessing.scale(df),columns = df.columns)
# PCA
pca = PCA(n_components=2)
pca.fit_transform(data_scaled)
# Dump components relations with features:
print(pd.DataFrame(pca.components_,columns=data_scaled.columns,index = ['PC-1','PC-2']))
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
PC-1 0.522372 -0.263355 0.581254 0.565611
PC-2 -0.372318 -0.925556 -0.021095 -0.065416
重要提示:作为旁注,请注意 PCA 符号不影响其解释,因为该符号不影响每个组件中包含的方差。 只有形成 PCA 维度的特征的相对符号才是重要的。 事实上,如果您再次运行 PCA 代码,您可能会得到符号反转的 PCA 尺寸。 为了直观地了解这一点,请考虑 3-D 空间中的向量及其负数 - 两者本质上都表示空间中的相同方向。 检查此帖子以获取进一步参考。
编辑:正如其他人评论的那样,您可能会从.components_
属性中获得相同的值。
每个主成分都是原始变量的线性组合:
其中X_i
s 是原始变量,而Beta_i
s 是相应的权重或所谓的系数。
要获得权重,您可以简单地将单位矩阵传递给transform
方法:
>>> i = np.identity(df.shape[1]) # identity matrix
>>> i
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
>>> coef = pca.transform(i)
>>> coef
array([[ 0.5224, -0.3723],
[-0.2634, -0.9256],
[ 0.5813, -0.0211],
[ 0.5656, -0.0654]])
上面的coef
矩阵的每一列都显示了线性组合中的权重,以获得相应的主成分:
>>> pd.DataFrame(coef, columns=['PC-1', 'PC-2'], index=df.columns)
PC-1 PC-2
sepal length (cm) 0.522 -0.372
sepal width (cm) -0.263 -0.926
petal length (cm) 0.581 -0.021
petal width (cm) 0.566 -0.065
[4 rows x 2 columns]
例如,上图显示第二主成分( PC-2
)大部分与sepal width
对齐,其绝对值最高权重为0.926
;
由于数据已归一化,您可以确认主成分的方差为1.0
,这相当于每个系数向量的范数为1.0
:
>>> np.linalg.norm(coef,axis=0)
array([ 1., 1.])
也可以确认主成分可以计算为上述系数和原始变量的点积:
>>> np.allclose(df_norm.values.dot(coef), pca.fit_transform(df_norm.values))
True
请注意,由于浮点精度错误,我们需要使用numpy.allclose
而不是常规相等运算符。
这个问题的措辞方式让我想起了当我第一次试图弄清楚它时对主成分分析的误解。 我想在这里通读一遍,希望其他人不会像我在一分钱最终落下之前那样,在无路可走的路上花费太多时间。
“恢复”特征名称的概念表明 PCA 可以识别数据集中最重要的特征。 这不完全正确。
据我了解,PCA 识别数据集中方差最大的特征,然后可以使用数据集的这种质量来创建一个较小的数据集,同时将描述能力的损失降至最低。 较小数据集的优势在于它需要较少的处理能力,并且数据中的噪声较小。 但是最大方差的特征并不是数据集的“最佳”或“最重要”特征,只要这些概念可以说是完全存在的。
将该理论带入上述@Rafa 示例代码的实用性中:
# load dataset
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# normalize data
from sklearn import preprocessing
data_scaled = pd.DataFrame(preprocessing.scale(df),columns = df.columns)
# PCA
pca = PCA(n_components=2)
pca.fit_transform(data_scaled)
考虑以下:
post_pca_array = pca.fit_transform(data_scaled)
print data_scaled.shape
(150, 4)
print post_pca_array.shape
(150, 2)
在这种情况下, post_pca_array
具有作为相同的150行数据data_scaled
,但data_scaled
的四列已经从四个减少到两个。
这里的关键点是,两列-或部件,要在术语一致-的post_pca_array
不是两个“最佳”列data_scaled
。 它们是两个新列,由sklearn.decomposition
的PCA
模块背后的算法确定。 sepal_width
示例中的第二列PC-2
由sepal_width
通知的sepal_width
比任何其他列sepal_width
多,但PC-2
和data_scaled['sepal_width']
中的值不相同。
因此,虽然找出原始数据中的每一列对 post-PCA 数据集的组成部分的贡献很有趣,但“恢复”列名的概念有点误导,而且肯定误导了我很长时间。 后 PCA 和原始列之间匹配的唯一情况是主成分的数量设置为与原始列中的列数相同。 但是,使用相同数量的列没有意义,因为数据不会改变。 你去那里只会再次回来,就像它一样。
获取 PC 上the most important feature name
:
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
np.random.seed(0)
# 10 samples with 5 features
train_features = np.random.rand(10,5)
model = PCA(n_components=2).fit(train_features)
X_pc = model.transform(train_features)
# number of components
n_pcs= model.components_.shape[0]
# get the index of the most important feature on EACH component i.e. largest absolute value
# using LIST COMPREHENSION HERE
most_important = [np.abs(model.components_[i]).argmax() for i in range(n_pcs)]
initial_feature_names = ['a','b','c','d','e']
# get the names
most_important_names = [initial_feature_names[most_important[i]] for i in range(n_pcs)]
# using LIST COMPREHENSION HERE AGAIN
dic = {'PC{}'.format(i+1): most_important_names[i] for i in range(n_pcs)}
# build the dataframe
df = pd.DataFrame(sorted(dic.items()))
这打印:
0 1
0 PC1 e
1 PC2 d
所以在PC1命名的功能e
是最重要和PC2的d
。
给定您的拟合估计量pca
,将在pca.components_
找到pca.components_
,它们表示数据集中方差最大的方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.