机器学习实战笔记(二):K邻近算法

时间:2021-12-13 01:23:37
<span style="font-size:12px;">from numpy import *
import operator

def classify0(inX,dataSet,labels,k): #inX:用于分类的输入向量;dataSet:输入的训练样本集;labels:标签向量(labels的数目与dataSet行数相同);k:选择的最近邻居的数目
dataSetSize=dataSet.shape[0] #dataSet.shape[0]:读取dataSet矩阵第一维度的长度
diffMat=tile(inX,(dataSetSize,1))-dataSet #tile():重复某个数组,这里(dataSetSize,1),是一个元组让inX这个数组重复dataSetSize个变为一个矩阵 分别减去dataSet的
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1) #sum(axis=1)将矩阵的每一行向量相加
distances=sqDistances**0.5 #计算距离
sortedDistIndicies=distances.argsort() #argsort()返回数组中从小到大的索引值,确定前k个距离的元素所在的分类
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]] #输入k总是正整数,sorted()产生一个新的列表,存放前k个距离元素的分类 放到vootellabel中
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1#在classCount字典中存放这个分类数组,再查看字典中是否有相同的分类,没有返回0,有就返回那个类+1
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0] #将classCount分解为元组列表,按照第二个元素(即元素的类出现的次数)从大到小排列,返回频率最高的元素标签

def creatDataSet():
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group,labels #第一个例子,导入group元组和labels列表,并测试

def file2matrix(filename): #第二个例子,约会分类器,有一个参数:需要导入的文件名
fr=open(filename) #打开文件,保存在fr中
arrayOLine=fr.readlines() #.readlines()读去整个文件,并自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for... in ... 结构进行处理
numberOfLines=len(arrayOLine)
returnMat=zeros((numberOfLines,3)) #创建一个numberOfLine*3的0矩阵,保存在returnMat中,3是因为要配合样本的大小
classLabelVector=[]
index=0
for line in arrayOLine:
line=line.strip() #使用strip()街去掉所有的回车字符
listFromLine=line.split('\t') #使用tab字符将上一步得到的数据分割行,成为一个元素列表
returnMat[index,:]=listFromLine[0:3] #取该行前三个元素,储存在特征矩阵(训练样本)中
classLabelVector.append(listFromLine[-1]) #取改行标签数据存入标签矩阵
index+=1
return returnMat,classLabelVector #返回训练样本矩阵和标签矩阵

def autoNurm(dataSet): #数据归一化,公式:newvalue=(oldvalue-min)/(max-min)
minVals=dataSet.min(0) #获得每列最小值
maxVals=dataSet.max(0) #获得每列最大值
ranges=maxVals-minVals #获得每列特征的取值范围
normDataSet=zeros(shape(dataSet)) #构建形同dataSet的0矩阵
m=dataSet.shape[0] #读取dataSet矩阵第一维度的长度
normDataSet=dataSet-tile(minVals,(m,1)) #构建一个重复m次的由每行最小值重复形成的数组,用dataSet,即每行数据对应相减
normDataSet=normDataSet/tile(ranges,(m,1)) #构建一个重复m次的由每行最大最小值之差重复形成的数组,对应相除,得到归一化后的数组
return normDataSet,ranges,minVals #返回归一化后的数组,每行最大最小值之差形成的数组,每行最小值形成的数组

def datingClassTest():
hoRatio=0.10
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
normMat,ranges,minVals=autoNurm(datingDataMat)
m=normMat.shape[0]
numTestVecs=int(m*hoRatio) #设置测试个数
errorCount=0.0 #计算错误数量
for i in range(numTestVecs):
classifierResult=classify0(normMat[i,:],normMat
[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print "the classifier came back with: %s,the real answer is: %s" % (classifierResult,datingLabels[i])
if (classifierResult!=datingLabels[i]):errorCount+=1.0 #计算错误率
print "the total error rate is %f" % (errorCount/float(numTestVecs))
print errorCount

def classifyPerson():
resultList=['not at all','in small doses','in large doses']
percentTats=float(raw_input("percentage of time spent playing vadio games?"))
ffMiles=float(raw_input("frequent flier miles earned per year?"))
iceCream=float(raw_input("liters of ice cream consumed per year?"))
datingDataMat,datingLabels=file2matrix('datingTestSet.txt')
normMat,ranges,minVals=autoNurm(datingDataMat)
inArr=array([ffMiles,percentTats,iceCream])</span>

1.优点:精度高,对异常值不敏感,无数据输入假定

  缺点:计算复杂度和空间复杂度高

  适用数据类型:数值型和标称型

2.工作原理:存在一个样本数据集合,也称训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与对应所属分类的关系。输入没有标签的新数据后,将新数据的每个特征与样本集中的数据的对应特征进行比较,算法提取出样本集中特征最相似(最邻近)的数据的分类标签,一般取前K个最相似数据(K<=20)

3.算法中所需要的计算公式:

   1>向量点之间的距离:机器学习实战笔记(二):K邻近算法(多维向量以此类推)

   2>归一化数据:机器学习实战笔记(二):K邻近算法(可将任意取值范围的数据转化为0-1区间内的值)