大数据,机器学习,人工智能人工智能/模式识别/机器学习精华专题机器学习与数据挖掘

机器学习系列(二十)——PCA在手写数字数据集的应用

2019-07-14  本文已影响11人  Ice_spring

本篇将在真实数据集——手写数字数据集上使用PCA。

PCA应用到真实数据集

简单手写数字数据集包括1797个样本,每个样本都是一个8×8的灰度图像,可以看作每个样本有64个特征。导入手写数字数据集:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

digits = datasets.load_digits()
X = digits.data
y = digits.target

首先不做pca降维直接用knn算法对其分类:

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
%%time
'''不对数据降维,使用knn对手写数字分类并测试性能'''
from sklearn.neighbors import KNeighborsClassifier

knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train,y_train)

时间消耗和准确率:

knn时间消耗 准确率

有上面的结果看到,直接使用knn准确率达到98.7%。接下来将数据降到2维,再使用knn算法:

'''PCA降维后,使用knn'''
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)
%%time
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction,y_train)

降维后时间消耗和准确率:

2维时间消耗 2维准确率

降到2维后由于数据量减少,训练速度比未降维的时候快的多,不过准确率却只有60.7%,这是因为数据由64维到2维,损失太多信息了,也许应该降到10维,20维什么的。实际上我们可以通过不断搜索不同维数进行数据集训练以得到更合适的维数。不过sklearn的pca中提供了一个指标explained_variance_ratio_,对于降到2维,该指标为:

e_v_r2

这个指标结果表示第一个轴方向能解释0.146原数据的方差,第二个轴能解释0.137原数据的方差,而剩下70%多的方差则由于降维而丢失。该指标大小是从大到小排列的,其数值即对应每个方向(主成分)的重要程度。下面对该64维数据提取其所有主成分,并给出该指标:

pca = PCA(n_components=X_train.shape[1])
pca.fit(X_train)
pca.explained_variance_ratio_

指标如下:

主成分重要程度排序

可以发现最后几个轴方向解释的方差还不到0.0001%,因此最后几个主成分是可以忽略的。
将主成分个数和它们能解释的总方差百分比绘图:

'''表示取前n个主成分能解释多少百分比的方差'''
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%,则取前大约30个主成分即可。这在sklearn的pca中也是能直接求的,比如我们要求主成分个数应能至少解释95%的方差:

pca = PCA(0.95)
pca.fit(X_train)
pca.n_components_
解释95%方差需要的主成分

可见需要28个主成分。取前28个主成分后的数据集进行训练结果如下:

训练结果

达到了98%的准确率。虽然比未降维的数据准确率要低,但0.006的差距也还可以接受,而且时间消耗要少的多。有时我们愿意用微小的准确率差换取时间性能的优势。


PCA用于MNIST数据集

MNIST数据集是机器学习领域中非常经典的一个数据集,共有70000个样本,由60000个训练样本和10000个测试样本组成,每个样本有784个特征,是一张28 * 28像素的灰度手写数字图片。
首先是从sklearn下下载sklearn数据集,这里要注意的是,不同机器学习框架下都有mnist数据集,他们可能格式不太一样,建议用sklearn学习机器学习的不要使用其它框架下的数据集。

from sklearn.datasets import fetch_openml
mnist = fetch_openml("MNIST original",data_home = 'datasets')

当然第一次下载可能需要一会儿时间,或者下载报错,这里给出笔者下载好的保存在百度云的mnist数据集链接:
链接: https://pan.baidu.com/s/1L8F9e3fHF3Nnd8yhvS7_zw 提取码: wb52
下面对数据进行训练:

X,y = mnist['data'],mnist['target']
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)
'''使用knn'''
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
%time knn_clf.fit(X_train,y_train)
knn训练时间消耗

对训练的模型进行准确率评价:

准确率

由于knn算法预测过程需要所有训练数据参与,而mnist数据量庞大,因此及其消耗时间,在笔者的PC上用时13分钟,准确率96.9%
接下来用PCA对数据进行降维,然后再用knn训练:

from sklearn.decomposition import PCA
pca = PCA(0.9)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)

这里PCA中参数给了0.9,扔掉了训练数据集10%的信息:

降维数据shape

此时784个特征只剩下87了,执行训练过程:

'''降维后使用knn'''
knn_clf1 = KNeighborsClassifier()
%time knn_clf1.fit(X_train_reduction,y_train)
降维后knn训练

准确率:

降维后准确率

发现预测过程用时明显减少,而且准确率97.3%比之前高,咦?为什么丢掉数据10%的信息准确率却更高了呢?这涉及到PCA的一个很重要的应用,那就是数据降噪,丢掉的数据很大程度上是噪声。降噪的更多例子将在下篇介绍。

上一篇下一篇

猜你喜欢

热点阅读