机器学习基础-k近邻

  • 本章内容主要基于机器学习实战

概述

k—近邻算法采用测量不同特征值之间的距离方法进行分类。
优点精度高,对异常值不敏感,无数据输入假定
缺点计算复杂度高、空间复杂度高
适用数据范围数值型和标称型

简单来说,就是根据给定的事实,判断样本集中各样本与给定事实的差距,来对样本进行分类。

k-近邻算法分类器

分类器可以满足的功能是:输入三类信息的数值,计算出该值与已知数据之间的距离,对该距离进行排序,取排序前k个数据,统计前k个数据中各种标签所占数量(本任务中,标签为海伦的喜欢程度),数量最多的,为分类器给出的结果,即给定数据的判定结果。

# 分类器
def classify0(inx, dataSet, labels, k):
    #
 inx:给定点的坐标。dataSet:点集。labels:点的标签集合。k: 选择近邻点的个数
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inx, (dataSetSize, 1)) - dataSet
    # tile()函数:tile(inx,(x,y));将inx重复x行,y列,返回数组array()类型
    # 此处将给定点与点集横纵坐标相减,得到△x,△y
    sqDiffMat = diffMat ** 2  # 将diffMat各项平方,得到△x^2,△y^2
    sqDistances = sqDiffMat.sum(axis=1)
    # 数组,array()类型sum()函数表示各项相加,axis = 0,表示按列相加,axis = 1,表示按行相加
    # 此处得到△x^2+△y^2
    distances = sqDistances ** 0.5  # 求得点集各点到给定点的距离
    sortedDistIndicies = distances.argsort()
    # shuzu.argsort()numpy库中的函数,用于返回一个数组,数组中存放的是shuzu中元素从小到大排序
    # 的索引值
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        # 字典对象的get()函数,get(x,y),返回指定键x的值,如果字典中不存在该指定键,返回y
        # 此句统计标签的数目
    sortedClassCount = sorted(classCount.items(),
                              key=operator.itemgetter(1), reverse=True)
    # dic.items()返回字典的键,键值元组数组。
    # key=operator.itemgetter(1)表示比较的元素为每一个元组的第二项,即数量。
    # reverse=True为降序排列,reverse=False为升序排列
    return sortedClassCount[0][0]
    # 返回第一个元组的第一个元素

在约会网站上使用k-临近算法

从文本文件中解析数据

def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()
    ### 读取文件中的每一行全部元素存入列表中,每一行组成列表的一个元素
    numberOfLines = len(arrayOLines)
    ### 获取列表长度,即文件的行数
    returnMat = zeros((numberOfLines, 3))
    ### 新建一个全0的数组。zeros()新建的是一个数组,array()类型
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        ### strip()删除字符串头尾指定的字符(默认为空格或换行符),不能删除中间部分的字符
        listFromLine = line.split('\t')  
        ### 对每一行的元素进行分割,得到相应列表。
        returnMat[index, :] = listFromLine[0:3]
        labels = {'largeDoses': 3, 'smallDoses': 2, 'didntLike': 1}
        ### 相较书中新增的字典
        classLabelVector.append(labels[listFromLine[-1]])
        index += 1
        ### 将listFromLine列表中数值按行,将前三项赋值给returnMat列表
    return returnMat, classLabelVector

使用matplotlib创建散点图

import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
### 创建图像,采用默认配置
ax = fig.add_subplot(111)
### 规定输出图像的格式,111表示创建1×1的网格,图像位于第一子图
ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
### 绘制散点图,用datingDataMat第一列的值定位x轴坐标,第二列的值定为y轴坐标
plt.show()

散点图颜色处理

###其他语句可不变,改变此句
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15*array(datingLabels))
### 新增两项
### 乘15是为了将差异放大
### 前一项为修改点的大小,此处可将datingLabels修改为数组,列表也可以操作,也不要求元素数量与点的数量相同,列表内元素可以循环使用。
### 后一项为修改点的颜色,此处必须将datingLabels修改为数组,或者组元也可,但元素数量必须与绘制的点的数量相同

在这里插入图片描述

对文件数据进行归一化

