通过书《机器学习实战》来学习机器、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
测试数据还是比较符合预期结果的