k-邻近算法学习笔记

来源:互联网 发布:2016淘宝新店扶持政策 编辑:程序博客网 时间:2024/04/25 07:04

目录

    • k-邻近算法概述
    • kNNpy
    • demo手写识别系统
      • 1 将图像转化为测试数据
      • 2 hand writing测试代码
      • 总结

1 k-邻近算法概述

采用测量不同特征值之间的距离进行分类。

  • 优点
    • 精度高
    • 对异常数据不敏感
  • 缺点
    • 计算复杂度、空间复杂度高
  • 适用范围

    • 数值型和标称型
      • 标称型目标变量的结果只能是有限目标集中的某一个
      • 数值型目标变量的结果可以在无限数集中取值,可以去任意的数
  • 工作原理

    • 我们已有一个训练样本集,知道样本集中的每一个数据与所属分类的关系。对输入的没有分类的数据,将这个新数据的各个特征与样本集中的特征进行比较,最后选择前k个最相似的数据的分类标签,这k个分类标签中出现最多的分类,我们就认为是这个没有分类数据的分类标签。

2 kNN.py

#!/usr/bin/python# -*- coding:utf8 -*-from numpy import *import operatorimport matplotlibimport matplotlib.pyplot as plt# 导入数据def createDataSet():    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])    labels = ['A','A','B','B']    return group,labels# group,labels = createDataSet()# print(group,'\n',labels)# 实施kNN分类算法# 分类的输入向量inX; 输入的训练样本集为dataSet; 标签向量为labels;# 最后的参数k表示用于选择最近邻居的数目def classify0(inX, dataSet, labels, k):    dataSetSize = dataSet.shape[0]    # 计算距离    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):        # 选择距离最小的k个点        voteIlable = labels[sortedDistIndicies[i]]        classCount[voteIlable] = classCount.get(voteIlable,0) + 1    # 排序    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)    return sortedClassCount[0][0]# 从文本文件中解析数据# 从文本记录转换为NumPy的解析程序def file2matrix(filename):    fr = open(filename)    arrayOLines= fr.readlines()    # 得到文件行数    numberOfLines = len(arrayOLines)    # 创建返回的NumPy矩阵    returnMat = zeros((numberOfLines,3))    classLabelVector = []    index = 0    for line in arrayOLines:        # 解析文件数据到列表        line = line.strip()        listFromLine = line.split('\t')        returnMat[index,:] = listFromLine[0:3]        classLabelVector.append(int(listFromLine(-1)))        index += 1    return returnMat,classLabelVector# 归一化特征值def autoNorm(dataSet):    minVals = dataSet.min(0)    maxVals = dataSet.max(0)    ranges = maxVals - minVals    normDataSet = zeros(shape(dataSet))    m = dataSet.shape[0]    normDataSet = dataSet - tile(minVals, (m,1))    normDataSet = normDataSet/tile(ranges, (m,1))   #特征值相除    return normDataSet, ranges, minVals
  • 分析数据
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')    fig = plt.figure()    ax = fig.add_subplot(111)    ax.scatter(datingDataMat[:,1], datingDataMat[:,2])    plt.show()

这里写图片描述

3 demo:手写识别系统

3.1 将图像转化为测试数据

将图像格式处理为一个向量,即把32×32的矩阵转换为1×1024的向量

# 将图像转化为向量def img2vector(filename):    returnVect = zeros((1,1024))    fr = open(filename)    for i in range(32):        lineStr = fr.readline()        for j in range(32):            returnVect[0,32*i+j] = int(lineStr[j])    return returnVect

3.2 hand writing测试代码

def handwritingClassTest():    hwLabels = []    # 获取目录内容    trainingFileList = listdir('trainingDigits')    m = len(trainingFileList)    trainingMat = zeros((m,1024))    for i in range(m):        # 从文件名中解析数字 e.g."0_53.txt"        fileNameStr = trainingFileList[i]        fileStr = fileNameStr.split('.')[0]        classNumStr = int(fileStr.split('_')[0])        hwLabels.append(classNumStr)        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)    testFileList = listdir('testDigits')    errorCount = 0.0    mTest = len(testFileList)    for i in range(mTest):        fileNameStr = testFileList[i]        fileStr = fileNameStr.split('.')[0]        classNumStr = int(fileStr.split('_')[0])        vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)        print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))        if (classifierResult != classNumStr): errorCount += 1.0    print("\nthe total number of errors is: %d" % errorCount)    print("\nthe total error rate is: %f" % (errorCount/float(mTest)))

结果
这里写图片描述


总结

k-近邻算法是分类数据最简单最有效的算法,也是我入门的算法。


end