在对数据进行分类过程中,因为有些数据值很大,在求距离时,所占比重较大,但对用户来说,这些数值的重要程度相同,此时就需要对数据进行归一化操作,采用百分比的形式:
N U M n e w = ( N U M o l d − N U M m i n ) ( N U M m a x − N U M m i n ) NUM_{new} = {(NUM_{old}-NUM_{min})\over(NUM_{max}-NUM_{min})} NUMnew=(NUMmaxNUMmin)(NUMoldNUMmin)

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    ### min(0)求每一列的最小值,min(1)返回每一行的最小值
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))  
    ### 新建一个同dataSet规模相同的零数组
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m, 1))
    normDataSet = normDataSet / tile(ranges, (m, 1))
    ### 相应元素做除法
    ### 矩阵除法用函数linalg.solve(matA,matB)
    return normDataSet, ranges, minVals

测试代码

我们已经拥有了1000组数据,其中记录了海伦希望知道的三类信息对喜欢程度的影响。为了验证分类器的性能,需要对分类器进行测试。
选取10%的数据用作测试,测试结果与测试数据不符的即为分类器失败的数据,由此可以判断分类器的准确度。

# 分类器针对约会网站的测试代码
def datingClassTest():
    hoRatio = 0.10  # 选择10%的数据进行测试
    datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
    # datingLabels 记录的是不喜欢的人,一般喜欢的人,特别喜欢的人,三类
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)  # numTestVecs为用做数据测试的数据的数量
    errorCount = 0.0  # 记录测试失败的数量
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :],
                                     datingLabels[numTestVecs:m], 3)
        # 以数据集中第i行的数据为标准,对训练集后90%条进行分类
        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)))

约会网站测试函数

面相用户的输入输出界面

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('datingTestSet.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = array([ffMiles, percentTats, iceCream])
    classifierReault = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)
    print('You will probably like this person: ',
          resultList[classifierReault - 1])

示例:手写识别系统

此处给出的示例是手写识别系统的简化版本,不多做记录。
提供了的文件,是需要识别的数字,已经使用图形处理软件,处理成32×32的黑白图像,全部由0和1构成,如图:在这里插入图片描述

准备数据:将图像转换为测试向量

所谓将图像转换成向量,就是想32×32的0,1数字全部存入一行数组中,构成[x_1,x_2,···,x_1024]的向量。

# 准备数据,将图像转化为测试向量
# 此处将txt文件中的32×32的数字转换成1024的向量,即将所有行放至一行里
def img2vector(filename):
    returnVect = zeros((1,1024))
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()  # 读取当前行的全部内容
        for j in range(32):
            returnVect[0, 32*i+j] = int(lineStr[j])
    return returnVect

测试算法

在程序中导入listdir(在代码前,写入from os import listdir)
listdir(path):获取该目录下的所有文件,返回列表

def handwritingClassTest():
    hwLabels = []  # 存储训练集向量对应的标签的列表
    trainingFileList = listdir('trainingDigits')
    # 获取该文件夹中所有文件,返回列表
    m = len(trainingFileList)
    trainingMat = zeros((m, 1024))  # 用于存储训练集每组数据转化成的向量的数组
    for i in range(m):  # 得到所有训练集的向量的数组,及该向量对应标签的列表
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        # 获取的文件名为:文件名.txt将文件名与格式分开,此句获取文件名
        classNumStr = int(fileStr.split('_')[0])
        # 文件名为 #_####,下划线前的数字是该文件记录的数字
        hwLabels.append(classNumStr)
        trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr)
    testFileList = listdir('testDigits')
    errorCount = 0.0  # 记录错误数量
    mTest = len(testFileList)  # 测试集资源的数目
    for i in range(mTest):  #
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        # 测试集每组向量对应的正确数字
        vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
        # 得到向量
        classfierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
        print('the classifier came back with: %d, the real answer is: %d'
              % (classfierResult, classNumStr))
        if classfierResult != classNumStr:
            errorCount += 1.0
    print('\n the total number of errors is: %d' % errorCount)
    print('\n the total error rate is: %f' % (errorCount/float(mTest)))

总结

