无公式无代码白话机器学习入门算法KNN(K近邻算法)

        学习机器学习的基本算法的时候,大部分人喜欢直接找一段对应的代码,只要代码跑通了,看懂了,这个算法貌似也就基本掌握了;而如果是在课堂上,老师上课时可能去倾向于用简洁的公式是描述一个算法的思想,这样虽然精炼,概括性强,但是却不利于深刻理解。而我评价自己对一个算法的掌握程度,喜欢白话,也就是抛开代码,抛开公式,用最平实的话来描述这个算法。如果从头到尾说通了,说明对这个算法基本熟悉了。至于具体的公式代码,只要你对思想有了深刻理解,那么在具体操作的时候再细致描述也不迟。而且白话有另一个好处,那就是便于记忆,便于联想,同时也锻炼自己的表达能力,呵呵。

        下面带来一个机器学习的入门算法来测试一下自己的表达能力。这个算法的名字叫“K最邻近算法”,缩写为KNN。这个算法的主要用途就是用来分类。给定一个测试样本,这个样本到底属于哪一类呢?有句俗话说的好,“如果你想了解一个人,那么就去了解他的朋友就知道了。”古代孟母三迁的故事也给我们启示,人以类聚,物以群分,遇到不适合自己的环境,还是应该去找属于自己的地方。KNN就是基于这个原理实现的。我们要知道一个测试样本属于哪个类,只需要找到离它最近的k个样本,然后选择这k个样本中最多的那个类最为测试样本的类别。

       这里就遇到了KNN的第一个缺陷:如何确定这个k值呢?k值得选取关乎最后的分类结果。我感觉k取的大一点结果应该更靠谱一些,但是这个会影响到分类速度;k值取的小呢,又会导致分类结果的不稳定和随机性。通常k值得确定需要我们根据特定情况通过实验不断地试验出来的,我们选择速度又快准确率又高的k值。

        然而这个问题又带来了KNN的第二个缺陷:对训练数据在各个类的数量分布比较敏感。试想,如果在二分类的情况,A类在训练集中数据量大,B类在训练集中数据量小,那么当来到一个测试样本c,本来应该本质上属于B类,但由于A类数据量大,导致在最后的k的邻居投票的时候,A占尽优势,最后样本c便悲剧地被A霸占了。

        尽管这篇文章不是批判KNN,但是我们不得不马上提出KNN的第三个缺陷:那就是计算量太大。KNN模型的训练是一种非参数学习方法,所谓非参数学习方法就是最后训练处的模型没有实际的参数,模型的测试依靠的不是参数而是数据实体。每来到一个测试数据,KNN都要计算这个样本和训练集中的每一个数据的距离,然后去寻找k个最近的邻居。

        哈哈,让我一下子把KNN的缺陷都说出来。KNN的第四个缺陷就是:分类结果可理解性差,无法给出决策树那样的规则。想想也是,KNN在对一个样本分类的时候,并没有从自身的特点上去分类,而是“因为别人是那样的,我和他们是朋友,所以我也是那样的”。至于本质上为什么这样分类,不知道。这让我想起了在推荐系统中基于用户行为的协同过滤算法。该算法并不知道本质上为什么要推荐一个特定物品P给一个特定用户U,仅仅是因为用户U和其他喜欢这个物品的用户具有某种相似性(UserCF),或者因为用户U购买过其他物品XYZ,而很多购买了XYZ物品的用户通常也买了这个物品P(ItemCF)。而基于物品内容的推荐就不是这样,比如隐语义模型等。

       好啦好啦,KNN的缺陷终于说完了。其实,KNN是一个非常优秀和广泛应用的算法。KNN的优点首先就是简单,易于理解,易于实现,无需估计参数,无需训练。我们应该敬畏那些简单并且概括性强的东西。就像模型选择时用到的奥卡姆剃刀原理,越是简单的模型越是最好的。又像欧几里得提出的几何五大公理中的:所有的直角都是相等的。基于此美国政治家提出所有人都是平等的人权主义和法制理念。KNN的原理非常容易理解,即使你讲给五岁小孩都能懂。

        其次,KNN的第二个优点是:对异常值不敏感。因为KNN是KNN而不是1NN,它是对k个邻居的类别进行投票,选择类别数量最多的那个类,而不是选择距离最近的那个1个类。既然是投票,那就是相对公平的啦,即使有一两个“败类”使坏,但是我们相信“群众的眼睛是雪亮的”。

        下面都是表扬KNN的时刻!KNN的第三个优点是:特别适合多分类问题,在这方面甚至要比SVM都好。我们都知道有些机器学习算法在面对二分类问题的时候很牛逼,比如SVM啊,逻辑斯蒂回归啊等等,但是当进行多分类的时候就不那么容易了。为了解决逻辑斯蒂回归的多分类问题,有专门的softmax算法,而解决SVM的多分类问题一般是将多分类问题转化为若干个二分类问题然后再进行融合。而KNN解决多分类问题就简单多了,只是在投票阶段多了几个“候选人”而已。感觉它天生就是为解决多分类问题而生的。所以,在多分类问题的一个重要应用——文档分类方面,KNN表现出色,同样表现出色的是朴素贝叶斯分类器。

        传说中KNN还有第四个优点:对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为合适。很多时候我们遇到的分类问题会是很多类域之间相互交叉,这就给分类任务带来困难。SVM解决这个问题的时候提出了“软间隔”,而KNN完全不用理会这个困难。因为KNN只是靠周围的有限样本做出决策,而不是靠判别类域的方法,因此可以直接回避掉这个问题。毕竟类域交叉本来就是一个挺无解的事儿,KNN至少给出了自己的解决方法并且有一定道理,不管准确与否,都很具有说服力。

        KNN是这样一个缺点和优点同样明显的机器学习方法,让人又爱又恨。那么,我们有没有办法尽量避免它的缺点而发挥它的优点呢?显然可以,这也是从事在一些科研工作者和算法工程师一直在做的事。下面我们就简单探讨一下:

        针对KNN的第二个缺点,我们可以精心设计这样一个训练集,训练集中的各个类的数据都特征明显并且分布均匀数量大致相等。数量相等这个很容易实现,但是分布均匀就有点难度了,尤其是面对高维并且海量的数据。不过话又说回来,如果真是海量数据,我们就不用KNN了,嘿嘿。所以KNN还是适合数据量不大的情况下使用。

        针对KNN的第三个缺点,有人提出了几种改进的方法。首先就是样本集剪裁,选取一定数量有代表性的样本,也可以选择有代表性的属性,这其实也可以归类到上面刚说的设计训练集的问题。其次,引入类中心向量法和KNN相结合。这种方法在分类的类别较多的时候更有效果。其步骤是这样的:首先根据训练集的标注计算每一类的中心向量,假设有m类就有m个中心向量,然后将待分类测试样本与这m个向量计算距离。选取距离最近的n个中心向量代表的类的数据作为下一步的训练集。n是一个阈值,通常取m的一半。

        好啦,上面就是KNN在分类问题上的一些特性。其实,KNN不仅可以分类,而且可以用于回归。KNN用于回归的时候,就是将某个样本的属性设置为它周围K个邻居的属性的均值,这一点让我想到了另一个回归算法,局部加权线性回归。KNN和局部线性加权回归还真有些共同点,比如他们都是非参数的学习算法,他们都依赖周围的邻居,而且离的越近影响越大。

        OK,终于写完了,希望在锻炼了自己的梳理能力之外,能对同学们有点帮助。


参考文献:

http://baike.baidu.com/link?url=_w3jlVqpM_dGP4mrZTwgbwIYlpO-_sUDLDR_Oj1KjmvK5UUT362rNi7QZC0iG7veRnnAN5c-MMHkzaytaN8FH-Ec5xMtT9lwE71MKxooQWob0D-MA3_DcUoyGPlsQLBSJpOSSASyXI6j5seuBQHAI_

http://express.ruanko.com/ruanko-express_56/tech-overnight3.html

你可能感兴趣的:(机器学习)