K--近邻算法解析

代码测试环境:Python,需要安装Numpy库

首先讲解关于K--近邻算法的工作原理:

       K--近邻算法的工作原理是根据所给已知标签的数据集计算出与未知标签数据的最近的K个数据,这K个数据的标签中所占比重最大的那个数据的标签即为所要预测数据的标签。下面进行详细解释一下:假设现在有一个已知标签数据的样本,它包含5个属性值,则这个样本被称作训练样本集。当输入一个没有标签的数据样本时。训练样本中的所有数据就会计算与这个没有标签的数据样本之间的距离(具体的计算公式稍后会详细讲解),最后得出与这个测试样本之间最近的K个训练样本数据。K一般不超过20.最后选择出这K个相似数据中出现最多的分类作为预测数据的分类。

详细讲解K--近邻算法的实现过程:

       首先创建一个名为KNN.py的文件在KNN.py中添加如下代码:

from numpy import *
import operator
def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group, labels

    在上面的代码中首先导入了一个计算包NumPy,还有一个运算符模块operator。接下来createDataSet()函数用于创建一个数据集和标签,首先是一个二维数组接下来是其对应的标签。从文件中输入的数据格式也像上面一样,这里为了讲解自己创造的数据集。接下来开始真正的实施KNN算法,在KNN.py文件中加入如下代码:

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()     
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]
  这个函数有四个输入参数,inX为测试数据集,dataSet是去除标签的训练数据集,labels是标签列表,k是要预测的最相似数据集的个数。

  首先计算出训练数据集中所包含数据的条数。接下来的第3~~6行是进行距离的计算。这里用到的距离计算公式是欧氏距离计算公式,也就是我们从初中就用到的两点之间的距离计算公式。对!没错!这里不再具体解释。计算出所有训练数据到预测点的距离之后就要对其进行排序,然后取出距离测试点最近的K个点。最后根据最近的点的出现次数进行排序,这里按照从大到小的顺序进行排序,所以第一个就是我们想要的最佳答案。


接下来我们根据具体的数据进行算法的实现,我们所使用的数据格式如下所示:datingTestSet.txt下载 (提取码:6fa1)

40920	8.326976	0.953952	largeDoses
14488	7.153469	1.673904	smallDoses
26052	1.441871	0.805124	didntLike
75136	13.147394	0.428964	didntLike
38344	1.669788	0.134296	didntLike
72993	10.141740	1.032955	didntLike
35948	6.830792	1.213192	largeDoses
42666	13.276369	0.543880	largeDoses
67497	8.631577	0.749278	didntLike
35483	12.273169	1.508053	largeDoses
50242	3.723498	0.831917	didntLike
63275	8.385879	1.669485	didntLike
5569	4.875435	0.728658	smallDoses
51052	4.680098	0.625224	didntLike
77372	15.299570	0.331351	didntLike
43673	1.889461	0.191283	didntLike
61364	7.516754	1.269164	didntLike
69673	14.239195	0.261333	didntLike
15669	0.000000	1.250185	smallDoses
28488	10.528555	1.304844	largeDoses
6487	3.540265	0.822483	smallDoses
37708	2.991551	0.833920	didntLike

这里的前三列是属性列,最后一列是标签列。这里我们首先将文本解析为算法能够读取的格式。在KNN.py文件中添加下面这个函数:

def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         
    returnMat = zeros((numberOfLines,3))       
    classLabelVector = []                      
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector

这个函数比较简单这里不再详细介绍,就是将数据解析为属性矩阵和标签列表,和上面的数据格式一样。接下来我们需要对数据进行准备工作:

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   
    return normDataSet, ranges, minVals
这个函数的主要功能是对数据进行归一化。这里进行归一化的原因是避免在计算两点之间的距离是由于其中一个属性之间相差较大影响其他属性在计算中发挥的作用。这里的归一化就是使其所有属性值都处于0到1之间,具体的做法就是找到每个属性中的最小值和最大值,然后用现有属性之减去最小值除以最大值和最小值的差。这就是上面的代码完成的工作。好了!到这里大部分工作基本已经完成,最后要做的就是进行测试:

def datingClassTest():
    hoRatio = 0.10
    datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
    normMat,ranges,minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classifyO(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        print "the classifier came back with : %d ,the real answer is ; %d " % (classifierResult , datingLabels[i])
        if (classifierResult != datingLabels[i]):
            errorCount += 1.0
    print "the total error rate is : %f the error number is %d" % (errorCount /float(numTestVecs),errorCount)
这个函数是对上面的代码进行测试,我们注意到里边有一个变量hoRatio这个变量决定有多少数据是训练数据,多少数据是测试数据。所以我们可以改变它的值来观察预测结果的变化。同时我们也可以改变K的之来进行结果的观察。我们可以在IDLE终端输入KNN.datingClassTest()观察输出结果。到这里我们已经完成算法的所有代码的实现。KNN算法总体来说并不难,很容易理解。下一节我将为大家展示一个实例的应用。


   小弟在这献丑了,希望能给大家一点帮助,欢迎大家前来围观更欢迎大家七嘴八舌!骂人


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值