K-近邻算法01 from机器学习实战

这篇博客基于《机器学习实战》学习K-近邻算法,介绍了如何解决导入模块问题,实现最近邻算法,以及对python的sort()、sorted()和argsorted()函数的理解。核心是利用argsorted()获取最近邻索引,通过构建映射统计标签频率,最终找出最常见的标签作为预测结果。测试显示预期结果一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过书《机器学习实战》来学习机器、python部分

import numpy as np
import matplotlib.pyplot as plt

'''
K近邻算法
思想:选择样本集中前K个最相近的数据中出现最多的分类,
作为新数据的分类
'''


# 预备栗子的数据
def createdataset():
    groups = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return groups, labels


验证如下

>>> import KNN
>>> groups,labels =KNN.createdataset()
>>> groups
array([[1. , 1.1],
       [1. , 1. ],
       [0. , 0. ],
       [0. , 0.1]])
>>> labels
['A', 'A', 'B', 'B']

注明:最初导入KNN.py时提示找不到对应的模块

ModuleNotFoundError: No module named 'KNN'

查阅网上资料后,通过改变工作区间解决这一问题

>>> import os
>>> os.getcwd()
'C:\\Users\\SSY\\AppData\\Local\\Programs\\Python\\Python37'
os.chdir('D:\\pyt_example\\01\\venv')

进一步实现最近邻算法

'''
K近邻算法实现
inX:数据集的数据个数
dataSet数据集labels对应的标签
k 取前K个相近值做判断
'''
def calssify0(inX, dataSet, labels, k):
    #有多少个特征
    datasetsize = dataSet.shape[0]
    diffmat = np.tile(inX, (datasetsize,1))-dataSet
    sqdiffmat =diffmat**2
    # 每一行求和,得到的是每一行的和(也就是距离平方)
    sqdistance = sqdiffmat.sum(axis =1)
    distance =sqdistance**0.5
    #上述过程计算出了距离

    #排序
    #建立一个空字典
    sortedDistanceIndices =distance.argsort()
    classCount={}
    for i in range(k):
        voteIlabel =labels[sortedDistanceIndices[i]]
        # get(key[, default])方法,返回序号(否则返回0)这样,就建立了最近的排名的一个映射
        classCount[voteIlabel]=classCount.get(voteIlabel, 0)+1
    
    sortedClassCount =sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

整个k近邻算法的实现还是比较好理解的,核心思路是,我寻找和要判断的节点最近的k个值,这K个值里面,出现次数最多的标签就是作为我要判断的点的标签

但是在处理这个问题的时候,我发现我对python的排序算法不熟悉,也就是argsorted(),sort(),sorted()函数以及他们具体参数的含义
sort()和sorted()是python自带的排序算法
1.sort()方法,仅对列表有效,sorted()就没有这些限制,对所有的可迭代序列都可行
2.sorted()方法返回一个新的list,新的list的元素基于小于运算符(lt)来排序,而list.sort()方法会直接修改原有的list

>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.
    
    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.
# 默认返回递增序
# key参数:指定一个函数,在此函数将在每个元素比较前被调用(例如把大写变成小写)


print(sorted("This is a test string from Andrew".split(), key=str.lower))
#输出为:['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

# reversed就是反转(升序变降序,降序变升序)
# 还可以自己写cmp函数
print(sorted(list1,cmp = lambda x,y: cmp(x[0],y[0])))#按照第一个位置的字母序排序
 #[('david', 90), ('lily', 95), ('mary', 90), ('sara', 80)]

argsort()函数,是numpy库中的函数,他的作用是返回排序后的索引值
eg:

>>> x = np.array([3, 1, 2])
>>> np.argsort(x)
array([1, 2, 0])
Two-dimensional array:二维数组

>>> x = np.array([[0, 3], [2, 2]])
>>> x
array([[0, 3],
[2, 2]])

>>> np.argsort(x, axis=0) #按列排序
array([[0, 1],
[1, 0]])

>>> np.argsort(x, axis=1) #按行排序
array([[0, 1],
[0, 1]])

再回到k临近算法实现的过程
通过argsort()排序获得了距离最近的点的索引值
因此在后面,可以通过

 for i in range(k):
        voteIlabel =labels[sortedDistanceIndices[i]]
        # get(key[, default])方法,返回序号(否则返回0)这样,就建立了最近的排名的一个映射
        classCount[voteIlabel]=classCount.get(voteIlabel, 0)+1

建立一个映射(能够找到排序后的元素原始对应的labels列表里面的标签)

    ///这里看错了 请忽略
    得到和目标点按由近到远的一个字典,字典中的健为标签(A/B)值为排序(从1到K),也就是距离最近的k个点

实际上是建立了一个字典,标签为健,每次找到新的该标签的元素时,元素的值+1
这样获得的字典应该类似于
{‘A’:1, ‘B’:2} 这个样子

然后我们把字典拆分成元组列表
a.key()对应健
a.items()对应健值的列表
对健值排序
注意:书里的写法是python2.7的语法,用的是a.iteritems(),而在python3中就是简单的a.items()

operator.itemgetter函数

operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号)
举例如下:
op={'1':(1,0,6),'3':(0,45,8),'2':(2,34,10)}                
lp3=sorted(op.items(),key=operator.itemgetter(0),reverse=True)
print(lp3)
输出:[('3', (0, 45, 8)), ('2', (2, 34, 10)), ('1', (1, 0, 6))]                      #注意这里对字典op的key进行了排序

这里的情况与之类似,对字典的值进行排序,字典值按降序排序,
最后输出的结果是出现最多的那个标签,也就是ans[0][0]

测试:

进行一个测试

>>> import imp
>>> imp.reload(KNN)
<module 'KNN' from 'D:\\pyt_example\\01\\venv\\KNN.py'>
>>> KNN.calssify0([0,0],groups,labels,3)
'B'

注明:
1.KNN.py文件新写入了函数,需要重载reload()
2.reload函数在新版本的python里面属于imp模块,需要导入imp
测试数据还是比较符合预期结果的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值