前段时间根据项目需要,了解了PCA的降维方法,现将自己的心得与代码记录下来。
本文主要从python代码的实现入手,对理论知识剖析较少。
PCA,即为主成分分析法,旨在通过纯数理的方式将多个特征维度降到期望的维度,将原来含有物理意义的特征量重构为没有物理意义的特征量。PCA的核心思想就是将众多维度沿着某一维度进行映射,根据其余维度在此维度上的贡献度进行排序,筛选,最后实现降维的功能。另外需要注意的是,PCA属于无监督学习,即样本标签值在训练过程中不起任何作用。
PCA的核心步骤主要分为:
1.求样本均值和样本协方差矩阵。
2.计算协方差矩阵的特征值和特征向量,并将特征值排序。
3.保留前N个最大特征值对应的特征向量。
4.重构原始特征,写出主成分表达式。
好了,在对PCA有了大致的了解之后,我们切入正题,讨论如何利用python代码实现PCA!
首先,我们导入需要的库。其中,joblib用来存储和读取PCA训练完的模型。

import numpy as np
from sklearn.decomposition import PCA
import joblib

接着,我们生成一个用于训练的样本集。

data=[[1,2,2,1,3],
     [3,4,1,1,2],
     [1,5,4,3,2],
     [5,2,4,5,3],
     [2,3,3,4,3],
     [1,5,4,3,2],
     [5,2,4,5,3],
     [2,3,3,4,3]]
data = np.array(data)

样本集大小为8*5,即8个样本,每个样本具有五个特征。
接着,我们实例化一个PCA模型,实例化模型时可根据需要选择需要保留的维度。然后根据样本集训练PCA模型。

pca=PCA(4)
res=pca.fit_transform(data)

将结果打印:

[[-2.13304052  1.87768626 -1.39131618 -0.51953994]
 [-1.9487569   2.03690624  1.66303823  0.26251356]
 [-1.60137005 -1.94830402  0.34020724 -0.23502009]
 [ 3.40364775  0.27472059  0.25116985 -0.24057084]
 [ 0.23862101 -0.28371281 -0.72723811  0.60410411]
 [-1.60137005 -1.94830402  0.34020724 -0.23502009]
 [ 3.40364775  0.27472059  0.25116985 -0.24057084]
 [ 0.23862101 -0.28371281 -0.72723811  0.60410411]]

可以看到现在已将原来的五个维度降到四个维度了。
我们保存下来训练好的模型。

pca_model=joblib.dump(pca,"PCA_model.m")

我们载入保存好的模型,进行下一步测试。

pca_model=joblib.load("PCA_model.m")

利用库提供的函数接口读取原始特征每个维度的权重系数。

U = pca_model.components_
print(U)
[[ 0.64768873 -0.35442225  0.26210994  0.60542837  0.14013941]
 [ 0.36615776 -0.52530671 -0.59689483 -0.46845176  0.11937696]
 [ 0.63446896  0.63968154 -0.12293985 -0.16237753 -0.38311355]
 [-0.14775347  0.2495218  -0.73877695  0.58688423  0.1602601 ]]

尝试利用系数复原降维后的特征。

res_cal=np.matrix(data)*np.matrix(U).I
print(res_cal)
[[ 1.4889107  -1.98856622  0.35623416 -0.05859923]
 [ 1.67319431 -1.82934623  3.41058856  0.72345428]
 [ 2.02058117 -5.81455649  2.08775758  0.22592062]
 [ 7.02559896 -3.59153188  1.99872019  0.22036988]
 [ 3.86057223 -4.14996529  1.02031223  1.06504482]
 [ 2.02058117 -5.81455649  2.08775758  0.22592062]
 [ 7.02559896 -3.59153188  1.99872019  0.22036988]
 [ 3.86057223 -4.14996529  1.02031223  1.06504482]]

可以看出结果并不符合(这里存在疑问,是否是函数接口提供的并不是权重系数,但看其他博客说是权重系数)。
自己计算权重系数:

XS=np.matrix(res).T*(np.matrix(data).I).T
print(XS)
[[ 0.49677409 -0.71661737  0.14137823  0.81670886 -0.7653484 ]
 [ 0.52725162 -0.13868146 -0.46801975 -0.69398316  1.08594007]
 [ 0.56165436  0.46492651 -0.18119153 -0.06043709 -0.82000114]
 [-0.16695934  0.20342773 -0.75414164  0.61377243  0.04502493]]

验证结果:

print(np.dot(np.matrix(data),XS.T))
[[-2.13304052  1.87768626 -1.39131618 -0.51953994]
 [-1.9487569   2.03690624  1.66303823  0.26251356]
 [-1.60137005 -1.94830402  0.34020724 -0.23502009]
 [ 3.40364775  0.27472059  0.25116985 -0.24057084]
 [ 0.23862101 -0.28371281 -0.72723811  0.60410411]
 [-1.60137005 -1.94830402  0.34020724 -0.23502009]
 [ 3.40364775  0.27472059  0.25116985 -0.24057084]
 [ 0.23862101 -0.28371281 -0.72723811  0.60410411]]

可以看出结果与降维后的特征一致。

附:PCA模型的其他属性

pca_model.explained_variance_         #所有的特征值
pca.model.explained_variance_ratio_   #每一个特征向量对应的特征值占总的特征值之和的比值
pca.singular_values_                  #奇异值
pca_model.mean_                       #通过训练数据估计的每个特征上的均值