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]
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-近邻算法改进约会网站配对效果结束