machine learning in action 第二章 KNN

作为一个菜鸟,在刚开始做这个的时候很多函数都不懂,所以打算把它写下来,做一个详细的说明,可能有很多地方用词不准确,欢迎指证,感激不尽。

首先是构造分类器函数:

from numpy import *
import operator
def classfuction(inx,dataset,labels,k):     #输入需要分类的数据inx,数据集dataset,数据集对应标签为labels,最临近数目k
    datasetsize=dataset.shape[0]   # shape[1] 为第二维的长度,shape[0] 为第一维的长度。就是列的长度。
    diffmat=tile(inx,(datasetsize,1))-dataset #重复A,B次,这里的B可以时int类型也可以是元祖类型。计算inx和每个样本的距离。
    sqdiffmat=diffmat**2    
    sqdistances=sqdiffmat.sum(axis=1)     #加入axis=1以后就是将一个矩阵的每一行向量相加
    distances=sqdistances**0.5 #开根号,计算欧几里得距离即a与b之间的距离等于根号下对应各个特征的差的平方。
    sorteddistindicies=distances.argsort() #返回从小到大的索引
    classcount={}   #创建一个字典
    for i in range(k):
        voteilabel=labels[sorteddistindicies[i]]
        classcount[voteilabel]=classcount.get(voteilabel,0)+1 #Python 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值。
    sortdeclasscount=sorted(classcount.items(),key=operator.itemgetter(1),reverse=True)   #排序sorted(iterable, key=None, reverse=False)
    #iterable -- 可迭代对象。key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
    return sortdeclasscount[0][0]  #是降序排列,所以返回的是数目最多的类别的标签
group=np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])  #构造数据集。。。
labels=['A','A','B','B']
classfuction([0,0],group,labels,3)

然后是转换数据格式

import numpy as np
 def file2matrix(filename):
    fr=open(filename)  #首先打开文件
    arrayolines=fr.readlines() #读取文件所以行并返回列表
    numberoflines=len(arrayolines)#计算出一共有多少行数据
    returnmax=np.zeros(( numberoflines,3))#建立出一个相同大小的零值矩阵
    classlabelvector=[]#建立一个列表
    index=0#初始索引
    for line in arrayolines :
        line=line.strip()#用于移除字符串头尾指定的字符(默认为空格)。
        listfromline=line.split('\t')#通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则仅分隔 num 个子字符串,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等
        returnmax[index,:]=listfromline[0:3]#将得到的行数据赋给我们建立好的零值矩阵
        classlabelvector.append(int(listfromline[-1]))#观察原数据我们可知,标签为最后一列,所以将最后一位数据赋给标签列表
        index+=1#索引加一,给下一行继续赋值
    return returnmax,classlabelvector#返回数据矩阵以及标签列表
datingdatamat,datinglabels=file2matrix("datingTestSet2.txt")

接下来是数据可视化,我个人认为这在机器学习中比较重要,它可以展现出哪些特征用于分类会有更好的效果。

import matplotlib
import matplotlib.pyplot as plt
zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\STXINWEI.ttf')
fig=plt.figure()#得到fig对象
ax=fig.add_subplot(111)#得到axis对象,图像在一行一列的第一位
ax.scatter(datingdatamat[:,1],datingdatamat[:,2],17.0*np.array(datinglabels),17.0*np.array(datinglabels))#绘制散点图,后两位设置尺寸和颜色
plt.xlabel("玩视频游戏的时间百分比",fontproperties=zhfont) #设置标签以及中文字体
plt.ylabel("每周冰淇淋消耗公升数",fontproperties=zhfont) #设置标签以及中文字体
plt.show()

对数据进行归一化处理。避免出现因为数据的取值范围的原因影响预测结果。

#归一化处理
from  numpy import *
def autonorm(dataset):
    minvals=dataset.min(0) #每列最小,索引为0.如果为1,代表每行的最小值,若无参数,为所有中的最小值
    maxvals=dataset.max(0)#同理
    ranges=maxvals-minvals#列表相减
    normdataset=np.zeros(shape(dataset))#建立一个同样规格的零值矩阵
    m=dataset.shape[0]#读取矩阵的长度,shape[0]就是读取矩阵第一维度的长度。
    normdataset=dataset-tile(minvals,(m,1))#重复A B次,相当于每个数据都减去了最小值。
    normdataset=normdataset/tile(ranges,(m,1))#上一步减去最小值之后,现在再除以最大值减去最小值
    return normdataset,ranges,minvals
normmat,ranges,minvals=autonorm(datingdatamat)
进行分类测试,用之前构建的分类器函数以及前面提到的各种数据处理。最后输出错误率以及预测结果和实际结果。
def datingclasstest():
    horatio=0.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=classfuction(normmat[i,:],normmat[numtestvecs:m,:],datinglabels[numtestvecs:m],3)#将后0.9的数据用于训练集
        print(classifierresult,datinglabels[i])
        if  classifierresult!=datinglabels[i]:
            errorcount+=1.0
    print(errorcount/float(numtestvecs))#计算错误率
datingclasstest() 

最后是建立一个可以用来预测新数据的分类函数。

def classifyperson():
    resultlist=['不喜欢','有一点点喜欢','很喜欢']#输出有几类结果
    percenttats=float(input("一周玩多久的电子游戏"))#输入三个特征
    ffmiles=float(input("每年飞多远"))
    icecream=float(input("一周吃多少冰淇淋"))
    datingdatamat,datinglabels=file2matrix("datingTestSet2.txt")
    normmat,ranges,minvals=autonorm(datingdatamat)
    inarr=array([ffmiles,percenttats,icecream])
    classifierresult=classfuction((inarr-minvals)/ranges,normmat,datinglabels,3)#输入归一化数据
    print(resultlist[classifierresult-1])#标签是1,2,3.所以需要减一才能作为索引。
classifyperson()

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值