您的位置:首页 > 其它

py2.7 : 《机器学习实战》 k-近邻算法 11.19 更新完毕

2016-11-14 20:09 369 查看
主要有几个总结的:

1.python支持文件模块化,所以在同一个目录下import就可以调用了;

2.中文注释要加上 # -*- coding: utf-8 -*-

3.import numpy 和 from numpy import * 区别是, 对于前者,调用的时候需要加上名字:numpy.方法() ; 对于后者,直接 方法();

剩下的多多少少的放在代码的注释里了。

2.1.2 实施kNN算法

# -*- coding: utf-8 -*-
from numpy import *
import operator
def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']
return group,labels

def classify0(inX , dataSet , labels, k): #4个输入参数分别为:用于分类的输入向量inX,输入的训练样本集dataSet,标签向量labels,选择最近邻居的数目k
dataSetSize = dataSet.shape[0]#把行数求出来
diffMat = tile(inX , (dataSetSize,1) ) - dataSet #tile是将inx数组重复n次,把相对距离的x y 求出来
sqDiffMat = diffMat**2 #表示乘方,diffMar^2
sqDistance = sqDiffMat.sum(axis=1) #axis = 1代表行向量相加, 0就是普通的求和
distance = sqDistance**0.5#距离
sortedDisIndicies = distance.argsort() #np排序,代表的是返回从小到大排序的下标
classCount = {}
for i in range(k): #取欧氏距离计算
voteIlabel = labels[sortedDisIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #get返回指定键的值,否则返回默认值
sortedClasscount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #排序
return sortedClasscount[0][0]


test.py:

import kNN
group , labels = kNN.createDataSet()
print kNN.classify0([0,0],group,labels,3


输出:

B


2.2 示例:使用k-近邻算法改进约会网站的配对效果

2-2 将文本记录转换为Numpy的解析程序

数据集放在 2.2data 中, 可以下载使用(注意文件名字是:datingTestSet2 , 打开文件书上没这个‘2’)

在kNN.py中加入如下代码

def file2matrix(filename):#讲文本记录解析为Numpy的解析程序
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = zeros((numberOfLines,3)) #填充0,另一纬度设置为固定的3
classLabelVector = [] #把分类labels存为列表
index = 0
for line in arrayOLines:
line = line.strip() #去除最右端回车
listFromLine = line.split('\t') #用空格把字符串分成列表
returnMat[index,:] = listFromLine[0:3] #选取前三个特征存到特征矩阵里,然后index自加
classLabelVector.append(int(listFromLine[-1])) #负索引把特征值提取出来并且标为int变量
index+=1
return returnMat,classLabelVector


在test.py中运行

import kNN
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
print(datingDataMat)
print(datingLabels[0:20])

输出答案:

[[  4.09200000e+04   8.32697600e+00   9.53952000e-01]
[  1.44880000e+04   7.15346900e+00   1.67390400e+00]
[  2.60520000e+04   1.44187100e+00   8.05124000e-01]
...,
[  2.65750000e+04   1.06501020e+01   8.66627000e-01]
[  4.81110000e+04   9.13452800e+00   7.28045000e-01]
[  4.37570000e+04   7.88260100e+00   1.33244600e+00]]
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3]


2.2.2 : 分析数据:使用matplotlib创建散点图

先分析 ‘玩游戏视频所耗时间半分比’ 和 ‘每周消费的冰淇淋公升数’

import kNN
import matplotlib
import matplotlib.pyplot as plt
from numpy import *
import operator
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
fig = plt.figure()#创建图形
ax = fig.add_subplot(111)#也可以写为1,1,1 ; 代表创建1行1列为p1的子图
# 对训练样本矩阵进行画图
#使用第二列和第三列数据,代表的是“玩视频游戏所耗时间”和“每周消费冰淇淋数”
ax.scatter(datingDataMat[:,1], datingDataMat[:,2],15*array(datingLabels),15*array(datingLabels), label=u'散点图')
plt.xlabel(u'玩视频游戏所耗时间半分比')
plt.ylabel(u'每周消费的冰淇淋公升数')
plt.show()


效果图:



本题目一共有三组特征值:玩游戏视频所耗时间的百分比;每周消费的冰淇淋公升数;每年获取的飞行常客里程数;

由于上述特征描绘出来的属性值不是特别的好,所以改进后选用了列1和列2;



2.2.3 准备数据:归一化数值

理由:当数据的样本特征权重不一样,就会导致某一个特征权重的差距太大影响到整体的距离,因此要使用归一化来将这种不同取值范围的特征值归一化,将取值范围处理为0到1,或者-1到1之间;使用如下公式可以讲任意取值范围的特征值转化为0到1区间内的值:

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

这里的new和old都针对的是某一列里的一个,而在这里使用应该是列表整体的使用了公式,故得到的是一个列表类型的newValue;

def autoNorm(dataSet):#输入为数据集数据
minVals = dataSet.min(0)#获得数据每列的最小值,minval是个列表
maxVals = dataSet.max(0)#获得数据每列的最大值,maxval是个列表
ranges = maxVals - minVals#获得取值范围
normDataSet = zeros(shape(dataSet)) #初始化归一化数据集
m = dataSet.shape[0]#得到行
normDataSet = dataSet - tile(minVals,(m,1))
normDataSet = normDataSet/tile(ranges,(m,1)) #特征值相除
return normDataSet,ranges , minVals#返回归一化矩阵,取值范围, 最小值
test测试:

# -*- coding: utf-8 -*-
import kNN
from numpy import *
import operator
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
normMat , ranges , minval= kNN.autoNorm(datingDataMat)
print(normMat,'\n' ,ranges,'\n' , minval)
样例输出:

[[ 0.44832535  0.39805139  0.56233353]
[ 0.15873259  0.34195467  0.98724416]
[ 0.28542943  0.06892523  0.47449629]
...,
[ 0.29115949  0.50910294  0.51079493]
[ 0.52711097  0.43665451  0.4290048 ]
[ 0.47940793  0.3768091   0.78571804]] #归一化矩阵
[  9.12730000e+04   2.09193490e+01   1.69436100e+00] #取值范围:max-min
[ 0.        0.        0.001156] #最小值

2-4:分类器针对约会网站的测试代码

先拿出10%的数据进行测试,我这个是5%

kNN,py

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):#对样本集进行错误收集
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m], 3)#kNN
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 if :%f" % (errorCount/float(numTestVecs)))#计算错误率并输出


