K-近邻算法的学习和实现
K-近邻算法的原理是采用测量不同特征值之间的距离方法进行分类。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
使用数据范围:数值型和标称型。
实现K-近邻算法的计算路径,对未知类别熟悉的数据集中的每个点依次执行以下操作:
- 计算已知类别数据集中的点与当前点之间的距离;
- 按照距离递增次序排序;
- 选取与当前点距离最近的K个点;
- 缺点前K个点所在类别的出现频率;
- 返回前K个点出现频率最高的类别作为当前点的预测分类。
以下是函数学习过程以及算法实现步骤。
array函数
numpy中的array是用来创建数组的,使用array函数创建时,参数必须是由方括号括起来的列表,而不能使用多个数值作为参数调用array。
>>> from numpy import *
>>> a=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
>>> a
array([[1. , 1.1],
[1. , 1. ],
[0. , 0. ],
[0. , 0.1]])
shape函数
shape函数是numpy.core.fromnumeric中的函数,它的功能是查看矩阵或者数组的维数。
首先a.shape是查询数组的形状,从第一维、第二维、依次查询数组长度,查询结果为tuple数据类型,如:
>>> from numpy import *
>>> a=array([[[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]],[[1.0,1.1],[1.0,1.0],[0,0],[0,0
.1]]])
>>> a
array([[[1. , 1.1],
[1. , 1. ],
[0. , 0. ],
[0. , 0.1]],
[[1. , 1.1],
[1. , 1. ],
[0. , 0. ],
[0. , 0.1]]])
>>> a.shape
(2, 4, 2)
然后制定查询第几维的长度,就是指定查询shape结果的tuple中的数据,因此查询第一维数组的长度,使用
>>> a.shape[0]
2
tile函数
原型:numpy.tile(A,reps)
tile共有2个参数,A指待输入数组,reps则决定A重复的次数。整个函数用于重复数组A来构建新的数组。这里的reps参数可以是任意长度的tuple,依次标识构建的新数组,前面的数字分别代表构建的第几维数组的长度,最后一个数字指定A数组在最低维的重复次数。如:
>>> b=tile([0,1],(3,2))
>>> b
array([[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 0, 1]])
>>> b=tile([0,1],(3,1))
>>> b
array([[0, 1],
[0, 1],
[0, 1]])
>>> b=tile([0,1],(1,2))
>>> b
array([[0, 1, 0, 1]])
>>> b=tile([0,1],(3,2,3))
>>> b
array([[[0, 1, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 1]],
[[0, 1, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 1]],
[[0, 1, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 1]]])
数组运算
数组运算请参考高等代数中数组运算章节,不过numpy中的数组运算与高等代数中有一点区别,对缺失的维度会从第一行依次自动进行补全,然后进行加减运算,如:
>>> a=array([1,2,3,4])
>>> b=array([[2,3,4,5],[7,6,5,4]])
>>> b-a
array([[1, 1, 1, 1],
[6, 4, 2, 0]])
sum函数
首先sum()是求和函数
>>> a=array([6,3,7])
>>> a.sum() #对数组进行求和
16
>>> a=array([[6,3,7],[2,3]])
>>> a.sum() #并没有求和,而是按照list对数组进行了打印
[6, 3, 7, 2, 3]
然后尝试在sum()中加入参数,如array.sum(axis=1)和array.sum(axis=1),axis的参数只允许为0或者1,其中axis=0, 表示对列求和,7 axis=1, 表示对行求和。
>>> a=array([[6,3,7],[2,3,4],[9,7,5]])
>>> a.sum()
46
>>> a.sum(axis=0)
array([17, 13, 16])
>>> a.sum(axis=1)
array([16, 9, 21])
>>> a.sum(axis=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\Administrator\Anaconda3\lib\site-packages\numpy\core\_methods.p
y", line 36, in _sum
return umr_sum(a, axis, dtype, out, keepdims, initial)
numpy.core._internal.AxisError: axis 3 is out of bounds for array of dimension 2
根据以上函数可以计算两个向量点之间的距离,数学过程见下图,
python实现代码如下:
from numpy import *
import operator
def creatDateSet(): #导入已知类别数据集和分类结果
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group,labels
def classify0(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0] #求已知样本的数组形状
diffMat=tile(inX,(dataSetSize,1))-dataSet #未知点与已知点的差向量集合
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1) #对差向量矩阵的行求和
distances=sqDistances**0.5 #求每个差向量的距离(欧式距离)
return dataSetSize,diffMat,sqDiffMat,sqDistances,distances #返回各变量的结果,打印计算过程
group,labels=creatDateSet() #调用已知类别数据集
a=classify0([0,0],group,labels,3) #调用K-近邻算法函数,并输入未知向量inX,及K值
print(a[4])
array([1.48660687, 1.41421356, 0. , 0.1 ])
argsort函数
argsort函数返回的是数组值从小到大的索引值,如:
>>> a=array([1.48660687, 1.41421356, 0. , 0.1 ])
>>> a.argsort()
array([2, 3, 1, 0], dtype=int64)
字典的使用
Python 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值。
from numpy import *
import operator
def creatDateSet():
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group,labels
def classify0(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistances