KNN算法原理与实现
一、算法原理
0、惰性学习法
Bayes,决策树, SVM等分类方法均属于急切学习法,它在接收到待分类的新元组前就构建了分类模型,新无级直接经过模型就可以得到结果。
而惰性学习法则相反,它会在接收到待分类的新元组时才开始处理训练数据(或者之前只做一些简单的预处理),新元组会与训练数据逐一匹配,从而得出分类结论。
1、基本思路
算法思路:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
看下面这幅图:
KNN的算法过程是是这样的:
从上图中我们可以看到,图中的数据集是良好的数据,即都打好了label,一类是蓝色的正方形,一类是红色的三角形,那个绿色的圆形是我们待分类的数据。
如果K=3,那么离绿色点最近的有2个红色三角形和1个蓝色的正方形,这3个点投票,于是绿色的这个待分类点属于红色的三角形
如果K=5,那么离绿色点最近的有2个红色三角形和3个蓝色的正方形,这5个点投票,于是绿色的这个待分类点属于蓝色的正方形
我们可以看到,KNN本质是基于一种数据统计的方法!其实很多机器学习算法也是基于数据统计的。
KNN是一种memory-based learning,也叫instance-based learning,属于lazy learning。即它没有明显的前期训练过程,而是程序开始运行时,把数据集加载到内存后,不需要进行训练,就可以开始分类了。
具体是每次来一个未知的样本点,就在附近找K个最近的点进行投票。
2、一个真实示例
对于某个ID,它会有很多的属性值,形成一个向量K,以身高、体重、性别为例,假如已经有以下训练数据:
ID1 172 60 1
ID2 163 50 0
ID3 188 70 1
ID4 155 40 0
现在有一个需要分类的数据进来:
ID5 161 54
我们需要计算其性别,取k=3,即取3个与ID5最类似的样本:ID1, ID2, ID4,这3个ID中有2个属于性别0,因此我们判断ID5的性别也是0。
同理可分类:
ID6 199 82
ID7 172 50
。。。
3、与Bayes的比较
Bayes使用所有的训练数据为新元组分类,而KNN只使用与新元组最类似的K个训练数据。如果Bayes的前提条件成立(条件独立),则其效果更佳,否则相反。
比如上面说的身高和体重其实不是独立的因素的,身高高的大部分会体重较重。
4、距离的计算
如何判断2个元组是否类似呢?
一个最基本的方法就是欧氏距离。
一个补充是先要将各个属性的值进行归一化,否则部分属性的值由于数值较大,对结果的影响会更大,比如上面的身高数值就比体重数值要大。基本的方法是:
V' = (V - min)/(max-min)
min和max分别是这个属性值里面的最大和最小值。
对于类别属性值,如颜色,一种简单的方法是如果相同则记为1,不同则记为0。
欧氏距离为每个属性赋予了相同的权重,如果事实并非如此,可以考虑为各个属性加上权重。
5、KNN用于数值预测
求出K个最相近的元组后,用这些元组对应的数值的平均值作为最终结果。
6、K的选择
可以从K=1开始,逐步增加,用检验数据来分析正确率,从而选择最优K。这个结果要均衡考虑正确率与计算量,比如K=3时,正确率为90%,而K=10时,正确率为91%,则需要考虑计算量换来的1%提升是否合算了。
7、计算量
由于每一个待分类的元组(M个)都需要和所有的样本数据(N个)进行比较,从而找出最相近的K个近邻,因此计算量为M*N。即O(n^2)
一些优化技巧:
(1)如果可能的话先对样本数据进行排序,从而知道只需要与哪些数据进行比较。但对于高维数据,这几乎是不可行的。
(2)将样本数据划分为多个子集合,待分类数据只需要与其中的一个或者多个子集合进行比较。比如属性是经纬度,距离是2个经纬度点之间的距离,则可以将样本根据经纬度的整数部分将各个样本分到不同的子集合去,待分类元组只需要跟与自己整数部分相同的子集合进行比较即可,当子集合内的样本数据不足K时,再和邻近的集合进行比较。
二、算法实现
数据使用上面的示例,完成代码请见:https://github.com/lujinhong/lujinhong-commons/tree/master/lujinhong-commons-spark/src/main/scala/com/lujinhong/commons/spark/ml/knn
package com.lujinhong.commons.spark.ml.knnimport org.apache.spark.SparkContext
import scala.collection.mutable.{SortedSet,HashMap}/** * AUTHOR: LUJINHONG * CREATED ON: 17/3/2 14:06 * PROJECT NAME: lujinhong-commons * DESCRIPTION: KNN算法的示例。 * 示例数据如下: * $ cat knn_training_data.txt ID1 172 60 1 ID2 163 50 0 ID3 188 70 1 ID4 155 40 0 $ cat knn_to_do_data.txt ID5 164 54 ID6 199 82 ID7 172 50 * 输出如下: * $ hadoop fs -cat /tmp/ljhn1829/ml/knn/result/\* ID5 0 ID6 1 ID7 0 * */object KNNDemo {val TRAINING_DATA_PATH = "/tmp/ljhn1829/ml/knn/training_data";val TO_DO_DATA_PATH = "/tmp/ljhn1829/ml/knn/to_classify_data" val OUTPUT_PATH = "/tmp/ljhn1829/ml/knn/result" val SEPARATOR = " " val K = 3 val MALE_LABEL = "1" val FEMALE_LABLE = "0"def main(args: Array[String]): Unit = {val sc = new SparkContext()var traingDataSetBroadcast = sc.broadcast(sc.textFile(TRAINING_DATA_PATH).collect().toSet);sc.textFile(TO_DO_DATA_PATH).map(line => classify(line, traingDataSetBroadcast.value)).saveAsTextFile(OUTPUT_PATH)}def classify(line: String, traingDataSet: Set[String]): String = {//记录与待分类元组最小的3个距离 var minKDistanceSet = SortedSet[Double]()//记录与待分类元组最小的3个距离及其对应的分类。 var minKDistanceMap = HashMap[Double, Int]()for (i <- 1 to K) {minKDistanceSet += Double.MaxValue }val info = line.trim.split(SEPARATOR)val id = info(0)val height = info(1).toDoubleval weight = info(2).toDoublefor (trainSampleItem <- traingDataSet) {val sampleInfo = trainSampleItem.trim().split(SEPARATOR)val distance = Math.sqrt(Math.pow((height - sampleInfo(1).toDouble), 2) + Math.pow((weight - sampleInfo(2).toDouble), 2))if (distance < minKDistanceSet.lastKey) {minKDistanceSet -= minKDistanceSet.lastKeyminKDistanceSet += distanceminKDistanceMap += ((distance, sampleInfo(3).toInt))if (minKDistanceMap.size >= 3) {minKDistanceMap -= minKDistanceSet.lastKey}}}//根据距离最近的3个样本分类,得出最终分类结果。 var count = 0 for (entry <- minKDistanceMap) {count += entry._2}var result = FEMALE_LABLE if (count > K / 2) {result = MALE_LABEL }return id + SEPARATOR + result}}
KNN算法原理与实现相关推荐
- 机器学习之KNN算法原理
机器学习之KNN算法原理 1 KNN算法简介 2 算法思想 3 多种距离度量公式 ① 欧氏距离(Euclidean distance) ② 曼哈顿距离(Manhattan distance) ③ 闵式 ...
- 机器学习算法—KNN算法原理
机器学习算法-KNN算法原理 概述: KNN算法一般也会经常被称为K邻近算法,其核心思想是根据训练集中的样本分类计算测试集中样本与训练集中所有样本的距离,根据所设定的K值选取前K个测试样本与训练样本最 ...
- KNN算法原理及python实现
文章目录 1 KNN算法原理 1.1 基本概念 1.2 KNN算法原理 1.3 实现步骤 1.3 KNN算法优缺点 2 python手工实现KNN算法 2.1 KNN算法预测单个数据 2.2 KNN算 ...
- 详细的KNN算法原理步骤
KNN算法原理详解 KNN算法 1.1 解决监督学习中分类问题的一般步骤 1.2 什么是消极(惰性)的学习方法 2 首先从一个实例讲起 3 KNN分类算法入门 3.1.1算法综述 3.1.2算法思想 ...
- KNN算法原理与python实现
文章目录 KNN算法原理 KNN算法介绍 KNN算法模型 距离度量 k值的选择 分类的决策规则 KNN算法python实现 手写数字识别 sklearn代码实现 参考文献 KNN算法原理 KNN算法介 ...
- KNN算法原理与简单实现
KNN算法原理与简单实现 K最近邻(k-Nearest Neighbor,KNN)分类算法,是最简单的机器学习算法之一,涉及高等数学知识近乎为0,虽然它简单,但效果很好,是入门机器学习的首选算法.但很 ...
- KNN算法原理及实现
KNN算法原理及实现 1.KNN算法概述 kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.该方法在确定分类 ...
- 浅谈KNN算法原理及python程序简单实现、KD树、球树
最近比较空闲,打算利用这一段时间理一下机器学习的一些常见的算法.第一个是KNN算法: KNN 1.原理: KNN,K-NearestNeighbor---K最近邻 K最近邻,就是K个最近的邻居的意思, ...
- KNN算法(一) KNN算法原理
一.KNN算法概述 KNN可以说是最简单的分类算法之一,同时,它也是最常用的分类算法之一,注意KNN算法是有监督学习中的分类算法,它看起来和另一个机器学习算法Kmeans有点像(Kmeans是无监督学 ...
- 机器学习KNN算法原理和应用分析
KNN原理解析 K邻近算法(KNN),是一种非常简单有效的机器学习算法.KNN是通过计算不同特征值距离作为分类依据,即计算一个待分类对象不同特征值与样本库中每一个样本上对应特征值的差值,将每个维度差值 ...
最新文章
- 深入浅出时序数据库之预处理篇——批处理和流处理,用户可定制,但目前流行influxdb没有做...
- 成功解决WARNING: You do not appear to have an NVIDIA GPU supported by the 430.34 NVIDIA Linux graph
- 一些在NLP的面试中提问频率非常高的问题
- TypeScript 学习一 参数,函数,析构表达式
- 【设计模式】单例模式 Singleton Pattern
- 在香蕉派 Banana Pi BPI-M1上使用 开源 OxOffice Impress
- 网络规划设计师论文汇总(2012-2018)考前冲刺真题
- php计算单价乘数量,数量单价怎么算出金额
- 后台cs代码控制html控件,cshtml中正则表达式使用后台代码
- 如何开发油猴脚本来block掘金用户
- linux bash 删除所有空格,删除字符串中的所有的空白并用空格分割单词.md
- python3中文乱码解决方法
- hrbust/哈理工oj 1787 New Fibonacci Number【欧拉降幂+矩阵快速幂】
- 微信网页开发调试的一些方法
- 妇科宫颈细胞学计算机检查,宫颈细胞学检查是怎么回事?
- 【C++自学笔记 提高编程篇(二)STL初识】
- Arcgis 熟练和操作
- 岚图高管解读近50亿融资:东风跟投9亿 考虑后续IPO
- 【2022年度书法鉴赏网课答案】
- 手把手教你炫酷慕课网视频启动导航的完美实现