机器学习系列笔记六:主成分分析PCA[下]

文章目录

  • 机器学习系列笔记六:主成分分析PCA[下]
    • scikit-learn中的PCA
      • 基本使用
      • 进阶操作
        • 对比实验
        • 设置合理的n_components
        • 通过PCA完成对数据的可视化
        • 测试MNIST数据集
      • 使用PCA对数据进行降噪处理
        • 实验引入
        • 使用案例
      • PCA生成特征脸
    • 总结
    • 参考

在上一节,我们自定义实现了PCA主成分分析法,并通过多个测试验证了算法的有效性,当然与scikit-learn或其他机器学习框架封装的PCA算法相比差的很远,但也足以让我们理解PCA的原理。

在这一节,我们就利用scikit-learn框架中所提供的PCA来进行一系列的练习。学习利用框架所提供的工具来是实现主成分分析,并能用于实际的需求。

scikit-learn中的PCA

基本使用

准备数据

import numpy as np
import matplotlib.pyplot as pltX = np.empty((100,2))
X[:,0] = np.random.uniform(0,100,size=100)
X[:,1] = 0.75 * X[:,0] + 3 + np.random.normal(0,10,size=100)

首先需要从sklearn.decomposition包中导入PCA工具类

from sklearn.decomposition import PCA

其实上一节中PCA的实现是参照着scikit-learn来的,所以使用起来和之前的代码差别不大

pca = PCA(n_components=1)
pca.fit(X)
PCA(copy=True, iterated_power='auto', n_components=1, random_state=None,svd_solver='auto', tol=0.0, whiten=False)
pca.components_ #求解的n_components个主成分
array([[-0.78373823, -0.62109128]])

transform:根据求解的主成分对数据进行降维

X_reduction = pca.transform(X)
X_reduction.shape
(100, 1)

inverse_transform:根据求解的主成分将降维后的数据恢复为高维状态

X_restore = pca.inverse_transform(X_reduction)
X_restore.shape
(100, 2)

对比恢复后的数据与原始数据

plt.scatter(X[:,0],X[:,1],color="b",alpha=0.5)
plt.scatter(X_restore[:,0],X_restore[:,1],color="r",alpha=0.5)
plt.show()

进阶操作

对比实验

导入真实数据集

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets# 导入手写数据集
digits = datasets.load_digits()
X = digits.data
y = digits.target

分割数据集为测试/训练组

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=666)
X_train.shape
(1347, 64)
  • 对原始数据进行训练(KNN算法),看看识别率为多少
%%time
from sklearn.neighbors import KNeighborsClassifierknn_clf = KNeighborsClassifier()
knn_clf.fit(X_train,y_train)
Wall time: 32.7 msKNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=None, n_neighbors=5, p=2,weights='uniform')
knn_clf.score(X_test,y_test)
0.9866666666666667

可以看到对原始数据不作PCA处理,所耗费的训练时间为17.9 ms,模型识别精度为0.9866666666666667

  • 对原始数据进行PCA降维处理,看看识别率为多少

通过PCA.transform()将原始数据降维到2维

from sklearn.decomposition import PCApca = PCA(n_components=2)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)

使用同样的KNN算法训练处理后的数据

%%time
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction,y_train)
Wall time: 1.49 msKNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=None, n_neighbors=5, p=2,weights='uniform')
knn_clf.score(X_test_reduction,y_test)
0.6066666666666667

可以看到对于通过PCA处理后的数据,KNN模型训练所耗费的训练时间为1.49 ms,将近比利用原始数据训练快了15倍!!!

然而模型识别精度为0.6066666666666667,效果显然不如使用原始数据好,因为在降维过程中丢失了大量的细节特征。

设置合理的n_components

  • 通过PCA.explained_variance_ratio_可以查看计算出的主成分轴分别解释原数据的百分比(保留的信息量)
