k-近邻算法的概述
优点:精度高,对异常值不敏感,无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
工作原理:存在一个样本数据集合,也称为训练样本集,并且每个样本集都存在标签,我们知道每个数据与其分类的对应关系,输入没有标签的数据之后,将新数据的每个特征与样本中数据对用的特征进行比较,然后通过算法提取样本集中特征最相似数据(最近邻)的分类标签,作为对这个心得数据的分类标签。
简单代码实现
我们简单实现电影分类的例子,我们已知电影有两个特征,一个是接吻镜头个数,另一个是打斗镜头的个数。我们需要使用k-近邻算法将电影分为爱情片和动作片两类。
一、数据准备
我们设置了如下数据:
打斗镜头 | 接吻镜头 | 电影类型 |
3 | 104 | 爱情片 |
2 | 100 | 爱情片 |
1 | 81 | 爱情片 |
101 | 10 | 动作片 |
99 | 5 | 动作片 |
98 | 2 | 动作片 |
18 | 90 | 未知 |
最后一行的数据是我们需要分类的数据。
我们这里采用直接创建数据。简单粗暴!
import numpy as np
import operator
def createData():
data = array([[3, 104],
[2, 100]
[1, 81]
[101, 10]
[99, 5]
[98, 2]])
labels = {'爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片'}
return data, labels
二、算法实现
我们需要实现如下步骤:
- 计算已知类别数据的点到新的数据点的距离
- 按照距离依次递增次序排列
- 选取与当前点距离最小的k个点
- 确定k个点所在类型出现的概率
- 返回k个点出现概率最高的类别作为当前点的预测分类
"""
inX:新的数据点
dataSet:训练集矩阵
labels:训练集对应的标签集
"""
def classify(inX, dataSet, labels, k):
# 返回数据集的大小,shap()返回为(行数,列数),这里我们只需要行数
dataSetsize = dataSet.shape[0]
# 我们使用numpy的tile()方法,构造了一个每一行都为新的数据,一共和训练集一样多行的矩阵,并且让他们减去训练集这个矩阵
diffMat = np.tile(inX, (dataSetsize, 1)) - dataSet
# 将diffMat矩阵每个元素都平方
sqDiffMat = diffMat ** 2
# 将diffMat矩阵的每一行相加,返回得到一个1*6的矩阵,sum()函数中的参数axis=1的时候意味着让每一行相加,为0的时候为列相加
sqDistance = sqDiffMat.sum(axis=1)
# 将sqDistance再开一个根号,得到距离,此时distance存储的是新的数据点到每个数据的距离
distance = sqDistance ** 0.5
# 将得到的距离根据大小进行排序,并返回他们的序号的排序来体现大小,例如[4,8,1,6]的返回为[1,0,3,2]
sortedDistIndicies = distance.argsort()
# 创建一个空的字典,用来存储k个数据中电影类型和个数
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
# 使用get()函数将k个数据中的电影类型和所占个数对应
# get(voteIlabel, 0)表示取键为’voteIabel‘的值,如果没有值,则为设置为0,如果有,则返回该值
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# sort()方法根据classCount的值的大小进行排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
# 返回第一个键值对的键
return sortedClassCount[0][0]
三、程序结果展示
if __name__ == '__main__':
newdata = [18, 90]
data, group = createData()
result = classify(newdata, data, group, 3)
print("预测这部未知电影的类型为:" + result)
对于[18,90]的电影,我们预测为爱情片。
四、总结
这里的数据仅仅只有两个特征,但是现实中我们遇到的更多的是高维数据,往往有成百上千的特征,我们在计算距离的时候可以使用欧氏距离来计算。
其他步骤类似,通过距离来进行分类。
基于此,我们可以推测数据集的特征数量越多,预测的结果越准,数据集的数量越多,预测的结果越准,结果只是预测,不一定全对。