机器学习实践 之 K-近邻算法

使用此算法的前提:

k—紧邻算法属于监督学习算法。监督学习指的就是数据中有样本的标签。即我们知道样本集中的每一数据与所属分类的对应关系。
举个例子:(分类)

属性one属性two属性three标签
aabbccx

比如:假设体重、翼展、后背颜色、脚蹼这四个特征可以决定一只鸟属于什么种类。那么这里的体重、翼展、后背颜色、脚蹼这四个属于我们表中的属性。鸟属于什么种类就属于我们说的标签。所以,总而言之,k-近邻临算法其实是属于一种分类算法。注意:标签并不是说所有的样本都要有,比如我们拿来判断的样本就不需要有。因为我们的任务就是根据现有的知识去判断样本的标签。如果有了标签,那么就判断就没有意义。当然可以用来检测算法的准确度。看自己的具体应用情况

算法步骤

对未知标签的数据集中的每个样本执行以下操作:

  1. 计算已知类别数据集中的每个点与当前点的距离;
  2. 按照距离递增次序排序
  3. 选取与当前点距离最小的k个点(k是自己定义的,可以直接任意取,当然目的是使算法准确度更高)
  4. 确定k个点所在类别的出现频率
  5. 返回前k个点出现频率最高的类别作为当前点的预测分类

代码实现(Python版)

import numpy as np
import operator

def k_nearest(sample,dataSet,label,k):
	#计算样本之间的距离
    dataSetSize = dataSet.shape[0]              
    diffMat = np.tile(sample,(dataSetSize,1))-dataSet   
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
     #选择k个最近的距离
    sortedDistIndices = distances.argsort()
    classCount = {}
    for i in range(k):
        voteLabel = label[sortedDistIndices[i]]
        classCount[voteLabel] = classCount.get(voteLabel,0)+ 1
	#对距离进行排序
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

代码解读:
函数中的参数:
sample:待分类的样本
dataSet:已知样本的属性集
label:已知样本的标签
k:算法中的k值

每一行的解读:(从函数开始,带#号的不记录行号)
前面的import是导入相应的包

1:定义函数,python中的参数是不需要定义数据类型的。
2:获取数组的行数。在这里就是样本集中的数据个数。因为shape属性返回的是数组各维的维数。[0]代表第一维,即数组的行数。dataSetSize是一个整数
3:tile函数:通过后面指定的形式重复前面的数组。更多见后面的函数解读。后面的(dataSetSize,1)刚好是样本的个数。所以相当于将待分类样本副本成已经样本数,这样方便后面的计算。np.tile(sample,(dataSetSize,1))-dataSet :将待分类样本重复之后与已知样本作差,得到各个属性的差值;diffMat是numpy.ndarray类型,大小是n*m。n:dataSetSize,m:属性的个数
4:将各个属性的插值做平方.sqDiffMat是numpy.ndarray类型,大小是n*m。
5:将各个属性的值横向相加,axis=1说明横向相加,axis=0则说明是纵向相加。 sqDistances 是numpy.ndarray类型,大小是n*1。
6:将横向相加的结果开方。所以这里计算距离用的是欧式距离。distances是numpy.ndarray类型,大小是n*1。
7:按照距离的大小对数组中的元素进行排序,返回其在数组中的第几位。详情看下方面的函数解读中的argsort。sortedDistIndices是numpy.ndarray类型,大小是n*1。
8:创建一个字典
9:进行for循环。range函数是产生一个取值范围。
10:取出第i个最近的邻居的标签
11:将字典中键对应的值加1。若字典中没有这样的数据,则将键加入,操作之后,对应的值为1.因为classCount.get(voteLabel,0)说明的是,取字典中键为voteLabel的值,若没有,则将其值设为0;
11:对字典按照值的大小进行排序。reverse为True说明是反序,从大到小
12:返回第一个元素的键,即数据的分类。



函数解读:

numpy.tile

    numpy.tile(A, reps)
    Parameters:	
		A : (array_like) The input array.
		reps : (array_like)The number of repetitions of A along each axis.
	Returns:(ndarray)The tiled output array.

 案例见:[tile函数](https://docs.scipy.org/doc/numpy/reference/generated/numpy.tile.html?highlight=tile#numpy.tile)

这里也可以用
[numpy.broadcast_to](https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_to.html#numpy.broadcast_to)
相应语句替换:
diffMat = np.broadcast_to(sample,(dataSetSize,len(sample)))-dataSet 

argsort

举个例子:
>>>x = np.array([3, 1, 2])
>>> np.argsort(x)
输出:array([1, 2, 0])
解释:对于x这个数组([3,1,2]),按照从小到大的顺序对数组进行排序,那么结果应该是[1,2,3]。输出的结果就是表明:应该排在第一的数字1,他在原先的数组位置在第1位(第2个,数组的索引从0开始)。应该排在的第二的数字2,他在原先数组位置的第2位,应该排在第三的数字3,他在原先数组位置的第0位。

算法优点

精度高、对异常值敏感、无数据输入假定

算法缺点

计算复杂度高、空间复杂度高

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值