KNN Algorithm

1 KNN Algorithm

    1.1 KNN工作原理
 
“存在一个样本数据集,也称为训练样本集trainSet,每一个样本数据集中都对应一个标签labe,即我们知道样本集中的每一个数据与所分类之间的关系。 输入没有标签的数据后,将新输入的数据的特征与样本数据集中的特征比较,然后算法提取出特征最相似数据(最近邻)的分类标签 ,一般来说,我们只选择K个最相似的数据,通常K是不超过20 的整数。”

与trainSet中的数据特征值比较,是采用距离比较,这里采用 欧式距离 ,对于距离探究见参考文档1(CSDN对距离的各种描述)

在python中对该算法的实现:

"KNN Algorithm"
      def   knnClassify ( self , inx , dataset , labels , k )      
          dataSetSize   =   dataset.shape [ 0 ]        #读取训练集矩阵的行数
        diffMat   =   tile ( inx ,   ( dataSetSize , 1 ))   -   dataset 
        sqDiffMat   =   diffMat   **   2
        sqDistances   =   sqDiffMat.sum ( axis = 1 )       #计算欧式距离
        distance   =   sqDistances   **   0.5      
        sortedDistIndicies   =   distance.argsort ()   #对计算得到的距离排序
         classCount   =   {}     #分类集合
        for   i   in   range ( k ) :
            votelabel   =   labels [ sortedDistIndicies [ i ]]
            classCount [ votelabel ]   =   classCount.get ( votelabel , 0 )   +   1
        sortClassCount   =   sorted ( classCount.iteritems () , key   = operator.itemgetter ( 1 ) , reverse = True )
          return   sortClassCount [ 0 ][ 0 ]
         pass
    
    1.2 数据收集与预处理

一般我们都是从文本中得到并解析文件,所以我们需要做一个def,从文本中读取数据的函数:
"read data from the file"
      def   readfile ( self , path ) :
          self .path   =   path
        fr   =   open ( self .path , "r+" )
        arrayLines   =   fr.readlines ()
        numberlines   =   len ( arrayLines )            #读取行数
        getMat   =   zeros (( numberlines , 3 ))        #构建等行量矩阵
        classlabelVector   =   []
        index   = 0
          for   line   in   arrayLines:
             line   =   line.strip ()       #截取所有回车字符
            linePromLine   =   line.split ( '\t' )  #将整行分割成一个列表
            getMat [ index , : ]   =   linePromLine [ 0 :3 ]        #赋值矩阵
            classlabelVector.append ( float ( linePromLine [ - 1 ])) #添加分类
            index   +=   1
          return   getMat , classlabelVector
   

有时候我们的数据采用欧式距离,其中某些特征值数据过大,会影响我们的特征值比较结果,而且我们更想要一个等权特征值,所以进一步做数据归一化,将取值范围归到0-1之间或者-1-1之间,增加一个def autoNorm处理归一化数据
    
"deal data to normDataaet"
      def   autoNorm ( self , dataSet ) :
          self .dataSet   =   dataSet
        minVals   =   self .dataSet.min ( 0 )
        maxVals   =   self .dataSet.max ( 0 )
        ranges   =   maxVals   -   minVals
        m   =   self .dataSet.shape ( 0 )
        normDataSet   =   self .dataSet   -   tile ( minVals , ( m , 1 ))     #重点理解
        normDataSet   =   normDataSet / tile ( ranges , ( m , 1 ))
          return   normDataSet , ranges , minVals
  

完成对数据的收集与预处理之后,我们需要评估算法的正确性,即 算法的正确率,通常我们只提供90%作为训练样本来训练分类器,而使用其余10%数据去测试分类器,检测分类器的正确率 。我们写一个测试函数,来检测分类器的正确率:

