一、数据来源
手写数字数据集 digit recognizor.csv
二、模型选择
from sklearn.decomposition import PCA
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier as RFC
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
降维算法选择decomposition模块下的PCA
随机森林算法RandomForestClassifier
KNN算法KNeighborsClassifier
三、数据预处理
data=pd.read_csv("C:\\Users\\DRF\\Desktop\\digit recognizor.csv")
data.head()
x=data.iloc[:,1:]
y=data.iloc[:,0]
读取数据集后,选择前5行观察,第一列label为标签,后面列的数据为特征,因此切片令x=data.iloc[:,1:],y=data.iloc[:,0]
四、分析过程
1)画出累计方差贡献率曲线,找最佳降维后维度的范围
pca=PCA().fit(x)
plt.figure(figsize=[20,5])
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.xlabel("number of components after dimension reduction")
plt.ylabel("cumulative explained variance ratio")
plt.show()
首先,PCA实例化,n_components不填任何值,来观察可解释性方差贡献率曲线
通过上图可以看到,n_components在[0,100]直接可解释性方差贡献提高迅速,[100,400]提速逐渐降低,[400,800]几乎没有提高。我们需要找到一个明显变化转折点,可以看到当等于200的时候,可解释性方差累计贡献差不多达到了95%左右,后面几乎没有增加了。因此我们继续对n_components细化,希望找到最优点。
2)降维后维度的学习曲线,继续缩小最佳维度的范围
score=[]
for i in range(1,101,10):
x_dr=PCA(i).fit_transform(x)
once=cross_val_score(RFC(n_estimators=10,random_state=0),x_dr,y,cv=5).mean()
score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(1,101,10),score)
plt.show()
当细化到[0,101],步长为10时,最高点大约在10至30之间,继续进一步细化寻找最高点。
3)细化学习曲线,找出降维后的最佳维度
score=[]
for i in range(10,25):
x_dr=PCA(i).fit_transform(x)
once=cross_val_score(RFC(n_estimators=10,random_state=0),x_dr,y,cv=5).mean()
score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(10,25),score)
plt.show()
4)导入找出的最佳维度进行降维,查看模型效果
x_dr=PCA(21).fit_transform(x)
cross_val_score(RFC(n_estimators=10,random_state=0),x_dr,y,cv=5).mean()
可以看到,当n_components为21的时候,随机森林模型的准确率达到了最高点,达到了0.9179761257042178,超过了90%。
5)模型极限?更换模型?
优化1:那么将随机森林模型n_estimators调高至100呢?
x_dr=PCA(21).fit_transform(x)
cross_val_score(RFC(n_estimators=100,random_state=0),x_dr,y,cv=5).mean()
模型的准确度立刻上升至0.9434522864584884,提高了0.02954762!模型效果还好,跑出了94.49%的水平,随机森林模型极限最高可能也只有96%左右,有没有其他办法能够提高模型的表现呢?
优化2:更换模型KNN,模型的准确率会不会比随机森林有所提升?
在之前的建模过程中,因为计算量太大,所以我们一直使用随机森林,但事实上,我们知道KNN的效果比随机森林更好,KNN在未调参的状况下已经达到96%的准确率,而随机森林在未调参前只能达到93%,这是模型本身的限制带来的,这个数据使用KNN效果就是会更好。现在我们的特征数量已经降到不足原来的3%,可以使用KNN了吗?
from sklearn.neighbors import KNeighborsClassifier as KNN
cross_val_score(KNN(),x_dr,y,cv=5).mean()
未调参的KNN模型准确率直接达到了0.9675948870484117!可见KNN的效果是非常好的!下面进一步调参KNN,希望进一步提高模型的准确率。
6)KNN学习曲线
score=[]
for i in range(10):
x_dr=PCA(21).fit_transform(x)
once=cross_val_score(KNN(i+1),x_dr,y,cv=5).mean()
score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(10),score)
plt.show()
cross_val_score(KNN(3),x_dr,y,cv=5).mean()
根据上图得知,当横坐标等于2,KNN 参数 k = i+1 = 2+1 = 3 时,模型的准确率最高,达到0.9682375117716753。
可以发现,原本785列的特征被我们缩减到21列之后,用KNN跑出了目前位置这个数据集上最好的结果。如果再进行更细致的调整,我们也许可以将KNN的效果调整到98%以上。PCA能够帮助我们不会因为数据量太庞大而被迫选择更加复杂的模型。
·································································································································································
完整代码如下:
from sklearn.decomposition import PCA #导入降维算法PCA
from sklearn.model_selection import cross_val_score #导入交叉验证
from sklearn.ensemble import RandomForestClassifier as RFC #导入随机森林模块
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data=pd.read_csv("C:\\Users\\DRF\\Desktop\\digit recognizor.csv") #导入手写数字数据集
data.head() #观察前五行数据
x=data.iloc[:,1:] #划分特征
y=data.iloc[:,0] #划分标签
pca=PCA().fit(x) #实例化 拟合
plt.figure(figsize=[20,5]) #新建画布 大小为20x5
plt.plot(np.cumsum(pca.explained_variance_ratio_)) #绘制可解释性方差贡献率曲线图
plt.xlabel("number of components after dimension reduction") #x轴坐标名称
plt.ylabel("cumulative explained variance ratio") #y轴坐标名称
plt.show()
score=[]
for i in range(1,101,10):
x_dr=PCA(i).fit_transform(x) #实例化拟合训练转换
once=cross_val_score(RFC(n_estimators=10,random_state=0),x_dr,y,cv=5).mean() #交叉验证随机森林求准确率
score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(1,101,10),score)
plt.show()
score=[]
for i in range(10,25):
x_dr=PCA(i).fit_transform(x)
once=cross_val_score(RFC(n_estimators=10,random_state=0),x_dr,y,cv=5).mean()
score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(10,25),score)
plt.show()
x_dr=PCA(21).fit_transform(x)
cross_val_score(RFC(n_estimators=10,random_state=0),x_dr,y,cv=5).mean()
x_dr=PCA(21).fit_transform(x)
cross_val_score(RFC(n_estimators=100,random_state=0),x_dr,y,cv=5).mean()
from sklearn.neighbors import KNeighborsClassifier as KNN #导入KNN算法模块
cross_val_score(KNN(),x_dr,y,cv=5).mean()
score=[]
for i in range(10):
x_dr=PCA(21).fit_transform(x)
once=cross_val_score(KNN(i+1),x_dr,y,cv=5).mean()
score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(10),score)
plt.show()
cross_val_score(KNN(3),x_dr,y,cv=5).mean()