PCA最重要的降维方法之一,在数据压缩消除冗余和数据噪音消除等领域都有广泛的应用,一般我们提到降维最容易想到的算法就是PCA,目标是基于方差提取最有价值的信息,属于无监督问题。
方差
方差描述的是样本集合的各个样本点到均值的距离之平均,一般用来描述一维数据的离散程度的度量,在概率论和统计方差用来度量随机变量和数据期望之间的偏离程度。
V
a
r
(
a
)
=
1
m
∑
i
=
1
m
(
a
i
−
μ
)
2
Var(a) = \frac{1}{m}\sum_{i=1}^m(a_i-\mu)^2
Var(a)=m1i=1∑m(ai−μ)2
协方差
方差和协方差的关系:方差是用来度量单个变量的“自身变异大小”的总体参数,方差越大表明该变量变化越大。协方差是两个变量相互影响大小的参数,协方差的参数越大,则两个变量相互影响越大。
可以通俗的理解为:两个变量在变化过程中是同方向变化?还是反方向变化?同向或反向程度如何?你变大,同时我也变大,说明两个变量是同向变化的,这时协方差就是正的。你变大,同时我变小,说明两个变量是反向变化的,这时协方差就是负的。从数值来看,协方差的数值越大,两个变量同向程度也就越大。反之亦然。
协方差公式如下:
C
o
v
(
X
,
Y
)
=
E
[
(
X
−
μ
x
)
(
Y
−
μ
y
)
]
Cov(X,Y) = E[(X-\mu_x)(Y-\mu_y)]
Cov(X,Y)=E[(X−μx)(Y−μy)]
如果有X,Y两个变量,每个时刻的“X值与其均值之差”乘以“Y值与其均值之差”得到一个乘积,再对这每时刻的乘积求和并求出均值,也可以写成如下形式:
C
o
v
(
X
,
Y
)
=
1
m
∑
i
=
1
m
(
X
i
−
μ
x
)
(
Y
i
−
μ
y
)
Cov(X,Y) = \frac{1}{m}\sum_{i=1}^{m}{(X_i-\mu_x)(Y_i-\mu_y)}
Cov(X,Y)=m1i=1∑m(Xi−μx)(Yi−μy)
假设均值为0
如果协方差为0,表示两个特征是线性无关的,所以为了尽可能的展示数据更多的原始信息,我们需要特征之间是线性无关的,也即协方差为0。
优化目标:将一组N维向量降为K(0<k<n)维,目标选择K个单位正交基,使得原始数据变换到这组基上后,各字段两两间协方差为0,字段的方差尽可能最大。
X
=
(
a
1
a
2
⋯
a
m
b
1
b
2
⋯
b
m
)
1
m
X
X
T
=
(
1
m
∑
i
=
1
m
a
i
2
1
m
∑
i
=
1
m
a
i
b
i
1
m
∑
i
=
1
m
a
i
b
i
1
m
∑
i
=
1
m
b
i
2
)
X= \begin{pmatrix} a_1&a_2&\cdots&a_m\\ b_1&b_2&\cdots&b_m\\ \end{pmatrix} \\ \frac{1}{m}XX^\mathrm{ T }= \begin{pmatrix} \frac{1}{m}\sum_{i=1}^ma_i^2&\frac{1}{m}\sum_{i=1}^ma_ib_i\\ \frac{1}{m}\sum_{i=1}^ma_ib_i&\frac{1}{m}\sum_{i=1}^mb_i^2\\ \end{pmatrix}
X=(a1b1a2b2⋯⋯ambm)m1XXT=(m1∑i=1mai2m1∑i=1maibim1∑i=1maibim1∑i=1mbi2)
协方差矩阵对角线上的元素分别是字段的方差,而其他元素是a和b的协方差。并且是实对称矩阵。
举例
数据:
(
−
1
−
1
0
2
0
−
2
0
0
1
1
)
\begin{pmatrix} -1&-1&0&2&0\\ -2&0&0&1&1\\ \end{pmatrix}
(−1−2−10002101)
协方差矩阵:
C
=
1
5
(
−
1
−
1
0
2
0
−
2
0
0
1
1
)
(
−
1
−
2
−
1
0
0
0
2
1
0
1
)
=
(
6
5
4
5
4
5
6
5
)
C=\frac{1}{5} \begin{pmatrix} -1&-1&0&2&0\\ -2&0&0&1&1\\ \end{pmatrix} \begin{pmatrix} -1&-2\\ -1&0\\ 0&0\\ 2&1\\ 0&1 \end{pmatrix} =\begin{pmatrix} \frac{6}{5}&\frac{4}{5}\\ \\ \frac{4}{5}&\frac{6}{5}\\ \end{pmatrix}
C=51(−1−2−10002101)⎝⎜⎜⎜⎜⎛−1−1020−20011⎠⎟⎟⎟⎟⎞=⎝⎛56545456⎠⎞
特征值:
λ
1
=
2
,
λ
2
=
2
5
\lambda_1=2, \lambda_2=\frac{2}{5}
λ1=2,λ2=52
特征向量:
c
1
=
(
1
1
)
c
2
=
(
−
1
1
)
c_1= \begin{pmatrix} 1\\ 1\\ \end{pmatrix} \\ c_2= \begin{pmatrix} -1\\ 1\\ \end{pmatrix}
c1=(11)c2=(−11)
对角化:
P
C
P
T
=
(
1
2
1
2
−
1
2
1
2
)
(
6
5
4
5
4
5
6
5
)
(
1
2
−
1
2
1
2
1
2
)
=
(
2
0
0
2
5
)
PCP^\mathrm{ T }= \begin{pmatrix} \frac{1}{\sqrt2}&\frac{1}{\sqrt2}\\ \\ \frac{-1}{\sqrt2}&\frac{1}{\sqrt2}\\ \end{pmatrix} \begin{pmatrix} \frac{6}{5}&\frac{4}{5}\\ \\ \frac{4}{5}&\frac{6}{5}\\ \end{pmatrix} \begin{pmatrix} \frac{1}{\sqrt2}&\frac{-1}{\sqrt2}\\ \\ \frac{1}{\sqrt2}&\frac{1}{\sqrt2}\\ \end{pmatrix} =\begin{pmatrix} 2&0\\ \\ 0&\frac{2}{5}\\ \end{pmatrix}
PCPT=⎝⎛212−12121⎠⎞⎝⎛56545456⎠⎞⎝⎛21212−121⎠⎞=⎝⎛20052⎠⎞
降维:
Y
=
(
1
2
1
2
)
(
−
1
−
1
0
2
0
−
2
0
0
1
1
)
=
(
−
3
2
−
1
2
0
3
2
1
2
)
Y= \begin{pmatrix} \frac{1}{\sqrt2}&\frac{1}{\sqrt2} \end{pmatrix} \begin{pmatrix} -1&-1&0&2&0\\ -2&0&0&1&1\\ \end{pmatrix}= \begin{pmatrix} \frac{-3}{\sqrt2}&\frac{-1}{\sqrt2}&0&\frac{3}{\sqrt2}&\frac{1}{\sqrt2} \end{pmatrix}
Y=(2121)(−1−2−10002101)=(2−32−102321)
使用sklearn实现PCA降维
- 参数n_components:这个参数可以帮我们指定希望PCA降维后的特征维度数目。最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于等于1的整数。当然,我们也可以指定主成分的方差和所占的最小比例阈值,让PCA类自己去根据样本特征方差来决定降维到的维度数,此时n_components是一个(0,1]之间的数。当然,我们还可以将参数设置为"mle", 此时PCA类会用MLE算法根据特征的方差分布情况自己去选择一定数量的主成分特征来降维。我们也可以用默认值,即不输入n_components,此时n_components=min(样本数,特征数)。
- whiten :判断是否进行白化。所谓白化,就是对降维后的数据的每个特征进行归一化,让方差都为1.对于PCA降维本身来说,一般不需要白化。如果你PCA降维后有后续的数据处理动作,可以考虑白化。默认值是False,即不进行白化。
import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
# ==========================================================================================
X1 = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'b', 'c'],
columns=['one', 'two', 'three'])
print(X1)
print('=' * 8, 'shape:', X1.shape)
pca = PCA(n_components=1)
newData1 = pca.fit_transform(X1)
print(newData1)
print('=' * 8, '降维后shape:', newData1.shape)
pca.fit(X1)
newData12 = pca.transform(X1)
"""
newData1和newData2结果一致
"""
# ==========================================================================================
a = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
X2 = pd.DataFrame(np.array(a), index=['a', 'b', 'c'],
columns=['one', 'two', 'three'])
print(X2)
print('=' * 8, 'shape:', X2.shape)
pca_new = PCA(n_components=1)
pca_new.fit(X2)
newData12 = pca_new.transform(X2)
print(newData12)
print('=' * 8, '降维后shape:', newData12.shape)
输出结果如下:
one two three
a 0 1 2
b 3 4 5
c 6 7 8
======== shape: (3, 3)
[[ 5.19615242]
[-0. ]
[-5.19615242]]
======== 降维后shape: (3, 1)
one two three
a 0 1 2
b 3 4 5
c 6 7 8
======== shape: (3, 3)
[[ 5.19615242]
[ 0. ]
[-5.19615242]]
======== 降维后shape: (3, 1)