PYTHON机器学习实战——最近邻KNN分类器

来源:互联网 发布:加工中心仿真软件 编辑:程序博客网 时间:2024/06/04 01:25

    K近邻法是有监督学习方法,原理很简单,假设我们有一堆分好类的样本数据,    分好类表示每个样本都一个对应的已知类标签,当来一个测试样本要我们判断它的类别是,    就分别计算到每个样本的距离,然后选取离测试样本最近的前K个样本的标签累计投票,    得票数最多的那个标签就为测试样本的标签。

源代码详解:

#-*- coding:utf-8 -*-#!/usr/bin/python# 测试代码 约会数据分类 import KNN   KNN.datingClassTest1() 标签为字符串    KNN.datingClassTest2() 标签为整形# 测试代码 手写字体分类 import KNN   KNN.handwritingClassTest()from numpy import  *   # 科学计算包import operator        # 运算符模块from os import listdir # 获得指定目录中的内容(手写字体文件夹下样本txt)  类型命令行 lsimport matplotlib                  # 画图可视化操作import matplotlib.pyplot as plot# 显示一个 二维图def myPlot(x, y, labels):    fig = plot.figure()#创建一个窗口    ax = fig.add_subplot(111)# 画一个图    #ax.scatter(x,y)    ax.scatter(x,y,15.0*array(labels),15.0*array(labels)) # 支持 分类颜色显示    ax.axis([-2,25,-0.2,2.0])    plot.xlabel('Percentage of Time Spent Playing Video Games')# 坐标轴名称    plot.ylabel('Liters of Ice Cream Consumed Per Week')    plot.show()    # 创建假 的数据测试def createDataSet():    groop  = array([[1.0, 1.1],[1.0, 1.0],[0, 0],[0, 0.1]]) # numpy的array 数组格式    labels = ['A','A','B','B']# 标签 list    return groop, labels# 定义 KNN 分类函数def knnClassify0(inX, dataSet, labels, k):    # inX 待分类的点  数据集和标签 DataSet, label  最近领域个数 k    dataSetSize = dataSet.shape[0]  # 数据集大小(行数)        # tile(A,(行维度,列维度)) A沿各个维度重复的次数    # 点A 重复每一行 到 数据集大小行    differeMat  = tile(inX, (dataSetSize,1)) - dataSet  # 求 待分类点 与个个数据集点的 差值    sqDiffMat = differeMat**2                           # 求 平方    sqDistances = sqDiffMat.sum(axis=1)                 # 求 和(各行求和)    distances = sqDistances**0.5                        # 开方  得到 点A 与 数据集个点 的欧式距离    sortedDistIndicies = distances.argsort()            # 返回  递增排序后 的 原位置序列(不是值)        # 取得最近的 k个点 统计 标签类出现的频率    classCount={}  # 字典    for i in range(k):        voteIlabel = labels[sortedDistIndicies[i]]#从小到大 对应距离 数据点 的标签        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1  # 对于类标签 字典单词 的 值 + 1            # 对 类标签 频率(字典的 第二列(operator.itemgetter(1))) 排序 从大到小排序 reverse=True    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)    return sortedClassCount[0][0] # 返回 最近的 对应的标签# 真实数据的处理   输入TXT文本文件  返回 数据集和标签(已转化成数字) 列表 listdef file2matrix(filename):    fr = open(filename)                  # 打开文件                 numberOfLines = len(fr.readlines())  # 得到文件所有的行数    returnMat = zeros((numberOfLines,3)) # 创建一个用于存储返回数据的矩阵  数据集  每个数据的大小根据实际情况!! 即是 3 列数应根据 数据维度确定    classLabelVector = []                # 对应标签    fr = open(filename)    index = 0    for line in fr.readlines():          # 每一行        line = line.strip()              # 默认删除空白符(包括'\n', '\r',  '\t',  ' ')        listFromLine = line.split('\t')  # 按 制表符(\t) 分割字符串 成 元素列表        returnMat[index,:] = listFromLine[0:3]         # 前三个为 数据集数据        classLabelVector.append(int(listFromLine[-1])) # 最后一个 为 标签  整形        index += 1    return returnMat,classLabelVector# 真实数据的处理   输入TXT文本文件  返回 数据集和标签(为字符串) 列表 listdef file2matrix2(filename):    fr = open(filename)                  # 打开文件                 numberOfLines = len(fr.readlines())  # 得到文件所有的行数    returnMat = zeros((numberOfLines,3)) # 创建一个用于存储返回数据的矩阵  数据集  每个数据的大小根据实际情况!! 即是 3 列数应根据 数据维度确定    classLabelVector = []                # 对应标签    fr = open(filename)    index = 0    for line in fr.readlines():          # 每一行        line = line.strip()              # 默认删除空白符(包括'\n', '\r',  '\t',  ' ')        listFromLine = line.split('\t')  # 按 制表符(\t) 分割字符串 成 元素列表        returnMat[index,:] = listFromLine[0:3]         # 前三个为 数据集数据        classLabelVector.append(str(listFromLine[-1])) # 最后一个 为 标签  字符串型        index += 1    return returnMat,classLabelVector# 数据集 各个类型数据归一化  平等化 影响权值def dataAutoNorm(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))    # 扩展 minVals 成 样本总数行m行 1列(属性值个数)    normDataSet = normDataSet/tile(ranges, (m,1))   # 矩阵除法 每种属性值 归一化  numpy库 为(linalg.solve(matA,matB))    return normDataSet, ranges, minVals             # 返回 归一化后的数组 和 个属性范围以及最小值# 约会数据 KNN分类 测试# 标签为 字符串型def datingClassTest1(test_ret=0.1):    hoRatio = test_ret              # 测试的样本比例 剩下的作为 训练集    datingDataMat,datingLabels = file2matrix2('datingTestSet.txt')                #载入数据集    normMat, ranges, minVals = dataAutoNorm(datingDataMat)    m = normMat.shape[0]            # 总样本数量    numTestVecs = int(m*hoRatio)    # 总测试样本数    errorCount = 0.0                # 错误次数记录    for i in range(numTestVecs):    # 对每个测试样本        # KNN 分类                        测试样本       剩下的作为数据集               数据集对应的标签  最近 的三个        classifierResult = knnClassify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)        print "分类结果: %s,\t真实标签: %s" % (classifierResult, datingLabels[i])        if (classifierResult != datingLabels[i]): errorCount += 1.0        print "总错误次数: %d" %  errorCount    print "测试总数:   %d" %  numTestVecs    print "总错误率:   %f" % (errorCount/float(numTestVecs))# 标签为 整形 intdef datingClassTest2(test_ret=0.1):    hoRatio = test_ret              # 测试的样本比例 剩下的作为 训练集    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')                #载入数据集    normMat, ranges, minVals = dataAutoNorm(datingDataMat)    m = normMat.shape[0]            # 总样本数量    numTestVecs = int(m*hoRatio)    # 总测试样本数    errorCount = 0.0                # 错误次数记录    for i in range(numTestVecs):    # 对每个测试样本        # KNN 分类                        测试样本       剩下的作为数据集               数据集对应的标签  最近 的三个        classifierResult = knnClassify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)        print "分类结果: %d, 真实标签: %d" % (classifierResult, datingLabels[i])        if (classifierResult != datingLabels[i]): errorCount += 1.0        print "总错误次数: %d" %  errorCount    print "测试总数:   %d" %  numTestVecs    print "总错误率:   %f" % (errorCount/float(numTestVecs))# 根据用户输入的 样本的属性值 判断用户所倾向的类型(有点问题??)def classifyPerson():    resultList = ['讨厌','一般化','非常喜欢']    percent = float(raw_input("打游戏所花时间比例: "))    mile    = float(raw_input("每年飞行的里程数量: "))    ice     = float(raw_input("每周消费的冰淇淋量: "))    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')                #载入数据集    normMat, ranges, minVals   = dataAutoNorm(datingDataMat)    # 新测试样本 归一化    print  ranges, minVals    testSampArry     = array([mile, percent, ice])   # 用户输入的 测试样例    testSampArryNorm = (testSampArry-minVals)/ranges # 样例归一化    print  testSampArry ,testSampArryNorm    # 分类    classifierResult = knnClassify0(testSampArryNorm,normMat,datingLabels,3)    print  classifierResult    print "他是不是你的菜: ", resultList[classifierResult-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# 手写字体的 KNN识别 每个数字图片被转换成 32*32 的 0 1 矩阵def handwritingClassTest(k=3):    # 得到训练数据集    hwLabels = []                                # 识别的标签    trainingFileList = listdir('trainingDigits') # 加载手写字体训练数据集 (所有txt文件列表)    m = len(trainingFileList)                    # 总训练样本数    trainingMat = zeros((m,1024))                # 训练数据集    for i in range(m):        fileNameStr = trainingFileList[i]        # 每个训练数据样本文件  0_0.txt  0_1.txt  0_2.txt        fileStr = fileNameStr.split('.')[0]      # 以.分割 第一个[0]为文件名   第二个[1]为类型名 txt文件        classNumStr = int(fileStr.split('_')[0]) # 以_分割,第一个[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 = knnClassify0(vectorUnderTest, trainingMat, hwLabels, k) # 分类        print "KNN分类标签: %d, 真实标签: %d" % (classifierResult, classNumStr)        if (classifierResult != classNumStr): errorCount += 1.0    print "\n总的错误次数: %d" % errorCount    print "\n总的错误比例: %f" % (errorCount/float(mTest))


原创粉丝点击