一、简介

参考:https://blog.csdn.net/c406495762/article/details/75172850

环境:win 10, notebook,python 3.6

原blog较长,主要实现其算法,尽可能的简洁些,并对一些细节给出实例,

如果熟练,细节处的函数尽可能的可以忽略,写出来主要是未来加强印象。

三、四、五、三个实例,前两个同一种方法,分类函数是同一个,只是数据不一样,最后一个使用SKLerrn实现KNN,十分方便。

二、算法简介

1、原理:

输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

2、距离度量

欧式距离

3、步骤:

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

k-近邻算法的一般流程:

收集数据:可以使用爬虫进行数据的收集,也可以使用第三方提供的免费或收费的数据。一般来讲,数据放在txt文本文件中,按照一定的格式进行存储,便于解析及处理。
准备数据:使用Python解析、预处理数据。
分析数据:可以使用很多方法对数据进行分析,例如使用Matplotlib将数据可视化。
测试算法:计算错误率。
使用算法:错误率在可接受范围内,就可以运行k-近邻算法进行分类。

优缺点:

优点

简单好用,容易理解,精度高,理论成熟,既可以用来做分类也可以用来做回归;
可用于数值型数据和离散型数据;
训练时间复杂度为O(n);无数据输入假定;
对异常值不敏感。
缺点:

计算复杂性高;空间复杂性高;
样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
一般数值很大的时候不用这个,计算量太大。但是单个样本又不能太少,否则容易发生误分。
最大的缺点是无法给出数据的内在含义。

三、KNN简单实例

训练集是一个矩阵,测试集也是一个矩阵,要预测测试集中每一个数据的类别

算法步骤:

1、将测试集中的每一个数据扩展成和训练集一样大小的矩阵,用于该数据与训练集的每一个数据进行距离计算

2、扩展矩阵与训练集对应元素相减,

3、相减后的每一个元素进行平方,

4、每一行的元素相加

5、开根号,

6、找出k个最小的的值,这k个中,类别最多的那个即是预测类型

如图:

代码如下:

def classify(inX,dataSet,labels,k):# 返回行数dataSetSize = dataSet.shape[0]# 扩展维度,相减diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet# 平方sqDiffMat = diffMat**2# 求和sqDistances = sqDiffMat.sum(axis=1)# 开根号distances = sqDistances**0.5#返回distances中元素从小到大排序后的索引值sortedDistIndices = distances.argsort()classCount = {}for i in range(k):voteIlabel = labels[sortedDistIndices[i]]classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# 对字典按值排序,返回的是一个列表,列表元素是元组sortedClassCount = sorted(classCount.items(),key=lambda item:item[1],reverse=True)return sortedClassCount[0][0]

完整代码:

import numpy as npgroup = np.array([[1,101],[5,89],[108,5],[115,8]])
labels = ['爱情片','爱情片','动作片','动作片']def classify(inX,dataSet,labels,k):# 返回行数dataSetSize = dataSet.shape[0]# 扩展维度,相减diffMat = np.tile(inX, (dataSetSize, 1)) - dataSetsqDiffMat = diffMat**2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances**0.5#返回distances中元素从小到大排序后的索引值sortedDistIndices = distances.argsort()classCount = {}for i in range(k):voteIlabel = labels[sortedDistIndices[i]]classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# 对字典按值排序,返回的是一个列表,列表元素是元组sortedClassCount = sorted(classCount.items(),key=lambda item:item[1],reverse=True)return sortedClassCount[0][0]test = [101,20]
test_class = classify(test, group, labels, 3)
print(test_class)

预测结果:

动作片

注:源代码使用了operator模块对字典进行排序

python补充:

四个函数,tile(),  np.sum(),  np.argsort(),  sorted(),

(1)np.tile()

import numpy as npa = [2,3]
b  = np.tile(a,(4,3))
print(b)
[[2 3 2 3 2 3][2 3 2 3 2 3][2 3 2 3 2 3][2 3 2 3 2 3]]

(2)np.argsort():

返回从小到大排序后的索引值

