MachineLearning实战_03KNN实现约会网站预测

KNN实现约会网站预测

  • 样本包含3种特征:
    每年获得的飞行常客里程数
    玩视频游戏所耗时间百分比
    每周消费的冰淇淋公升数
  • 数据存放在文本文件中

程序包含以下部分

  • 从文本文件中解析数据

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

  • 准备数据:归一化数值
    对于新输入的数值,用训练样本的特征值范围对新数据进行归一化

  • 测试算法
    通常选取已有数据的10%作为测试集,检测分类器的正确率
    选择错误率来检测分类器性能

  • 构建完整的约会网站预测函数

import numpy as np
import operator
from matplotlib import pyplot as plt

def file2matrix(filename):
    """读取文件

    原文件为txt文本格式
    returnMat表示训练样本的特征矩阵
    classLabelVector表示每个训练样本的分类结果
    """
    fr=open(filename)
    arrayOLines=fr.readlines()  #readlines方法读取整个文件所有行,保存在一个列表(list)变量中,每行作为一个元素
    #arrayOLines=['40920\t8.326976\t0.953952\t3\n', '14488\t7.153469\t1.673904\t2\n',....
    numberOfLines=len(arrayOLines) #得到文件行数
    returnMat=np.zeros((numberOfLines,3))
    classLabelVector=[]
    index=0
    for line in arrayOLines:
        #循环一进来的line=40920	8.326976	0.953952	3
        line=line.strip() #截取掉所有的回车字符\n,得到整行数据,最后一个数据隐藏着转义字符\n
        #line=40920	8.326976	0.953952	3
        listFromLine=line.split('\t') #分割成一个元素列表,\t表示水平制表(HT) (跳到下一个TAB位置)
        #listFromLine=['40920', '8.326976', '0.953952', '3']
        returnMat[index,:]=listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index+=1
    return returnMat,classLabelVector

def autoNorm(dataSet):
    """将输入数据归一化

    归一化公式为:(x-min)/(max-min)
    normDataSet为归一化后的结果
    ranges为每个特征值的范围
    minVals为每个特征值的最小值
    """
    minVals=dataSet.min(0)#每一列最小值组成一个列表
    maxVals=dataSet.max(0)
    ranges=maxVals-minVals
    normDataSet=np.zeros(np.shape(dataSet))
    m=dataSet.shape[0]#m为输入数据的列数
    normDataSet=dataSet-np.tile(minVals,(m,1))
    normDataSet=normDataSet/np.tile(ranges,(m,1))
    return normDataSet,ranges,minVals
    
def classify0(New_data,train_data,labels,k):
    """K-近邻算法

    New_data表示需要预测的数据
    train_data表示训练样本集
    labels表示训练样本集的标签
    """
    train_dataSize=train_data.shape[0] #获取训练集行数,即样本个数
    diffMat=np.tile(New_data,(train_dataSize,1))-train_data
    #tile函数依次将每个输入数据重复train_dataSize次,目的是计算每个输入数据与样本数据的差值
    sqdiffMat=diffMat**2
    sqDistance=sqdiffMat.sum(axis=1) #按行计算和,并取消二维,即组成一维数据,每个数据代表输入数据与每个样本的距离
    distances=sqDistance**0.5
    sortedDistIndicies=distances.argsort() #从小到大排序,返回索引值
    classCount={
      }
    for i in range(k):
        voteIlabel=labels[sortedDistIndicies[i]] #获取距离最小的前k个样本对应的标签
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 #对于相同标签进行累加
    sortedclassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    #对字典classCount的值进行从大到小排序,key=1表示对字典的值,Reverse表示从大到小
    return sortedclassCount[0][0]

def classifyPerson():
    """赋予每个类别具体的意义,实现输入数据进行分类
    
    训练集采用原始文本采集的数据
    测试集为用户输入的数据
    """
    resultList=['not at all','in small doses','in large doses']
    percentTats=float(input("percentage of time spent playing video games?"))
    ffMiles=float(input("frequent flier miles earned per year?"))
    iceCream=float(input("liters of ice cream consumed per year?"))
    datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)
    inArr=np.array([ffMiles,percentTats,iceCream])
    classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    #对输入数据进行归一化,归一化的范围为训练集的范围
    print("You will probally like this person:",resultList[classifierResult-1])
    
    
    
def datingClassTest():
    """计算测试集错误率
    
    选取样本的10%作为测试集
    输出错误率
    """
    a_test=0.1 #选取样本的10%作为测试集
    datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)
    m=normMat.shape[0]
    numTestVecs=int(m*a_test)
    errorCount=0.0
    for i in range(numTestVecs):
        classifierResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        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 is :%f"%(errorCount/float(numTestVecs)))
    
#构建散点图
fig=plt.figure()
ax=fig.add_subplot(111)
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels))
#第三个参数点的大小,第四个参数点的颜色
plt.show

classifyPerson()

你可能感兴趣的:(MachineLearning,KNN)