聚类分析之KNN

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聚类分析之KNN相关的知识,希望对你有一定的参考价值。

参考技术A 我们先用一个例子体会下。

假设,我们想对电影的类型进行分类,统计了电影中打斗次数、接吻次数,当然还有其他的指标也可以被统计到,如下表所示。

我们很容易理解《战狼》《红海行动》《碟中谍 6》是动作片,《前任 3》《春娇救志明》《泰坦尼克号》是爱情片,但是有没有一种方法让机器也可以掌握这个分类的规则,当有一部新电影的时候,也可以对它的类型自动分类呢?

我们可以把打斗次数看成 X 轴,接吻次数看成 Y 轴,然后在二维的坐标轴上,对这几部电影进行标记,如下图所示。对于未知的电影 A,坐标为 (x,y),我们需要看下离电影 A 最近的都有哪些电影,这些电影中的大多数属于哪个分类,那么电影 A 就属于哪个分类。实际操作中,我们还需要确定一个 K 值,也就是我们要观察离电影 A 最近的电影有多少个。

KNN 的工作原理

“近朱者赤,近墨者黑”可以说是 KNN 的工作原理。整个计算过程分为三步:

计算待分类物体与其他物体之间的距离;

统计距离最近的 K 个邻居;

对于 K 个最近的邻居,它们属于哪个分类最多,待分类物体就属于哪一类。

K 值如何选择

你能看出整个 KNN 的分类过程,K 值的选择还是很重要的。那么问题来了,K 值选择多少是适合的呢?

如果 K 值比较小,就相当于未分类物体与它的邻居非常接近才行。这样产生的一个问题就是,如果邻居点是个噪声点,那么未分类物体的分类也会产生误差,这样 KNN 分类就会产生过拟合。

如果 K 值比较大,相当于距离过远的点也会对未知物体的分类产生影响,虽然这种情况的好处是鲁棒性强,但是不足也很明显,会产生欠拟合情况,也就是没有把未分类物体真正分类出来。

所以 K 值应该是个实践出来的结果,并不是我们事先而定的。在工程上,我们一般采用交叉验证的方式选取 K 值。

交叉验证的思路就是,把样本集中的大部分样本作为训练集,剩余的小部分样本用于预测,来验证分类模型的准确性。所以在 KNN 算法中,我们一般会把 K 值选取在较小的范围内,同时在验证集上准确率最高的那一个最终确定作为 K 值。

距离如何计算

在 KNN 算法中,还有一个重要的计算就是关于距离的度量。两个样本点之间的距离代表了这两个样本之间的相似度。距离越大,差异性越大;距离越小,相似度越大。

关于距离的计算方式有下面五种方式:

欧氏距离;

曼哈顿距离;

闵可夫斯基距离;

切比雪夫距离;

余弦距离。

其中前三种距离是 KNN 中最常用的距离,我给你分别讲解下。

欧氏距离是我们最常用的距离公式,也叫做欧几里得距离。在二维空间中,两点的欧式距离就是:

同理,我们也可以求得两点在 n 维空间中的距离:

曼哈顿距离在几何空间中用的比较多。以下图为例,绿色的直线代表两点之间的欧式距离,而红色和黄色的线为两点的曼哈顿距离。所以曼哈顿距离等于两个点在坐标系上绝对轴距总和。用公式表示就是:

闵可夫斯基距离不是一个距离,而是一组距离的定义。对于 n 维空间中的两个点 x(x1,x2,…,xn) 和 y(y1,y2,…,yn) , x 和 y 两点之间的闵可夫斯基距离为:

其中 p 代表空间的维数,当 p=1 时,就是曼哈顿距离;当 p=2 时,就是欧氏距离;当 p→∞时,就是切比雪夫距离。

那么切比雪夫距离怎么计算呢?二个点之间的切比雪夫距离就是这两个点坐标数值差的绝对值的最大值,用数学表示就是:max(|x1-y1|,|x2-y2|)。

余弦距离实际上计算的是两个向量的夹角,是在方向上计算两者之间的差异,对绝对数值不敏感。在兴趣相关性比较上,角度关系比距离的绝对值更重要,因此余弦距离可以用于衡量用户对内容兴趣的区分度。比如我们用搜索引擎搜索某个关键词,它还会给你推荐其他的相关搜索,这些推荐的关键词就是采用余弦距离计算得出的。

KD 树

其实从上文你也能看出来,KNN 的计算过程是大量计算样本点之间的距离。为了减少计算距离次数,提升 KNN 的搜索效率,人们提出了 KD 树(K-Dimensional 的缩写)。KD 树是对数据点在 K 维空间中划分的一种数据结构。在 KD 树的构造中,每个节点都是 k 维数值点的二叉树。既然是二叉树,就可以采用二叉树的增删改查操作,这样就大大提升了搜索效率。