pca.explained_variance_ratio_
array([0.14566817, 0.13735469])
pca = PCA(n_components=X_train.shape[1])
pca.fit(X_train)
pca.explained_variance_ratio_
array([1.45668166e-01, 1.37354688e-01, 1.17777287e-01, 8.49968861e-02,5.86018996e-02, 5.11542945e-02, 4.26605279e-02, 3.60119663e-02,3.41105814e-02, 3.05407804e-02, 2.42337671e-02, 2.28700570e-02,1.80304649e-02, 1.79346003e-02, 1.45798298e-02, 1.42044841e-02,1.29961033e-02, 1.26617002e-02, 1.01728635e-02, 9.09314698e-03,8.85220461e-03, 7.73828332e-03, 7.60516219e-03, 7.11864860e-03,6.85977267e-03, 5.76411920e-03, 5.71688020e-03, 5.08255707e-03,4.89020776e-03, 4.34888085e-03, 3.72917505e-03, 3.57755036e-03,3.26989470e-03, 3.14917937e-03, 3.09269839e-03, 2.87619649e-03,2.50362666e-03, 2.25417403e-03, 2.20030857e-03, 1.98028746e-03,1.88195578e-03, 1.52769283e-03, 1.42823692e-03, 1.38003340e-03,1.17572392e-03, 1.07377463e-03, 9.55152460e-04, 9.00017642e-04,5.79162563e-04, 3.82793717e-04, 2.38328586e-04, 8.40132221e-05,5.60545588e-05, 5.48538930e-05, 1.08077650e-05, 4.01354717e-06,1.23186515e-06, 1.05783059e-06, 6.06659094e-07, 5.86686040e-07,1.71368535e-33, 7.44075955e-34, 7.44075955e-34, 7.15189459e-34])

通过可视化展示主成分轴个数的选择对原始数据信息保留度的影响

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.ylabel('Original data information retention')
plt.xlabel('the number of principle components be choosen')
plt.show()

如果我们不知道要将数据降到多少维,但是又需要降维后模型预测率至少要95%,可以通过在PCA构造方法中传入n_components=0.95来解决

pca = PCA(0.95)
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)
pca.n_components_
28

这个结果说明对于原来的64维数据来说

我们只需使用28维的数据就能解释原本数据95%以上的方差(信息)

# 对原始数据降维64-->28
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)
X_train_reduction.shape
(1347, 28)
%%time
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction,y_train)
Wall time: 6.94 msKNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=None, n_neighbors=5, p=2,weights='uniform')
knn_clf.score(X_test_reduction,y_test)
0.98

可以看到,与使用包含全部信息的64维度特征相比,使用降维后的数据进行训练的时间是6.94 ms,提高了一倍多的训练速度

而模型精度却只损失了0.9866666666666667-0.98 = 0.006666667

可以看出PCA的强大性,它给了我们一个通过少量模型精度的牺牲来减少大量模型训练时长

通过PCA完成对数据的可视化

pca = PCA(n_components=2)
pca.fit(X)
X_reduction = pca.transform(X)
X_reduction.shape
(1797, 2)

将原数据降维至2维后,我们就可以很方便地对其进行绘制了

legend = []
for i in range(10):plt.scatter(X_reduction[y==i,0],X_reduction[y==i,1],alpha=0.8)legend.append(i)
plt.legend(legend)
plt.show()

可以看到在二维空间中,数字之间的区分度还是比较明显的

测试MNIST数据集

首先导入fetch_mldata

import numpy as np
from sklearn.datasets import fetch_mldata

通过fetch_mldata方法下载所需的数据集

这里我发现无法下载成功,决定才用手动下载数据集并放在sciki_learn的对应目录中C:\Users\ASUS\scikit_learn_data

链接:https://pan.baidu.com/s/13GA3FWzVi5mgoU0fqkmbNg
提取码:13h8

# mnist = fetch_mldata("MNIST original")
from sklearn.datasets.base import get_data_home
print(get_data_home())
C:\Users\ASUS\scikit_learn_data
mnist = fetch_mldata("MNIST original")
mnist
{'DESCR': 'mldata.org dataset: mnist-original','COL_NAMES': ['label', 'data'],'target': array([0., 0., 0., ..., 9., 9., 9.]),'data': array([[0, 0, 0, ..., 0, 0, 0],[0, 0, 0, ..., 0, 0, 0],[0, 0, 0, ..., 0, 0, 0],...,[0, 0, 0, ..., 0, 0, 0],[0, 0, 0, ..., 0, 0, 0],[0, 0, 0, ..., 0, 0, 0]], dtype=uint8)}
X,y = mnist['data'],mnist['target']
X.shape
(70000, 784)

MNIST数据集是帮我们把训练集和测试集分离好了的,所以可以直接调用

X_train = np.array(X[:60000],dtype=float)
y_train = np.array(y[:60000],dtype=float)
X_test = np.array(X[60000:],dtype=float)
y_test = np.array(y[60000:],dtype=float)
X_train.shape
(60000, 784)
y_train.shape
(60000,)
X_test.shape
(10000, 784)
y_test.shape
(10000,)

使用KNN来对MNIST原始数据集进行识别

