本文共 2924 字,大约阅读时间需要 9 分钟。
该项目通过算法识别图像的数字,图像由783个像素特征即灰度值组成,范围一般从0到255,白色为255,黑色为0,选择算法依据据783个特征判断图像是哪一个数字(标签),因为练习赛,难度还是比较低的。
提供数据集(在链接的data中可下载)有,train.csv(包含1列label 和783列pixelx,数据大小为42001785)、test.csv(含7834列pixelx,数据大小为28001784)
此处选择的算法是python的sklearn库中的K近邻算法,当然大家也可以尝试用其他算法,比如朴素贝叶斯、支持向量SVC等,最后K近邻算法的准确率最高所以选择此
K近邻算法KNN原理是:根据与待测试样本距离最近的k个训练样本的大概率分类来判断待测样本所归属的类别
过程是:
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
1. 预处理
读取训练数据集,拆分为trainlabel 和traindata两个矩阵,同时数值化和归一化
train = pd.read_csv("train.csv") trainlabel = ravel(toint(train.iloc[:, 0]).transpose()) traindata = toint(train.iloc[:, 1:]) test = pd.read_csv("test.csv") testdata = toint(test.values) # 对traindata和testdata归一化,将所有不为0的数值全部转换为1 train_rows = traindata.shape[0] train_columns = traindata.shape[1] test_rows = testdata.shape[0] test_columns = testdata.shape[1] traindata = nomalizing(traindata, train_rows, train_columns) testdata = nomalizing(testdata, test_rows, test_columns)
此处解释一下以上提到的两个预处理方法:
①数值化是指原数据集的数据类型可能是字符串,由于后面会做是否为0的判断,所以需要将数据类型转换为数值型,由toint()函数完成
def toint(array): """转为数值型数据""" array = mat(array)# 生成矩阵 m, n = shape(array) newArray = zeros((m, n)) for i in range(m): for j in range(n): newArray[i, j] = int(array[i, j]) return newArray
②归一化是指将所有不为0的数都转变为1,目的是简化操作,由nomalizing函数实现
def nomalizing(data,r,l): """一个标签对应784个特征,特征值为0-255的灰度值,0代表黑色,255代表白色,此处将所有不为0的值都以1转换,简化工作量""" for i in range(r): for j in range(l): if data[i,j] != 0: data[i,j] = 1 return data
2. 交叉检验
使用交叉检验,目的是评估n_neighbors参数的最佳取值,减少过拟合。
因为此处只控制一个参数k,即n_neighbors参数,所以用模型选择库中的cross_val_score(),若有多个参数则需使用GridSearchCV()scores_list = []k_range = range(1,10)for k in k_range: knnclf = KNeighborsClassifier(k) scores = cross_val_score(knnclf,traindata,trainlabel,cv=10,scoring="accuracy") scores_list.append(mean(scores))plt.plot(k_range,scores_list)plt.show()print(max(scores_list)) # 最大精准度k = argsort(array(scores_list))[-1] # 最大精准度对应的k值
此处将k值得范围锁定到1-9,cv=10设定为十折交叉验证,score ="accuracy"评分标准采用精确率,默认是以 scoring=’f1_macro’
取得k值和对应准确率的折线图,可得到最佳k值和最大准确率
3. 算法实现
def knnClassify(k,data,label,test): """KNN算法""" knnclf = KNeighborsClassifier(k) knnclf.fit(data,ravel(label)) # label降维一维数据 testlabel = knnclf.predict(test) save_result(testlabel,"testlabel.csv")def save_result(data,filename): """保存预测结果""" # newline参数是控制文本模式之下,一行的结束字符 with open(filename,'w',newline="") as f: w = csv.writer(f) for d in data: tmp = [] tmp.append(d) w.writerow(tmp)
lavel()的作用是将多维数组降为一维,由于label只有一列数值,每一行特征对应一个label,需要将shape转变为(42000,)的形式,所以必须降维
扩展:lavel()和flatten()有一样的效果,不过唯一区别是flatten返回的是副本,而如果改变lavel会改变原数据
最后得到预测的标签testlabel.csv文件,提交kaggle的准确率为96.4%
这个项目还有很多解法,这边介绍的较基础,如果有余力和兴趣可以去[]
看看更高深的解法同时本文还参考了[)]
敬礼
转载于:https://blog.51cto.com/14215529/2355043