【机器学习笔记】基于k-近邻算法的数字识别

本文深入解析k-近邻算法的基本原理与应用流程,通过示例‘DigitRecognizer’展示如何利用该算法进行数字识别。从数据收集到算法测试,详述了k-近邻算法在实际场景中的具体实施步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

更多详细内容参考《机器学习实战》

k-近邻算法简介

简单的说,k-近邻算法采用测量不同特征值之间的距离方法进行分类。它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每个数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似(最近邻)数据的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后选择k个相似数据中出现次数最多的分类,作为新数据的分类。

k-近邻算法的一般流程

  1. 收集数据
  2. 准备数据
  3. 分析数据
  4. 训练算法(此步骤不适用与k-近邻算法)
  5. 测试算法
  6. 使用算法

k-近邻算法的的伪代码

对未知类别属性的数据集中的每个点依次进行以下操作:

  1. 计算已知类别数据集中的点与当前点之间的距离
  2. 按距离递增次序排列按距离递增次序排列
  3. 选取与当前点距离最小的k个点
  4. 确定前k个点所在类别的出现频率
  5. 返回前k个点出现频率最高的类别作为当前点的预测分类

示例

示例为kaggle上的’Digit Recognizer’,实现数字识别
具体的题目描述和数据集下载可以点击链接Digit Recognizer

代码

from numpy import *
import operator
import csv

def getTrainData():									#获取训练集的数据
    with open('D:\\学习\\kaggle\\Digit Recoginzer\\train.csv') as f:
        traindata=[]    
        datafirst=csv.reader(f)     				#读取csv文件
        for row in datafirst:      					#训练数据放入列表中
            traindata.append(row)   
        traindata.pop(0)                                    #去除第一行文字说明
        
        trainlabel=[]                                       #取出训练标签
        for i in traindata:
            trainlabel.append(int(i[0]))
            i.pop(0)
            
        for i in range(len(traindata)):                     #把列表中字符类型变成整数类型
            for j in range(len(traindata[0])):              #同时便于计算,把非零常数改为1
                if traindata[i][j]!='0':
                    traindata[i][j]=1
                else:
                    traindata[i][j]=int(traindata[i][j])
                    
       
            
        return array(traindata),array(trainlabel)
            
def getTestData():									#获取测试集数据
    with open('D:\\学习\\kaggle\\Digit Recoginzer\\test.csv') as f:
        testdata=[]
        datafirst=csv.reader(f)
        for row in datafirst:
            testdata.append(row)
        testdata.pop(0)
        for i in range(len(testdata)):
            for j in range(len(testdata[0])):
                if testdata[i][j]!='0':
                    testdata[i][j]=1
                else:
                    testdata[i][j]=int(testdata[i][j])
        
        return array(testdata)

def classify0(inX,dataSet,labels,k):            			#inX是一个待分类的测试向量
    dataSetSize=dataSet.shape[0]                			#取出dataSet的行数
    #tile把inX整体在行上重复dataSetSize次,列上重复1次(下面代码中) 具体可以自己试一下
    diffMat=tile(inX,(dataSetSize,1))-dataSet   			#测试向量与每个训练向量的各分量差
    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  #累加距离排名前k个中每个标签出现的次数
    #把classCount中按标签的出现次数排序
    sortedclassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) 
    return sortedclassCount[0][0]


traindata,trainlabel=getTrainData()
testdata=getTestData()
testlabel=[]
for i in testdata:
    testlabel.append(classify0(i,traindata,trainlabel,5))

testlabel1=[[i]for i in testlabel]   
with open('testlabel.csv','w',newline='') as f:     #打开当前路径下的文件
    fwriter=csv.writer(f)                           #返回writer对象
    fwriter.writerows(testlabel1)                   #一行行写入,每行必须是可迭代的对象,所以要把label中每一个int变成列表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值