from sklearn.neighbors import KNeighborsClassifierknn_clf = KNeighborsClassifier(n_jobs=-1)
%time knn_clf.fit(X_train,y_train)
Wall time: 15.6 sKNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=-1, n_neighbors=5, p=2,weights='uniform')
%time knn_clf.score(X_test,y_test)
Wall time: 2min 23s0.9688

可以看到,在数据量比较大的时候,模型的预测花费了大量的时间,训练时间相对来说比较少是因为其内部做了大量的优化,比如对红黑树的转化等操作

使用PCA进行降维

from sklearn.decomposition import PCA
pca = PCA(0.9)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)
X_train_reduction.shape
(60000, 87)

可以看到,在保证样本信息保真度在0.9以上的前提下,通过PCA可以把样本的维度从784下降到87

knn_clf2 = KNeighborsClassifier(n_jobs=-1)
%time knn_clf2.fit(X_train_reduction,y_train)
Wall time: 365 msKNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=-1, n_neighbors=5, p=2,weights='uniform')
X_test_reduction = pca.transform(X_test)
%time knn_clf2.score(X_test_reduction,y_test)
Wall time: 17.3 s0.9728

使用PCA对数据进行降噪处理

实验引入

在前面的例子中,对自定义的数据进行了PCA处理

import numpy as np
import matplotlib.pyplot as plt
X = np.empty((100, 2))
X[:,0] = np.random.uniform(0., 100., size=100)
X[:,1] = 0.75 * X[:,0] + 3. + np.random.normal(0, 5, size=100)

在这里定义的y=X[:,1],其中np.random.normal(0, 5, size=100)是我们人为添加的噪声

我们不妨先看看如果没有噪声项的可视化结果

X2 = np.empty((100, 2))
X2[:,0] = np.random.uniform(0., 100., size=100)
X2[:,1] = 0.75 * X2[:,0] + 3. # 没有噪声
plt.scatter(X2[:,0],X2[:,1])
plt.title("no noise")
plt.show()

然后我们再看看加入了噪声后的可视化结果

plt.scatter(X[:,0],X[:,1])
plt.title("with noise")
plt.show()

最后,我们将X(带噪声数据)进行PCA处理(进行两次变换),然后与X2(无噪声数据)进行对比

from sklearn.decomposition import PCA
pca = PCA(n_components=1)
pca.fit(X)
X_reduction = pca.transform(X) # 正变换
X_restore = pca.inverse_transform(X_reduction) # 逆变换
plt.scatter(X_restore[:,0],X_restore[:,1],color='r',alpha=0.8)
plt.scatter(X2[:,0],X2[:,1],color='b',alpha=0.5)
plt.scatter(X[:,0],X[:,1],color='r',alpha = 0.2)plt.legend(['data after PCA preocess ','data no noise','data with noise'])plt.show()

可以看到通过PCA降维处理,然后再恢复可以将大量的噪声(不重要的特征)去除。

所以有时候通过PCA降维后处理的数据来训练模型,预测结果:

  • 不仅时间上更快
  • 而且预测精度更高

使用案例

我们可以通过对手写数字进行PCA降噪处理来理解PCA降噪的强大

首先导入手写数据集

from sklearn import datasetsdigits = datasets.load_digits()
X = digits.data
y = digits.target

为原始数据加入噪声

noisy_digits = X + np.random.normal(0,4,size=X.shape)

取出表示0~9的数据作为本次案例的样例

example_digits = noisy_digits[y==0,:][:10]
for num in range(1,10):example_digits = np.vstack([example_digits, noisy_digits[y==num,:][:10]])
example_digits.shape
(100, 64)

可视化加入噪声后的手写数字

def plot_digits(data):fig, axes = plt.subplots(10, 10, figsize=(10, 10),subplot_kw={'xticks':[], 'yticks':[]},gridspec_kw=dict(hspace=0.1, wspace=0.1)) for i, ax in enumerate(axes.flat):ax.imshow(data[i].reshape(8, 8),cmap='binary', interpolation='nearest',clim=(0, 16))plt.show()plot_digits(example_digits)

使用PCA对加入噪声后的数据example_digits进行降维去噪

pca = PCA(0.5).fit(noisy_digits)
pca.n_components_
12
components = pca.transform(example_digits)
filtered_digit = pca.inverse_transform(components)
plot_digits(filtered_digit)

可以看到,本次可视化的结果相比较上面的结果是要清晰很多的。

PCA生成特征脸

在上一节介绍PCA的时候,提到了PCA在图像处理方面有很大的应用面,其中比较典型的一个应用就是人脸识别,由于图片的维度非常大,一般都是上千个维度,所以在进行人脸识别模型训练之前一定要使用PCA进行降维处理,否则会造成人脸识别的低效。

