我尝试从使用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)']
提前感谢您的帮助。
答案 0 :(得分:56)
此信息包含在pca
属性中:components_
。如documentation中所述,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尺寸。对于这种直觉,考虑一个向量及其在三维空间中的负面 - 两者基本上代表了空间中的相同方向。 请查看this post以获取进一步的参考。
答案 1 :(得分:42)
修改:正如其他人所评论的那样,您可以从.components_
属性获得相同的值。
每个主成分是原始变量的线性组合:
其中X_i
是原始变量,而Beta_i
是相应的权重或所谓的系数。
要获得权重,您可以简单地将单位矩阵传递给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
还可以确认主成分可以计算为上述系数和原始变量的点积:
{{1}}
请注意,由于浮点精度错误,我们需要使用numpy.allclose
而不是常规相等运算符。
答案 2 :(得分:16)
这个问题的表达方式让我想起了当我第一次想出来时对主成分分析的误解。我想在这里通过它,希望其他人不会像在便士最终放弃之前那样花费在通往无处的路上。
“恢复”功能名称的概念表明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
与data_scaled
具有相同的150行数据,但data_scaled
的四列已从四列减少到两列。
这里的关键点是post_pca_array
的两列(或术语一致)不是data_scaled
的两个“最佳”列。它们是两个新列,由sklearn.decomposition
的{{1}}模块后面的算法决定。 @ Rafa示例中的第二列PCA
比{1}}更多地通知PC-2
,但sepal_width
和PC-2
中的值不同。
因此,虽然有趣的是找出原始数据中的每一列对后PCA数据集的组成部分有多大贡献,但“恢复”列名称的概念有点误导,并且肯定误导了我很长时间时间。如果主要组件的数量设置为与原始列中的列相同的数量,那么后PCA和原始列之间将匹配的唯一情况。但是,使用相同数量的列是没有意义的,因为数据不会改变。你只会去那里再回来,就像它一样。
答案 3 :(得分:4)
根据您的拟合估算器pca
,可以在pca.components_
中找到组件,它们代表数据集中方差最大的方向。
答案 4 :(得分:0)
在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
的功能。