一、K近邻算法
KNN是一种监督学习类别的算法,全称(K-NearestNeighbor)直译为K个最近的邻居,是一种聚类算法。该算法认为我们在判断一个物体的类别可以根据与他非常相似的K个物体的类别(这K个物体的类别是已知的)来决定。其工作机制是给定一个新的测试样本,基于某种距离度量找出训练集中离该新样本最近的前K个样本(训练集中样本标签已知),基于这K个样本的标签信息来预测新样本的类别,通常,在这K个样本中出现最多次数的类别标签即被预测为新样本的类别标签。
二. 使用Python导入数据
首先创建一个KNN.py文件,在文件中输入以下代码:
from numpy import * #导入numpy库
import operator #导入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
保存KNN.py文件,并改变当前路径到存储KNN.py的位置,打开Python开发环境。
输入以下代码导入KNN模块:
group,labels=KNN.createDataSet()
print(group)
print(labels)
输出为:
[[1. 1.1][1. 1. ][0. 0. ][0. 0.1]]
['A', 'A', 'B', 'B']
三、从文本中解析数据
具体代码如下:
def calssify0(inX,dataSet,labels,k): dataSetSize=dataSet.shape[0] diffMat=numpy.tile(inX,(dataSetSize,1))-dataSet sqDiffMat=diffMat**2sqDistances=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 sortclassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) return sortclassCount[0][0]
即通过欧式距离公式,计算两点的距离并选择距离最小的K个点并排序
欧式距离公式:
文本数据:
四、示例:
海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的
人选,但她并不是喜欢每一个人。经过一番总结,她发现曾交往过三种类型的人:
不喜欢的人
魅力一般的人
极具魅力的人
尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归入恰当的分类。她觉得可以在周一到周五约会那些魅力一般的人,而周末则更喜欢与那些极具魅力的人为伴。海伦希望我们的分类软件可以更好地帮助她将匹配对象划分到确切的分类中。此外海伦还收集了一些约会网站未曾记录的数据信息,她认为这些数据更有助于匹配对象的归类。
1.从文本文件中解析数据:
海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,每
个样本数据占据一行,总共有1000行。海伦的样本主要包含以下3种特征:
每年获得的飞行常客里程数
玩视频游戏所耗时间百分比
每周消费的冰淇淋公升数
在将上述特征数据输入到分类器之前,必须将待处理数据的格式改变为分类器可以接受的格式。在kNN.py中创建名为file2matrix的函数,以此来处理输入格式问题。该函数的输入为文件名字符串,输出为训练样本矩阵和类别标签向量。
def files2matrix(filename):fr=open(filename)arraylines=fr.readlines() lenoflines=len(arraylines) #返回集合长度,这里的集合一行为一个元素matrix=np.zeros((lenoflines,3))#创建全0矩阵,行数为lenoflines,列数为3labelmatrix=[] #创建空集合index=0for line in arraylines:line=line.strip() listFromline=line.split('\t') matrix[index,:]=listFromline[0:3] labelmatrix.append(int(listFromline[-1])) index+=1return matrix,labelmatrix
2.分析数据:使用Matplotlib 创建散点图
import matplotlib
import matplotlib.pyplot as plt
import pylab
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] #使中文字符能被显示在图表中
fig=plt.figure()
ax=fig.add_subplot(111) #图表画在分成一行一列的第一个表格中
ax.scatter(datingDataMat[:,0],datingDataMat[:,1],15*np.array(datingLabels),15*np.array(datingLabels))
ax.set_xlabel('玩视频游戏所耗时间百分比')
ax.set_ylabel('每周所消费的冰淇淋公升数')
plt.show()
3.未写色彩标记代码
ax.scatter(datingDataMat[:,0],datingDataMat[:,1],15*np.array(datingLabels),15*np.array(datingLabels))
输出效果:
加入色彩标记后效果:
5.归一化特征值代码:
import numpy as np
def autoNorm(dataSet):minVals = dataSet.min(0) maxVals = dataSet.max(0) ranges = maxVals - minVals normDataSet = np.zeros(np.shape(dataSet)) #创建形状大小与dataSet一样的0矩阵m = dataSet.shape[0] #m为dataSet行数normDataSet = dataSet - np.tile(minVals, (m,1)) normDataSet = normDataSet/np.tile(ranges, (m,1)) return normDataSet, ranges, minVals
6.测试算法代码:
def datingClassTest():hoRatio = 0.50 datingDataMat,datingLabels = files2matrix('datingTestSet2.txt') m = normMat.shape[0] #获取normMat的行数numTestVecs = int(m*hoRatio)errorCount = 0.0for i in range(numTestVecs):classifierResult =calssify0(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" % (errorCount/float(numTestVecs)))
7.使用算法:构建完整可用系统
上面我们已经在数据上对分类器进行了测试,现在终于可以使用这个分类器为海伦来对人们分类。我们会给海伦一小段程序,通过该程序海伦会在约会网站上找到某个人并输入他的信息。程序会给出她对对方喜欢程度的预测值
def classifyperson():resultList=['not at all','in small doses','in large doses']percentTats=float(input("percentage of tiome spent playing video games?")) ffMiles=float(input("frequent flier miles earned per year?"))iceCream=float(input("liters of ice cream consumed per year?"))datingDatMat,datingLabels=files2matrix('datingTestSet2.txt') #读取文件normMat,ranges,minVals=autoNorm(datingDatMat) #数据归一化inArr=np.array([ffMiles,percentTats,iceCream]) #创建数组classifierResult=calssify0((inArr-minVals)/ranges,normMat,datingLabels,3) print("You will probably like this person:",resultList[classifierResult-1])
输出结果:
classifyperson()
out:
percentage of tiome spent playing video games?100frequent flier miles earned per year?90liters of ice cream consumed per year?10
You will probably like this person: in large doses
注:以上代码来自于《机器学习实战》