https://www.zybuluo.com/ssdf93/note/54643
下面是我的kaggle比赛解题报告的第一弹,本人现在是小白菜,所以从简单的题目开始,如果大神看了,见笑了。
这个题目就是手写数字识别,比较经典的分类题目,它的数据取自MNIST项目。
数据分析
数据中训练数据大约是74M,测试数据大约50M.
数据内容是28*28=784个像素,其中训练数据的第1列是该实例对应的数字,也就是label.该数据有42,000个数据样例
训练数据没有label,该数据有28,000个样例
最后提交的格式如下
ImageId | Label |
---|---|
1 | 1 |
2 | 3 |
... | ... |
环境介绍
本文使用 CMD Markdown 编写
代码编写环境: Sublime Text 3
代码运行环境: MacX OS 10.10 + python 2.7.6
使用到的包: numpy,scikit-learn,pandas,csv
题目分析
这个题目第一看到,我就想到是使用KNN算法,第k临近算法,具体思路如下
看测试样例和训练样例最近的是哪个,就将其标签赋值给它
使用scikit-learn 代码如下
import pandas as pd
import numpy as np
import csv as csv
from sklearn.neighbors import KNeighborsClassifier
train_raw=pd.read_csv('train.csv',header=0)
test_raw=pd.read_csv('test.csv',header=0)
knn = KNeighborsClassifier()
train = train_raw.values
test = test_raw.values
print 'Start training'
knn.fit(train[0::,1::],train[0::,0])
print 'Start predicting'
out=knn.predict(test)
print 'Start writing!'
n,m=test.shape
ids = range(1,n+1)
predictions_file = open("out.csv","wb")
open_file_object = csv.writer(predictions_file)
open_file_object.writerows(["ImageId","Label"])
open_file_object.writerows(zip(ids,out)
predictions_file.close()
print 'All is done'
对这个程序的核心部分做一下说明,通常sklearn的分类器用法如下
clf = SomeAlgorithmClassifier()
clf.fit(train_X,train_y)
out=clf.predict(test)
先申请某个算法的实体,然后用训练数据对模型进行训练,最后将模型应用到测试数据样例上,得到分类结果.
其中在申请算法实体的时候可以对模型的参数进行设定,具体见scikit-learn的官方手册
可是这个程序运行了好久,大概30分钟以上,最后提交的结果,正确率0.96800,虽然很高了,但是相比大家的还是有差距,所以只排在了大约248/492,还没进50%,不甘心,于是想一想有不有什么更优的方法
其他方法
尝试了使用svm,决策树,可是比较慢,至少一个小时没有出结果,于是放弃这种直接套用算法的方法.
使用降维技术
由于其特征实在太多,700多个,所以有必要实行降维,降维准备降到100个特征,80个特征,50个特征,30个特征,10个特征.
常常使用的方法是PCA技术,也就是主成分分析法,就是分析各个特征之间的相关性,通过计算其协方差矩阵的特征值,将其按特征值由大到小排列,在通常情况下,只选取前面少部分特征便能够近似代表整个所有的特征了.
同样使用scikit-learn
首先降到100维
import pandas as pd
import numpy as np
import csv as csv
from sklearn.neighbors import KNeighborsClassifier
from sklearn.decomposition import RandomizedPCA
train_raw=pd.read_csv('train.csv',header=0)
test_raw=pd.read_csv('test.csv',header=0)
knn = KNeighborsClassifier()
train = train_raw.values
test = test_raw.values
print 'Start PCA to 100'
train_x=train[0::,1::]
pca = RandomizedPCA(n_components=100, whiten=True).fit(train_x)
train_x_pca=pca.transform(train_x)
test_x_pca=pca.transform(test)
print 'Start training'
knn.fit(train_x_pca,train[0::,0])
print 'Start predicting'
out=knn.predict(test_x_pca)
print 'Start writing!'
n,m=test_x_pca.shape
ids = range(1,n+1)
predictions_file = open("out_pca_100.csv","wb")
open_file_object = csv.writer(predictions_file)
open_file_object.writerow(["ImageId","Label"])
open_file_object.writerows(zip(ids,out))
predictions_file.close()
print 'All is done'
提交上去了,结果真是令人沮丧,正确率才0.93743,还没有降维前的高.
我们可以看一看pca能够代表原始数据的比例,使用pca.explained_variance_ratio_
t=pca.explained_variance_ratio_
print sum(t[:30])
print sum(t[:50])
print sum(t[:70])
print sum(t)
结果如下
0.731860948899
0.825551303121
0.874579424778
0.914284586422
最终的结果是0.914,已经可以代表大部分结果了.注意到将其降维到50维仍可以近似代表大多数数据的特征
又试了一下50和30维,其准确率分别为0.95429和0.96314,还是没有超过原始数据
由此看来,通过PCA降维后的数据通过KNN算法对于这个测试数据貌似不能获得更高的准确率,但看到其准确率在逐步上升,是否会有一个最大值要优于原始数据通过KNN算法得到的结果.
于是测试了一下30维,结果结果是0.96957,排名188/492,总算是进入前40%了.
看看是否能够有更好的突破,接下来我们就以30维和50维作为我们测试其他算法的主要数据.
下面首先使用SVM,我们使用50维来进行测试,代码如下:
import pandas as pd
import numpy as np
import csv as csv
from sklearn.neighbors import KNeighborsClassifier
from sklearn.decomposition import RandomizedPCA
from sklearn.cross_validation import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import svm
train_raw=pd.read_csv('train.csv',header=0)
test_raw=pd.read_csv('test.csv',header=0)
train = train_raw.values
test = test_raw.values
print 'Start PCA to 50'
train_x=train[0::,1::]
train_label=train[::,0]
pca = RandomizedPCA(n_components=50, whiten=True).fit(train_x)
train_x_pca=pca.transform(train_x)
test_x_pca=pca.transform(test)
a_train, b_train, a_label, b_label = train_test_split(train_x_pca, train_label, test_size=0.33, random_state=23323)
print a_train.shape
print a_label.shape
print 'Start training'
rbf_svc = svm.SVC(kernel='rbf')
rbf_svc.fit(a_train,a_label)
print 'Start predicting'
b_predict=rbf_svc.predict(b_train)
score=accuracy_score(b_label,b_predict)
print "The accruacy socre is ", score
print 'Start writing!'
out=rbf_svc.predict(test_x_pca)
n,m=test_x_pca.shape
ids = range(1,n+1)
predictions_file = open("out3.csv","wb")
open_file_object = csv.writer(predictions_file)
open_file_object.writerow(["ImageId","Label"])
open_file_object.writerows(zip(ids,out))
predictions_file.close()
print 'All is done'
在这个程序里,我将原来的测试数据1/3分出来用来进行检验,使用了train_test_split函数
最终的准确率是0.97843,排名156/594,还有进步.