k-近邻算法 Python实现

首先讲,什么是k-近邻算法?

k-近邻算法是一种有监督学习方法,即训练样本中的每个样本的类别标签都是已知的。对于一个新来的样本,我们将它的特征与训练样本集中的每个样本进行特征比较,然后算出与该样本最相似的k个样本,利用投票法,将k个样本中类别出现次数最多的那个类作为新来样本的类别。特别地,当k=1时,k-近邻算法就简化为最近邻分类算法。

其中刻画相似性的度量方法有:欧氏距离、曼哈顿距离、切比雪夫距离、马氏距离等等。常用的是欧式距离。


k-近邻算法

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

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

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


我们结合例子来进行讲解:为了简单起见,假设训练集中存在四个样本,它们分别是二维平面上的四个点,(1.0,1.1)、(1.0,1.0)、(0,0)、(0,0.1),假定分别属于A、A、B、B类,明显这是一个二分类问题。测试数据是(0.5,0.5),我们的目标是根据k-近邻算法判定(0.5,0.5)属于哪一类。

首先创建训练数据集,添加createDataSet()函数:

from numpy import *
import operator

def createDataSet():
    group = [[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]
    labels = ['A','A','B','B']
    return group,labels

group,labels = createDataSet()

print("样本的特征:")
print(group)
print("样本的标签:")
print(labels)

结果如下:


然后,我们为了便于理解,把每个步骤的运算结果打印出来(使用欧式距离)。

print(len(group))      #得到训练集中样本数量

diffMat = tile([0.5,0.5],(len(group),1)) - group   #将新样本数据与训练集中的每个样本作差
print(diffMat)

sqDiffMat = diffMat**2        #差的平方
print(sqDiffMat)

sqDistances = sqDiffMat.sum(axis=1)    #作和
print(sqDistances)

distances = sqDistances**0.5      #开根号,求欧式距离
print(distances)

sortedDistanceIndices = distances.argsort()   #根据距离大小由大到小排序,并将其索引输出
print(sortedDistanceIndices)

classCount = {}               #一个字典,记录每个标签和它对应的次数
labels = ['A','A','B','B']
for i in range(3):            #假设k=3
    voteLabel = labels[sortedDistanceIndices[i]]    #得到前三个的标签
    classCount[voteLabel] = classCount.get(voteLabel,0) + 1  #将对应的标签的value加1
print(classCount)

sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)  #根据value的大小对字典进行排序
print(sortedClassCount)
print(sortedClassCount[0][0])    #得到新样本的类别

运行结果:


从结果中,我们可以看到根据k-近邻算法,该新样本属于B类。

下面,我们写一个函数classify()将以上代码综合起来,方便以后又来了一个新样本,可以直接调用classify函数识别。

from numpy import *
import operator

def createDataSet():
    group = [[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]
    labels = ['A','A','B','B']
    return group,labels

group,labels = createDataSet()

def classify(input,dataSet,labels,k):
    dataSetSize = len(dataSet)
    diffMat = tile(input,(dataSetSize,1)) - group
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistanceIndices = distances.argsort()
    classCount = {}
    for i in range(k):
        voteLabel = labels[sortedDistanceIndices[i]]
        classCount[voteLabel] = classCount.get(voteLabel,0) + 1
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

print(classify([0.5,0.5],group,labels,3))


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值