【机器学习实战笔记】第2章 k-近邻算法【02】

第2章 k-近邻算法【02】

实战2:在约会网站上使用k-近邻算法

一、涉及的Python函数功能介绍:

1、append() 函数的作用

在列表末尾添加新的对象
http://www.runoob.com/python/att-list-append.html

2、split()函数作用

切分数据
http://www.runoob.com/python/att-string-split.html

3、strip()函数作用

移除字符串头尾指定的字符(默认为空格)
http://www.runoob.com/python/att-string-strip.html

4、readlines()函数作用

读取所有行(直到结束符 EOF)并返回列表
http://www.runoob.com/python/file-readlines.html

5、add_subplot()函数作用

定义图片的位置
http://www.codeweblog.com/matplotlib-pyplot%E4%B8%ADadd_subplot%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0111%E7%9A%84%E5%90%AB%E4%B9%89/

6、scatter()函数作用

http://blog.csdn.net/u013634684/article/details/49646311

7、for i in range ()作用

http://blog.csdn.net/weixin_38705903/article/details/79238226

8、min()与max()函数作用

http://blog.csdn.net/weixin_38705903/article/details/79238249

9、符号&和\作用

& 是位运算“与”
\ 是“续行”的意思

二、实际操作

1、读取数据

1)在kNN.py内新增代码

#提取datingTestSet2.txt中的数据
def file2matrix(filename):
    fr = open(filename) #打开datingTestSet2.txt
    arrayOLines = fr.readlines()    #读取每一行的内容
    numberofLines = len(arrayOLines)    #记录训练集的行数(即样本数)
    #定义returnMat,用于存放提取后的数据,参数3的意思是3列,因为有3个特征
    returnMat = zeros((numberofLines,3))

    classLabelVector = []
    index = 0

    #把每一行的数据依次放入line中
    for line in arrayOLines:
        line = line.strip() #去掉\n
        listFromLine = line.split('\t') #以\t为依据,对数据进行切片
        #提取切片后的前三个数据,即三个特征的数值,只会读取到listFromLine[2]
        returnMat[index,:] = listFromLine[0:3]  
        classLabelVector.append(int(listFromLine[-1]))  #将label放入classLabelVector中
        index += 1  #returnMat下移一行以便存放新的样本数据

    return returnMat,classLabelVector

2)将datingTestSet.txt文件放在kNN.py的目录下,datingTestSet.txt文件可在此处免费下载:http://www.ituring.com.cn/book/1021
(如果不介意施舍我2个积分的话也可以到这里。。。
http://download.csdn.net/download/weixin_38705903/10235455

3)在kNN.py目录下打开cmd窗口 (cmd窗口快速定位到具体文件夹方法
然后输入以下代码

reload(kNN)
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')

再次输入datingDataMat和datingLabels即可查看数据

2、分析数据:使用Matplotlib创建散点图

在cmd窗口下继续输入,得到普通散点图
(可以直接粘贴整块代码到cmd窗口中,电脑会自动执行每一行)
这里写图片描述

import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
plt.show()

关闭图片,继续输入,得到不同颜色和尺寸的散点图
这里写图片描述

fig = plt.figure()
ax = fig.add_subplot(111)
from numpy import * 
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
plt.show()

这段分析的代码记住,会用即可

3、准备数据:归一化数值

归一化方法为:
newValue = (oldValue-min)/(max-min)

1)在kNN.py内新增代码

#归一化特征值
def autoNorm(dataSet):
    minVals = dataSet.min(0)    #把每一列最小值放到minVals中
    maxVals = dataSet.max(0)    #把每一列最大值放到maxVale中
    #minVals,maxVals为1行n列(n个特征)
    ranges = maxVals - minVals  #计算可能的取值范围

    normDataSet = zeros(shape(dataSet)) #初始化normDataSet
    m = dataSet.shape[0]    #记录data的行
    normDataSet = dataSet - tile(minVals, (m,1))    #得到每一个样本的(oldValue-min),并放入normDataSet中
    #tile(minVals, (m,1))生成m行n列的矩阵,即将minVals复制m份(因为有m个样本)
    normDataSet = normDataSet/tile(ranges, (m,1))   #newValue = (oldValue-min)/(max-min),得到归一化后的特征值

    #返回归一化后的特征值,取值范围和最小值
    return normDataSet, ranges, minVals

