使用 KNN 算法改进约会网站的配对效果
为了提高给 Helen 女士匹配约会对象的成功率,收集了各位男士的以下三种信息:
- 每年的飞行里程数
- 玩游戏所耗时间百分比
- 每周消费的冰淇淋公升数
先看一下数据集的内容:这里截取了三行,前三列分别是每年的飞行里程数、玩游戏所耗时间百分比和每周消费的冰淇淋公升数,最后一列是 Helen 女士对他们的 feel,largeDoses 表示 Helen 女士认为他非常有魅力,smallDoses 表示 Helen 女士对他感觉一般般,而 didntLike 则表示 Helen 女士不喜欢他。
40920 8.326976 0.953952 largeDoses
14488 7.153469 1.673904 smallDoses
26052 1.441871 0.805124 didntLike
1. 准备数据:从文本文件中解析数据
将收集来的数据输入到 KNN 分类器以前,应该将其处理成分类器能够接收的格式,即应该先分成特征和标签两部分,同时还要记得将标签转化为 int 型数字,用 1 代表不喜欢,2 代表魅力一般,3 代表极具魅力。
在 KNN_EXP01.py 文件中创建一个处理数据的函数:
def file2matrix(filename):
# 打开文件
fr = open(filename)
# 按行读取文件
arrayOLines = fr.readlines()
# 得到文件行数
numberOfLines = len(arrayOLines)
# 创建用 0 填充的矩阵
returnMat = zeros((numberOfLines, 3))
# 创建用于存放标签的列表
classLabelVector = []
# 行的索引
index = 0
# 解析文件数据得到列表
for line in arrayOLines:
# 去掉所有回车字符
line = line.strip()
# 将整行数据分割成元素列表
listFromLine = line.split('\t')
# 选取前 3 个元素存储到特征矩阵中
returnMat[index,:] = listFromLine[0:3]
# 将最后一列存储到标签向量中
if listFromLine[-1] == 'didntLike':
classLabelVector.append(1)
elif listFromLine[-1] == 'smallDoses':
classLabelVector.append(2)
else:
classLabelVector.append(3)
index += 1
return returnMat, classLabelVector
在 python 命令提示符中输入命令,检查一下数据内容:
>>> import KNN_EXP01
>>> datingDataMat, datingDataLabels = KNN_EXP01.file2matrix('datingTestSet.txt')
>>> datingDataMat
array([[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],
...,
[2.6575000e+04, 1.0650102e+01, 8.6662700e-01],
[4.8111000e+04, 9.1345280e+00, 7.2804500e-01],
[4.3757000e+04, 7.8826010e+00, 1.3324460e+00]])
>>> datingDataLabels[0:20]
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3]
2. 分析数据:用图形化方式直观展示数据
由于直接查看文本文件的方式不友好,所以一般会采用图形化的方式直观地展示数据,我们可以使用 Matplotlib 制作原始数据的散点图:
>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
<matplotlib.collections.PathCollection object at 0x000000DD7EDBC828>
>>> plt.show()
散点图使用 datingDataMat 矩阵的第二、第三列数据分别作为 x、y轴,即 x 轴为玩游戏所耗时间百分比,y 轴为每周消费的冰淇淋公升数。