"testing the KNN Algorithm"
def   test () :   
    knn   =   textClassify ()                                #这是我放在一个类中,生成的对象
    hoRatio   =   0.10
    dataMat , dataLabels   =   knn.readfile ( 'testdata.txt' )  #获取数据
    normMat , ranges , minVals   =   knn.autoNorm ( dataMat )  #得到归一化数据集矩阵
    m   =   normMat.shape [ 0 ]
    numtestVecs   =   int ( m * hoRatio )
    errorCount   =   0.0                           #错误计数
      for   i   in   range ( numtestVecs ) :
        classifierResult   =   knn.knnClassify ( normMat [ i , : ] , normMat [ numtestVecs:m , : ] ,   dataLabels [ numtestVecs:m ] ,   3)            #分类结果 )  
          print   "the classifier came back with:%d,the real answer is %d"   %   ( classifierResult , dataLabels [ i ])               
          if   ( classifierResult   !=   dataLabels [ i ]) :
            errorCount   +=   1
          print   "the classifier error rate is : %f"   %   ( errorCount / float ( numtestVecs ))
                                                  #计算错误率

经过以上的小结,可以基本完成一个分类系统:

"build the completion system"
def   classify () :
     knn   =   textClassify ()
    resultList   =   [ 'one' , 'two' , 'three' ]                    #测试向量
    num1   =   float ( raw_input ( "the first   num :\n" ))
    num2   =   float ( raw_input ( "the second   num :\n" ))
    num3   =   float ( raw_input ( "the third   num :\n" ))
    dataMat , dataLabels   =   knn.readfile ( 'testdata.txt' )
    normMat , ranges , minVals   =   knn.autoNorm ( dataMat )
    inArr   =   array ([ num1 , num2 , num3 ])
    classifierResult   =   knn.knnClassify (( inArr - minVals ) / ranges ,   normMat ,   dataLabels ,   3 )
      print   "the classifierResult you get is : " , resultList [ int ( classifierResult   - 1 )]

这就是KNN算法的基本内容,在过程中为了能更好的体现数据的可视化效果,也可以通过matplotlib库来展示数据集效果

  "draw the data group"
      def   draw ( self , dataMat , dataLabels , classfeature ) :
        fig   =   plt.figure ()
        ax   =   fig.add_subplot ( 111 )
           if   classfeature   ==   1 :
            ax.scatter ( dataMat [ : , 1 ] , dataMat [ : , 2 ] , 15.0 * array ( dataLabels ) , 15.0 * array ( dataLabels ))
            plt.xlabel ( "second data" )
            plt.ylabel ( "third data" )
          elif   classfeature   == 2 :
          ax.scatter ( dataMat [ : , 1 ] , dataMat [ : , 0 ] , 15.0 * array ( dataLabels ) , 15.0 * array ( dataLabels ))
            plt.xlabel ( "second data" )
            plt.ylabel ( "first data" )
          elif   classfeature   == 3 :
            ax.scatter ( dataMat [ : , 0 ] , dataMat [ : , 2 ] , 15.0 * array ( dataLabels ) , 15.0 * array ( dataLabels ))
            plt.xlabel ( "first data" )
            plt.ylabel ( "third data" )
        plt.show ()

K-近邻算法是非常有效简单的算法,但是存在着很大的不足:
1 需要对训练集中的每个数据计算距离值,实际使用在考虑非常大的数据的时候非常耗时(计算复杂度高)
2 无法给出数据的基础结构信息,因此无法知道平均实例样本和典型实例样本具有什么特征

    1.3 实战项目: 使用KNN算法改善约会网站

通过对以上KNN算法的探究,我们可以做一个实际的小项目 使用KNN算法改善约会网站, 需要的只是对数据集的收集。比如准备数据
trainSet { 年龄 身高 体重 收入 课余活动时长.......等等}
labelList { 不感兴趣:A ;一般感兴趣:B;十分感兴趣:C;可望立即交往:D}
根据上面的步骤即可简单的得到一个分类结果:你可能对谁“感兴趣”。当然,在这个过程中,我们需要人工的为每一个数据添加label分类,这是一个监督学习的特征,工作量还是蛮大的!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值