众所周知,电影可以按照题材分类,然而,题材本身是如何定义的?由谁来判定某部电影属于哪个题材?也就是说同一题材的电影具有哪些公共特征?这些都是在电影分类时必须考虑的问题。没有哪一个电影人会说自己制作的电影和以前某部电影类似,点我们确实知道每部电影在风格上的确有可能会和同题材的电影相近。通过KNN分类算法,我们可以将从某几个关键特征中寻找同类电影的分类规则,同时对新电影进行分类判断。
优点: 精度高,对异常值不敏感,无数据输入假定
缺点:计算复杂度高,空间复杂度高
适用范围:数值型和标称型
存在一个样本数据集合,也称做训练样本集,并且样本集中每个数据都存在标签,即我们有一组数据,同时知道样本中每一数据域所属分类的关系。在分类过程中,我们关系的问题是没有标签的新数据。为此,在输入新数据后,将新数据的每个特征与样本集中数据对应特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,选择样本数据集前K 个最相似数据,这就是K-近邻算法k的出处。选择k个相似数据中出现次数最多的分类,作为新数据的分类。
实施KNN分类算法
本文首先给出K-邻近算法的伪代码和实际的python代码,并对每句代码做了详细注解
其中需要用到的package有
import numpy
import operator
对未知类别属性的数据集中每个点依次执行以下操作:
(1)计算已知类别数据集中的点与当前点之间的距离;
(2)按照距离递增次序排序;
(3)选取与当前点距离最小的k个点;
(4)确定前K个点所在类别出现的频率;
(5)返回前k个点出现频率最高的类别作为当前点的预测分类
# -- coding: utf-8 --
# K-近邻算法KNN
from numpy import *
import operator
def createDataSet(): # 创建数据集和标签,具体数据集可替换,该数据为示例
group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
labels = ['A', 'A', 'B', 'B']
return group, labels
'''
classify0()函数有四个输入参数,
inX:待分类向量
dataSet:输入的训练样本集
labels:标签向量
k:表示用于选择最近邻居数目
'''
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0] # 返回训练样本集的行数
diffMat = tile(inX, (dataSetSize, 1)) - dataSet # 利用tile复制待分类向量行数使其与训练集个数相等,依次相减以矩阵形式保存
sqDiffMat = diffMat**2 # 每个元素平方
sqDistance = sqDiffMat.sum(axis=1) # 按列相加得到待分类向量与训练样本每个向量的距离平方
distances = sqDistance**0.5 # 开根号得欧式距离
sortedDistIndicies = distances.argsort() # 按行升序排列,返回下标值
classCount = {} # 初始化字典,以键值对形式按分类标签存储数量
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] # 按距离由小到大循环输出分类标签
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 以元组形式记录每种分类标签的个数,初始化为0
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
# iteritems返回一个字典迭代器,operator.itemgetter获取对象的哪些维的数据,参数为一些序号,True表示为降序
return sortedClassCount[0][0] # 最终函数返回判断次数最多的类别名,即距离最短,可能性最大的类别
# test.py
import kNN
group, labels = kNN.createDataSet()
classCount = kNN.classify0([0, 100], group, labels, 3) # 这里按照参数要求调用classCount函数,数据集,测试向量,k值均可替换
print classCount