首页 > 学院 > 开发设计 > 正文

《机器学习实战》K-近邻算法代码解析(1)

2019-11-06 07:11:13
字体:
来源:转载
供稿:网友

from numpy import *   #调用numpy模块

import Operator        #调用operator模块

from os import listdir     #调用os模块

 

 

def classify0(inX, dataSet, labels, k):#定义一个有四个参数的函数,四个参数分别是,“用于输入的样本向量”,“数据集”,“标签向量”,“K的大小”

    dataSetSize= dataSet.shape[0] #读取数据集的行数,其中shape[0]是读取数据的行数

    diffMat =tile(inX, (dataSetSize,1)) – dataset#计算输入的样本向量的每个属性与样本集中的每个样本的每个属性的差值。tile(A,reps)函数,是将数组A在维度上进行重复,reps是各个维度的重复次数。这里tile(inX, (dataSetSize,1))就是将inX在行维度上不重复,在列维度上重复dataSetSize次。然后减去dataset即得到差值。

    sqDiffMat =diffMat**2#将刚刚得到的差值的每个分量进行平方运算,diffMat**2是将diffMat里面的每个元素都进行平方运算。

    sqDistances= sqDiffMat.sum(axis=1)#这一步是将上一步平方完后的式子进行按行相加。即得到sqDistances的分量就是用于输入的样本向量与数据集每个样本的欧氏距离的平方。其中.sum(axis=0或者1),axis=0代表按列相加 axis=0代表按行相加。

    distances =sqDistances**0.5 #这一步将欧氏距离的平方进行开方处理,得到distances的分量就是用于输入的样本向量与数据集每个样本的欧氏距离。distances是一个列向量。

   sortedDistIndicies = distances.argsort()     #这一步按照distances中分量的大小返回索引值。.argsort即是升序返回索引值。如argsort(array([3,1,2])),>>>array[1,2,0],这里的[1,2,0]分别代表最小的数字来自于原数组中的第二个位置,次小的数字来自于原数组中的第三个位置,最大的数字来自于原数组中的第一个位置。

   classCount={}          #创建一个空字典。

    for i inrange(k): #for循环,来找出上面欧式距离中最小的k个距离。

       voteIlabel = labels[sortedDistIndicies[i]] #第一次循环中,sortedDistIndicies[0]的数字代表欧氏距离数组distances中最小的数的索引值,labels[sortedDistIndicies[i]]就是这个最小距离的样本数据对应的标签,labels是原数据集标签数组,故就得到了最小的欧式距离对应的标签voteIlabel。

       classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#由于classCount是字典,classCount[“火车”] = “车”,这个语句代表给字典添加键值对,即{“火车”:“车”},这里就是计算每个标签出现的次数,如果classCount中之前没有这个标签,给这个标签一次,如果classCount中之前有这个标签,就将对应的值加上1。这样,最终就得到这样形式的classCount = {“A”:2,”B”:3,”C”:5},ABC分别在最小的10个中占据2个,3个,5个。

   sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1), reverse=True) #这里是将字典中的键值对按照值的大小降序排列。sort()函数,对迭代类型进行排序。classCount.iteritems(),将字典classCount的键值对转化为元祖,存放在列表中。key=operator.itemgetter(1),按照迭代类型的第n个元素进行排序。True降序排列。

returnsortedClassCount[0][0] #取列表sortedClassCount第0个对象中的第0个对象。

这个函数有“输入的样本向量”,“数据集”,“标签向量”,“K的大小”,是在输入的样本已知,数据集已经存在,k值已经确定好的情况下,K-近邻的核心算法。

 

 

 

def createDataSet():                                  #创建一个数据集

    group =array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])         #定义数据集中的属性数据

    labels =['A','A','B','B']                            #给定每个样本的标签

    returngroup, labels                             #返回数据集的属性和标签

这里只是在KNN.py模块中定义一个测试函数,以后需要调用KNN.py的函数需要用import KNN       KNN.函数名()

 

文件

1,2,3,1

3,4,5,1

1,1,1,2

def file2matrix(filename):             #定义一个函数,这个函数的参数是文件名。

fr = open(filename)             #打开文件,并赋值给fr这里fr是一个文本对象

arrayOLines = fr.readlines()       #读取整个文本,按行以字符串的形式存储在列表中,并且每个字符串后面借一个换行符。

形如:['1,2,3,1/n', '3,4,5,1/n', '1,1,1,2']

 

 

   numberOfLines = len(arrayOLines)        #读取数据的总行数,这里就是列表中有几个字符串 3

returnMat =zeros((numberOfLines,3))        #创建一个3(3个样本)行,3(3个属性)列的0矩阵。之后会用来存储属性值

([0,0,0]

[0,0,0]

[0,0,0])

   classLabelVector = []                       #创建一个空列表,之后用来存储标签。

    index = 0                                 #创建一个初始值为0的变量

for line in arrayOLines:                      #用for循环来提取每个样本的属性值

每一次提取都是提取出的字符串,如第一次,则有line = '1,2,3,1/n'

        line =line.strip()                        #删除字符串line中的空白值,这里就是删除/n这个换行符。

       变成了'1,2,3,1'

       listFromLine = line.split('/t')               #这里用tab字符将字符串切割,并以列表的形式储存。(不明白这里为什么要用换行符,不用也能得到一样的结果)

              得到['1,2,3,1']这个列表

       returnMat[index,:] = listFromLine[0:3]      #将得到的列表的的前三个元素,赋值给numpy矩阵的第0行。

       ([1,2,3]

[0,0,0]

[0,0,0])

       classLabelVector.append(int(listFromLine[-1]))      #将得到的矩阵的最后一列赋值给标签列表,且必须是整型!

        index +=1                                    #将index加上1,下次就提取第1个字符串。

returnreturnMat,classLabelVector                    #返回矩阵和标签列表,就得到的我们需要的数据格式。

这个函数的参数是文件名,作用是将导入的数据转化为我们需要的格式。

 

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表