##KNN使用场景
电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢?
动作片:打斗次数更多
爱情片:亲吻次数更多
基于电影中的亲吻、打斗出现的次数,使用 k-近邻算法构造程序,就可以自动划分电影的题材类型。
本期推送整理了初学者可能会用到的Python资料,含有书籍/视频/在线文档和编辑器/源
代码,关于Python
的安装qun:850973621
现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影。
假定 k=3,则三个最靠近的电影依次是, He’s Not Really into Dudes 、 Beautiful Woman 和 California Man。
knn 算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。
KNN开发流程
收集数据:任何方法
准备数据:距离计算所需要的数值,最好是结构化的数据格式
分析数据:任何方法
训练算法:此步骤不适用于KNN
测试算法:计算错误率
使用算法:输入样本数据和结构化的输出结果,然后运行KNN算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理
KNN算法特点
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
KNN是最简单的机器学习算法,没有之一
KNN算法伪代码:
"""
对于每一个在数据集中的数据点:
计算目标的数据点(需要分类的数据点)与该数据点的距离
将距离排序:从小到大
选取前K个最短距离
选取这K个中最多的分类类别
返回该类别来作为目标数据点的预测值
"""
def classify0(inX, dataSet, labels, k):
"""
距离度量 度量公式为欧氏距离
inX 图像文本转化的向量
dataSet <class 'numpy.ndarray'> 矩阵的长度
labels 存储0~9对应的index位置
k
"""
# >>print(type(dataSet))
# <class 'numpy.ndarray'>
# shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度。
dataSetSize = dataSet.shape[0]
# 原型:numpy.tile(A,reps)
# tile共有2个参数,A指待输入数组,reps则决定A重复的次数。整个函数用于重复数组A来构建新的数组。
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5
# 将距离排序:从小到大
sortedDistIndicies = distances.argsort()
# 选取前K个最短距离, 选取这K个中最多的分类类别
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
KNN项目案例:手写数字识别系统
项目概述
构造一个能识别数字 0 到 9 的基于 KNN 分类器的手写数字识别系统。
需要识别的数字是存储在文本文件中的具有相同的色彩和大小:宽高是 32 像素 * 32 像素的黑白图像。
开发流程
收集数据:提供文本文件
准备数据:编写函数 img2vector,将图像格式转换为分类器使用的向量格式
分析数据:在python命令提示符中检查数据,确保它符合要求
训练算法:此步骤不适用于KNN
测试算法:编写函数使用提供的部分数据集作为测试样本,测试样本与非测试样本的区别在于测试样本是已经完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误
第一步:收集数据:提供文本文件
第二步:准备数据,导入依赖包
#将图像文本数据转为向量
from numpy import zeros
from os import listdir
from numpy import zeros, tile
import operator
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
在python命令行中输入下列命令测试img2vector函数,然后与文本编辑器打开的文件进行比较:
testVector = img2vector('/Users/xiehao/Desktop/MachineLearning-master/input/2.KNN/testDigits/0_0.txt')
>>print(testVector[0,0:32])
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
>>print(testVector[0,32:64])
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 1. 1. 1.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
文本原件
训练算法:此步骤不适用于KNN
因为测试数据每一次都要与全量的训练数据进行比较,所以这个过程是没有必要的。
测试算法:编写函数使用提供的部分数据集作为测试样本,如果预测分类与实际类别不同,则标记为一个错误
def handwritingClassTest():
# 1\. 导入训练数据
hwLabels = []
trainingFileList = listdir(
'/Users/xiehao/Desktop/MachineLearning-master/input/2.KNN/trainingDigits/') # load the training set
m = len(trainingFileList)
print(m)
trainingMat = zeros((m, 1024))
# hwLabels存储0~9对应的index位置, trainingMat存放的每个位置对应的图片向量
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0] # take off .txt
classNumStr = int(fileStr.split('_')[0])
hwLabels.append(classNumStr)
# 将 32*32的矩阵->1*1024的矩阵
trainingMat[i, :] = img2vector(
'/Users/xiehao/Desktop/MachineLearning-master/input/2.KNN/trainingDigits/%s' % fileNameStr)
# 2\. 导入测试数据
testFileList = listdir(
'/Users/xiehao/Desktop/MachineLearning-master/input/2.KNN/testDigits/') # iterate through the test set
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0] # take off .txt
classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = img2vector(
'/Users/xiehao/Desktop/MachineLearning-master/input/2.KNN/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)))
执行handwritingClassTest()
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 0, the real answer is: 0
........
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the total number of errors is: 11
the total error rate is: 0.011628
可以看到1934个样本只有11个错误,分类准确率99.43%,还是很可以的
作者:raphah
链接:https://www.jianshu.com/p/13d5cb16ef2e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。