PCA是一种无监督学习方式(不需要label)。
直观理解PCA
PCA
是最常用的一种降维方法。以下图为例,我们的目标是要把二维点降到一维。
为了达到这个目标,我们要找到一个投影平面(该例是一条蓝色直线),使投影误差(红色线段)最小。找到这条投影直线后,就可以用投影到直线上的点(一维),来表示二维数据了。
所以,推广到高维,
PCA
的原理就是,为了将数据从n维降低到k维,需要找到k个向量,用于投影原始数据,是投影误差(投影距离)最小。
这样看,
PCA
最终会找到一个投影平面,而
线性回归
的目的也是要找到一个平面,那
PCA
岂不是有点类似
线性回归
?
PCA与线性回归的区别
下图是
PCA
与
线性回归
的示意图。
从图中可以看到它们有以下几点区别
-
PCA
属于
无监督学习
,其过程中没有label(y轴信息);
线性回归
属于
有监督学习
,有label -
PCA
的误差是用投影误差表示,而
线性回归
的误差是真实值(叉叉)与预测值(圈圈)之间的距离 -
PCA
的最终结果是投影点,而
线性回归
的最终结果是预测的直线
PCA的实现过程
举例:假设有4个样本及他们的特征如下
样本 | 特征1 | 特征2 | 特征3 |
---|---|---|---|
1 | 10001 | 2 | 55 |
2 | 16020 | 4 | 11 |
3 | 12008 | 6 | 33 |
4 | 13131 | 8 | 22 |
PCA主要是对数据做如下四步操作
- (1) 特征归一化
-
(2) 计算
协方差矩阵
(协方差矩阵满足对称正定) -
(3) 对
协方差矩阵
做
奇异值分解
,得到U - (4) 从U中取出k列(Ur),得到降维后的Z=X*Ur
下面详细说明将该例样本特征从3维降到2维的过程。
特征归一化
StandardScaler的归一化方式是用每个特征减去列均值,再除以列标准差。
from sklearn.preprocessing import StandardScaler
x=np.array([[10001,2,55], [16020,4,11], [12008,6,33], [13131,8,22]])
X_scaler = StandardScaler()
x = X_scaler.fit_transform(x)
归一化后的x为
样本 | 特征1 | 特征2 | 特征3 |
---|---|---|---|
1 | -1.2817325 | -1.34164079 | 1.52127766 |
2 | 1.48440157 | -0.4472136 | -1.18321596 |
3 | -0.35938143 | 0.4472136 | 0.16903085 |
4 | 0.15671236 | 1.34164079 | -0.50709255 |
计算协方差矩阵
对特征归一化后的矩阵计算协方差矩阵。计算协方差矩阵,既可以根据协方差矩阵的定义,用下面的代码来实现
m = 4 # sample number
cov_mat = np.dot(x.transpose(),x)/(m-1) # 协方差矩阵
也可以直接用numpy中的协方差矩阵计算方法来实现
cov_mat = np.cov(x, rowvar = 0)
对
协方差矩阵
做
奇异值分解
协方差矩阵
奇异值分解
numpy中直接提供了
奇异值分解
的计算函数
svd
。
[U,S,V] = np.linalg.svd(cov_mat) # 奇异值分解
这里得到了三个矩阵:U,S,V
这些矩阵的维数如下
- x: n x m (n表示样本个数(行),m表示特征个数(列))
- cov_mat: m x m
- U: m x m
- S: m x m
- V: m x m
降维
降维就是从U中取出k列(这里去2列),并与特征归一化后的矩阵x相乘。
Ur = U[:,0:2]
Z = np.dot(x, Ur)
对x降维后的结果Z为
样本 | 特征1 | 特征2 |
---|---|---|
1 | 2.36863319 | 0.38298087 |
2 | -1.50952734 | 1.23481789 |
3 | 0.14360068 | -0.58040917 |
4 | -1.00270653 | -1.03738959 |
这就是PCA的最终结果。
几个矩阵的维数如下
- x: n x m
- U: m x m
- Ur: m x k (k表示降维维度,这里为2。表示从3维(m)降到2维)
- Z: n x k
用sklearn做PCA
from sklearn.decomposition import PCA
import numpy as np
from sklearn.preprocessing import StandardScaler
x=np.array([[10001,2,55], [16020,4,11], [12008,6,33], [13131,8,22]])
X_scaler = StandardScaler()
x = X_scaler.fit_transform(x)
pca = PCA(n_components=2)
pca.fit(x)
Z=pca.transform(x)
降维的结果Z为
样本 | 特征1 | 特征2 |
---|---|---|
1 | 2.36863319 | 0.38298087 |
1 | -1.50952734 | 1.23481789 |
1 | 0.14360068 | -0.58040917 |
1 | -1.00270653 | -1.03738959 |
(这个结果与上面实现的PCA结果一致)
数据复原
PCA是数据压缩的过程
Z=X*Ur
其中各个矩阵的维度是
* x: n x m
* U: m x m
* Ur: m x k
* Z: n x k
数据复原的计算如下
X=Z*UrT
UrT是Ur的转置,UrT的维度是k x m
np.dot(z, Ur.transpose())# 数据复原,即x
样本 | 特征1 | 特征2 | 特征3 |
---|---|---|---|
1 | -1.28505803 | -1.34271509 | 1.51751098 |
2 | 1.48450422 | -0.44718044 | -1.18309969 |
3 | -0.34955552 | 0.45038782 | 0.18016022 |
4 | 0.15010934 | 1.3395077 | -0.51457151 |
可见复原后的x,与“特征归一化”一节中,归一化后的x一致。
参考
- Andrew NG在coursera的机器学习课程
-
PCA的完整实现过程代码详解