机器学习实战笔记——分类之k-近邻算法

着手学习机器学习了,打算根据《机器学习实战》这本书从头到尾把这书里的代码撸个遍,想必就应该能入门了吧。写笔记目的一是记录,二是加深记忆,三是分享。cd尽量减少摘抄性文字。
书中的所有代码来源可到官网下载:https://www.manning.com/books/machine-learning-in-action

这里博客的代码及相关数据放在了cd的github上:https://github.com/ChenDdon/mechine_learning_practice.git



k-近邻算法



一 定义、优缺点及工作原理

定义:k-近邻算法采用测量不同特征值的距离方法进行分类。
优点:进度稿、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高、
适用数据范围:数值型和标称型。

工作原理
存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。
输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数,且最好为奇数(涉及到判定分类时的投票过程)。
最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。



二 k-近邻算法实践

2.1 k-近邻算法的一般流程

1、收集数据:任意方法。
2、准备数据:距离计算所需要的数值,最好是格式化的数据格式。
3、分析数据:可以使用任何方法。
4、测试算法:计算错误率。
5、使用算法:首先输入样本数据和结构化的输出结果,然后进行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续处理。


2.2 示例说明(任务说明)

这里cd主要基于书本中给的使用k-近邻算法改进约会网站的配对结果这个示例来写的。

示例背景: 海伦一直用一个约会平台在找对象。海伦将约会的众多对象分成了三类:

  • didntLike;
  • smallDoses;
  • largeDoses

然后,海伦将之前每个约会对象数据记录下来,每个人主要是三个数据:

  • 玩视频游戏所耗时间百分比
  • 每年获取的飞行常客里程数
  • 每周消费的冰淇淋公升数

海伦将每个人的数据以及分类整理在了datingTestSet.txt这个文件里了。希望能有个分类程序,每当她拿到一个没约会过的人的前述三个数据,就能知道这个人她会不会喜欢。

给出的数据:datingTestSet.txt与datingTestSet2.txt这两个文件。其中我们要用的是datingTestSet2.txt这个文件与datingTestSet.txt的区别就在于,数据文件中的第四列数值做了如下转换:

第四列数值意义
largeDoses ——> 3
smallDoses ——> 2
didntLike ——> 1

任务:得到一个基于k-近邻算法的分类器,对一行新的向量能进行正确的分类判定。

分类器需要达到的效果,即:input为1*4的向量;output为相应的分类结果。


2.3 代码实践

首先,创建名为kNN.py的python文件。
然后,要清楚我们要做哪些事情,需要哪些功能,从而确定框架。

#1收集数据
#这里提供的datingTestSet2.txt文件就是收集到的数据
#准备数据:将收集的到的数据转换成格式化的数据格式
def img2matrix():
	pass
#分析数据,可以用matplotlib创建可视化的图形
def analyseShow():
    pass
#分类器构建
def classify0():
	pass
#测试算法部分
def datingClassTest():
	pass
#使用算法部分
def classifyPerson():
    pass

2.3.1 收集数据

因为这个例子里的数据是准备好了的,所以直接拿来用就行了。代码和数据都同意放在文末的连接里吧。


2.3.2 准备数据

准备数据其实也是为了后续处理方便,我们首先看一下这个例子中的数据特征:

40920	8.326976	0.953952	3
14488	7.153469	1.673904	2
26052	1.441871	0.805124	1
75136	13.147394	0.428964	1
38344	1.669788	0.134296	1
72993	10.141740	1.032955	1
35948	6.830792	1.213192	3
...     ...			...			...

这里罗列的数据前几行,前三列是三个特征分别是:每年获得的飞行常客里程数;玩视频游戏所耗时间百分比;每周消费的冰淇淋公升数。
第四列是分类结果,用数字1,2,3表示三种结果。

那么可以将特征数据,与分类结果数据分开来,代码如下:

import numpy as np
def file2matrix(filename):
    with open(filename) as fr:
        lines = fr.readlines()
        numberOfLines = len(lines)         		#获取文件行数
        returnMat = np.zeros((numberOfLines,3)) #准备回传的矩阵-零矩阵
        classLabelVector = []                   #准备返回的结果数值-空list
        index = 0
        for line in lines:
            line = line.strip()
            listFromLine = line.split('\t')
            returnMat[index,:] = listFromLine[0:3]
            classLabelVector.append(int(listFromLine[-1]))
            index += 1
    return returnMat,classLabelVector

结果如以下截图所示:
returnMat与classLabelVector

此外,我们可以看到三个特征属性的数值存在巨大差异,那么在计算两个样本之间的差距时,数值大的特征将占到主导地位,而对于这个示例而言,三种特征是同等重要的。因此,在准备数据阶段,我们还需要将特征值的数据进行归一化处理,如将数值取值均归一化到0到1,或者-1到1之间。(不归一化容易导致欠拟合的情况)

下面公式是将特征值转化为0到1区间的值:

newValue = (oldValue-min)/(max-min)

因此,在准备数据这个模块里我们还需要加进去归一化处理的功能:

#准备数据:将收集的到的数据转换成格式化的数据格式
import numpy as np
def file2matrix(filename):
    with open(filename) as fr:
        lines = fr.readlines()
        numberOfLines = len(lines)         #获取文件行数
        returnMat = np.zeros((numberOfLines,3))        #准备回传的矩阵-零矩阵
        classLabelVector = []                       #准备返回的结果数值-空list
        index = 0
        for line in lines:
            line = line.strip()
            listFromLine = line.split('\t')
            returnMat[index,:] = listFromLine[0:3]
            classLabelVector.append(int(listFromLine[-1]))
            index += 1
    
    #数据归一化的部分
    dataSet = returnMat
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m,1))
    normDataSet = normDataSet/np.tile(ranges, (m,1))   #element wise divide
    
#    return returnMat,classLabelVector
    return normDataSet,classLabelVector,ranges, minVals

这样一来,输出的normDataSet就是经过归一化之后的数据了。

由于后续会用到每列的数值范围,因此也一起返回了取值范围(ranges)和最小值(minVals)。


2.3.3 分析数据

这里我们使用matplotlib制作原始数据的散点图:

#分析数据,可以用matplotlib创建可视化的图形
'''
Parameters:
	datingDataMat: 数据特征矩阵(包含n个样本的数据集合)
	datingLabels: 样本标签集合(各个样本的结果的集合)
'''
def analyseShow(datingDataMat, datingLabels):
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif']=['Microsoft YaHei'] #用来正常显示中文标签
    plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
    
    fig = plt.figure(figsize=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值