import numpy as npa = np.array([1,2,3,4])
b = np.array([4,3,2,1])
print(a.argsort())
print(b.argsort())
[0 1 2 3]
[3 2 1 0]

(3)np.sum():

0:返回列相加

1:返回行相加

import numpy as npa = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
print(a)
print('---------axis=0-----------')
b = a.sum(axis=0)
print(b)
print('---------axis=1-----------')
c = a.sum(axis=1)
print(c)
[[ 1  2  3][ 4  5  6][ 7  8  9][10 11 12]]
---------axis=0-----------
[22 26 30]
---------axis=1-----------
[ 6 15 24 33]

(4)sorted():

第一个参数:可迭代对象

第二个参数,排序规则

第三个参数,是否降序,True为降序,False为升序,

返回值是一个列表,

d = {'mom':23,'linme':34,'ioio':89,'falali':232}
a = sorted(d.items(),key=lambda item:item[1],reverse=True)
print(a)
c = sorted(d.items(),key=lambda item:item[1],reverse=False)
print(c)
[('falali', 232), ('ioio', 89), ('linme', 34), ('mom', 23)]
[('mom', 23), ('linme', 34), ('ioio', 89), ('falali', 232)]

(5)数据处理过程:

import numpy as npgroup = np.array([[1,2],[6,4],[80,81],[78,83]])
print('----------group------------')
print('group: ')
print(group)test = [3,4]
mat = np.tile(test,(4,1))
print('----------mat------------')
print('mat: ')
print(mat)mat_g = mat - group
print('----------mat_g------------')
print('mat_g: ')
print(mat_g)mat_2 = mat_g**2
print('----------mat_2------------')
print('mat_2: ')
print(mat_2)mat_sum = mat_2.sum(axis=1)
print('----------mat_sum------------')
print('mat_sum: ')
print(mat_sum)
----------group------------
group:
[[ 1  2][ 6  4][80 81][78 83]]
----------mat------------
mat:
[[3 4][3 4][3 4][3 4]]
----------mat_g------------
mat_g:
[[  2   2][ -3   0][-77 -77][-75 -79]]
----------mat_2------------
mat_2:
[[   4    4][   9    0][5929 5929][5625 6241]]
----------mat_sum------------
mat_sum:
[    8     9 11858 11866]

四、海伦数据

文件总共四列,最后一列是标签,海伦收集的样本数据主要包含以下3种特征:

每年获得的飞行常客里程数
玩视频游戏所消耗时间百分比
每周消费的冰淇淋公升数

分析数据:数据可视化,数据归一化

数据读取,获取特征矩阵和标签,

在windows上使用open打开utf-8编码的txt文件时开头会有一个多余的字符\ufeff,它叫BOM,是用来声明编码等信息的,但python会把它当作文本解析。对UTF-16, Python将BOM解码为空字串。然而对UTF-8, BOM被解码为一个字符\ufeff。

步骤:

打开文件, 去除BOM, 获取行数, 对于每一行:

去除每行前后空白符, 按tab切分 前三列保存到特征矩阵中, 最后一保存到标签中,

def file2matrix(filename):fr = open(filename,'r',encoding = 'utf-8')arrayOLines = fr.readlines()#针对有BOM的UTF-8文本,应该去掉BOM,否则后面会引发错误。arrayOLines[0]=arrayOLines[0].lstrip('\ufeff')numberOfLines = len(arrayOLines)returnMat = np.zeros((numberOfLines,3))classLabelVector = []index = 0for line in arrayOLines:line = line.strip()listFromLine = line.split('\t')#将数据前三列提取出来,存放到returnMat的NumPy矩阵中,也就是特征矩阵returnMat[index,:] = listFromLine[0:3]if listFromLine[-1] == 'didntLike':classLabelVector.append(1)elif listFromLine[-1] == 'smallDoses':classLabelVector.append(2)elif listFromLine[-1] == 'largeDoses':classLabelVector.append(3)index += 1return returnMat, classLabelVector

归一化步骤:

1、找出每一列最大、小值,返回值是一维列表,每个元素代表该列最大、小值

2、最大值列表减去最小值列表得出差列表

3、将最小值列表扩展为数据集大小,