在这里,我们不需要对 KD 树的数学原理

了解太多,你只需要知道它是一个二叉树的数据结构,方便存储 K 维空间的数据就可以了。而且在 sklearn 中,我们直接可以调用 KD 树,很方便。

用 KNN 做回归

KNN 不仅可以做分类,还可以做回归。首先讲下什么是回归。在开头电影这个案例中,如果想要对未知电影进行类型划分,这是一个分类问题。首先看一下要分类的未知电影,离它最近的 K 部电影大多数属于哪个分类,这部电影就属于哪个分类。

如果是一部新电影,已知它是爱情片,想要知道它的打斗次数、接吻次数可能是多少,这就是一个回归问题。

那么 KNN 如何做回归呢?

对于一个新电影 X,我们要预测它的某个属性值,比如打斗次数,具体特征属性和数值如下所示。此时,我们会先计算待测点(新电影 X)到已知点的距离,选择距离最近的 K 个点。假设 K=3,此时最近的 3 个点(电影)分别是《战狼》,《红海行动》和《碟中谍 6》,那么它的打斗次数就是这 3 个点的该属性值的平均值,即 (100+95+105)/3=100 次。

总结

今天我给你讲了 KNN 的原理,以及 KNN 中的几个关键因素。比如针对 K 值的选择,我们一般采用交叉验证的方式得出。针对样本点之间的距离的定义,常用的有 5 种表达方式,你也可以自己来定义两个样本之间的距离公式。不同的定义,适用的场景不同。比如在搜索关键词推荐中,余弦距离是更为常用的。

另外你也可以用 KNN 进行回归,通过 K 个邻居对新的点的属性进行值的预测。

KNN 的理论简单直接,针对 KNN 中的搜索也有相应的 KD 树这个数据结构。KNN 的理论成熟,可以应用到线性和非线性的分类问题中,也可以用于回归分析。

不过 KNN 需要计算测试点与样本点之间的距离,当数据量大的时候,计算量是非常庞大的,需要大量的存储空间和计算时间。另外如果样本分类不均衡,比如有些分类的样本非常少,那么该类别的分类准确率就会低很多。

当然在实际工作中,我们需要考虑到各种可能存在的情况,比如针对某类样本少的情况,可以增加该类别的权重。

同样 KNN 也可以用于推荐算法,虽然现在很多推荐系统的算法会使用 TD-IDF、协同过滤、Apriori 算法,不过针对数据量不大的情况下,采用 KNN 作为推荐算法也是可行的。

KmeansKmeans++和KNN算法比較

K-Means介绍

       K-means算法是聚类分析中使用最广泛的算法之中的一个。它把n个对象依据他们的属性分为k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。其聚类过程能够用下图表示:


        如图所看到的。数据样本用圆点表示,每一个簇的中心点用叉叉表示。(a)刚開始时是原始数据。杂乱无章,没有label,看起来都一样。都是绿色的。

(b)如果数据集能够分为两类。令K=2。随机在坐标上选两个点,作为两个类的中心点。(c-f)演示了聚类的两种迭代。先划分,把每一个数据样本划分到近期的中心点那一簇;划分完后,更新每一个簇的中心。即把该簇的全部数据点的坐标加起来去平均值。这样不断进行”划分—更新—划分—更新”,直到每一个簇的中心不在移动为止。

该算法过程比較简单,但有些东西我们还是须要关注一下。此处。我想说一下"求点中心的算法"

一般来说。求点群中心点的算法你能够非常简的使用各个点的X/Y坐标的平均值。也能够用另三个求中心点的的公式:

1)Minkowski Distance 公式 —— λ 能够任意取值。能够是负数,也能够是正数,或是无穷大。

2)Euclidean Distance 公式 —— 也就是第一个公式 λ=2 的情况

3)CityBlock Distance 公式 —— 也就是第一个公式 λ=1 的情况

这三个公式的求中心点有一些不一样的地方,我们看下图(对于第一个 λ 在 0-1之间)。

(1)Minkowski Distance (2)Euclidean Distance (3)CityBlock Distance

上面这几个图的大意是他们是怎么个逼近中心的,第一个图以星形的方式。第二个图以同心圆的方式,第三个图以菱形的方式。


Kmeans算法的缺陷

  • 聚类中心的个数K 须要事先给定,但在实际中这个 K 值的选定是非常难以预计的,非常多时候。事先并不知道给定的数据集应该分成多少个类别才最合适
  • Kmeans须要人为地确定初始聚类中心。不同的初始聚类中心可能导致全然不同的聚类结果。

    (能够使用Kmeans++算法来解决)

针对上述第2个缺陷,能够使用Kmeans++算法来解决

