• 机器学习第一篇——最近邻kNN


    机器学习监督学习中,根据解决问题的连续性和离散型,分为分类问题和回归问题。最邻近算法kNN是一种最为直接和简便的分类方法。

    kNN本质上,是计算目标到模型的欧式距离,从而判定目标所属的类别。

    首先,在解决机器学习问题的时候,我们首先,其实面对这样一个问题:对数据的清洗。因为通常的,我们的程序设计语言,只能处理诸如数组,矩阵,字符,以及其他我们在程序设计中常见的一些数据类型。而通常的,我们手中的数据都是以文件的格式给出。比如.TXT格式的。

    所以,首先第一步:完成数据类型的转换:

    下面给出一段python 代码,旨在说明其中的思想:

     1 def file2matrix(filename):
     2     fr = open(filename)   #打开文件
     3     array0Lines = fr.readlines()#读取文件的内容(实际上,查看array0lines的内容时,发现文件的每一行,为一个字符串,且字符串中包含了“	(制表位,就是对其的那个东西)”,“
    ”)
     4     number0fLines = len(array0Lines)#获取行数
     5     returnMat = zeros((number0fLines,3))创造一个行数×3的矩阵
     6     classLabelVector = []创建一个空的列表,注意这里只是列表
     7     index = 0
     8     for line in array0Lines:  开始完成数据清洗
     9         line = line.strip()#去掉"
    ",但此时制表位还在,数据格式仍然是我们处理不了的,如123     0.324   2.12(数据与数据的制表位仍然在)
    10         listFromLine = line.split('	')#去掉制表位(将每个数据转化为列表式数据),如['123', '0.324', '2.12'](很明显,变成了列表数据,列表数据是字符串,是我们可以处理的)
    11         returnMat[index,:] = listFromLine[0:3]#将转化好的列表前三个数拷贝到矩阵每一行里面(主要疑问在于为什么字符串类型变成了浮点型(还是自己理解错误))
    12         classLabelVector.append(int(listFromLine[-1]))#将listFromLine列表最后一个数据先转化为整型(请记住文件中数据为字符型),再存储到classLabelVector列表中
    13 index +=1 14 return returnMat,classLabelVector

    上述Python代码的输入文件是一个n乘以4的“矩阵”数据(在文件中看起来像矩阵,但是需要转化成真正能够处理的数据类型),前三列为一组数据,最后一列为另一组数据。很明显,我们将前三列数据转化成了矩阵,最后一列数据保存成了列表。

    数据转化成了可以处理的数据,前三列的数据分别表示三个不同的参考指标。但是每个指标的量纲不一样,数量级不一样,比如第一列的数据范围是[0,1],第二列数据范围是[0,10000],第三列数据范围是[100,1000].前面说过,kNN本质上要计算欧式距离,那么这里为:sqrt((x-x1)2+(x-x2)2+(x-x3)2),但是面临这样一个问题:比如x2范围在[0,10000],很明显x2对结果的影响是很大的,从而降低了其他参考量的影响因子,但很多时候,我们需要这些影响因子具有相同的权重,甚至我们给定不同的参考因子一个不同的权重。因此,我们通常需要对数据进行归一化的处理。

    下面给出Python代码:

    1 def autoNorm(dataSet):
    2     minvals = dataSet.min(0)#min(0)获取列最小值,min(1)获取行最小值
    3     maxvals = dataSet.max(0)
    4     ranges = maxvals-minvals
    5     normDataSet = zeros(shape(dataSet))#shape()返回矩阵的行数和列数即(行,列)
    6     m = dataSet.shape[0]#我们要理解这种打点的操作,对dataSet进行shape 操作取其第一个元素,即我们获取矩阵的行数信息(也可以用shape(dataSet)[0]这种用法)
    7     normDataSet = dataSet-tile(minvals,(m,1))#tile的作用是复制,将minval数组复制成m行×1列的,这样是为了完成对应相减
    8     normDataSet = normDataSet/tile(ranges,(m,1))#tile 的作用是相同的
    9     return normDataSet,ranges,minvals #返回归一化后的数据矩阵,取值范围,最小值

    上述两个过程,完成了对数据的基本清洗工作。

    在完成数据分类之前,应该先构建一个数据分类器。这个分类器是分类的核心,Python代码如下:

    1 def classify0(inx,dataSet,labels,k):#inx 是我们要进行分类的数据,dataSet是知道类别标签的数据,labels是dataSet的类别标签。k是选择最邻近的数目
    2     dataSetSize = dataSet.shape[0]#获取行数
    3     diffMat = tile(inx,(dataSetSize,1))-dataSet#将要分类的数据复制成dataSetSize行×1列,从而保证相减的时候维数相等
    4     sqDiffMat = diffMat**2#平方运算
    5     sqDistances = sqDiffMat.sum(axis=1).sum是numpy模块中的函数,sum(axis=1)表示二维数组按照行相加,sum(axis=0)表示按列相加,很明显这里是按照行相加
    6     distances = sqDistances**0.5#开根运算
    7     sortedDistIndicies = distances.argsort()#.argsort()将数组从小到大排列,并返回其索引。比如x=([3,1,2]),则返回[1,2,0]
    8     classCout = {}#定义字典

            for i in range(k):
                voteIlabel = labels[sortedDistIndicies[i]]#返回前K个比较小的索引对应的分类
                classCout[voteIlabel] = classCout.get(voteIlabel,0)+1#?????????????????????????
            sortedClassCout = sorted(classCout.items(),key = operator.itemgetter(1),reverse = True)#????????????????????/
            return sortedClassCout[0][0]

    完成分类器的构造之后,需要完成的是,对数据测试,即从数据中选出一定的数据建立模型,剩下的数据训练模型的出错率,Python代码如下:

     1 def datingClassTest():
     2     horatio = 0.1#选定10%的数据作为检测数据
     3     datingDataMat,datingLables = file2matrix('datingTestSet2.txt')
     4     normMat,ranges,minvals = autoNorm(datingDataMat)
     5     m = normMat.shape[0]
     6     numTestVecs = int(m*horatio)#得到检测数据的数目
     7     errorcount = 0.0
     8     for i in range(numTestVecs):
     9         classifirerResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLables[numTestVecs:m],3)
    10         print("the classifier came back with:%d,the real answer is: %d"%(classifirerResult,datingLables[i]))
    11         if (classifirerResult != datingLables[i]):
    12             errorcount +=1.0#如果分类出错,分类计数加1
    13     print("the total error rate is: %f"%(errorcount/float(numTestVecs)))#计算分类错误率

    以上过程,完成了对数据完成kNN最邻近方法分类模型训练的全部过程。

    在这其中,强调这么几点:

    1上述频繁使用矩阵计算,使得程序和计算变的更加简单,但矩阵并不是python自带的数据结构,因此numpy在数学计算中是一个十分重要的python库

    2 列表是[],数组是([]),矩阵是([],[]),不要把列表当成了数组。

    3 python 是解释性语言,因此比如我们在某一个程序文件中用到kNN.py文件中的函数。我们在开头处使用了import kNN。在kNN文件中我们使用from numpy import *,在kNN文件中导入了numpy库,假如我们想在当前文件中使用numpy中的矩阵运算,并不能因为当前文件包含了kNN文件,而kNN文件中导入了numpy库,我们就认为当前文件导入了numpy。因为python 是解释性语言,因此在运行某个矩阵运算的时候,并不能找到该矩阵运算的来源,因此,我们除了要写导入了kNN,也要写重新写一句from numpy import *

  • 相关阅读:
    Lesson 43-44 Vacation Season is Approaching?
    Lesson 41-42 How would you respond?
    Lesson 37-38 Do you want to be a millionaire?
    Lesson 35-36 What did you forget?
    Lesson 33-34 Dieting
    保送
    陈老师搬书
    水题(原 USACO Mother's Milk)
    最大公约数和最小公倍数问题(luogu 1029)
    最大子矩阵(OJ 1768)
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/9615360.html
Copyright © 2020-2023  润新知