机器学习——k-近邻算法(学习记录)

目录

一、k-近邻算法概述

1.概念

2.工作原理

3.k-近邻算法的一般流程

4.距离度量

5.kNN算法的优势

二、基于k-近邻算法的实例

三、总结

一、k-近邻算法概述

1.概念

给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的k个实例,也就是所说的k个邻居,这k个实例的多数属于某个类,就把该输入实例分类到这个类中(类似于现实生活中少数服从多数的思想)。k近邻算法是一种用于分类和回归的统计方法,可以说是最简单的分类算法之一,同时,也是最常用的分类算法之一。

2.工作原理

如上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的绿色的圆表示为待分类的数据。相当于来了一个新的数据点,想求得它的类别是什么?那么,我们可以根据k近邻算法来给绿圆进行分类。

*如果k=3,绿圆最邻近的3个点为2个红色小三角和1个蓝色小正方形,少数服从多数,判定绿圆这个待分类点属于红色的三角形一类。

*如果k=5,绿圆最邻近的5个点为2个红色小三角和3个蓝色小正方形,还是少数服从多数,判定绿圆这个待分类点属于蓝色的正方形一类。

^{T}懂了,也知道怎么给新来的点如何进行归类,只要找到离它最近的k个实例,哪个类别最多即可。

3.k-近邻算法的一般流程

(1)收集数据:可以使用任何方法。

(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。

(3)分析数据:可以使用任何方法。

(4)训练算法:此步骤不适用于k-近邻算法。

(5)测试算法:计算错误率。

(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

4.距离度量

特征空间中两个实例点之间的距离是二者相似程度的反应,所以k近邻算法中一个重要的问题是计算样本之间的距离,以确定训练样本中哪些样本与测试样本更加接近。

L_{p}距离

        

当p=2,为欧氏距离(Euclidean Distance)

当p=1,为曼哈顿距离(Manhattan Distance)

当p=∞,为各个坐标距离的最大值

(1)欧氏距离(Euclidean Distance)

        欧氏距离是最常见的距离度量,衡量的是多维空间中两个样本点之间的绝对距离。假设多维空间的维度为N,x_{1}=x_{11}x_{12},……,x_{1N}x_{2}=x_{21}x_{22},……,x_{2N}是两个样本点,则x_{1}x_{2}之间的欧氏距离计算公式为

可见,欧氏距离由两个样本之间每一维度之差的平方和计算而来。当维度之间的取值范围差别太大时,欧氏距离容易被那些取值范围大的变量所主导,从而大大降低模型的效果。因此,如果采用欧氏距离作为相似度度量,最好提前对数据进行标准化转换

(2)曼哈顿距离(Manhattan Distance)

曼哈顿距离,也被称为出租车几何。曼哈顿距离计算公式为:

曼哈顿距离等于两个样本之间每一维度之差的绝对值之和。曼哈顿距离的含义可以对应到规划为方框建筑的城市(如曼哈顿),两个地点的出租车最短行驶距离。在使用曼哈顿距离时,也需要考虑变量之间取值范围不同对结果的影响。

5.kNN算法的优势

(1)精度高

(2)对异常值不敏感

(3)无数据输入假定

二、基于k-近邻算法的实例

1.准备数据:从文本文件中解析数据

def fileMatrix(filename):
    file = open(filename)
    arrayOLines = file.readlines()
    numberOfLines = len(arrayOLines)
    returnMat = zeros((numberOfLines, 3))
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector

2.分析数据:用Matplotlib创建散点图

def showdatas(datingDatMat, datingLabels, numScatter, xylabel):
    fig = plt.figure()
    font = {'family': 'MicroSoft YaHei'}
    matplotlib.rc("font", **font)
    ax = fig.add_subplot(111)
    ax.scatter(datingDatMat[:, numScatter[0]], datingDatMat[:, numScatter[1]], 15.0 * array(datingLabels), 15.0 * array(datingLabels))
    ax.set_xlabel(xylabel[1])
    ax.set_ylabel(xylabel[2])
    plt.title(xylabel[0])
    plt.show()
 
datingDatMat, datingLabels = fileMatrix('datingTestSet.txt')
numScatter = array([[0, 1], [0, 2], [1, 2]])
xylabel = array([['每年获得飞行常客里程数与玩视频游戏所消耗占比', '每年获得的飞行常客里程数', '玩视频游戏所消耗时间占'],
                 ['每年获得飞行常客里程数与每周消费的冰激淋公升数', '每年获得的飞行常客里程数', '每周消费的冰激淋公升数'],
                 ['玩视频游戏所消耗时间占比与每周消费的冰激淋公升数', '玩视频游戏所消耗时间占比','每周消费的冰激淋公升数']])
showdatas(datingDatMat, datingLabels, numScatter[0], xylabel[0])
showdatas(datingDatMat, datingLabels, numScatter[1], xylabel[1])
showdatas(datingDatMat, datingLabels, numScatter[2], xylabel[2])

3.准备数据:数据归一化

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

datingDatMat, datingLabels = fileMatrix('datingTestSet.txt')
normData, ranges, minVals = autoNorm(datingDatMat)
print('normData')
print(normData)
print('ranges')
print(ranges)
print('minVals')
print(minVals)

4.测试算法:作为完整程序验证分类器

def datingClassTest():
    hoRatio = 0.1    #10%的测试数据
    datingDatMat, datingLabels = fileMatrix('datingTestSet.txt')  #从文件读数据
    normMat, ranges, minVals = autoNorm(datingDatMat)              #数据的归一化
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)                                   #测试数据数量
    errorCount = 0.0                                               #错误数量统计
    for i in range(numTestVecs):
        classifierResult = classify(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("分类器返回的结果是:%d,真实结果是:%d"%(classifierResult, datingLabels[i]))
        if(classifierResult != datingLabels[i]):
            errorCount += 1.0
    print('分类器处理约会数据集的错误率是:%f'%(errorCount/float(numTestVecs)))

5.使用算法:构建完整可用系统

def classifyPerson():
    #输出结果
    resultList = ['讨厌','有些喜欢','非常喜欢']
    #三维特征用户输入
    ffMiles = float(input("每年获得的飞行常客里程数:"))
    precentTats = float(input("玩视频游戏所耗时间百分比:"))
    iceCream = float(input("每周消费的冰激淋公升数:"))
    #打开的文件名
    filename = "datingTestSet.txt"
    #打开并处理数据
    datingDataMat, datingLabels = file2matrix(filename)
    #训练集归一化
    normMat, ranges, minVals = autoNorm(datingDataMat)
    #生成NumPy数组,测试集
    #inArr = np.array([precentTats, ffMiles, iceCream])
    inArr = np.array([ffMiles, precentTats, iceCream])
    #测试集归一化
    norminArr = (inArr - minVals) / ranges
    #返回分类结果
    classifierResult = classify0(norminArr, normMat, datingLabels, 3)
    #打印结果
    print("你可能%s这个人" % (resultList[classifierResult-1]))

三、总结

我们提出了k近邻算法,算法的核心思想是,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。即来了一个新的输入实例,我们算出该实例与每一个训练点的距离,然后找到前k个,这k个哪个类别数最多,我们就判断新的输入实例就是哪类。

得:k值太小欠拟合,k值过大过拟合。

至此,本次学习结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值