昨天找到一个数据分析的众包网站(kaggle),希望借此来练习一下前段时间学习到的ML算法。
今天就来回顾一下之前学习到的 KNN 算法,并用KNN算法进行手写数字的识别。
KNN 算法_手写识别实例
1.算法介绍:
kNN算法,即K最近邻(k-NearestNeighbor)分类算法,是最简单的机器学习算法之一,算法思想很简单:从训练样本集中选择k个与测试样本“距离”最近的样本,这k个样本中出现频率最高的类别即作为测试样本的类别。
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型、标称型
K-近邻算法的一般步骤:
1.数据收集:可以使用任何方法
2.准本数据:距离计算所需要的数值,最好是结构化的数据格式
3.分析数据:可以使用任何方法
4.训练算法:此步骤不适用于K-近邻算法
5.测试算法:计算错误率
6.使用算法:首先需要输入样本数据和结构化的输出结果,然后运行K-近邻算法判定输入数据分别属于哪一分类,最后应用对计算出的分类执行后续的处理
分类过程如下:
1.确定K值(K值是指对于一个待分类的数据点,我们要寻找K个它的邻居,即训练样品中与它距离最近的K个数据点) K的取值一般不大于20(《机器学习实战》)
2.根据事先确定的距离度量公式(如:欧式距离等),得到待分类数据点和所有训练样品(已知类别的样品点)中距离最近的K个样品
3.统计这K个样品点中各个类别的数量。选取K个样品点中所属类别数量最多的类别作为待分类样品点的类别。
2.算法代码与实践:
<span style="font-size:14px;">def classify0(inx,dataSet,labels,k):
# """kNN algorithm:
# 1. 计算已知类别数据集中的点与当前点之间的距离
# 2. 按照距离递增次序排序
# 3. 选取与当前点距离最小的k个点
# 4. 确定前k个点所在类别的出现频率
# 5. 返回前k个点出现频率最高的类别作为当前点的预测分类"""
dataSetSize = dataSet.shape[0] #返回矩阵的行数和列数
diffMat = tile(inx ,(dataSetSize,1))-dataSet #tile :复制函数,返回一个list
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis = 1)
distances = sqDistances **0.5
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
sortedClassCount = sorted(classCount.iteritems(),key = operator.itemgetter(1),reverse = True)
return sortedClassCount[0][0]</span>
<span style="font-size:14px;">def gettrainData(filename):
"""获取训练用的数据 """
datas = []
labels = []
with open(filename,'rb') as myfile:
lines = csv.reader(myfile)
lines.next()
for line in lines:
data = []
for n,num in enumerate(line):
data.append(int(num))
datas.append(data)
for data in datas:
labels.append(data[0])
del data[0]
datas = array(datas)
print 'get traindata ok'
return datas,labels</span>
<span style="font-size:14px;">def gettestData(filename):
"""获取测试用的数据"""
datas = []
with open(filename,'rb') as myfile:
lines = csv.reader(myfile)
lines.next()
for line in lines:
data = []
for n,num in enumerate(line):
data.append(int(num))
datas.append(data)
datas = array(datas)
print 'get testdata ok'
return datas</span>
<span style="font-size:14px;">def testKNN0(filename,trainRate,k):
"""对KNN算法进行测试 从训练数据中截取一部分进行训练,另一部分进行测试,检测正确率"""
datalist,datalabels = gettrainData(filename)
# datalist = autpNorm(datalist)
count = len(datalist)
trainNum = int(count*trainRate)
trainData,trainlabels = datalist[0:int(trainNum)],datalabels[0:int(trainNum)]
testCorrectRate = 0.0
for i in range(trainNum,count):
idx = classify0(datalist[i],trainData,trainlabels,k)
print i - trainNum
if idx == datalabels[i]:
# print '预测的类别为:'.decode('utf-8').encode('gbk'),idx,"实际类别为:".decode('utf-8').encode('gbk'),datalabels[i],'right'
testCorrectRate = testCorrectRate + 1
else:
pass
# print '预测的类别为:'.decode('utf-8').encode('gbk'),idx,"实际类别为:".decode('utf-8').encode('gbk'),datalabels[i]
testCorrectRate = testCorrectRate/(count - trainNum )
return testCorrectRate</span>