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

1. 说明一下,文本数据格式:文本名字为:datingTestSet2.txt,该文件我放在项目里面的python文件同级

2. 使用python转化文件

 def file2matrix(filename):
"""
Cynthia:解析文本数据,将属性数据放在returnMat,将标签放在classLabelVector
导入训练数据
:param filename: 数据文件路径
:return: 数据矩阵returnMat和对应的类别classLabelVector
"""
# 打开文件
fr = open(filename, 'r')
# 获得文件中的数据行的行数
numberOfLines = len(fr.readlines())
# 生成对应的空矩阵
# 例如:zeros(2,3)就是生成一个 2*3 的矩阵,各个位置上全是 0
returnMat = zeros((numberOfLines, 3)) # prepare matrix to return
classLabelVector = [] # prepare labels return
fr = open(filename, 'r')
index = 0
for line in fr.readlines():
# str.strip([chars]) --返回移除字符串头尾指定的字符生成的新字符串
line = line.strip()
# 以 '\t' 切割字符串
listFromLine = line.split('\t')
# 每列的属性数据,即 features
returnMat[index] = listFromLine[0: 3]
# 每列的类别数据,就是 label 标签数据
classLabelVector.append(int(listFromLine[-1]))
index += 1
# 返回数据矩阵returnMat和对应的类别classLabelVector
return returnMat, classLabelVector

3. 数据归一化:

 def autoNorm(dataSet):
"""
Desc:
归一化特征值,消除属性之间量级不同导致的影响
Args:
dataSet -- 需要进行归一化处理的数据集
Returns:
normDataSet -- 归一化处理后得到的数据集
ranges -- 归一化处理的范围
minVals -- 最小值 归一化公式:
Y = (X-Xmin)/(Xmax-Xmin)
其中的 min 和 max 分别是数据集中的最小特征值和最大特征值。该函数可以自动将数字特征值转化为0到1的区间。
"""
# 计算每种属性的最大值、最小值、范围
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
# 极差
ranges = maxVals - minVals
normDataSet = (dataSet - minVals) / ranges
return normDataSet, ranges, minVals

4. KNN分类的算法核心:

 1 def classify0(inX, dataSet, labels, k):
2 """
Desc:
kNN 的分类函数
Args:
inX -- 用于分类的输入向量/测试数据
dataSet -- 训练数据集的 features
labels -- 训练数据集的 labels
k -- 选择最近邻的数目
Returns:
sortedClassCount[0][0] -- 输入向量的预测分类 labels 注意:labels元素数目和dataSet行数相同;程序使用欧式距离公式. 预测数据所在分类可在输入下列命令
kNN.classify0([0,0], group, labels, 3)
""" # -----------实现 classify0() 方法的第一种方式----------------------------------------------------------------------------------------------------------------------------
# 1. 距离计算
#shape函数是查看矩阵或者数组的维数
dataSetSize = dataSet.shape[0]
# tile生成和训练样本对应的矩阵,并与训练样本求差
#tile是用于对某个序列进行重复。
#示例:tile([1,2],(2,2,3)),输出为array([[[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]]  ,  [[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]]    ])
#(1)可以看到是先将[1,2]重复3次得到[1, 2, 1, 2, 1, 2],
#(2)再将[1, 2, 1, 2, 1, 2]重复2次得到[[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]],
#(3)最后再将[[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]]重复两次[[[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]]  ,  [[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]]]。
#总结:从上面的例子可以看出,tile(A,rep)按照rep里面从右到左的序列顺序对A进行重复,每对重复完一次,A就增加一个维度。
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
#目的是计算出该测试点对训练集中的每个点的距离。
"""
欧氏距离: 点到点之间的距离
"""
# 取平方
sqDiffMat = diffMat ** 2
# 将矩阵的每一行相加
sqDistances = sqDiffMat.sum(axis=1)
# 开方
distances = sqDistances ** 0.5
# 根据距离排序从小到大的排序,返回对应的索引位置
# argsort() 是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y。
# print 'distances=', distances
sortedDistIndicies = distances.argsort()
# print 'distances.argsort()=', sortedDistIndicies # 2. 选择距离最小的k个点
classCount = {}
for i in range(k):
# 找到该样本的类型
voteIlabel = labels[sortedDistIndicies[i]]
# 在字典中将该类型加一
# 字典的get方法
# 如:list.get(k,d) 其中 get相当于一条if...else...语句,参数k在字典中,字典将返回list[k];如果参数k不在字典中则返回参数d,如果K在字典中则返回k对应的value值
# l = {5:2,3:4}
# print l.get(3,0)返回的值是4;
# Print l.get(1,0)返回值是0;
# 感觉像Java中的键值对原理,键是这里的标签类型,值是标签出现的次数
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 3. 排序并返回出现最多的那个类型
# 字典的 items() 方法,以列表返回可遍历的(键,值)元组数组。
# 例如:dict = {'Name': 'Zara', 'Age': 7} print "Value : %s" % dict.items() Value : [('Age', 7), ('Name', 'Zara')]
# sorted 中的第2个参数 key=operator.itemgetter(1) 这个参数的意思是先比较第几个元素
# 例如:a=[('b',2),('a',1),('c',0)] b=sorted(a,key=operator.itemgetter(1)) >>>b=[('c',0),('a',1),('b',2)] 可以看到排序是按照后边的0,1,2进行排序的,而不是a,b,c
# b=sorted(a,key=operator.itemgetter(0)) >>>b=[('a',1),('b',2),('c',0)] 这次比较的是前边的a,b,c而不是0,1,2
# b=sorted(a,key=opertator.itemgetter(1,0)) >>>b=[('c',0),('a',1),('b',2)] 这个是先比较第2个元素,然后对第一个元素进行排序,形成多级排序。
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]

