KNN算法应用—电影题材分类
我们知道,电影可以按题材分类,但题材本身是如何定义的?由谁来判定某部电影属于哪个题材?即同一题材的电影会具有哪些公共特征?这些都是在做电影分类时一定要搞清楚的问题。这里以动作片和爱情片为例做简要说明。动作片具有哪些公共特征,使得动作片之间非常相似,却明显有别于爱情片?动作片中也可能有接吻镜头,爱情片中也可能存在打斗镜头,所以,不能简单地依靠是否存在打斗或者接吻来判断一部电影的类型。但很明显的是,动作片中的打斗镜头更多、爱情片中的接吻次数更频繁,基于此类场景在一部电影中出现的次数可用来进行电影分类。
有人曾经统计过很多电影的打斗镜头和接吻镜头, 下方图1-1 给出了6部电影的打斗和接吻镜头。假如现在有一部从未看过的电影,你如何判断它属于动作片还是爱情片呢?
首先,我们弄清楚这部未知电影中存在多少打斗镜头、多少接吻镜头,图1-1中问号位置是该未知电影出现的镜头数图示,具体见下方表1-1。
由图1-1和表1-1,可用将未知电影在图1-1的具体位置标出,利用欧式距离公式,计算出未知电影与样本集中其他电影之间的距离,相见下方表2-2所示。
由表2-2所示,显然,如果样本集中所有电影与未知电影之间的距离按照递增排序的话,可以得到k个距离最近的电影,这里假设k=2的话,则未知电影与电影He’s Not Really into Dudes,Beautiful Woman影片类型最为相似,判定未知电影属于爱情片。
KNN算法代码
#-*- coding: utf-8 -*-
import numpy as np
import operator
'''
trainData - 训练集
testData - 测试集
labels - 分类
'''
def knn(trainData, testData, labels, k):
# 计算训练样本的行数
rowSize = trainData.shape[0]
# 计算训练样本和测试样本的差值
diff = np.tile(testData, (rowSize, 1)) - trainData
# 计算差值的平方和
sqrDiff = diff ** 2
sqrDiffSum = sqrDiff.sum(axis=1)
# 计算距离
distances = sqrDiffSum ** 0.5
# 对所得的距离从低到高进行排序
sortDistance = distances.argsort()
count = {}
for i in range(k):
vote = labels[sortDistance[i]]
count[vote] = count.get(vote, 0) + 1
# 对类别出现的频数从高到低进行排序
sortCount = sorted(count.items(), key=operator.itemgetter(1), reverse=True)
# 返回出现频数最高的类别
return sortCount[0][0]
trainData = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
labels = ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']
testData = [18, 90]
X = knn(trainData, testData, labels, 3)
print(X)
网友评论