2)在kNN.py目录下打开cmd窗口,然后输入

reload(kNN)
normMat, ranges, minVals = kNN.autoNorm(datingDataMat)

输入normMat即可看到归一化后的数据

4、测试算法:作为完整程序验证分类器

1)在kNN.py内新增代码

#分类器针对约会网站的测试代码
def datingClassTest():

    hoRatio = 0.10  #设置测试集比重,此处为前10%作为测试集,后90%作为训练集

    #提取datingTestSet2.txt内数据
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    #得到归一化后的训练集,取值范围和最小值
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]    #得到样本数量m
    numTestVecs = int(m*hoRatio)    #得到测试集最后一个样本的位置
    errorCount = 0.0    #初始化定义错误的个数为0个

    #range(numTestVecs)=100,因为数组从0开始,故共100个测试样本
    for i in range(numTestVecs):

        #测试集中元素逐一放进分类器测试,k = 3,\是续行的意思
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m, :],\
        datingLabels[numTestVecs:m],3)

        #输出分类结果与实际label
        print "the classifier came back with: %d, the real answer is: %d"\
                            % (classifierResult, datingLabels[i])

        #若预测结果与实际label不同,则errorCount+1
        if (classifierResult != datingLabels[i]):errorCount += 1.0

    #输出错误率 = 错误的个数 / 总样本个数
    print "the total error rate is: %f" % (errorCount/float(numTestVecs))

2)在kNN.py目录下打开cmd窗口,然后输入

reload(kNN)
kNN.datingClassTest()

得到错误率是:0.050000

5、使用算法:构建完整可用系统

1)在kNN.py内新增代码

#约会网站预测函数
def classifyPerson():
    resultList = ['not at all','in small doses','in large doses']   #给label贴上名字

    #得到特征1(玩视频游戏所耗时间百分比)数据
    percentTats = float(raw_input("percentage of time spent playing video games?")) 
    #得到特征2(每年获得的飞行常客里程数)数据
    ffMiles = float(raw_input("frequent flier miles earned per year?")) 
    #得到特征3(每周消费的冰淇淋公升数)数据
    iceCream = float(raw_input("liters of ice cream consumed per year?"))   

    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') #加载训练集
    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]    #输出结果

2)在kNN.py目录下打开cmd窗口,然后输入

reload(kNN)
kNN.classifyPerson()

用以下数据测试:
percentage of time spent playing video games?10
frequent flier miles earned per year?10000
liters of ice cream consumed per year?0.5

得到结果为:
You will probably like this person:in small doses

三、常见错误

1、NameError:name ‘kNN’ is not defined

可能原因:之前关闭了cmd窗口,因此需要重新加载kNN
解决办法:输入import kNN

2、输入ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels),15.0*array(datingLabels))一直在等待,无反应

这里写图片描述
解决办法:按回车键

3、classify0时报错:AttributeError: ‘module’ object has no attribute ‘xxx:

这里写图片描述
解决办法:输入import kNN

from numpy import * 
4、plot()后,不能输入新的scatter函数,输入代码没反应

这里写图片描述
需要关掉图片,从ax = fig.add_subplot(111)开始重新输入

5、import kNN或者reload(kNN)报错

正常情况下import kNN成功不会返回信息,reload(kNN)成功会返回module ‘kNN’ from
若是cmd报错了,必然是kNN内代码错误,错误提示信息里面会具体告诉你是哪一行出现了问题
例如下图:
这里写图片描述
解决办法:根据错误提示去更改kNN里面的错误

6、出现错误ValueError: invalid literal for int() with base 10: ‘largeDoses’

可能原因:’datingTestSet1.txt’内的label不是数字
解决办法:P22页,命令
datingDataMat,datingLabels=kNN.file2matrix(‘datingTestSet.txt’)
要改为
datingDataMat,datingLabels=kNN.file2matrix(‘datingTestSet2.txt’)
变化的地方是’datingTestSet2.txt’

猜你喜欢

转载自blog.csdn.net/weixin_38705903/article/details/79238313