5. 用约会网站的数据进行训练中的数据标签测试

 #分类器针对约会网站的进行测试代码
def datingClassTest():
"""
Desc:
对约会网站的测试方法,并将分类错误的数量和分类错误率打印出来
Args:
None
Returns:
None
"""
# 设置测试数据的的一个比例(训练数据集比例=1-hoRatio)
hoRatio = 0.1 # 测试范围,一部分测试一部分作为样本
# 从文件中加载数据
datingDataMat, datingLabels = file2matrix("datingTestSet2.txt") # load data setfrom file
# 归一化数据
normMat, ranges, minVals = autoNorm(datingDataMat)
# m 表示数据的行数,即矩阵的第一维
m = normMat.shape[0]
# 设置测试的样本数量, numTestVecs:m表示训练样本的数量
numTestVecs = int(m * hoRatio)
print('numTestVecs=', numTestVecs)
errorCount = 0
for i in range(numTestVecs):
# 对数据测试
classifierResult = classify0(normMat[i], normMat[numTestVecs : m], datingLabels[numTestVecs : m], 3)
print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
errorCount += classifierResult != datingLabels[i]
print("the total error rate is: %f" % (errorCount / numTestVecs))
print(errorCount)

6. 做预测

 def classifyPerson():
resultList = ['not at all','in small doses', 'in large doses']
percentTats = float(input("percentage of time spent playing video games?"))
ffMiles = float(input("frequent flier miles earned per years?"))
iceCream = float(input("liters of ice cream consumed per year?"))
datingDataMat, datingLabels = file2matrix("datingTestSet2.txt")
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([ffMiles, percentTats, iceCream])
classifierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
print("you will probably like this person:",resultList[classifierResult-1])

注:python3中的控制台交互是input

python2的是raw_input

控制台测试结果:

kNN代码测试已完毕。

本人github代码链接:https://github.com/CynthiaWendy/Machine-Learning-in-Action-KNN



项目案例2:构造k-近邻分类器的手写识别系统

  说明:这里构造的系统只能识别数字0到9.如下图所示:

  需要识别的数据已经使用图像处理软件,处理成具有相同的色彩和大小:宽高是32像素*32像素的黑白图像。尽管采用的文本格式存储图像不饿呢过有效地利用内存空间,但是为了方便理解,还是将图像转化为文本格式。

1. 数据准备:我们有两个数据集文件,一个是训练数据trainingDigits(大约2000个例子,每个数字大约有200个样本),一个是测试数据(大约有900个测试数据)。这两组数据没有覆盖。

  我们将把一个32*32的二进制图像矩阵转化为1*1024的向量,这样我们上面项目1的knn的分类器就可以处理数字图像信息。

 def img2vector(filename):
'''
该函数创建1*1024的Numpy数组,然后打开给定的文件,循环读出文件的前32行,
并将每行的头32个字符值存储在Numpy数组中,最后返回数据。
:param filename:
:return:
'''
returnVect = zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr=fr.readline()
for j in range(32):
#将信息取出,放在1*1024向量相应的位置上
returnVect[0,32*i+j]=int(lineStr[j])
return returnVect

2. 项目1中的knn核心函数被使用在测试中。

3. 测试代码

 def handwritingClassTest():
"""
Desc:
手写数字识别分类器,并将分类错误数和分类错误率打印出来
Args:
None
Returns:
None
"""
hwLabels=[]
#装入训练数据
trainingFileList=os.listdir('trainingDigits')
#得到该文件夹的文件个数
m=len(trainingFileList)
trainingMat=zeros((m,1024))
for i in range(m):
fileNameStr=trainingFileList[i]
#得到文件的名字
fileStr=fileNameStr.split('.')[0]
#得到文件名字的分隔
classNumStr=int(fileStr.split('_')[0])
#将类别存在数组中
hwLabels.append(classNumStr)
#将每个文件的数据以1*1024的形式保存
trainingMat[i]=img2vector("trainingDigits/%s" % fileNameStr)
#导入测试数据
testFileList=os.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)))

运行结果:

该项目的代码及数据放在本人的github上:欢迎指导。

https://github.com/CynthiaWendy/Machine-Learning-in-Action-KNN1

