好吧,已经3个月没碰博客了,今天打开发现里面已经积了一层灰了……今天重启博客是因为最近接触了一个新的领域,机器学习,而要实现机器学习又要使用Python语言,所以同时接触这两大块的新知识,不免会有些吃力,特别是要做出来一个应用(即使很简单),虽然做的时候里面的语句通过各种途径搞明白了,但是还是有些生疏,所以就先在这里记下,后面忘记了可以再回来看看。
另外,预告一下下一篇博客的内容:手写识别的实现,也是使用与本次应用一样的K-邻近算法。
我们先说一下里面的一些概念
训练数据:就是一开始就准备的那些从记录里扒下来的男生的数据,专门用来训练这个程序的,训练的数据越多,程序预测的就越精确
K-邻近算法:顾名思义,邻近,就是找最近的数据,至于K呢,就是要找K个最近的数据,怎么找呢,就是利用我们初中就会用的距离公式,已知两点或三点或…点的各轴坐标,求这两点间距离,这样计算待测数据和每一个训练数据之间的距离,就能找到距离最近的K个训练数据,这K个训练数据的结果就是带预测的数据被预测出的结果,看,是不是很简单呢~
我们还需要理清这个应用的思路:
应用很简单,通过分析一菇凉在相亲网站上的记录,得到她喜欢的和不喜欢的男生的属性数据,在这里我们使用的是三个属性:薪水、平时玩游戏的时间、每年吃多少冰激凌(这个有点无厘头的感觉……),得到足够多的数据后分析这些属性和对男生的好感度之间的关系,这样我们就可以按照这个菇凉的喜好来给他推荐相亲对象了~
步骤如下:
1、得到三个属性的值以及喜好程度(1代表不喜欢、2代表待考虑、3代表喜欢)的数据集
2、将所有的数据导入到一个矩阵中便于计算
3、将数据归一化,这是机器学习中常用的一种处理数据的方法,让数据变得易于处理
4、测试,把训练数据中的一部分当做测试数据进行测试,看准确率是否达到预期效果
5、利用K-邻近算法计算输入的数据与训练数据之间的举例,将之分到距离最近的一类当中
6、大功告成~
下面就是吧上面的步骤一一实现了,代码的解释都写在了后面的注释行里了
1、数据
已有现成数据(已传到附件中,如需要可以下载直接使用),其中一部分如下图所示
第一列为半年的薪水,第二列为,游戏时间占所有时间的百分比,第三列为每年吃多少升(= =||)冰激凌
第四列为喜好程度
2,、导入数据
代码如下:
def change(filename): # 从文件中读取数据的方法
fl=open(filename) #打开文件
fllines=fl.readlines()
linenumber=len(fllines) #计算文本行数
Mat=zeros((linenumber,3)) #创建矩阵Mat
labelVector=[] #创建空白向量
index=0
for line in fllines: #循环直到line等于fllines
line=line.strip() #除去数字间的空白格
lst=line.split('\t')
Mat[index,:]=lst[0:3] #给矩阵Mat的第index行赋值
labelVector.append(int(lst[-1])) #把数据集的最后一列加到labelVector
index +=1
return Mat,labelVector
3、归一化
def autoNorm(dataSet): #归一化的方法、
maxV=dataSet.max(0) #求最大值
minV=dataSet.min(0) #最小值
ranges=maxV-minV #范围
normDataSet=zeros(shape(dataSet)) #创建矩阵
m=dataSet.shape[0] #数据大小
normDataSet=dataSet-tile(minV,[m,1]) #new=(old-min)/(max-min)
normDataSet=normDataSet/tile(ranges,[m,1])
return normDataSet,ranges,minV
4、测试
def datingTest():
tst=0.01 #设置测试数据占总数据的百分比
datingMat,datingLabels=change('datingTestSet2.txt') #赋值并调用change函数,见上面的数据导入
normData,ranges,minV=autoNorm(datingMat) #赋值并调用autoNorm函数,见上面的归一化
m=datingMat.shape[0] #计算datingMat的大小
tstnum=int(m*tst) #计算测试数据的数量
errorCount=0.0
for i in range (tstnum): #循环,直到i=tstnum tstresult=classify0(normData[i,:],normData[tstnum:m,:],datingLabels[tstnum:m],3) #调用距离计算函数,见下面计算距离并分类
print"the result I give is : %d,the real result is : %d" %(tstresult,datingLabels[i]) #输出预测值与实际值
if (tstresult!=datingLabels[i]):errorCount+=1.0
print"the error rate is %f"%(errorCount/float(tstnum)) #计算并输出错误率
进行测试所需操作:
在python命令行中输入:
程序名.datingTest(),例如程序名字为KNN,那么就输入KNN.datingTest()
5、计算距离并分类
def classify0(inX,DataSet,labels,k):
DataSize=DataSet.shape[0] #得到训练数据的长度
DiffDataSet=tile(inX,(DataSize,1))-DataSet #将输入数据与训练数据各项相减
sqDiffDataSet=DiffDataSet**2 #各项平方
sqDistance=sqDiffDataSet.sum(axis=1) #各项平方后相加
Distance=sqDistance**0.5 #开方
sortedDistance=Distance.argsort() #将距离数据按升序排序
classCount={} #新建字典
for i in range(k): #循环,从0到k
sortedLabel=labels[sortedDistance[i]] #将排好序的距离数据按顺序赋给sortedLabel
classCount[sortedLabel]=classCount.get(sortedLabel,0)+1 #加入字典
sortedclassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #将字典排序输出
return sortedclassCount[0][0]
6、将代码总体展示如下
from numpy import *
import operator
def classify0(inX,DataSet,labels,k):
DataSize=DataSet.shape[0] #得到训练数据的长度
DiffDataSet=tile(inX,(DataSize,1))-DataSet #将输入数据与训练数据各项相减
sqDiffDataSet=DiffDataSet**2 #各项平方
sqDistance=sqDiffDataSet.sum(axis=1) #各项平方后相加
Distance=sqDistance**0.5 #开方
sortedDistance=Distance.argsort() #将距离数据按升序排序
classCount={} #新建字典
for i in range(k): #循环,从0到k
sortedLabel=labels[sortedDistance[i]] #将排好序的距离数据按顺序赋给sortedLabel
classCount[sortedLabel]=classCount.get(sortedLabel,0)+1 #加入字典
sortedclassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #将字典排序输出
return sortedclassCount[0][0]
def change(filename): # 从文件中读取数据的方法
fl=open(filename) #打开文件
fllines=fl.readlines()
linenumber=len(fllines) #计算文本行数
Mat=zeros((linenumber,3)) #创建矩阵
labelVector=[] #创建空白向量
index=0
for line in fllines:
line=line.strip()
lst=line.split('\t')
Mat[index,:]=lst[0:3]
labelVector.append(int(lst[-1]))
index +=1
return Mat,labelVector
def autoNorm(dataSet): #归一化的方法、
maxV=dataSet.max(0) #求最大值
minV=dataSet.min(0) #最小值
ranges=maxV-minV #范围
normDataSet=zeros(shape(dataSet)) #创建矩阵
m=dataSet.shape[0] #数据大小
normDataSet=dataSet-tile(minV,[m,1]) #new=(old-min)/(max-min)
normDataSet=normDataSet/tile(ranges,[m,1])
return normDataSet,ranges,minV
def datingTest():
tst=0.01
datingMat,datingLabels=change('datingTestSet2.txt')
normData,ranges,minV=autoNorm(datingMat)
m=datingMat.shape[0]
tstnum=int(m*tst)
errorCount=0.0
for i in range (tstnum):
tstresult=classify0(normData[i,:],normData[tstnum:m,:],datingLabels[tstnum:m],3)
print"the result I give is : %d,the real result is : %d" %(tstresult,datingLabels[i])
if (tstresult!=datingLabels[i]):errorCount+=1.0
print"the error rate is %f"%(errorCount/float(tstnum))
def Predict():
Preresult=("I'll never date with him",'Maybe I should know more about him','Please marry me!!!')
Salary=float(raw_input('How much money do you earn per half year?'))
Game=float(raw_input('How manny percent time do you spend on playing computer games?'))
iceCream=float(raw_input("How many liters(0~2) iceCream do you consumed per year?"))
datingMat,datingLabels=change('datingTestSet2.txt')
normMat,ranges,minV=autoNorm(datingMat)
resultArray=([Salary,Game,iceCream])
Result=classify0((resultArray-minV)/ranges,normMat,datingLabels,3)
print"Her opinion about this man :",Preresult[Result-1]
好啦,大功告成啦,下面就是演示我们成果的时候了~见图片:
在命令行输入程序名.Predict(),例如KNN.Predict(),之后按照他提示的输入内容就好啦~
第一种结果:
第二种结果:
我就不再贴其他的结果了,大家有兴趣的话可以自己来搞,如果给加上界面就更好了~