在这里就代码的形式给出PCA生成特征脸的步骤。

首先需要导入人脸数据集

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_lfw_people
faces = fetch_lfw_people()

观察数据集

faces.keys()
dict_keys(['data', 'images', 'target', 'target_names', 'DESCR'])
faces.target_names
array(['AJ Cook', 'AJ Lamas', 'Aaron Eckhart', ..., 'Zumrati Juma','Zurab Tsereteli', 'Zydrunas Ilgauskas'], dtype='<U35')
faces.images.shape
(13233, 62, 47)
faces.data.shape
(13233, 2914)

随机生成样本

random_indexes = np.random.permutation(len(faces.data))
X = faces.data[random_indexes]
example_faces = X[:36,:]
example_faces.shape
(36, 2914)

可以看到我们只是随机去了36个样本,每个样本有2914个特征,这如果不进行降维处理,计算机要骂娘了

样本可视化

def plot_faces(faces):fig, axes = plt.subplots(6, 6, figsize=(10, 10),subplot_kw={'xticks': [], 'yticks': []},gridspec_kw=dict(hspace=0.1, wspace=0.1))for i, ax in enumerate(axes.flat):ax.imshow(faces[i].reshape(62, 47), cmap='bone')plt.show()plot_faces(example_faces)


PCA处理,特征降维

生成所有主成分

%%time
from sklearn.decomposition import PCA
pca = PCA(svd_solver="randomized") # 没有指定n_components,默认生成n(样本特征数)个z=主成分
pca.fit(X)
Wall time: 19.6 sPCA(copy=True, iterated_power='auto', n_components=None, random_state=None,svd_solver='randomized', tol=0.0, whiten=False)
pca.components_.shape
(2914, 2914)

取出前36个主成分(等同于取出前36张脸)

feature_face1 =pca.components_[:36,:]
plot_faces(feature_face1)

在该数据集中,有一些人的图片样本比较多而有一些人的图片样本比较少,为了获取拥有较多样本的人所对应的这些图片

我们可以在调用fetch_lfw_people()的时候向里面传一个参数:

  • min_faces_per_person=photo_num
faces2 = fetch_lfw_people(min_faces_per_person=60) # 要求获取的数据中每个人至少拥有60张图片
faces2.data.shape
(1348, 2914)

可以看到只有1348张图片样本了

faces2.target_names
array(['Ariel Sharon', 'Colin Powell', 'Donald Rumsfeld', 'George W Bush','Gerhard Schroeder', 'Hugo Chavez', 'Junichiro Koizumi','Tony Blair'], dtype='<U17')
len(faces2.target_names)
8

可以看到只有8个人满足这样的条件

使用KNN进行人脸识别

X,y = faces['data'],faces['target']
train_index = int(0.8*len(X))X_train = np.array(X[:train_index],dtype=float)
y_train = np.array(y[:train_index],dtype=float)
X_test = np.array(X[train_index:],dtype=float)
y_test = np.array(y[train_index:],dtype=float)
X_train.shape
(10586, 2914)
X_test.shape
(2647, 2914)
from sklearn.neighbors import KNeighborsClassifierknn_clf = KNeighborsClassifier(n_jobs=-1)
from sklearn.decomposition import PCA
pca = PCA(n_components=36)
pca.fit(X_train)
PCA(copy=True, iterated_power='auto', n_components=36, random_state=None,svd_solver='auto', tol=0.0, whiten=False)
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)
X_train_reduction.shape
(10586, 36)
X_test_reduction.shape
(2647, 36)
knn_clf.fit(X_train_reduction,y_train)
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=-1, n_neighbors=5, p=2,weights='uniform')
knn_clf.score(X_test_reduction,y_test)
0.04722327162825841

可以看到识别率是真的垃圾,但是不要灰心,因为在后面我们会专门利用卷积神经网络来处理图像的问题。

总结

参考

liuyubobo:https://github.com/liuyubobobo/Play-with-Machine-Learning-Algorithms

liuyubobo:https://coding.imooc.com/class/169.html

莫烦Python:https://www.bilibili.com/video/BV1xW411Y7Qd?from=search&seid=11773783205368546023

