文章目录
一、PCA有什么用?(对PCA的综合理解)
PCA是数据降维的一种方法,其中的核心理论是矩阵的
特征值和特征向量
。
特征向量和特征值的作用可以理解为将高维数据沿一个特定的方向拓展,使得不同记录的数据在该方向上区别明显,而在其他方向上表现的相似。
在保持数据如果我们一个矩阵的特征值的大小,有时为了减少计算了,我们可以只保留特征值较大的,这样可以将庞大、冗余的数据集降维成可以理解和处理的小数据集或者数据对,便于提供直观的判断依据与结论。
既然提到了“保留特征值较大”与“直观”,那么其代价一定是“舍弃了部分特征”,这可能降低了精准度,但具体是好事还是坏事?其实都有可能,这就与具体的数据集有关了,有的数据集本来就可以只根据几个变量进行良好的区分,多的部分是冗余和噪声;单有的数据集无论怎么变换都很区分出。对此,可以通过各个特征值贡献率来看看几个特征值是否能够整体概括数据集。(对于这点的理解可以在经过实际应用后理解,例如,使用sklearn中的PCA模型,会有explained_variance_ratio_参数,查看前两到个值之和是否能达到95%或者更高就可以大致判断数据的降维保留特征度)
特征值与特征向量通常为了实现压缩算法,可以只保留特征值较大(对数据集分析贡献较大)的变换。 尤其是在面对高维情况,PCA会把多维矩阵按某种向量和的方法,沿着个方向延伸,以降低维度,有的方向可能拉伸幅度很小,而有的很大,最后保留幅度大的作为降维后的维度。
二、PCA数学原理
PCA数学原理的简单理解(适合初学者)可见以下链接:
如何通俗易懂地讲解什么是 PCA(主成分分析)?
对于多元统计有一定基础的同学可以看以下链接:
详细推导PCA算法
在PCA中还有一点需要详细解释,就是奇异值分解(SVD),可以参考以下链接:
奇异值分解(SVD)
复习一下基础的线代知识,向量与坐标轴的旋转对于进一步理解矩阵的分解、坐标变换计算都有帮助:
坐标轴旋转
将
a
′
a’
a
′
拆成
a
1
+
a
2
a_1+a_2
a
1
+
a
2
,即有:
a
′
=
a
1
+
a
2
=
a
⋅
c
o
s
θ
+
b
⋅
s
i
n
θ
a’=a_1+a_2=a·cos\theta+b·sin\theta
a
′
=
a
1
+
a
2
=
a
⋅
cos
θ
+
b
⋅
s
in
θ
同理,将
b
′
b’
b
′
看作
b
1
−
b
2
b_1-b_2
b
1
−
b
2
,有:
b
′
=
b
1
−
b
2
=
−
a
⋅
s
i
n
θ
+
b
⋅
c
o
s
θ
b’=b_1-b_2=-a·sin\theta+b·cos\theta
b
′
=
b
1
−
b
2
=
−
a
⋅
s
in
θ
+
b
⋅
cos
θ
因此,以
(
e
1
,
e
2
)
(e1,e2)
(
e
1
,
e
2
)
为基与以
(
e
1
′
,
e
2
′
)
(e1′,e2′)
(
e
1
′
,
e
2
′
)
为基的坐标轴旋转公式为:
(
e
1
′
,
e
2
′
)
=
U
(
c
o
s
θ
s
i
n
θ
−
s
i
n
θ
c
o
s
θ
)
(
e
1
,
e
2
)
(e1′,e2′) = U \left( \begin{matrix} cos\theta & sin\theta\\ -sin\theta & cos\theta \end{matrix} \right)(e1,e2)
(
e
1
′
,
e
2
′
)
=
U
(
cos
θ
−
s
in
θ
s
in
θ
cos
θ
)
(
e
1
,
e
2
)
向量旋转
事实上,对于以
(
e
1
,
e
2
)
(e1,e2)
(
e
1
,
e
2
)
为基的坐标轴上任意向量
(
x
,
y
)
(x,y)
(
x
,
y
)
按逆时针方向旋转
θ
\theta
θ
角度后到以
(
e
1
′
,
e
2
′
)
(e1′,e2′)
(
e
1
′
,
e
2
′
)
为基的坐标轴,都可以利用三角函数公式代换,得到得转化后的坐标
(
s
,
t
)
(s,t)
(
s
,
t
)
,假设
(
x
,
y
)
(x,y)
(
x
,
y
)
与原坐标轴
x
x
x
的夹角为
β
\beta
β
:
设
(
x
,
y
)
(x,y)
(
x
,
y
)
的模长为
r
r
r
,关于
(
s
,
t
)
(s,t)
(
s
,
t
)
坐标,有以下等式
s
=
r
c
o
s
(
β
+
θ
)
=
r
c
o
s
(
β
)
c
o
s
(
θ
)
−
r
s
i
n
(
β
)
s
i
n
(
θ
)
s = r cos( \beta +\theta ) = r cos(\beta)cos(\theta) – r sin(\beta)sin(\theta)
s
=
rcos
(
β
+
θ
)
=
rcos
(
β
)
cos
(
θ
)
−
rs
in
(
β
)
s
in
(
θ
)
t
=
r
s
i
n
(
β
+
θ
)
=
r
s
i
n
(
β
)
c
o
s
(
θ
)
+
r
c
o
s
(
β
)
s
i
n
(
θ
)
t = r sin( \beta +\theta) = r sin(\beta)cos(\theta) + r cos(\beta) sin(\theta)
t
=
rs
in
(
β
+
θ
)
=
rs
in
(
β
)
cos
(
θ
)
+
rcos
(
β
)
s
in
(
θ
)
其中
x
=
r
c
o
s
(
β
)
x = r cos(\beta)
x
=
rcos
(
β
)
,
y
=
r
s
i
n
(
β
)
y = r sin(\beta)
y
=
rs
in
(
β
)
,代入以上公式,有
s
=
x
c
o
s
(
b
)
−
y
s
i
n
(
b
)
s = x cos(b) – y sin(b)
s
=
x
cos
(
b
)
−
ys
in
(
b
)
t
=
x
s
i
n
(
b
)
+
y
c
o
s
(
b
)
t = x sin(b) + y cos(b)
t
=
x
s
in
(
b
)
+
ycos
(
b
)
即
(
s
,
t
)
=
U
(
c
o
s
θ
−
s
i
n
θ
s
i
n
θ
c
o
s
θ
)
(
x
,
y
)
(s,t) = U \left( \begin{matrix} cos\theta & -sin\theta\\ sin\theta & cos\theta \end{matrix} \right)(x,y)
(
s
,
t
)
=
U
(
cos
θ
s
in
θ
−
s
in
θ
cos
θ
)
(
x
,
y
)
了解了这两点后,当我们再去理解将基向量从
(
e
1
,
e
2
)
(e1,e2)
(
e
1
,
e
2
)
转化成
(
e
1
′
,
e
2
′
)
(e1′,e2′)
(
e
1
′
,
e
2
′
)
,再将后者视为标准坐标轴,即将原
O
A
OA
O
A
向量转化成
O
A
′
OA’
O
A
′
向量,就十分容易了。
三、PCA算法流程概述
-
(建议步骤)按需求将多维矩阵
XX
X
进行标准化处理(sklearn中的PCA并不会自动进行这一步) -
计算各个维度的均值,得到向量
Xˉ
\bar{X}
X
ˉ
,将原,将原矩阵
XX
X
中的值减去对应向量的均值,得到
X′
=
X
−
X
ˉ
X’=X-\bar{X}
X
′
=
X
−
X
ˉ
-
计算
X′
X’
X
′
的协方差矩阵(或者相关系数矩阵,按需),记为
Co
v
(
X
′
)
Cov(X’)
C
o
v
(
X
′
)
(相关系数矩阵为
Co
r
r
(
X
′
)
Corr(X’)
C
orr
(
X
′
)
,下面只用
Co
v
(
X
′
)
Cov(X’)
C
o
v
(
X
′
)
举例) -
用SVD计算
Co
v
(
X
′
)
Cov(X’)
C
o
v
(
X
′
)
的非特征值和对应的特征向量 -
将特征值按照从大到小的排序,选择其中最大的
kk
k
个,然后将其对应的
kk
k
个特征向量分别作为列向量组成特征向量矩阵
WW
W
-
计算
X′
⋅
W
X’·W
X
′
⋅
W
即为多维向量在几个主要方向上的投影
四、PCA算法的python实现
1、numpy按步骤实现
import numpy as np
X_new=X_scaled-[np.mean(col) for col in X_scaled.T]
#X_new=X_scaled
#eigenvalue, featurevector = np.linalg.eig(np.cov(X_new.T)) #取特征值
u, s, vh = np.linalg.svd(np.cov(X_new.T)) #用svd分解
#第一次写的版本是eig后的eigenvalue, featurevector需要排序,用svd后无需排序,可以适当删减
#sorted_eigenvalue = -np.sort(s*(-1))
#order_index=np.argsort(-s)
k=3
result1=[]
for i in range(k):
print(s[i],u.T[i]) #查看前K个向量对应的特征值
result1.append(np.dot(X_new,u.T[i]))
result2=[]
for record_index in range(len(X_new)):
record=[]
for component_index in range(k):
record.append(result1[component_index][record_index])
result2.append(record)
result2[:5]
2、sklearn实现(方便应用)
from sklearn.decomposition import PCA
pca = PCA(n_components=3)
pca.fit(X_scaled)
print(pca.n_features_)
print(pca.n_samples_)
print(pca.explained_variance_ratio_)
#print(pca.explained_variance_)
#print(pca.components_)
result=pca.transform(X_scaled)
五、绘图
选取第一和第二主成分进行可交互式绘图
#绘图
fig, ax = plt.subplots(dpi=80,figsize=(9,6))
def call_back(event):
#text1 = ax.text(event.xdata, event.ydata, 'event', ha='center', va='center', fontdict={'size': 10})
text2 = ax.text(event.xdata, event.ydata, 'event', ha='center', va='center', fontdict={'size': 10})
xd=[[data_continuous.iloc[index].name,customer_dict[data_continuous.iloc[index].name],y[index]]\
for index,xdata in enumerate(result[:,0]) \
if abs(xdata-event.xdata)<0.01 and abs(result[:,1][index]-event.ydata)<0.01]
#info1 = 'xdata,ydata:{:.2f},{:.2f}'.format(event.xdata, event.ydata)
info2 = '{}'.format(xd)
#text1.set_text(info1)
if xd!=[]:
text2.set_text(info2)
else:
text2.set_text('')
fig.canvas.draw_idle()
fig.canvas.mpl_connect('button_press_event', call_back)
pca_x1=result[:,0]
pca_x2=result[:,1]
plt.scatter(pca_x1,pca_x2,c=y)
plt.show()
点击图上的点即可展示对应的数据