Sklearn中的降维算法
PCA和SVD
class sklearn.decomposition.PCA (n_components=None, copy=True, whiten=False, svd_solver=’auto’, tol=0.0,
iterated_power=’auto’, random_state=None)
二维数据的降维
重要参数:n_components
案例:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
#导入digits手写数据集
digits = datasets.load_digits()
X = digits.data
y = digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,random_state=666)
knn = KNeighborsClassifier()
knn.fit(X_train,y_train)
#原始数据集共有64维
array([[ 0., 0., 6., ..., 4., 0., 0.],
[ 0., 1., 3., ..., 14., 0., 0.],
[ 0., 0., 5., ..., 14., 3., 0.],
...,
[ 0., 3., 15., ..., 12., 3., 0.],
[ 0., 0., 1., ..., 7., 0., 0.],
[ 0., 0., 9., ..., 0., 0., 0.]])
knn.score(X_test,y_test)
#0.9888888888888889
#使用PCA降维,设置降为2维
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train) # 训练数据集降维结果
X_test_reduction = pca.transform(X_test) # 测试数据集降维结果
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction, y_train)
knn_clf.score(X_test_reduction, y_test)
#0.6055555555555555
PCA算法提供了一个特殊的指标pca.explained_variance_ratio_(解释方差比例),我们可以使用这个指标找到某个数据集保持多少的精度:
pca.explained_variance_ratio_
# 输出:
#array([ 0.14566817, 0.13735469])
对于现在的PCA算法来说,得到的是二维数据:0.14566817表示第一个轴能够解释14.56%数据的方差;0.13735469表示第二个轴能够解释13.73%数据的方差。PCA过程寻找主成分,就是找使得原数据的方差维持的最大。这个值就告诉我们,PCA最大维持了原来所有方差的百分比。对于这两个维度来说,[ 0.14566817, 0.13735469]涵盖了原数据的总方差的28%左右的信息,剩下72%的方差信息就丢失了,显然丢失的信息过多.
# 横轴是是样本X的i个特征数,纵轴是前i个轴解释方差比例的和
plt.plot([i for i in range(X_train.shape[1])],
[np.sum(pca.explained_variance_ratio_[:i+1]) for i in range(X_train.shape[1])])
plt.show()
如果我们希望保持95%以上的信息,就能得到相应的降维后的主成分个数。在sklearn中,实例化时传入一个数字,就表示保持的方差比例:
pca = PCA(0.95,svd_solver="full")
pca.fit(X_train)
# 输出:
#PCA(copy=True, iterated_power='auto', n_components=0.95, random_state=None,
# svd_solver='auto', tol=0.0, whiten=False)
#查看一下降维后主成分的个数为28,即对于64维数据来说,28维数据就可以解释95%以上的方差。
pca.n_components_
#28
数据降维还有一个作用是可视化,降到2维数据之后:
pca = PCA(n_components=2)
pca.fit(X)
X_reduction = pca.transform(X)
for i in range(10):
plt.scatter(X_reduction[y==i,0], X_reduction[y==i,1], alpha=0.8)
plt.show()
PCA中的SVD
SVD有一种惊人的数学性质,即是它可以跳过数学神秘的宇宙,不计算协方差矩阵,直接找出一个新特征向 量组成的n维空间,而这个n维空间就是奇异值分解后的右矩阵
(所以一开始在讲解降维过程时,我们说”生成新 特征向量组成的空间V",并非巧合,而是特指奇异值分解中的矩阵
重要参数:svd_solver 与 random_state
重要属性:components_
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np
faces = fetch_lfw_people(min_faces_per_person=60)#实例化 min_faces_per_person=60:每个人取出60张脸图
faces.images.shape#(1277,62,47) 1277是矩阵中图像的个数,62是每个图像的特征矩阵的行,47是每个图像的特征矩阵的列
#怎样理解这个数据的维度?
faces.data.shape#(1277,2914) 行是样本,列是样本相关的所有特征:2914 = 62 * 47
#换成特征矩阵之后,这个矩阵是什么样?
X = faces.data
#创建画布和子图对象
fig, axes = plt.subplots(4,5#4行5列个图
,figsize=(8,4)#figsize指的是图的尺寸
,subplot_kw = {"xticks":[],"yticks":[]} #不要显示坐标轴
)
#不难发现,axes中的一个对象对应fig中的一个空格
#我们希望,在每一个子图对象中填充图像(共24张图),因此我们需要写一个在子图对象中遍历的循环
axes.shape#(4,5)
#二维结构,可以有两种循环方式,一种是使用索引,循环一次同时生成一列上的四个图
#另一种是把数据拉成一维,循环一次只生成一个图
#在这里,究竟使用哪一种循环方式,是要看我们要画的图的信息,储存在一个怎样的结构里
#我们使用 子图对象.imshow 来将图像填充到空白画布上
#而imshow要求的数据格式必须是一个(m,n)格式的矩阵,即每个数据都是一张单独的图
#因此我们需要遍历的是faces.images,其结构是(1277, 62, 47)
#要从一个数据集中取出24个图,明显是一次性的循环切片[i,:,:]来得便利
#因此我们要把axes的结构拉成一维来循环
# [*axes.flat]#2维
axes.flat#降低一个维度
# [*axes.flat] #1维
#填充图像
for i, ax in enumerate(axes.flat):
ax.imshow(faces.images[i,:,:]
,cmap="gray" #选择色彩的模式
)
fig
# cmap参数取值选择各种颜色:https://matplotlib.org/tutorials/colors/colormaps.html
#原本有2900维,我们现在来降到150维
pca = PCA(150).fit(X)#这里X = faces.data,不是faces.images.shape ,因为sklearn只接受2维数组降,不接受高维数组降
# x_dr = pca.transform(X)
# x_dr.shape#(1277,150)
V = pca.components_#新特征空间
V.shape#V(k,n) (150, 2914)
fig, axes = plt.subplots(3,8,figsize=(8,4),subplot_kw = {"xticks":[],"yticks":[]})
#取出每一个图片的特征矩阵并重新塑造其维度
for i, ax in enumerate(axes.flat):
ax.imshow(V[i,:].reshape(62,47),cmap="gray")