机器学习实战-K-近邻算法(kNN)的更多相关文章

  1. 机器学习实战-k近邻算法

    写在开头,打算耐心啃完机器学习实战这本书,所用版本为2013年6月第1版 在P19页的实施kNN算法时,有很多地方不懂,遂仔细研究,记录如下: 字典按值进行排序 首先仔细读完kNN算法之后,了解其是用 ...

  2. 机器学习之K近邻算法(KNN)

    机器学习之K近邻算法(KNN) 标签: python 算法 KNN 机械学习 苛求真理的欲望让我想要了解算法的本质,于是我开始了机械学习的算法之旅 from numpy import * import ...

  3. k近邻算法(KNN)

    k近邻算法(KNN) 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别. from sklearn.model_selection ...

  4. 【机器学习】k近邻算法(kNN)

    一.写在前面 本系列是对之前机器学习笔记的一个总结,这里只针对最基础的经典机器学习算法,对其本身的要点进行笔记总结,具体到算法的详细过程可以参见其他参考资料和书籍,这里顺便推荐一下Machine Le ...

  5. 机器学习(四) 分类算法--K近邻算法 KNN (上)

    一.K近邻算法基础 KNN------- K近邻算法--------K-Nearest Neighbors 思想极度简单 应用数学知识少 (近乎为零) 效果好(缺点?) 可以解释机器学习算法使用过程中 ...

  6. 机器学习(四) 机器学习(四) 分类算法--K近邻算法 KNN (下)

    六.网格搜索与 K 邻近算法中更多的超参数 七.数据归一化 Feature Scaling 解决方案:将所有的数据映射到同一尺度 八.scikit-learn 中的 Scaler preprocess ...

  7. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

  8. 机器学习中 K近邻法(knn)与k-means的区别

    简介 K近邻法(knn)是一种基本的分类与回归方法.k-means是一种简单而有效的聚类方法.虽然两者用途不同.解决的问题不同,但是在算法上有很多相似性,于是将二者放在一起,这样能够更好地对比二者的异 ...

  9. 《机器学习实战》---第二章 k近邻算法 kNN

    下面的代码是在python3中运行, # -*- coding: utf-8 -*- """ Created on Tue Jul 3 17:29:27 2018 @au ...

  10. 机器学习之K近邻算法

    K 近邻 (K-nearest neighbor, KNN) 算法直接作用于带标记的样本,属于有监督的算法.它的核心思想基本上就是 近朱者赤,近墨者黑. 它与其他分类算法最大的不同是,它是一种&quo ...

随机推荐

  1. java高并发核心要点|系列文章

    java高并发核心要点|系列1|开篇 java高并发核心要点|系列2|锁的底层实现原理 java高并发核心要点|系列3|锁的底层实现原理|ABA问题 java高并发核心要点|系列4|CPU内存指令重排 ...

  2. SOA,Webservice,SOAP,REST,RPC,RMI,JMS的区别与联系(转载)

    原文地址:http://blog.csdn.net/pcceo1/article/details/51245249 SOA面向服务的软件架构(Service Oriented Architecture ...

  3. 使用 python 开发 Web Service

    使用 python 开发 Web Service Python 是一种强大的面向对象脚本语言,用 python 开发应用程序往往十分快捷,非常适用于开发时间要求苛刻的原型产品.使用 python 开发 ...

  4. python主流框架简介和Django框架的使用

    目录 一.手撸简易web框架 二.动静态网页 1. 静态网页 2. 动态网页 三.jinja2模板语法 1. jinja2的作用 四.python主流web框架 1. django 3. tornad ...

  5. java常用类与包装类--常用类字符串String类、StringBuffer类、Stringbuilder类

    1.String类 1.1String类的概念和储存结构: (1)字符串是一个比较特殊的对象,可以使用new,也可以不使用new来创建字符串对象 String s1 = new String(&quo ...

  6. [LOJ 6704] 健身计划

    问题描述 九条可怜是一个肥胖的女孩. 她最近长胖了,她想要通过健身达到减肥的目的,于是她决定每天做n次仰卧起坐以达到健身的目的. 她可以将这n次动作分为若干组完成,每一次完成ai次仰卧起坐,每做完一次 ...

  7. 对ECMAScript的研究-----------引用

    ECMAScript 新特性与标准提案 一:ES 模块 第一个要介绍的 ES 模块,由于历史上 JavaScript 没有提供模块系统,在远古时期我们常用多个 script 标签将代码进行人工隔离.但 ...

  8. 关于Fibonacci博弈的一些学习

    关于Fibonacci博弈的一些学习 一道例题 问题 给定n(n≥2)个石头,游戏双方轮流取至少一个石子,取到最后一个石子的人算赢,但是要满足一下规则: 第一次取不能全部取完所有的石子. 设前一次取的 ...

  9. JMS学习二(简单的ActiveMQ实例)

    下载安装ActiveMQ服务,下载地址当然可以去官网下载 http://activemq.apache.org/download-archives.html ActiveMQ安装很简单,下载解压后到b ...

  10. FP回写阶段卡住或报错

    FP在autosap阶段往往会因各种各样的因素导致回写报错,卡住等异常: 本次由于一个视图的性能突然下降导致回写长期卡住没有完成: 这时如果要重新执行回写的话就要检查哪部分的数据回写到SAP端,一般有 ...