机器学习系列笔记六:主成分分析PCA[下]相关推荐

  1. 机器学习系列笔记一:Introduction

    机器学习系列笔记一:Intro 文章目录 机器学习系列笔记一:Intro 数据 基本任务 1. 分类 2. 回归 机器学习的工作流程 机器学习算法的传统分类 监督学习 无监督学习 半监督学习 增强/强 ...

  2. 机器学习系列笔记十三: 集成学习/模型聚合

    机器学习系列笔记十三: 集成学习/模型聚合 文章目录 机器学习系列笔记十三: 集成学习/模型聚合 什么是集成学习 Voting Hard Voting 模拟实现Hard Voting 集成学习 使用V ...

  3. 机器学习系列笔记:林轩田机器学习基石——机器学习的可行性

    机器学习系列笔记:林轩田机器学习基石--机器学习的可行性

  4. 机器学习系列18-无监督学习之PCA深入探讨(Ⅱ)

    Unsupervised Learning: PCA(Ⅱ) 如果本文对你有帮助,请给我的github打个star叭,上面附有全系列目录和内容! 注:更多优质内容欢迎关注我的微信公众号"Sak ...

  5. 吴恩达|机器学习作业7.1.主成分分析(PCA)

    7.1.主成分分析对人脸图像降维 1)题目: 在这个练习中,你将运用主成分分析(PCA)来实现降维.首先,你将用一个二维的样本集来实验,从而对PCA如何运行的有一个直观的感受,然后再在一个更大的由50 ...

  6. 吴恩达机器学习 EX7 第二部分 主成分分析(PCA)

    2 主成分分析 主成分分析通过协方差矩阵提取数据的主要成分,如90%的成分,通常用户数据压缩和数据可视化(维度降低方便可视化) 2.1 导入模块和数据 该部分通过将二维数据压缩成一维数据演示主成分分析 ...

  7. 机器学习读书笔记之10 - PCA

    通常在特征提取过程中,会遇到一个很严重的问题,那就是特征维度过多,实际上这些特征对于 表示和分类的贡献度不同,那么哪些特征是重要的?哪些是次要的呢? 这时轮到PCA出场了(想必早已名声在外),PCA即 ...

  8. 吴恩达“机器学习”——学习笔记六

    最优边界分类器(最大间隔分类器)(续学习笔记五) 在线性分类器中,我们要找到一个边界线,使得几何间隔最大,即: ||w||在几何间隔中是无关紧要的,这里取1,使得几何间距和函数间距一致. 但是这个并不 ...

  9. 计算机网络系列笔记(六) - 物理层

    数据通信基础 常见数据通信术语 信源: 将消息转换为信号的设备 发送设备: 将信源产生的信号进行适当的变换装置, 使之适合于在信道中传输, 主要包括编码和调制 信道: 信号传输通道, 如物理介质 噪声 ...

最新文章

  1. 深度!移动机器人(AGV)产业链全分析
  2. 程序员杂记:我们的爱情故事
  3. navicat for mysql 怎么连接远程数据库服务器
  4. 为什么需要握三次手,两次或者四次可以吗??
  5. 关于OC中的block自己的一些理解(二)
  6. BZOJ 2768 [JLOI2010]冠军调查
  7. 基于模板的通用代码生成器LKGenerator(一)-发布和主要功能介绍
  8. LSTM和GRU的解析从未如此通俗易懂(动图)
  9. 计算机网络 Kurose 第二章 应用层 2.5 P2P文件分发 2.6 视频流和内容分发网
  10. 如何激活Windows Server 2008 R2
  11. UCHome全面大解析【二】----基本体系结构
  12. 批量生成测试非重复命名的图片数据
  13. 三星S5P6818移植工程
  14. Day004--MySQL中的多表查询
  15. 基于VB和单片机的智能家居监控系统设计
  16. 长微博android,凑合着用吧:Android版长微博
  17. calcite解读专栏前言
  18. 几个重要的排列组合定理公式
  19. 分享者最爱,全是限免软件,大佬们都是在这儿找的
  20. 途风大数据 2013北美旅游最IN盘点

热门文章

  1. u盾显示服务器没有收到,【江苏银行信用卡】江苏银行企业版U盾插上去显示服务器没有收到您的证书,但在别人电脑上可以使用 - 信用卡吧...
  2. 华硕ac68u aimesh 连接不稳定的主要原因之一
  3. VirtualBox 安装Mac OS 10.13 及安装增强功能
  4. CSS基础入门(详细总结笔记)
  5. MDK5(keil5)源文件列表中黄色的钥匙标识
  6. 在js或者App中,调起第三方地图产品(URI API)的汇总
  7. 基于html5的考试系统,基于HTML5的自学考试管理系统的设计与实现
  8. 时尚渐变职业生涯规划PPT模板
  9. 刚删除的文件怎么找回?
  10. android 清除布局缓存,android – RecyclerView:如何清除缓存/回收视图?