1、PCA算法:
PCA过程的实现:(1)numpy可以模拟 (2)sklearn可以实现
1.1、使用numpy模拟PCA过程
import numpy as np
A=np.array([[3,2000],
[2,3000],
[4,5000],
[5,8000],
[1,2000]],dtype='float')
#使用numpy模拟PCA过程
#数据降维
#1、数据归一化
mean=np.mean(A,axis=0)#axis=0所有行
norm=A-mean
#2、数据缩放 因为两个特征不是一个数量级
scope=np.max(norm,axis=0)-np.min(norm,axis=0)
norm=norm/scope
#3、对协方差矩阵进行奇异值分解,求解其特征向量
U,S,V=np.linalg.svd(np.dot(norm.T,norm))
#4、因为需要将二维数据降为一维,因此取特征矩阵的第一列来构造主成分矩阵
U_reduce=U[:,:1]#等价于U[:,0].reshape(2,1)#提取1列,却返回了1行,所以需要再转换成1列
#5、开始降维
R=np.dot(norm,U_reduce)#要将训练集投影到超平面上,简单地计算训练集矩阵norm和矩阵U_reduce的点积即可
#降维数据还原
#1、升维
Z=np.dot(R,U_reduce.T)
#2、数据缩放和归一化还原
A_restore=np.multiply(Z,scope)+mean#np.multiply是矩阵的点乘运算
与原始矩阵A相比,恢复后的A_restore存在失真,但这是不可避免的
输出R:
1.2、使用sklearn进行PCA过程
#使用sklearn进行PCA过程
from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import MinMaxScaler
#约定俗成:
#*args:可以理解为长度不固定的列表。
#**kwarg:可以理解为长度不固定的字典
#**argv:获取参数
def std_PCA(**argv):
scaler=MinMaxScaler()
pca=PCA(**argv)
pipeline=Pipeline([('scaler',scaler),('pca',pca)])
return pipeline
pca=std_PCA(n_components=1)
R2=pca.fit_transform(A)
输出R2:
sklearn降维输出的数值和numpy降维输出的数值符号相反,这不是错误,是降维选择的坐标方向不同而已。
降维数据还原如下:
R2_restore=pca.inverse_transform(R2)#先进行PCA还原,再进行预处理的逆运算
还原的数据:
原来的数据A:
2、PCA的物理含义
方形点:原始数据经过预处理后(归一化、缩放)的数据。
圆形点:一维恢复到二维后的数据。
u(1)、u(2):主成分特征向量。
结论:
(1)圆形点实际上就是方形点在向量 U(1)所在的直线上的投射点,降维就是方形点在主成分特征向量U(1)上的投影。
(2)PCA数据恢复,不是真正的恢复,只是把降维后的坐标转换为原坐标系中的坐标而已。
(3)主成分特征的向量U(1)、U(2)是相互垂直的
(4)方形点和圆形点之间的距离是PCA数据降维后的误差
3、PCA属性
3.1 特征方差贡献率和特征方差
#pca的方法explained_variance_ratio_计算了每个特征方差贡献率,所有总和为1,
#explained_variance_为方差值,通过合理使用这两个参数可以画出方差贡献率图
#或者方差值图,便于观察PCA降维最佳值。
pca1=PCA(n_components=1)
pca1.fit_transform(A)
print("方差值:{0}".format(pca1.explained_variance_))
print("方差解释率:{0}".format(pca1.explained_variance_ratio_))
print("主成分向量数:{0}".format(pca1.n_components_))
表示第一条轴贡献了99.99999991%,剩下的第二条轴还不到0.00000001%,有理由认为它没什么信息
3.2 如何确定正确数量的维度
方法一、将靠前的主成分方差解释率依次相加,直到得到足够大比例的方差(例如 95%),这时的维度数量就是很好的选择。
pca=PCA()
pca.fit(X)
cumsum=np.cumsum(pca.explained_variance_ratio_)
d=np.argmax(cumsum>=0.95)+1
pca_final=PCA(n_components=d)
pca_final.fit(X)
方法二、n_components设置为0.0到1.0之间的浮点数,表示希望保留的方差比
pca=PCA(n_components=0.95)
X_reduced=pca.fit_transform(X)
方法三、解释方差可视化
3.3 增量PCA(IPCA)
from sklearn.datasets import fetch_openml
mnist=fetch_openml("mnist_784",data_home="C:/Users/EDZ/PycharmProjects/datasets/")
X_mnist=mnist.data
方法一、使用NumPy的array_split()函数拆分数据
import numpy as np
from sklearn.decomposition import IncrementalPCA
n_batches=100
inc_pca=IncrementalPCA(n_components=154)
for x_batches in np.array_split(X_mnist,n_batches):
inc_pca.partial_fit(x_batches)
X_mnist_reduced=inc_pca.transform(X_mnist)
方法二、使用NumPy的memmap类
这个类允许你巧妙地操控一个存储在磁盘二进制文件里的大型数组,就好似它也完全在内存里 一样,而这个类(memmap)仅在需要时加载内存中需要的数据。由于IncrementalPCA在任何时间都只使用数组的一小部分,因此内存的使用情况仍然受控。
x_mm=np.memmap(filename,dtype='float32',mode='readonly',shape=(m,n))
n_batches=100
batch_size=x_mm/n_batches
inc_pca=IncrementalPCA(n_components=154,batch_size=batch_size)
inc_pca.fit()
3.4 随机PCA
可以快速找到前d个主成分的近似值。计算复杂度是是O(m×d2)+O(d3)
rnd_pca=PCA(n_components=164,svd_solver='randomized')
X_reduced=rnd_pca.fit_transform(X)
3.5 核PCA
核技巧:将低维数据映射到高维的空间
from sklearn.decomposition import KernelPCA
rbf_PCA=KernelPCA(n_components=2,kernel="rbf",gamma=0.04)
X_reduced=rbf_PCA.fit_transform(X)
3.5.1 选择核函数核调整超参数
方法一、用GridSearchCV搜索最优参数
kPCA是一种无监督的学习算法,因此没有明显的性能指标来帮助选择最佳的核函数和超参数值。
降维是监督式学习任务的准备步骤,所以可以结合起来用网格搜索来选择最佳的核函数和超参数值。
from sklearn.decomposition import KernelPCA
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LogisticRegression
clf=Pipeline([('kcpa',KernelPCA(n_components=2)),
('log_reg',LogisticRegression)])
param_grid=[{
'kcpa__gamma':np.linspace(0.03,0.05,10),
'kcpa__kernel':['rbf','Sigmoid']
}]
grid_search=GridSearchCV(clf,param_grid=param_grid)
grid_search.fit(x,y)
#获得最优参数
grid_search.best_params_
方法二、找到使重建原像和原始图像误差最小的核和超参数
from sklearn.decomposition import KernelPCA
rbf_cpa=KernelPCA(n_components=2,kernel='rbf',gamma=0.0433,fit_inverse_transform=True)
X_reduced=rbf_cpa.fit_transform(X)
X_preimage=rbf_cpa.inverse_transform(X_reduced)
#默认情况下为fit_inverse_transform=False,并且KernelPCA没有inverse_transform()方法。只有在设置fit_inverse_transform=True
#时才会创建该方法。
#计算原像与重建原像的误差
from sklearn.metrics import mean_squared_error
mean_squared_error(X,X_preimage)
然后用网格搜索寻找最小误差的参数
5.6 局部线性嵌入LLE——流形学习技术
局部线性嵌入(LLE)是另一种非常强大的非线性降维(NLDR)技术
LLE首先测量每个算法如何与其最近的邻居线性相关,然后为训练集寻找一个能最大程度保留这些局部关系的低维表示。这使得它特别擅长展开弯曲的流形,特别是没有太多噪声时。
LLE算法主要分为三步:
第一步是求K近邻的过程,这个过程使用了和KNN算法一样的求最近邻的方法。
第二步,就是对每个样本求它在邻域里的K个近邻的线性关系,得到线性关系权重系数W。
第三步就是利用权重系数来在低维里重构样本数据
from sklearn.manifold import LocallyLinearEmbedding
lle=LocallyLinearEmbedding(n_components=2,n_neighbors=10)
X_reduced = lle.fit_transform(X)