简单的相亲推荐应用——Python以及机器学习中K-邻近算法的应用

       好吧,已经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(),之后按照他提示的输入内容就好啦~

 

第一种结果:


 第二种结果:

   

我就不再贴其他的结果了,大家有兴趣的话可以自己来搞,如果给加上界面就更好了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值