AiLearning——Kapitel 2 k-近邻算法(约会网站)

前言

把CSDN当作学习笔记,并无任何商业用途,希望和大家多多交流,共同进步。
学习资料来源于Github: link

模块及函数

Github 源程序中引用的函数

from numpy import *
import operator

文本文件处理

海伦约会对象文本文件 datingTestSet2.txt
因为后续涉及到很多数据的命令,因此把数据的变化过程展示出来,原始数据

for line in fr.readlines():
    print(line)
-->
40920	8.326976	0.953952	3

14488	7.153469	1.673904	2

这里仅展示两行数据,数据类型为字符串,每行作为一个单独的字符串存在
关于zeros
在处理文件的过程中,文件的 句柄(fr)需要生成两次,否则循环语句将没有输出
经过 .strip 命令后得到的数据

for line in fr.readlines():
    line = line.strip()
    print(line)
-->
40920	8.326976	0.953952	3
14488	7.153469	1.673904	2

可以看到,行与行之间的空行消失了,因为strip命令中的chars选项为空,即消除行与行之间的空字符
经过 .split 命令后得到的数据

for line in fr.readlines():
    line = line.strip()
    line = line.split('\t')
    print(line)
-->
['40920', '8.326976', '0.953952', '3']
['14488', '7.153469', '1.673904', '2']

因为经过.strip命令后,单行的各个数据中间隔着制表符,因此通过制表符(’\t’)来分割每个字符串,每行的数据类型由字符串变为列表
数据处理步骤的结果

print(type(returnMat))
print(returnMat)
-->
<class 'numpy.ndarray'>
[[4.0920000e+04 8.3269760e+00 9.5395200e-01]
 [1.4488000e+04 7.1534690e+00 1.6739040e+00]
 [2.6052000e+04 1.4418710e+00 8.0512400e-01]
 ...

变量 returnMat 是一个 ndarray 类型

print(type(classLabelVector))
print(classLabelVector)
-->
<class 'list'>
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 2, 1, ...]

变量 classLabelVektor 是一个整型列表

归一化处理

函数autoNorm的变量dataSet是数据处理后的returnMat
通过 .max 和.min 命令获取单项指标的最大值和最小值。(0)为列元素,如果是(1)则为行元素

print(returnMat.min(0))
print(type(returnMat.min(0)))
-->
[0.       0.       0.001156]
<class 'numpy.ndarray'>

根据约会对象的评价有三个指标,因此创建的数组array是二维的,所以通过.max和.min 命令得到的不是一个数字,而是一个二维数组
通过 shape 命令得到dataSet的维度,进而创建空白数组 normDataSet,shape(0) 读取第一维度的维数,这里也就是dataSet的行数,以此类推
与 zeros不同,tile 可以提高创建数组的丰富性
本步骤归一化的思路为,通过由数据得到的极值和极差生成与dataSet相同维度的数据,从而进行整体相减和相除,将单一数值的运算提升为数组运算

算法伪代码

先介绍一下函数 classify0 各个参数的意义,便于理解函数的构造
inX:某个数据个体,也就是某个约会对象的二维数据
dataSet:训练样本中个体的数量
labels:训练样本的标签,与dataSet保持一致
k:前k个数据
数组乘方与矩阵乘方 **
.sum 函数通过 axis 定义相加的维度
.argsort 返回排序后的索引列表

voteIlabel = labels[sortedDistIndicies[i]]

提取第i个个体的标签

classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 

classCount被定义为字典,这句代码实际上是通过字典对标签 1,2,3 分别进行计数,.get方法来提取上一次计数的结果并加一,而将默认值设置为0是为了给出初始值

print(classCount)
-->
{1: 5, 3: 23, 2: 2}

简单设置一下参数运行classify0函数,得到的classCount如上,分别对标签1,2,3进行k范围内的计数

sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)

方法 .iteritems 是python 2.x中的方法,python 3.x中简化为 .item,

print(classCount.items())
-->
dict_items([(1, 5), (3, 23), (2, 2)])

经过 .item处理后的classCount返回了一个列表形式的迭代器,每个键和对应的值组成了一个元组
.itemgetter 是operator模块下提取数组某一维度数据的方法,默认值为1则提取元组的第二个值,用上述例子则分别提取5,23,2进行排序。reverse为True则是降序排列,处理后的结果为:

print(sortedClassCount)
-->
[(3, 23), (1, 5), (2, 2)]

最后函数返回sortedClassCount[0][0],将分类个体与前K个数据相似最多的标签输出,这里是3

测试代码

这里通过numTestVecs将数据分为两组,一组是numTestVecs之前作为测试样本数量,一组是numTestVecs之后,也就是numTestVecs:m作为测试样本的数量
如果理解了上一步,这部分应该很容易
学习资料中print少了括号,自己加上就好

约会网站预测函数

如果是python 3.x 的环境,应当将 raw_input 改为 input

总结

k-近邻算法的原理比较容易理解,个人觉得这个项目的难点在于数据的递进处理过程,因此把每一步数据处理的结果展示出来,有一部分的结果来源于我个人设置的参数,仅仅为了展示数据的结构,便于自己和大家更好的理解学习这段代码。
非常感谢本文引用的各个作者撰写的学习资料,因为比较多所以未一一列举,希望大家可以一起学习进步,不足之处还望大家指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值