k-近邻算法简介
k-近邻算法(KNN)是一种非常简单且直观的分类算法,它采用测量不同特征值之间的距离的方法进行分类。k-近邻算法是一种非常直观的分类方法,从直观的角度来看就是数据点和哪一类的点最近就属于哪一类。
1、k-近邻算法的优缺点
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
2、KNN的工作原理
是:存在一个样本数据集合,也叫训练样本集,其中训练样本集中的每个数据都存在标签,即已知样本集中每一个数据与其所属类别的分类关系。输入没有标签的新数据之后,计算新数据与原来数据中点的聚类,然后提取样本集中特征最相似数据(最近邻)的分类标签。一般来讲,我们选取样本集中前k个最相似的数据(k-近邻名称的来源),通常k是不大于20的整数,然后,选择这k个最相似数据中出现次数最多的分类,作为新数据的分类。
3、距离计算
明氏距离又叫做明可夫斯基距离,是一种通用的度量标准
$\left(\sum_{i=1}^{n}\left|x_{i}-y_{i}\right|^{p}\right)^{1 / p}$
不过,在实际使用中,我们更常见到的一般是以下三种距离
曼哈顿距离
$\left(\sum_{i=1}^{n}\left|x_{i}-y_{i}\right|\right)$
通常用于街区或城市中距离计算等情况
欧氏距离
$\left(\sum_{i=1}^{n}\left|x_{i}-y_{i}\right|^{2}\right)^{1 / 2}=\|x\|_{2} :=\sqrt{x_{1}^{2}+\cdots+x_{n}^{2}}$
一般来讲最常用的距离计算公式,也是空间几何中的距离计算公式
切比雪夫距离
$\lim _{p \rightarrow \infty}\left(\sum_{i=1}^{n}\left|x_{i}-y_{i}\right|^{p}\right)^{\frac{1}{p}}=\max _{i=1}^{n}\left|x_{i}-y_{i}\right|$
也称棋盘距离,是国际象棋上王从一个位置移动到另外一个位置所需的最小步数
4、KNN的python实现def k_nearest_neighbor(inX,data_set,labels,k):
"""
:param inX: 输入的新向量
:param data_set: 训练集
:param labels: 训练集对应的标签
:param k: 最近邻的数目
:return: 输入向量的预测标签
"""
diff_mat = np.tile(inX,(data_set.shape[0],1)) - data_set #将输入向量展成和训练集相同的维度,然后做差
distance = ((diff_mat ** 2).sum(axis=1)) ** 0.5 #欧氏距离
sort_distance_indices = distance.argsort() #按照从小到大的顺序,返回对应索引值
vote_label = []
for i in range(k):
vote_label.append(labels[sort_distance_indices[i]]) #记录前k个临近点的标签
Xlabel = Counter(vote_label).most_common(1) #出现次数最多的标签即为当前点的预测分类
print(Xlabel)
return Xlabel[0][0]
5、补充:numpy.tile()函数
在这个函数中,numpy.tile()函数起到了一个重要的地位,但其实,仅仅借助numpy的广播特性也可以完成相关计算,但在这里还是介绍一下numpy.tile()函数
numpy.tile(A,reps)函数是将A按照reps从后向前的顺序按照每个元素的大小来进行展开
比如numpy.tile(A,(1,2,3))是将A先在第一个维度复制3份,然后作为一个整体复制两份,最后新的整体复制一份>>>import numpy as np
>>>np.array([3, 6, 8])
>>>np.tile(a, (3, 2, 1))
array([[[3 6 8]
[3 6 8]]
[[3 6 8]
[3 6 8]]
[[3 6 8]
[3 6 8]]])
>>>np.tile(a, (1, 2, 3))
array([[[3 6 8 3 6 8 3 6 8]
[3 6 8 3 6 8 3 6 8]]])
6、数据归一化
在处理实际问题中,kNN认为数据的几种特征的权重是相同的(在距离计算中不同特征地位相同),但是不同的特征可能范围和大小相差很大,这时候直接计算距离会使得数字差值最大的属性对结果产生的影响远大于其它属性,为此,我们需要归一化数值,以保证各种特征影响因素相同
即$newValue = \frac{oldValue-min}{max-min}$import numpy as np
def autoNorm(dataSet):
min_values = dataSet.min(axis=0)
max_values = dataSet.max(axis=0)
ranges = max_values - min_values
norm_data_set = np.zeros(dataSet.shape)
norm_data_set = dataSet - np.tile(min_values, (dataSet.shape[0], 1))
norm_data_set = norm_data_set / np.tile(ranges, (dataSet.shape[0], 1))
return norm_data_set