test.py:

# -*- coding: utf-8 -*-
import kNN
from numpy import *
import operator
group , labels = kNN.createDataSet()
print kNN.datingClassTest()


输出:

The classifier came back with : 1 , the real answer is : 1
The classifier came back with : 3 , the real answer is : 3

...
The classifier came back with : 1 , the real answer is : 1
The classifier came back with : 3 , the real answer is : 1
the total error rate if :0.050000
None


2-5 约会网站预测函数

最后一个主要是构建分类器,然后自己读入数据给出结果。

def classfyPerson():
resultList = ['not at all' , 'in small doese ' , 'in large dose'] #分类器
precentTats = float(raw_input("precentage of time spent playint video games?")) #输入数据
ffMiles = float(raw_input("frequent flier miles earned per year"))
iceCream = float(raw_input("liters of ice cream consumed per year?"))
datingDataMat , datingLabels = file2matrix('datingTestSet2.txt') #训练集
normMat , ranges , minVals = autoNorm(datingDataMat) #进行训练
inArr =array([ffMiles,precentTats,iceCream]) #把特征加入矩阵
#4个输入参数分别为:用于分类的输入向量inX,输入的训练样本集dataSet,标签向量labels,选择最近邻居的数目k
classfierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3) #归一化处理矩阵,并且结果就是序列号-1就是对应
print "You will probably like this person : " , resultList[classfierResult - 1 ]

输出结果:
You will probably like this person : in small doses


至此2.2:使用k-近邻算法改进约会网站配对效果结束
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: