PCA降维算法应用实例----kaggle手写数字识别
Posted iostreamzl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PCA降维算法应用实例----kaggle手写数字识别相关的知识,希望对你有一定的参考价值。
文章目录
序言
在前面的博文中我们了解了降维算法PCA,以及PCA的参数。这篇文章建立在对PCA有了一定的基础的前提上。本篇文章主要将PCA算法在实际中的应用。包含PCA参数的选择,训练集,测试集上PCA的使用,解决PCA实际应用中的困惑。本文使用的是kaggle上digit-regognizer数据集。
正题
编程环境
- python3.7
- anaconda
- jupyter notebook
数据准备
可以通过官方渠道获得数据,也可以通过博主上传的数据下载。
这次使用的数据集是kaggle的digit-recognizer数据集。数据集中包含三个csv文件如下图
sample_submission.csv是提交到kaggle的csv文件格式。train.csv是数据的训练集,包含了784个特征和一个标签列。共42000组数据。test.csv为测试集,包含了784个特征,该数据集没有标签这一列,共28000组数据。本次仅使用该数据集中的训练集。通过sklearn将原训练集划分为新的训练集,测试集。
导包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA # PCA降维算法
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score # 交叉检验
from sklearn.neighbors import KNeighborsClassifier # KNN分类器
from sklearn.model_selection import train_test_split # 分割训练集,测试集
%matplotlib inline
导入数据
file = "../data/digit-recognizer/train.csv" # 换成自己本地的数据集路径
df = pd.read_csv(file)
df.shape #(42000, 785)
# 可以看出数据集非常的庞大
# 特征标签分离
X = df.loc[:, df.columns != 'label']
y = df.loc[:, df.columns == 'label'].values.ravel()
PCA参数的选择
画降维后特征的信息量累计和曲线
这一步PCA不人为设置任何参数,使用PCA的默认值。通过explained_variance_ratio_属性获得新的特征的信息量占原信息的信息量的比例
# 默认返回值PCA返回的特征个数为min(shape(X))
# 获得经过一次变化后的特征的信息量
pca_default = PCA()
X_defaule = pca_default.fit_transform(X)
# 获得每一个新特征的信息量占比
explained_vars = pca_default.explained_variance_ratio_
# 通过np.cumsum计算特征信息量的累计和
var_sum = np.cumsum(explained_vars)
# 画出特征信息量的累计和曲线
plt.figure(figsize=(10, 5))
plt.plot(range(X.shape[1]), var_sum)
plt.xticks(range(0, X.shape[1], 50))
plt.show()
结合模型,进一步选择n_components的值
前面已经提到过了,对n_components参数的选择,一般是选择曲线的转折点处。
# 对于n_components的选择一般选择曲线上的转折点附近的值
# 从图中可以看出转折点在50-100之间
# 在50 的时候信息量已经达到了80%,在100信息量已经达到了接近90%了
# 再继续网上,信息量增加比较缓慢。继续纠结于更多的特征
# 就与我们降维的目的相悖了。索引选择特征较小的0-100
# 可以知道0-100之间一定有一个值是我们需要的
# 接下来将n_components设置在0-100之间,通过模型的评分
# 选择出一共较优的参数
n_components = range(1, 101, 10)
scores = []
for i in n_components :
X_new = PCA(n_components=i).fit_transform(X)
scores.append(cross_val_score(RandomForestClassifier(n_estimators=21, random_state=1),
X_new, y, cv=5).mean())
fig = plt.figure(figsize=(10, 5))
plt.plot(n_components, scores)
plt.xticks(range(0, 101, 10))
plt.show()
结合模型,寻得最佳参数
# 从图中可以看出只要10个特征我们的模型就可以有一个很好的表现
# 当特征数量在20的时候模型的表现达到最好,这是步长为10的学习曲线
# 下面进行细致的学习曲线
# 将特征数量控制在10-30之间,画出学习曲线确定最终的PCA参数
n_components = range(10, 30)
scores = []
for i in n_components :
X_new = PCA(n_components=i).fit_transform(X)
scores.append(cross_val_score(RandomForestClassifier(n_estimators=21, random_state=1),
X_new, y, cv=5).mean())
fig = plt.figure(figsize=(10, 5))
plt.plot(n_components, scores)
plt.xticks(range(9, 31))
plt.show()
从图中可以看出当n_components=24时模型的表选达到最好
确定了PCA的最佳参数,接下来要将模型的表现推到最好就需要对模型进行调参了。关于随机森林的调参看我前面的博文。关于调参这里不进行展示了。如果经过调参,模型的表现还是没有多大提高,就可以考虑换一个模型试试了。但是换模型可能遇到的问题有:可能需要重新进行PCA降维操作。
KNN模型表现
# 经过PCA降维后的特征只有24个特征了,与之之前的784给特征相比
# 无疑是少了非常多的,这里可以选择使用KNN模型来试试
X_final = PCA(n_components=24).fit_transform(X)
knn = KNeighborsClassifier()
score = cross_val_score(knn, X_final, y, cv=10).mean()
print(score) # 0.971355806769633
PCA用于训练集测试集
上面已经将来PCA的参数选择了。但是还是有一个疑惑留给我们。那就是怎样让我的降维PCA能够适用于训练集,测试集呢。这里沿用上面的数据进行讲解。
可能的两种思路
- 思路1:直接实例化PCA并分别再训练姐,测试集上fit_transform获得新的特征
- 思路2:实例化PCA,再训练集上进行PCA训练,并将训练后的PCA应用到训练集,测试集。
显而易见思路二是正确的。这个思路可参考模型训练应用的过程。
两种思路的对比
训练集测试集的划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=3)
思路一结果
# 不fit直接再训练集,测试集上使用pca
# *******************************
pca_24 = PCA(n_components=24)
# ********************************
pca_X_train = pca_24.fit_transform(X_train)
pca_X_test = pca_24.fit_transform(X_test)
knn = KNeighborsClassifier()
knn.fit(pca_X_train, y_train)
score = knn.score(pca_X_test, y_test)
print(score) # 0.7936507936507936
# 难以形象居然有79%的准确度。这属于是运去非常好的了
# 之前的几次表现只有0.3左右。说明这次训练集测试集的划分非常完美
思路二结果
# fit后使用pca
# 不fit直接再训练集,测试集上使用pca
# ******************************************
pca_24 = PCA(n_components=24).fit(X_train)
# *******************************************
pca_X_train = pca_24.transform(X_train)
pca_X_test = pca_24.transform(X_test)
knn = KNeighborsClassifier()
knn.fit(pca_X_train, y_train)
score = knn.score(pca_X_test, y_test)
print(score) # 0.9691269841269842
对比两个结果可以看出,通过训练后再应用pca,明显才是正确的做法。模型的表现简直是质的飞跃。
总结
到这里关于PCA的基础已经学习完了。需要注意的就是PCA参数的选择方法。PCA再训练集,测试集上的使用,一定要经过“训练”。PCA再训练集,测试集上的使用,一定要经过“训练”。PCA再训练集,测试集上的使用,一定要经过“训练”。。重要的事情说三遍。
欢迎在评论区和我进行讨论,互相学习
以上是关于PCA降维算法应用实例----kaggle手写数字识别的主要内容,如果未能解决你的问题,请参考以下文章
机器学习实战基础(二十七):sklearn中的降维算法PCA和SVDPCA对手写数字数据集的降维