K-Means ++ 算法

 k-means++算法选择初始seeds的基本思想就是:初始的聚类中心之间的相互距离要尽可能的远。

  1. 从输入的数据点集合中随机选择一个点作为第一个聚类中心
  2. 对于数据集中的每个点x。计算它与近期聚类中心(指已选择的聚类中心)的距离D(x)
  3. 选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大
  4. 反复2和3直到k个聚类中心被选出来
  5. 利用这k个初始的聚类中心来执行标准的k-means算法
 从上面的算法描写叙述上能够看到。算法的关键是第3步,怎样将D(x)反映到点被选择的概率上,一种算法例如以下:
  1. 先从我们的数据库随机挑个随机点当“种子点”
  2. 对于每一个点。我们都计算其和近期的一个“种子点”的距离D(x)并保存在一个数组里。然后把这些距离加起来得到Sum(D(x))。

  3. 然后。再取一个随机值。用权重的方式来取计算下一个“种子点”。

    这个算法的实现是。先取一个能落在Sum(D(x))中的随机值Random。然后用Random -= D(x),直到其<=0。此时的点就是下一个“种子点”。

  4. 反复2和3直到k个聚类中心被选出来
  5. 利用这k个初始的聚类中心来执行标准的k-means算法

能够看到算法的第三步选取新中心的方法,这样就能保证距离D(x)较大的点,会被选出来作为聚类中心了。

至于为什么原因比較简单,例如以下图 所看到的:  

                                                

      如果A、B、C、D的D(x)如上图所看到的,当算法取值Sum(D(x))*random时,该值会以较大的概率落入D(x)较大的区间内,所以相应的点会以较大的概率被选中作为新的聚类中心。

k-means++代码:http://rosettacode.org/wiki/K-means%2B%2B_clustering


KNN(K-Nearest Neighbor)介绍

算法思路:假设一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。该方法在定类决策上仅仅根据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。

看以下这幅图:

KNN的算法过程是是这种:

       从上图中我们能够看到。图中的数据集是良好的数据。即都打好了label,一类是蓝色的正方形,一类是红色的三角形,那个绿色的圆形是我们待分类的数据。

     假设K=3,那么离绿色点近期的有2个红色三角形和1个蓝色的正方形,这3个点投票。于是绿色的这个待分类点属于红色的三角形

     假设K=5。那么离绿色点近期的有2个红色三角形和3个蓝色的正方形,这5个点投票,于是绿色的这个待分类点属于蓝色的正方形

     我们能够看到。KNN本质是基于一种数据统计的方法!

事实上非常多机器学习算法也是基于数据统计的。

     KNN是一种memory-based learning,也叫instance-based learning。属于lazy learning。即它没有明显的前期训练过程,而是程序開始执行时,把数据集载入到内存后,不须要进行训练,就能够開始分类了。

详细是每次来一个未知的样本点。就在附近找K个近期的点进行投票。

再举一个样例。Locally weighted regression (LWR)也是一种 memory-based 方法。例如以下图所看到的的数据集。

用不论什么一条直线来模拟这个数据集都是不行的,由于这个数据集看起来不像是一条直线。可是每一个局部范围内的数据点,能够觉得在一条直线上。每次来了一个位置样本x。我们在X轴上以该数据样本为中心,左右各找几个点,把这几个样本点进行线性回归。算出一条局部的直线。然后把位置样本x代入这条直线,就算出了相应的y。完毕了一次线性回归。也就是每次来一个数据点,都要训练一条局部直线,也即训练一次,就用一次。LWR和KNN非常相似,都是为位置数据量身定制,在局部进行训练。


KNN和K-Means的差别

KNN

K-Means

1.KNN是分类算法

2.监督学习

3.喂给它的数据集是带label的数据。已经是全然正确的数据

1.K-Means是聚类算法

2.非监督学习

3.喂给它的数据集是无label的数据。是杂乱无章的。经过聚类后才变得有点顺序。先无序。后有序

没有明显的前期训练过程,属于memory-based learning 有明显的前期训练过程
K的含义:来了一个样本x,要给它分类,即求出它的y。就从数据集中。在x附近找离它近期的K个数据点,这K个数据点,类别c占的个数最多,就把x的label设为c K的含义:K是人工固定好的数字,如果数据集合能够分为K个簇,因为是依靠人工定好,须要一点先验知识


相似点:都包括这种过程,给定一个点,在数据集中找离它近期的点。

即二者都用到了NN(Nears Neighbor)算法,一般用KD树来实现NN。

以上是关于聚类分析之KNN的主要内容,如果未能解决你的问题,请参考以下文章

用聚类分析鸢尾花数据

聚类问题中都有哪些常用的测试数据集

KmeansKmeans++和KNN算法比較

在 Scikit 的谱聚类中使用预先计算的亲和矩阵时的 KNN?

R语言聚类分析之层次聚类(hierarchical clustering)实战

scikit-learn估计器-KNN均值聚类