电影类别分类
四、 任务分析
每部电影的打斗镜头数、接吻镜头数以及电影类型。如图1所示。

就是已有的数据集合,也称训练样本集。数据集有两个特征,打斗镜头数和接吻镜头数。也知道每部电影的类型,既分类标签。根据经验可以通过电影中打斗镜头数和接吻镜头数判断出该电影属于什么类型。但是在K-近邻算法中不会告诉这些,会根据提取样本集中特征最相似的数据分类标签来判断电影属于爱情片还是动作片。
电影分类。如图2所示

从散点图可以判断出该电影属于动作片,因为距离已知的动作片更近。那么,K-近邻算法怎么判断呢,可以使用两点距离公式计算距离。如图3所示。

通过公式计算得知红色圆点标记到动作片(108,5)的距离最近,通过算法直接得知电影类型,这个算法是最近邻算法,而非k-近邻算法。
♥ 知识链接 |
1、计算已知类别数据集中点与当前点的距离 2、按照距离递增次序排序 3、选取与当前点距离最小的K个点 4、确定前K个点所属类别出现频率 5、返回当前K个点出现频率最高的类别作为当前点的预测分类 |
五、 任务实施
步骤1、环境准备
右击Ubuntu操作系统桌面,从弹出菜单中选择【Open in Terminal】命令 打开终端。
通过【cd /home】切换到home目录下。【ls】查看该目录下的所有内容。如图4所示。

【mkdir KNN】在home目录下创建KNN文件夹。如图5所示。

步骤2、数据集
数据可以使用Numpy进行创建。
【cd KNN】切换目录,【vim kNN_movie.py】回车后创建并编辑名为kNN_movie的Python文件。如图6所示。

回车后进入编辑框内,按键盘【i】进入编辑状态,编译如下程序。如图7所示。
createDataSet()方法内通过np.array生成四组二维数据特征和四组特征标签列表。在main方法内调用createDataSet()方法并将二维数据和特征标签打印。

编辑完毕后,按【esc】退出编辑状态,【:wq】保存并退出编辑框,【python kNN_movie.py】执行kNN_movie的Python文件。如图8所示。
四组二维数据特征及特征标签打印。

步骤3、k-近邻算法
根据两点距离公式,计算距离,选择最小的前k个点,并返回分类结果。
再次进入kNN_movie.py文件编辑状态,修改程序(需要导入运算符模块【import operator】)。如图9所示。
根据公式计算并排序对类别进行返回。

在main方法内定义测试数据集,并调用分类器的方法,将测试数据集、创建的数据集、分类标签、k值当做参数并输出最后的结果。如图10所示。

编辑完毕后,按【esc】退出编辑状态,【:wq】保存并退出编辑框,【python kNN_movie.py】执行kNN_movie的Python文件。如图11所示。
得知该部电影的类型为动作片。

步骤4、源码
1 #coding:utf-8 2 import numpy as np 3 import operator 4 from os import listdir 5 from sklearn.neighbors import KNeighborsClassifier as kNN 6 """ 7 将32x32的二进制图像转换为1x1024向量 8 """ 9 def img2vector(filename): 10 returnVect = np.zeros((1,1024)) #生成1x1024零向量 11 fr = open(filename) #打开文件 12 for i in range(32): #文本格式是32x32的,读取所有行 13 lineStr = fr.readline() #读一行数据 14 for j in range(32): #读取行中所有元素 15 returnVect[0, 32*i+j] = int(lineStr[j]) #将所有的元素添加到returnVect中 16 return returnVect #返回转换后的1x1024向量 17 """ 18 手写数字分类测试 19 """ 20 def handwritingClassTest(): 21 hwLabels = [] #训练集的Labels 22 trainingFileList = listdir('digits/trainingDigits') #返回trainingDigits目录下的文件名 23 m = len(trainingFileList) #返回文件夹下文件的个数 24 trainingMat = np.zeros(((m,1024))) #初始化训练的矩阵 25 for i in range(m): 26 fileNameStr = trainingFileList[i] #获得文件的名字 27 classNumber = int(fileNameStr.split('_')[0]) #获得分类的数字 28 hwLabels.append(classNumber) #将获得的类别添加到hwLabels中 29 #将每一个文件的1x1024数据存储到trainingMat矩阵中 30 trainingMat[i,:] = img2vector("digits/trainingDigits/%s" % (fileNameStr)) 31 neigh = kNN(n_neighbors=3,algorithm="auto") #构建kNN分类器 32 neigh.fit(trainingMat,hwLabels) #训练模型 33 testFileList = listdir("digits/testDigits") #返回TestDigits目录下的文件列表 34 errorCount = 0.0 #错误检测计数 35 mTest = len(testFileList) #测试数据的数量 36 for i in range(mTest): #从文件中解析出测试集的类别并进行分类测试 37 fileNameStr = testFileList[i] #获得文件名字 38 classNumber = int(fileNameStr.split("_")[0]) #获得分类的数字 39 vectorUnderTest = img2vector("digits/testDigits/%s" % (fileNameStr)) #获得测试集的1x1024向量,用于训练 40 classifierResult = neigh.predict(vectorUnderTest) #获取预测结果 41 print "分类返回结果为%d\t真实结果为%d" % (classifierResult,classNumber) 42 if (classifierResult != classNumber): 43 errorCount += 1.0 44 print "总共错了%d个数据\n错误率为%f%%" % (errorCount,errorCount/mTest * 100) 45 if __name__ == '__main__': 46 handwritingClassTest()