Quo的随手笔记之K近邻算法

算法的介绍

机器学习算法可以分为三个大类 —— 监督学习、无监督学习和强化学习。

监督学习,对训练有标签的数据有用,但是对于其他没有标签的数据,则需要预估。
无监督学习,用于对无标签的数据集(数据没有预处理)的处理,需要发掘其内在关系的时候。
强化学习,介于两者之间,虽然没有精准的标签或者错误信息,但是对于每个可预测的步骤或者行为,会有某种形式的反馈。
而k近邻算法是一种监督学习算法,因为需要知道分类的标签来将数据及进行分类

自我介绍

工作中主要使用java编程,基于Spring系列框架进行开发。人工智能一直很火,辞职后闲来无事,很久之前就希望好好研究一下机器学习,这段时间正好得以时间,所以开始自己的机器学习的生涯。本篇博客也是开山之作,希望能够不断的坚持,与大家分分享学习中的点点滴滴。用词不当也请多多指出。
参考文献:《Machine Learning in Action》,知乎百科

k近邻算法思想阐述

用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。

k近邻算法实例一

目标:
已得到被分为A,B两类点的测试集,对于一个新加入点,判断其属于哪一类别。

伪代码:

  1. 计算测试集dataSet中每个点与新加入点inX的距离
  2. 按照距离递增排序
  3. 选取距离最近的k个点(k一般小于20)
  4. 确定前k个点的标签的频率分布
  5. 取占比例最多的为分类结果

python代码如下:

// By Quo &Peter Harrington
from numpy import *
import operator
#初始化数据
def createDataSet():
    group=array([[1,1.1],[1,1],[0,0],[0,0.1]])
    labels=['A','A','B','B']
    return group,labels

group,labels=createDataSet()
#分类器
def classfy0(inX,dataSet,labels,k):
    dataSetSize=dataSet.shape[0]
    #使得矩阵大小相同,从而做减法运算
    diffMat=tile(inX,(dataSetSize,1))-dataSet
    sqDiffMat=diffMat**2
    sqDistances=sqDiffMat.sum(axis=1)
    #axis=1代表每一行之前求和,为0表示每一列之间求和
    distances=sqDistances**0.5
    #以上为计算目标矩阵和训练集的距离,即相减之后 求平方的和,最后开方
    sortedDistanceRank=distances.argsort()
    #argsort排序,首先按照递增排序,之后将值变成原先位置的标号(用以定位)
    classCount={}
    for i in range(k):
        voteIlabel=labels[sortedDistanceRank[i]]
        #argsort的作用下 正好对应到之前的位置,所以找到对应的分类标签
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
    sortedClassCount= sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    #从根据频率大到小的排名
    return sortedClassCount[0][0]
print(classfy0([0,0],group,labels,3))

k近邻算法实例二

根据已有数据文件生成对应的数据矩阵,即海伦相亲问题
海伦已经收集约会数据一段时间了,他把每个相亲对象数据总结为4列

  1. 每年的飞行里数
  2. 每天玩游戏所占的时间比例
  3. 每周吃的冰淇淋KG
  4. 好感程度(即1为不满意,2为满意,3为非常满意)
    数据格式实例
    40920 8.326976 0.953952 3
    14488 7.153469 1.673904 2
    26052 1.441871 0.805124 1
    75136 13.147394 0.428964 1
    38344 1.669788 0.134296 1
    72993 10.141740 1.032955 1
    35948 6.830792 1.213192 3

问题:怎样利用已有的1000个数据来写一个分类器帮助海伦选择自己的心动男生呢?

算法思想:

  1. 文本数据处理,转换为矩阵的形式,以便在程序中使用
  2. 归一化数据,使三个维度的数据能够具有同样的0到1的范围值
  3. 选取训练集和测试集,使用实例一中的classfy0的分类器进行分类
  4. 统计正确率

代码:

from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plot
#文件转化为矩阵
def file2matrix(filename):
    fr=open(filename)
    arrayOflines =fr.readlines()
    numerOfLines=len(arrayOflines)
    #获取行数,即数据总量
    returnMat=zeros((numerOfLines,3))
    #建立空矩阵
    classLabelVector=[]
    index=0
    for line in arrayOflines:
        line=line.strip()
        #截取回车字符
        listFromLine=line.split('\t')
        #利用数字之间的tab拆分成一个数组
        returnMat[index:]=listFromLine[0:3]
        #前三个数录入特征矩阵
        classLabelVector.append(int(listFromLine[-1]))
        #最后一个数作为分类向量
        index=index+1
    return returnMat,classLabelVector
#归一化处理
def autoNorm(dataSet):
    minVals=dataSet.min(0)
    maxVals=dataSet.max(0)
    #选出每一列的最小值组成的一维向量
    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

def datingClassTest():
    hoRatio=0.1
    datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
    normDataMat, ranges, minVals = autoNorm(datingDataMat)
    m=normDataMat.shape[0]
    numTestVecs=int(m*hoRatio)
    #取百分之十作为测试,百分之九十用来训练
    errorCount=0
    #本循环,代表着对于测试集中的每一项依次进行分类
    for i in range(numTestVecs):
        classifierResult = classfy0(normDataMat[i,:],normDataMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        #参数一为待分类元素,参数二为测试集,参数三为测试集对应的标签分类,参数四为k值,这里选取了3
        dict0={1:'不满意',2:'满意',3:'非常满意'}
        print("分类器返回结果为",dict0.get(classifierResult),"实际结果为",dict0.get(datingLabels[i]))
        if(classifierResult!=datingLabels[i]):
            errorCount=errorCount+1
    print("错误率为",errorCount/numTestVecs)
datingClassTest()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值