4、将差值列表扩展为数据集大小,

5、原始数据减去最小值扩展,然后除以差值扩展

def autoNorm(dataSet):minVals = dataSet.min(0)maxVals = dataSet.max(0)ranges = maxVals - minValsnormDataSet = np.zeros(np.shape(dataSet))m = dataSet.shape[0]# 原始值减去最小值normDataSet = dataSet - np.tile(minVals, (m, 1))normDataSet = normDataSet / np.tile(ranges, (m, 1))return normDataSet, ranges, minVals

则全部代码:

import numpy as npdef classify(inX,dataSet,labels,k):# 返回行数dataSetSize = dataSet.shape[0]# 扩展维度,相减diffMat = np.tile(inX, (dataSetSize, 1)) - dataSetsqDiffMat = diffMat**2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances**0.5#返回distances中元素从小到大排序后的索引值sortedDistIndices = distances.argsort()classCount = {}for i in range(k):voteIlabel = labels[sortedDistIndices[i]]classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# 对字典按值排序,返回的是一个列表,列表元素是元组sortedClassCount = sorted(classCount.items(),key=lambda item:item[1],reverse=True)return sortedClassCount[0][0]def file2matrix(filename):fr = open(filename,'r',encoding = 'utf-8')arrayOLines = fr.readlines()#针对有BOM的UTF-8文本,应该去掉BOM,否则后面会引发错误。arrayOLines[0]=arrayOLines[0].lstrip('\ufeff')numberOfLines = len(arrayOLines)returnMat = np.zeros((numberOfLines,3))classLabelVector = []index = 0for line in arrayOLines:line = line.strip()listFromLine = line.split('\t')#将数据前三列提取出来,存放到returnMat的NumPy矩阵中,也就是特征矩阵returnMat[index,:] = listFromLine[0:3]if listFromLine[-1] == 'didntLike':classLabelVector.append(1)elif listFromLine[-1] == 'smallDoses':classLabelVector.append(2)elif listFromLine[-1] == 'largeDoses':classLabelVector.append(3)index += 1return returnMat, classLabelVectordef autoNorm(dataSet):minVals = dataSet.min(0)maxVals = dataSet.max(0)ranges = maxVals - minValsnormDataSet = np.zeros(np.shape(dataSet))m = dataSet.shape[0]# 原始值减去最小值normDataSet = dataSet - np.tile(minVals, (m, 1))normDataSet = normDataSet / np.tile(ranges, (m, 1))return normDataSet, ranges, minValsdef main():filename = "datingTestSet.txt"datingDataMat, datingLabels = file2matrix(filename)normMat, ranges, minVals = autoNorm(datingDataMat)# 行数m = normMat.shape[0]# 测试比率hoRatio = 0.10numTestVecs = int(m * hoRatio)#分类错误计数errorCount = 0.0for i in range(numTestVecs):classifierResult = classify(normMat[i,:], normMat[numTestVecs:m,:], datingLabels[numTestVecs:m], 4)print("分类结果:%s\t真实类别:%d" % (classifierResult, datingLabels[i]))if classifierResult != datingLabels[i]:print('分类: ',classifierResult)print('真实: ',datingLabels[i])errorCount += 1.0print("错误率:%f%%" %(errorCount/float(numTestVecs)*100))main()

结果(只输出最后几行):

分类结果:2   真实类别:3
分类:  2
真实:  3
分类结果:1  真实类别:1
分类结果:2  真实类别:2
分类结果:1  真实类别:1
分类结果:3  真实类别:3
分类结果:3  真实类别:3
分类结果:2  真实类别:2
分类结果:2  真实类别:1
分类:  2
真实:  1
分类结果:1  真实类别:1
错误率:4.000000%

python函数:min(),max(),    列表切分

(1)min(),max()

0:列最值

1:行最值

空:全局最值

