既然是K-近邻算法,很明显有两个重要因素,一个是K值,一个是近邻。其实就是K个最近的邻居。也就是说,预测新值就去找它最近的K个邻居,看看邻居是什么类别就可以啦。
这个K值取多少?还有这个怎么算近呢?
实现流程:
1)计算已知类别数据集中的点与当前点之间的距离
2)按距离递增次序排序
3)选取与当前点距离最小的k个点
4)统计前k个点所在的类别出现的频率
5)返回前k个点出现频率最高的类别作为当前点的预测分类
# 安装 pip3 install scikit-learn==0.19.1 #检查安装是否成功 import sklearn #注:安装scikit-learn需要Numpy, Scipy等库
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5) # n_neighbors:int,可选(默认= 5),k_neighbors查询默认使用的邻居数
回顾一下机器学习的流程
1.获取数据集
2.数据的基本处理
3.特征工程
4.机器学习
5.模型评估
仅执行获取数据集和机器学习的步骤
1、导入模块
from sklearn.neighbors import KNeighborsClassifier
2、构造数据集
x = [[0], [1], [2], [3]] y = [0, 0, 1, 1]
3、机器学习-模型训练
# 实例化API estimator = KNeighborsClassifier(n_neighbors=2) # 使用fit方法进行训练 estimator.fit(x, y) estimator.predict([[1]])
两个样本的距离可以用欧氏距离求。
二维、三维、n维之间的欧氏距离,可参考两点间的距离公式,以此类推。
如现在有n部电影,可以将电影的搞笑镜头、拥抱镜头、打斗镜头的数量统计一下,来判断电影类型。
给一个新的电影,这个镜头数量可以用来计算距离去预测。直接求每个电影和待预测电影的距离,然后求解。找出最近的K个,看看它们都是什么类型的就行啦。
在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离”。
d = |x1-x2| + |y1 - y2|
国际象棋♟中,国王可以走到相邻的8个方格中的任意一个。从一个格子走到另一个格子最少需要多少步就是切比雪夫距离
d = max( |x1 - x2| , | y1 - y2 |)
闵式距离不是一种距离,而是一组距离的定义,也就是把几种距离概括性的表示了一下。
当p=1时,就是曼哈顿距离;
当p=2时,就是欧氏距离;
当p→∞时,就是切比雪夫距离。
根据p的不同,闵氏距离可以表示某一类/种的距离。
小结:
这些缺点其实有点大啊,得出相同的数字的话,有可能天差地别。
二维样本(身高[单位:cm],体重[单位:kg]),现有三个样本:a(180,50),b(190,50),c(180,60)。
a与b的闵氏距离(无论是曼哈顿距离、欧氏距离或切比雪夫距离)等于a与c的闵氏距离。但实际上身高的10cm并不能和体重的10kg划等号。
闵式距离的缺点:
将每个分量的单位,相同看待,没有考虑到各个分量的分布(如期望和方差)可能是不同的。
改进来了
分布不同,那可以先将各个分量都标准化到均值、方差相等。
标准化变量为
标准化距离公式为
在几何中,夹角余弦代表的是两个方向向量的差异。在机器学习中可以衡量样本向量之间的差异。
这个我就不说类推了,确实没前几个类推明显。列一下
二维:
n维:
余弦越大呢,夹角就越小,重合时余弦值最大为1,完全相反余弦值最小为-1
第一次听说这个啊
两个等长字符串s1与s2的汉明距离为:将其中一个变为另外一个所需要作的最小字符替换次数。
如果说你想从一个字符串变成另一个字符串是需要去变动的(等长)
那么从字符串1变为字符串2需要替换几次字符呢
从字符串2变为字符串1需要替换几次字符呢
最小的这个次数就是汉明距离
汉明重量
是字符串相对于同样长度的零字符串的汉明距离,也就是说,它是字符串中非零的元素个数:对于二进制字符串来说,就是 1 的个数,所以 11101 的汉明重量是 4。因此,如果向量空间中的元素a和b之间的汉明距离等于它们汉明重量的差a-b。
应用:
汉明重量分析在包括信息论、编码理论、密码学等领域都有应用。比如在信息编码过程中,为了增强容错性,应使得编码间的最小汉明距离尽可能大。但是,如果要比较两个不同长度的字符串,不仅要进行替换,而且要进行插入与删除的运算,在这种场合下,通常使用更加复杂的编辑距离等算法。
杰卡德相似系数
集合AB的交集元素在A,B的并集中所占的比例
杰卡德距离
与杰卡德相似系数相反,用两个集合中不同元素占所有元素的比例来衡量两个集合的区分度:
貌似是最难的,但是理解起来还算是可以。
如果有两个正态分布图,分别有不同均值,方差也不同。
如果这个时候有一个A点,看看A点距离哪个图更近一些,此时与前面提到的欧氏距离就没关系了。它就是看看更大概率属于谁。
其实就是基于这个样本分布的距离了。这个倒是正好弥补了欧式距离不考虑分布区域只是机械求值的劣势。
马氏距离的定义如下:
公式理解起来有点费劲哈
m就是m个指标,也就是m维
均值向量:
协方差阵:
特性:
1.没有变量之间相关性的干扰
2.同样的样本放在不同的总体(如不同的分布图)中,计算的值不同,除非协方差恰好相同
3.总体样本维数大于样本,不然就判断不出来啦
太大了不行,太小了也不行。如果有异常点,K值过小就是一场灾难,K值过大,样本均衡控制不住啦。
选择较小的K值,整体模型反而变得复杂,容易发生过拟合
选择较大的K值,虽说减少学习的估计误差但是学习的近似误差会增大。与输入实例不想死的训练实例也会对预测器起作用导致预测发生错误,且K值的增大就意味着整体的模型变得简单。
可以使用交叉验证法来选择一个最优的k值。把训练数据分成两组:训练集和验证集。对这个简单的分类器,用核方法把线性扩展成非线形,低维映射到高维。
那么如何对训练数据进行快速k近邻搜索呢
如果特征空间的维数特别大及训练数据容量大的时候,这个快速显得是不是更重要啦
最简单的也是最耗时的就是线性扫描,穷举扫描。计算输入实例与每一个训练实例的距离,计算一下,存储下来,再查找k近邻。
那么如何提高knn搜索的效率呢,那就想办法用数据结构存储来训练数据,可以减少重复计算或者是见效计算距离的次数。
根据KNN每次预测一个点时,需要计算训练数据集的里的每个点到这个点的距离,然后选出距离最近的k个点进行投票。复杂度为O(DN^2),计算成本可太大了。
kd树出来啦
可以把距离信息保存在树里,避免重复计算。也就是说如果A和B距离很远,B和C距离很近,那么A和C的距离也很远。复杂度为:O(DNlog(N))
左子树和右子树总是有神威的。不断的划分不断的划分,例如左边小于3,右边大于3,那么这个分割线就是分割超平面。简单来说,一维中就是一个点,二维中就是一条线,三维就是一个面。
最近邻域搜索
kd树是一种对k维空间中的实例点进行存储一边对其进行快速检索的树形数据结构。kd树是一种二叉树,表示对k维空间的一个划分。构造kd树相当于不断地用垂直于坐标轴的超平面将K维空间切分,构成一系列的K维超矩形区域。kd树的每个结点对于一个k维超矩形区域。利用kd树可以省去对大部分数据点的搜索,从而减少搜索的计算量。
类比“二分查找”
把二分查找中的数据点换成k维数据点,这样的划分就变成了用超平面对k维空间的划分。空间划分就是对数据点进行分类,“挨得近”的数据点就在一个空间里面。
1、构造根结点,使根结点对应于K维空间中包含所有实例点的超矩形区域
2、通过递归的方法,不断对k维空间进行切分,生成子结点。找一个切分点来确定超平面,然后划分为两个区域,也就是生成子结点,实例就被分到两个区域啦。
3、一直执行2过程,直到子区域中没有实例时候终止,也就是叶子结点。在这个过程中,实例就可以保存到相应的结点上。
4、循环的选择坐标轴对空间进行切分,选择训练实例点在坐标轴上的中位数为切分点,这样得到的kd树是平衡的,也就是平衡二叉树。
kd树中的每个节点都可以作为一个向量。KD树每层需要选定向量中的某一维,然后根据这一维按左小右大的方式划分数据。
构建树的时候有两个问题:
选择向量的哪一维进行划分?可随机可顺序,找数据分散的那一维划分是最好的。那这个分散如何算是分散可以根据方差来衡量。
如何划分数据? 每次选择中位数进行划分。
未完待续