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) 类型命令行 ls 
 
import 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文本文件 返回 数据集和标签(已转化成数字) 列表 list 
def 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文本文件 返回 数据集和标签(为字符串) 列表 list 
def 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)) 
 
# 标签为 整形 int 
def 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)) 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?