import numpy as np
a = np.array([[1,2,3,10,4,5],[2,3,4,3,5,6],[3,4,5,4,6,7]])
print(a)print('-------全局最大小------')
print(a.min())
print(a.max())print('------列最大小-------')
print(a.min(0))
print(a.max(0))print('------行最大小-------')
print(a.min(1))
print(a.max(1))
[[ 1  2  3 10  4  5][ 2  3  4  3  5  6][ 3  4  5  4  6  7]]
-------全局最大小------
1
10
------列最大小-------
[1 2 3 3 4 5]
[ 3  4  5 10  6  7]
------行最大小-------
[1 2 3]
[10  6  7]

(2)列表切分:

import numpy as np
a = np.array([[1,2,3,4,5],[2,3,4,5,6],[3,4,5,6,7]])
print(a)
print('----------------')
print('a[2,:]: ')
print(a[2,:])
print('----------------')
print('a[0:2,:]: ')
print(a[0:2,:])
print('----------------')
print('a[0:2]: ')
print(a[0:2])
[[1 2 3 4 5][2 3 4 5 6][3 4 5 6 7]]
----------------
a[2,:]:
[3 4 5 6 7]
----------------
a[0:2,:]:
[[1 2 3 4 5][2 3 4 5 6]]
----------------
a[0:2]:
[[1 2 3 4 5][2 3 4 5 6]]

五、使用SKLearn中的KNN对手写字体进行处理

步骤:

1、获取训练集特征矩阵,标签

2、使用训练集特征矩阵、标签初始化KNN实例

3、获取测试集特征矩阵,标签 4、预测测试集,记录正确率

其实即代码:

实例KNN: neigh = kNN(n_neighbors = 3, algorithm = 'auto') neigh.fit(trainingMat, hwLabels)

预测: classifierResult = neigh.predict(vectorUnderTest)

首先将32*32的数据展开成1*1024,然后实例KNN,预测,代码如下:

import numpy as np
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as kNN# 将32*32展开成1*1024
def img2vector(filename):returnVect = np.zeros((1, 1024))fr = open(filename)for i in range(32):lineStr = fr.readline()#每一行的前32个元素依次添加到returnVect中for j in range(32):returnVect[0, 32*i+j] = int(lineStr[j])return returnVectdef handwritingClassTest():hwLabels = []# 训练集列表trainingFileList = listdir('trainingDigits')m = len(trainingFileList)trainingMat = np.zeros((m, 1024))# 获取训练集特征矩阵及其标签for i in range(m):# 训练集文件名fileNameStr = trainingFileList[i]# 数字classNumber = int(fileNameStr.split('_')[0])# 训练集标签列表hwLabels.append(classNumber)# 训练集特征矩阵,即 M*1024trainingMat[i,:] = img2vector('trainingDigits/%s' % (fileNameStr))# 构建分类器neigh = kNN(n_neighbors = 3, algorithm = 'auto')neigh.fit(trainingMat, hwLabels)# 测试集文件名列表testFileList = listdir('testDigits')errorCount = 0.0# 测试集数量mTest = len(testFileList)for i in range(mTest):# 文件名fileNameStr = testFileList[i]# 类别classNumber = int(fileNameStr.split('_')[0])# 特征矩阵vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))# 预测结果classifierResult = neigh.predict(vectorUnderTest)print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumber))if(classifierResult != classNumber):errorCount += 1.0print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount/mTest * 100))handwritingClassTest()

结果(最后几行输出):

分类返回结果为9 真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
分类返回结果为9    真实结果为9
总共错了12个数据
错误率为1.268499%

我们发现,使用SKLearn确实比自己手写要方便的多。

