机器学习——K-近邻算法
来源:互联网 发布:js怎么使用正则表达式 编辑:程序博客网 时间:2024/05/22 22:21
简而言之,k-近邻算法采用测量不同特征值之间的距离来进行分类。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用数据范围:数值型和标称型(目标变量的结果只在有限目标集中取值)。
算法的工作原理:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的关系。输入没有标签的新数据后,将数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法的出处。通常k是不大于20的整数,最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
k-近邻算法的一般流程:
(1)收集数据:可以使用任何方法。
(2)准备数据:距离计算所需的数值,最好是结构化的数据格式。
(3)分析数据:可以使用任何方法。
(4)测试算法:计算错误率。
(5)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。
下面是一个使用k-近邻算法改进约会网站配对效果的实例。
数据中主要包含了3个属性,分别是:(1)每年获得的飞行常客里程数(2)玩视频游戏所耗时间百分比(3)每周消费冰淇淋公升数。以及最后约会的满意程度,1:不喜欢;2:比较喜欢;3:非常喜欢。
部分数据的截图如下:
首先,我们需要创建一个函数,该函数用于解析数据文件中的信息,并最终返回我们所需的训练样本集和对应的类标签向量。函数的具体定义如下:
def file2matrix(filename): fr = open(filename) numberOfLines = len(fr.readlines()) #获取文件的总行数 returnMat = zeros((numberOfLines,3)) #初始化一个0矩阵 classLabelVector = [] fr = open(filename) index = 0 for line in fr.readlines(): line = line.strip()#删除前、后的空白符 listFromLine = line.split('\t')#将3个属性和分类放入列表listFromLine returnMat[index,:] = listFromLine[0:3]#依次装入了属性值 classLabelVector.append(int(listFromLine[-1]))#将最后的分类情况添加到classLabelVector中 index += 1 return returnMat,classLabelVector#返回提取到的属性矩阵和分类向量
将数据解析之后,我们可以进行一些可视化的展示,主要代码如下:
#解析文件,获得数据datingDataMat, datingLables = kNN.file2matrix('E:/PythonItem/DateSet/datingTestSet2.txt')fig = plt.figure()ax = fig.add_subplot(111)#设置图片标题title = u'属性可视化展示'title.decode('utf-8')ax.set_title(title)#设置坐标轴文字plt.xlabel(u'玩视频游戏所耗时间百分比')plt.ylabel(u'每周消耗冰淇淋公升数')p = ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15.0*array(datingLables), 15.0*array(datingLables))plt.show()
运行后的情况如下:
从上图中我们已经可以大致看出三类不同人群的分布区域。
在进行进一步的分析之前,我们需要对数据做归一化处理。因为在三个属性中“飞行里程”这个属性的数值较大,从而也将产生相对于其它两个属性更大的影响。但我们认为这三种属性特征是同等重要的,因此作为三个等权重的特征之一,飞行常客里程数不应该如此严重地影响到结果的判断。
在这里,我们采用如下的公式将数据转化为0到1区间内的值:
newValue= (oldValue - min) / (max - min)
其中,min和max分别是数据集中最小和最大的特征值。下面就是实现上述归一化方法的具体代码:
def autoNorm(dataSet):#分别取得每一列的最小值和最大值 minVals = dataSet.min(0) maxVals = dataSet.max(0)#计算最值间的差值 ranges = maxVals – minVals#构造行列与输入矩阵相同的0矩阵 normDataSet = zeros(shape(dataSet))#获取输入矩阵的行数 m = dataSet.shape[0]#矩阵中每一列的元素减去该列的最小值 normDataSet = dataSet - tile(minVals, (m,1))#在上一步的基础上再除以对应列的最值差 normDataSet = normDataSet/tile(ranges, (m,1)) #返回归一化后的矩阵、每列的最值差以及每列的最小值 return normDataSet, ranges, minVals
对数据进行归一化后就可以输入分类器进行具体分类操作了,实现的分类器代码如下:
def classify0(inX, dataSet, labels, k):#获得训练数据集的行数 dataSetSize = dataSet.shape[0]#计算训练集和输入向量之间每个分量的差值 diffMat = tile(inX, (dataSetSize,1)) – dataset#计算分类差值之后求和并取平方根,即计算欧氏距离 sqDiffMat = diffMat**2 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances**0.5#返回数组从小到大的索引 sortedDistIndicies = distances.argsort() classCount={} #根据前k个最小距离的值来判断目标向量所属的分类 for i in range(k): voteIlabel = labels[sortedDistIndicies[i]]#统计每个分类在距离最小的k个例子中出现的次数 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#根据字典的值来对字典项进行从大到小的排序 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)#最后返回字典值最大的字段的键,即对应的分类 return sortedClassCount[0][0]
到这里为止,k-近邻算法的主体部分就全部实现了。可以通过如下的代码来测试我们编写的分类器的错误率:
def datingClassTest(): hoRatio = 0.10 #测试数据为10% datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] numTestVecs = int(m*hoRatio)#接收测试的向量数 errorCount = 0.0 for i in range(numTestVecs):#数据集中前numTestVecs作为测试集 classifierResult = classify0(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)) print errorCount
接下来可以构建对应的应用,根据用户输入的信息进行分类。具体代码如下:
def classifyPerson(): resultList = ['not at all', 'in small doses', 'in large doses'] percentTats = float(raw_input(\ "percentage of time spent playing video games?")) ffMiles = float(raw_input("frequent flier miles earned per year?")) iceCream = float(raw_input("liters of ice cream consumed per week?")) datingDataMat, datingLabels = file2matrix('datingDataMat') normMat, ranges, minVals = autoNorm(datingDataMat) inArr = array([ffMiles, percentTats, iceCream])#先将输入向量做归一化,然后再进行测试 classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3) print "You will probably like this person:", \ resultList[classifierResult-1]
- 《机器学习》——k-近邻算法
- 机器学习—— k-近邻算法
- 机器学习——K-近邻算法
- 《机器学习实战》—K-近邻算法
- 机器学习k—近邻算法实例
- 机器学习算法(分类算法)—k-近邻算法
- 机器学习初探———【K-近邻算法】
- 机器学习实战—知识梳理—k-近邻算法
- 机器学习笔记(二)——k-近邻算法
- 机器学习实战——第二章:K-近邻算法
- 机器学习python实战——K近邻算法
- 机器学习——K近邻算法(KNN)
- 机器学习实战——k-近邻算法(KNN)
- 机器学习整理笔记——k-近邻算法
- <机器学习实战>——k近邻算法
- 《机器学习实战》——K近邻算法实现
- 机器学习实战笔记(1)——k-近邻算法
- 机器学习实战笔记(1)——k-近邻算法
- 跨浏览器事件的添加与删除
- 计算导论与C语言基础week12期末题
- LeetCode 349. Intersection of Two Arrays
- ubuntu17.04安装搜狗输入法
- Java中@Override的作用
- 机器学习——K-近邻算法
- 隐藏header头部信息中apache和php的版本信息
- 分布式架构实现
- cadence元件库的说明
- 信号报告
- git安装到使用
- 网站的构建
- (174)实用程序表达式
- 简单理解Socket及TCP/IP、Http、Socket的区别