首页 > 代码库 > 在SCIKIT中做PCA 逆运算 -- 新旧特征转换

在SCIKIT中做PCA 逆运算 -- 新旧特征转换

PCA(Principal Component Analysis)是一种常用的数据分析方法。PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。

在Scikit中运用PCA很简单:

import numpy as np
from sklearn import decomposition
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target

pca = decomposition.PCA(n_components=3)
pca.fit(X)
X = pca.transform(X)

以上代码是将含有4个特征的数据经过PCA压缩为3个特征。PCA的压缩由如下特点:

  • 新的3个特征并不是随便删除一个特征后留下的,而是4个特征的线性组合。
  • 新的3个特征保留了原有4个特征的绝大部分特征,换句话说就是略有损失。

 

那么PCA的损失到底是什么? 新特征能否转回旧特征?

 

这要从PCA过程说起,我把过程缩减如下,毕竟本文重点不是说PCA过程: 

PCA过程

1.均值化矩阵X

2.通过一系列矩阵运算得出  特征矩阵P

3.矩阵运算 Y = P * X

Y 即为原始数据降维后的结果,也就是说,得到矩阵P后,我们还可以通过Y=P * X这个算式, 反推回X:

 Y = P * X ==>   P(-1) * Y = P(-1) * P * X,  P(-1)是P的逆矩阵, 即 P(-1) * P = 1

                ==>   P(-1) * Y = X

需要注意的是,程序一开始就已经将原始数据均值化,所以实际上, P(-1)*Y的结果需要去均值化才是原来的样子

在Scikit中,pca.components_就是P的逆矩阵.  从源代码就可以看出(行号33)

 1    def transform(self, X, y=None):
 2         """Apply dimensionality reduction to X.
 3 
 4         X is projected on the first principal components previously extracted
 5         from a training set.
 6 
 7         Parameters
 8         ----------
 9         X : array-like, shape (n_samples, n_features)
10             New data, where n_samples is the number of samples
11             and n_features is the number of features.
12 
13         Returns
14         -------
15         X_new : array-like, shape (n_samples, n_components)
16 
17         Examples
18         --------
19 
20         >>> import numpy as np
21         >>> from sklearn.decomposition import IncrementalPCA
22         >>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
23         >>> ipca = IncrementalPCA(n_components=2, batch_size=3)
24         >>> ipca.fit(X)
25         IncrementalPCA(batch_size=3, copy=True, n_components=2, whiten=False)
26         >>> ipca.transform(X) # doctest: +SKIP
27         """
28         check_is_fitted(self, [mean_, components_], all_or_any=all)
29         print self.mean_
30         X = check_array(X)
31         if self.mean_ is not None:
32             X = X - self.mean_
33         X_transformed = fast_dot(X, self.components_.T)
34         if self.whiten:
35             X_transformed /= np.sqrt(self.explained_variance_)
36         return X_transformed


回到开头的压缩代码增加一些输出语句:

iris = datasets.load_iris()
X = iris.data
y = iris.target

print X[0]
pca = decomposition.PCA(n_components=3)
pca.fit(X)
X = pca.transform(X)

a = np.matrix(X)
b = np.matrix(pca.components_)
c = a * b
mean_of_data = np.matrix([5.84333333, 3.054,       3.75866667,  1.19866667])

print c[0]
print c[0] + mean_of_data

程序打印出原始数据中的第一行,然后将降维后的数据乘上特征矩阵的逆矩阵,加上均值还原回原来的4特征。

输出如下:

1 [ 5.1  3.5  1.4  0.2]
2 
3 [[-0.74365254  0.44632609 -2.35818399 -0.99942241]]
4 
5 [[ 5.09968079  3.50032609  1.40048268  0.19924426]]

由此可看, 经还原后的特征值(行号5)和原来(行号1)相比是略有损失的。

如果维度不降,我们可以再看看结果

pca = decomposition.PCA(n_components=4)
pca.fit(X)
X = pca.transform(X)

a = np.matrix(X)
b = np.matrix(pca.components_)
c = a * b
mean_of_data = np.matrix([5.84333333, 3.054,       3.75866667,  1.19866667])

print c[0]
print c[0] + mean_of_data


完美还原:

1 [ 5.1  3.5  1.4  0.2]
2 
3 [[-0.74333333  0.446      -2.35866667 -0.99866667]]
4 
5 [[ 5.1  3.5  1.4  0.2]]

 

在SCIKIT中做PCA 逆运算 -- 新旧特征转换