机器学习实战(一)----KNN

kNN算法是一种简单有效的lazy-learning算法,适用于样本容量较大的类域自动分类。本文介绍kNN算法的工作原理,包括分类和回归应用,并探讨其在样本不平衡及计算量方面的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     kNN算法本身简单有效,它是一种lazy-learning算法,分类器不需要使用训练集进行训练,训练时间复杂度为0。kNN分类的计算复杂度和训练集中的文档数目成正比,也就是说,如果训练集中文档总数为n,那么kNN的分类时间复杂度为O(n)。

KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成正比。

     该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的 K个邻居中大容量类的样本占多数。因此可以采用权值的方法(和该样本距离小的邻居权值大)来改进。该方法的另一个不足之处是计算量较大,因为对每一个待分 类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该 算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。

kNN算法本身简单有效,它是一种lazy-learning算法,分类器不需要使用训练集进行训练,训练时间复杂度为0。kNN分类的计算复杂度和训练集中的文档数目成正比,也就是说,如果训练集中文档总数为n,那么kNN的分类时间复杂度为O(n)。

from numpy import *
import operator


def createDataSet():
    '''
    创建训练集以及对应的分类标签
    :return: 返回集合和分类标签
    '''
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group, labels


def classify0(intX,dataSet,labels,k):
    '''
    k均值算法分类器简单实现
    :param intX: 输入待测样本
    :param dataSet: 训练集合
    :param labels: 已知分类标签
    :param k: 最近的k个样本点
    :return: 返回待测样本点的分类结果
    '''
    # 获取已知样本行数
    dataSetSize = dataSet.shape[0]
    # tile 表示重复A 输出,计算intX 与每个样本的差值
    diffMat = tile(intX,(dataSetSize,1)) - dataSet
    # 每个值取平方
    sqDiffMat = diffMat**2
    print "sqDiffMat = %s" % sqDiffMat
    # 欧式距离 axis=1 行之和,0 列之和
    sqDistances = sqDiffMat.sum(axis=1)
    print "sqDistances = %s" % sqDistances
    # 开平方
    distances = sqDistances**0.5
    # 返回从小到大的索引值
    sortedDistIndieies = distances.argsort()

    classCount = {}
    # 取最近的k个样本点
    for i in range(k):
        voteIlabel = labels[sortedDistIndieies[i]]
        # 用字典保存最近样本点的次数
        classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
    sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
    # 返回出现最高的那一个分类
    print sortedClassCount[0][0]

if '__main__==__name__':
    dataSet,labels = createDataSet()
    # print dataSet
    # print labels
    classify0([0,0],dataSet,labels,3)
结果:

sqDiffMat = [[ 1.    1.21]
 [ 1.    1.  ]
 [ 0.    0.  ]
 [ 0.    0.01]]
sqDistances = [ 2.21  2.    0.    0.01]
B


该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的 K个邻居中大容量类的样本占多数。因此可以采用权值的方法(和该样本距离小的邻居权值大)来改进。该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该 算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值