k-近邻算法是分类数据最简单有效的算法。
缺陷:
1、但是对于给定一条需要分类的信息,想要有效对其进行分类,就必须需要大量的训练集,且需要保存。如果训练集很大,就必须使用大量的存储空间。而且必须对训练集中的每个数据计算距离,这在使用时可能很耗时。
2、另一个缺陷,没看懂啥意思,先不写了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 机器学习实战是一本使用Python3语言编写的教程,提供了丰富的示例代码和实际应用案例,帮助读者深入了解机器学习算法和实践。本书具体介绍了Python机器学习库scikit-learn的常用功能和使用方法,以及如何应用这些算法解决实际问题。 该书分为七个部分,分别是:机器学习基础、k-近邻算法、决策树、朴素贝叶斯分类器、逻辑回归、支持向量机和集成方法。每个部分都包含多个章节,通过讲解算法原理、提供示例代码和实战案例来帮助读者逐步学习和应用机器学习。 本书适合有一定Python编程基础的读者学习,对于想要深入理解机器学习算法和应用的开发者来说,这是一本很好的入门书籍。读者可以通过跟随书中的示例代码和练习题,逐步掌握Python编程和机器学习算法的实践技巧。 机器学习实战的亮点是注重实践应用,书中大量的案例和实例代码帮助读者更好地理解和掌握机器学习算法。另外,本书还介绍了一些常用的数据预处理和特征工程方法,以及如何评估和优化模型的性能。通过这些内容的学习,读者可以开始尝试在自己的项目中使用机器学习模型进行预测和分类任务。 总之,《机器学习实战》是一本很好的Python3机器学习实践教程,提供了丰富的示例代码和实际案例,帮助读者深入理解机器学习算法的原理和实践技巧。无论是对于初学者还是有一定经验的开发者来说,这本书都是学习和应用机器学习的有力工具。 ### 回答2: 《机器学习实战 Python3版本》是一本关于机器学习算法实现的经典教材。本书使用Python3作为编程语言,详细介绍了常用的机器学习算法及其在实际问题中的应用。 本书的主要内容包括监督学习、无监督学习和半监督学习等方面。其中,监督学习部分介绍了K近邻算法、决策树、朴素贝叶斯、逻辑回归、支持向量机等常用的分类算法,以及回归算法,如线性回归和岭回归。无监督学习部分介绍了聚类算法,如K均值和层次聚类,以及降维算法,如主成分分析。半监督学习部分介绍了半监督聚类和标签传播算法。 本书着重强调算法的实现,以及如何解决实际问题。每个算法都会给出实现的Python代码,并通过实例详细说明如何使用该算法解决实际问题。读者可以通过运行代码来进一步理解算法的原理和应用。 《机器学习实战 Python3版本》既适合初学者入门,也适合有一定基础的读者深入学习。对于初学者来说,本书提供了基本的机器学习知识和实现代码,帮助他们快速上手。对于有一定基础的读者来说,本书提供了更多实战经验和案例,帮助他们在实际项目中应用机器学习算法。 总之,本书《机器学习实战 Python3版本》以Python语言为工具,详细介绍了机器学习常用算法的实现和应用。对于想要学习机器学习并在实际问题中应用的读者来说,这是一本很好的教材。 ### 回答3: 《机器学习实战 Python3》是一本深入介绍机器学习算法及其实践应用的教材。本书以Python3作为主要编程语言,通过示例代码和案例分析帮助读者理解和应用机器学习技术。 这本书主要分为两部分:第一部分是机器学习基础知识的介绍,包括数据预处理、特征选择、模型训练和评估等内容。读者可以学习如何将原始数据转换为可供算法使用的格式,以及如何选择合适的特征来建立模型。此外,还介绍了常用的机器学习算法,如决策树、朴素贝叶斯、支持向量机等。 第二部分则是实践应用,通过多个具体的案例来展示机器学习算法在实际问题中的应用。比如,如何利用分类算法进行垃圾邮件的识别,如何利用回归算法进行房价预测,如何通过聚类算法进行用户分群等。每个案例都会详细介绍问题背景、数据准备、模型选择、结果评估等步骤,读者可以按照作者的指导一步步完成任务。 这本书适合对机器学习有一定兴趣的初级读者。读者需要具备一定的Python编程基础,并对统计学和概率论等有一定的了解。通过阅读本书,读者可以掌握机器学习的基本概念和常用技术,并能够运用Python编程语言进行机器学习实践。 总之,《机器学习实战 Python3》是一本适合初学者入门的机器学习教材。通过学习本书,读者可以系统地了解机器学习的基本理论和实践技巧,并能够在实际问题中应用机器学习算法。这本书对于希望掌握机器学习技术的读者来说是一本不可多得的参考资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值