一、Kaggel简介
Kaggel是一个主要为开发商和数据科学家提供举办机器学习竞赛、托管数据库、编写和分享代码的平台。Digit Recognizer是平台上的一个简单的练习项目。
二、Digit Recognizer介绍
题目大意是做一个手写数字识别的分类任务,所给的数据有sample_submission.csv,test.csv和train.csv。sample_submission.csv给出了提交文件的例子(参考其格式),test.csv给出了需要进行分类的测试数据,train.csv给出了带有标签的训练数据。数据是28*28的图像,在提供的数据文件中以一个1*784的一维向量表示,csv文件中一行代表一张图片的向量表示。train.csv中每行开头有附加的一个标签,表示这张图片中写的数字。
三、kNN算法解决方案
kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
在该题中,根据kNN算法的思想,我们要做两件事情,
(1)计算测试数据和训练数据之间的距离。就是对两个一维向量的对应位置求差,然后平方,再将各个位置的结果求和就是距离。
(2)找出距离最小的k个训练样本,统计他们的分类标签,找出出现次数最多的那个标签作为当前测试数据的标签。排序然后取前k个统计即可得出分类。
因为算法的缺点,计算量很大,运算比较慢。
代码如下,详见注释:
# coding:utf8
import pandas as pd
import numpy as np
import datetime
def getTrainLabelAndMat():
# 读取train.csv文件
traincsv = pd.read_csv(r'digit recognizer\train.csv')
# 取出label
trainLabel0 = traincsv.values[0:, :1]
# 取出训练数据
trainMat = traincsv.values[0:, 1:]
n = trainLabel0.shape[0]
trainLabel = np.zeros(n)
for i in range(0, n):
trainLabel[i] = trainLabel0[i][0]
# 返回训练标签和训练数据矩阵
return trainLabel, trainMat
def getTestMat():
testcsv = pd.read_csv(r'digit recognizer\test.csv')
testMat = testcsv.values[0:, 0:]
# 返回测试数据矩阵
return testMat
# 分类函数,输入当前向量、训练矩阵,矩阵中向量对应标签,k值大小,返回类别
def classifyDigit(nowVect, dataSet, labels, k):
# 得到训练矩阵行数
dataSetSize = dataSet.shape[0]
# 做差,平方,按行相加,开根
diffMat = np.tile(nowVect, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistance = sqDiffMat.sum(axis=1) # 按行相加,axis=0按列相加
distances = sqDistance ** 0.5
# 根据距离排序
sortedDistIndicies = distances.argsort()
# 统计前k近的点中各个类别的数量
classCount = {}
for i in range(k):
nowlabel = labels[sortedDistIndicies[i]]
classCount[nowlabel] = classCount.get(nowlabel, 0) + 1
# 迭代一遍找到出现次数最多的类别
maxCount = 0
answer = ""
for k, v in classCount.iteritems():
if v > maxCount:
maxCount = v
answer = k
return answer
def check(k):
trainLabel, trainMat = getTrainLabelAndMat()
testMat = getTestMat()
# 储存结果的列表
testLabel = []
testId = range(1, testMat.shape[0] + 1)
cnt = 0
# 对每一个测试数据向量进行分类,并记录结果
for nowVect in testMat:
nowLabel = classifyDigit(nowVect, trainMat, trainLabel, k)
testLabel.append(int(nowLabel))
cnt += 1
print cnt, int(nowLabel)
# 按照给定格式生成csv文件
dataframe = pd.DataFrame({'ImageId': testId, 'Label': testLabel})
dataframe.to_csv("submissions.csv", index=False)
if __name__ == '__main__':
start = datetime.datetime.now()
check(3)
end = datetime.datetime.now()
print '使用时间:' + (end - start)
四、提交
直接将生成的submissions.csv提交,最后准确率为0.96885。
代码打包:https://github.com/MBXH/Kaggle_Digit_Recognizer_kNN.git