机器学习实战——KNN相关推荐

  1. 机器学习实战-KNN算法-20

    机器学习实战-KNN算法-鸢尾花分类 # 导入算法包以及数据集 from sklearn import neighbors from sklearn import datasets from skle ...

  2. 机器学习实战——KNN及部分函数注解

    书籍:<机器学习实战>中文版 IDE:PyCharm Edu 4.02 环境:Adaconda3  python3.6 本系列主要是代码学习记录,其中设计的理论知识,不做过多解释.书中代码 ...

  3. 机器学习实战——KNN算法预测电影类型

    预测电影类型 现有爱情片和动作片(不是爱情动作片,雾)的打斗场面和接吻场面的次数统计,然后给出一个电影打斗场面和接吻场面出现的次数,预测其类型. 那么如何预测呢?当然用KNN了. KNN算法的原理就是 ...

  4. knn的python代码_《机器学习实战》之一:knn(python代码)

    数据 标称型和数值型 算法 归一化处理:防止数值较大的特征对距离产生较大影响 计算欧式距离:测试样本与训练集 排序:选取前k个距离,统计频数(出现次数)最多的类别 def classify0(inX, ...

  5. 机器学习实战笔记(Python实现)-02-k近邻算法(kNN)

    k近邻算法(kNN) 本博客来源于CSDN:http://blog.csdn.net/niuwei22007/article/details/49703719 本博客源代码下载地址:CSDN免费下载. ...

  6. 《机器学习实战》chapter02 K-近邻算法(KNN)

    2.2 示例:使用K-近邻算法改进约会网站的配结果 收集数据:提供文本文件 准备数据:使用Python解析文本文件(文本转numpy矩阵.归一化数据等) 分析数据:使用Matplotlib画二维扩散图 ...

  7. 算法代码[置顶] 机器学习实战之KNN算法详解

    改章节笔者在深圳喝咖啡的时候突然想到的...之前就有想写几篇关于算法代码的文章,所以回家到以后就奋笔疾书的写出来发表了     前一段时间介绍了Kmeans聚类,而KNN这个算法刚好是聚类以后经常使用 ...

  8. 基于kNN的手写字体识别——《机器学习实战》笔记

    看完一节<机器学习实战>,算是踏入ML的大门了吧!这里就详细讲一下一个demo:使用kNN算法实现手写字体的简单识别 kNN 先简单介绍一下kNN,就是所谓的K-近邻算法: [作用原理]: ...

  9. 机器学习实战(一)k-近邻kNN(k-Nearest Neighbor)

    目录 0. 前言 1. k-近邻算法kNN(k-Nearest Neighbor) 2. 实战案例 2.1. 简单案例 2.2. 约会网站案例 2.3. 手写识别案例 学习完机器学习实战的k-近邻算法 ...

最新文章

  1. python3 subprocess.Popen 报错 No such file or directory
  2. rknn 学习资料整理
  3. Leetcode 208. 实现 Trie (前缀树) 解题思路及C++实现
  4. 困扰程序员的30种软件开发问题,你是否时曾相识?
  5. java mysql 语句解析器_几种基于Java的SQL解析工具的比较与调用
  6. 为什么中国人穷得只剩房子
  7. Netty工作笔记0039---Netty模型--详细版
  8. httpclient 下载大文件
  9. 系统同步网络时间服务器不可用,电脑时间同步出错 RPC服务器不可用解决方案...
  10. Azure通过Vnet Peering和用户自定义路由(UDR)实现hub-spoken连接
  11. 既要面子,也要里子,车企成不了自动驾驶的“独行侠”
  12. java博客论坛设计报告,javaweb课程设计报告-个人博客网站的实现(Java).doc
  13. 著名的菲尔人格测试,看看你适合做什么类型的工作
  14. 【高效沟通技巧】与人交流要求我们巧妙地听和说
  15. ros2中navigation2的BT常用语法总结1
  16. 十部门发促消费“24条”:提高相对低收入群体待遇
  17. U盘安装centos遇到bootmgr is missing
  18. Java项目:SSH羽毛球馆管理系统
  19. 什么是DQL?其含义及其常用命令解析
  20. CK-GL16-AB传感器|读卡器在工业自动化AGV小车磁导航RFID定位领域应用与解决方案

热门文章

  1. java生成6位唯一id
  2. 用CrashDump定位应用错误
  3. 中国智能互联炊具行业市场供需与战略研究报告
  4. Linux账号加入群组,Linux新手入门:Linux中的账号与群组
  5. oracle decode 空值,常用函数--decode的使用,NULL值的意思
  6. elasticsearch :unassigned错误解决
  7. Halcon深度学习1 -- 环境搭建及准备工作-halcon18版本下载安装
  8. windows CMD 命令总结
  9. xp sql2000 安装SP4失败解决方案
  10. 20221121 秩相同,值域不一定相同