kNN分类器简单原理

k-近邻算法的概述

        优点:精度高,对异常值不敏感,无数据输入假定

        缺点:计算复杂度高、空间复杂度高

        适用数据范围:数值型和标称型

        工作原理:存在一个样本数据集合,也称为训练样本集,并且每个样本集都存在标签,我们知道每个数据与其分类的对应关系,输入没有标签的数据之后,将新数据的每个特征与样本中数据对用的特征进行比较,然后通过算法提取样本集中特征最相似数据(最近邻)的分类标签,作为对这个心得数据的分类标签。

简单代码实现

        我们简单实现电影分类的例子,我们已知电影有两个特征,一个是接吻镜头个数,另一个是打斗镜头的个数。我们需要使用k-近邻算法将电影分为爱情片和动作片两类。

一、数据准备

我们设置了如下数据:

打斗镜头接吻镜头电影类型
3104爱情片
2100爱情片
181爱情片
10110动作片
995动作片
982动作片
1890未知

最后一行的数据是我们需要分类的数据。

我们这里采用直接创建数据。简单粗暴!

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

二、算法实现

我们需要实现如下步骤:

  1. 计算已知类别数据的点到新的数据点的距离
  2. 按照距离依次递增次序排列
  3. 选取与当前点距离最小的k个点
  4. 确定k个点所在类型出现的概率
  5. 返回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]的电影,我们预测为爱情片。

四、总结 

这里的数据仅仅只有两个特征,但是现实中我们遇到的更多的是高维数据,往往有成百上千的特征,我们在计算距离的时候可以使用欧氏距离来计算。distance = \sqrt{\left ( q_{1} - p_{1} \right)^{2} + \left ( q_{2} - p_{2} \right)^{2} + \left ( q_{3} - p_{3} \right)^{2} + ... +\left ( q_{n} - p_{n} \right)^{2}} =\sqrt{\sum_{i=1}^{n}\left ( q_{i} - p_{i} \right)^{2}}

其他步骤类似,通过距离来进行分类。

基于此,我们可以推测数据集的特征数量越多,预测的结果越准,数据集的数量越多,预测的结果越准,结果只是预测,不一定全对。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会掉头发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值