C++实现的简单的K近邻算法(K-Nearest Neighbor,K-NN)

前一段时间学习了K近邻算法,对K近邻算法有了一个初步的了解,也存在一定的问题,下面我来简单介绍一下K近邻算法。本博客将从以下几个方面开始介绍K近邻算法:
1、K近邻算法的介绍
2、K近邻算法的模型及其三要素
3、C++实现的简单KNN算法
4、KNN算法的优缺点
5、遇到的问题
一、K近邻算法的介绍
K近邻算法(K-Nearest Neighbour,K-NN)是一种基本分类与回归方法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
K近邻算法简单,直观。给定一个训练数据集,对于新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数某个类,就把该输入实例归入这个类。K近邻法没有显示的学习过程。
1.1 算法(K近邻法)
1.2 KNN算法的实现步骤:
step.1---初始化距离为最大值
step.2---计算未知样本和每个训练样本的距离dist
step.3---得到目前K个最临近样本中的最大距离maxdist
step.4---如果dist小于maxdist,则将该训练样本作为K-最近邻样本
step.5---重复步骤2、3、4,直到未知样本和所有训练样本的距离都算完
step.6---统计K个最近邻样本中每个类别出现的次数
step.7---选择出现频率最大的类别作为未知样本的类别
空洞的描述不易理解,生动的例子会方便我们进行理解,下面将举例帮助我们理解。
 如图所示,有两类不同的数据样本,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。也就是说,现在,我们不知道中间那个绿色的数据是从属于哪一个类(蓝色小正方形or红色小三角形),那么这个数据到底是哪个类呢?
1、如果K=3,绿色圆点的最近的三个邻居是2个红色小三角形和1个蓝色小正方形,那么就可以判定这个绿色的待分类的圆形点属于红色小三角形类。
2、如果K=5,绿色圆点的最近的五个邻居是2个红色小三角形和3个蓝色小正方形,那么就可以判定这个绿色的待分类的圆形点属于蓝色小正方形类。
我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。
二、K近邻的模型及其三要素
2.1 K近邻模型
K近邻法中,当训练集、距离度量(如欧氏距离)、K值以及分类决策规则(如多数表决)确定后,对于任何一个新的输入实例,它所属的类唯一地确定,这相当于根据上述要素将特征空间划分成一个个子空间,确定子空间里的每个点所属的类。
K近邻算法使用的模型实际上对应于对特征空间的划分,模型由三个基本要素——距离度量、K值的选择和分类决策规则决定。
2.2 距离度量
特征空间两个实例点的距离是两个实例点相似程度的反映,K近邻模型的特征空间一般是n维实数向量空间Rn ,使用的距离一般是欧氏距离,但也可以是其他距离,如更一般的LP距离(LPdistance)或曼哈顿距离(Manhanttan distance)。
2.2 欧氏距离
欧氏距离是最常见的两点之间或多点之间的距离表示法,又称之为欧几里得度量,它定义于欧几里得空间中,如点x = (x1,...,xn) 和y = (y1,...,yn) 之间的距离为:

(1)二维平面上两点a(x1,y1)b(x2,y2)间的欧氏距离:
(2)三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:
(3)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:
也可以用表示成向量运算的形式:
2.3 K值的选择
KNN算法的分类效果很大程度上依赖于K值的选取,以往人们都是根据个人经验来定。K值选择过小,就相当于用较小的邻域中的训练实例进行预测,只有与输入示例较近的(相似的)训练实例才会对预测起作用,得到的近邻数目过少,预测结果会对近邻的实例点非常敏感,会降低分类精度,如果邻近的实例点恰好是噪声,预测就会出错;而如果K值过大,就相当于用较大邻域中的训练实例作为预测,与输入示例较远的(不相似的)训练实例也会对预测起作用,使预测发生错误。
两个极端情况:
1、当K=1时,K近邻问题就转化成了K最近邻问题,即无论新的输入实例是什么,都只选择距离它最近的样本类别归属。
2、当K=N时,无论输入实例是什么,都将简单的预测它属于在训练实例中最多的类,这时候,模型过于简单,完全忽略训练实例中的大量有用信息。所以当K=N时,是不可取的。
2.4 分类决策规则

K近邻算法中的分类决策规则往往是多数表决,即由输入示例的K个邻近的训练实例中的多数类决定输入实例的类。

三、C++实现的简单KNN算法
算法目的:根据已经给出的样本坐标点,每个坐标点都有相应的坐标(x,y)以及其所属的类别A/B,现给出待分类点,坐标为(x1,y1),判断该点所属的类别。
在测试中,设置K值为5,即选择距离待分类点最近的5个点,判断这5个点中,哪个类别的数据多,待分类点就属于这个类。源代码及测试结果如下:
源代码:
</#include<map>
#include<vector>
#include<stdio.h>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<fstream>using namespace std;typedef char tLabel;
typedef double tData;
typedef pair<int, double>  PAIR;
const int colLen = 2;
const int rowLen = 12;
ifstream fin;
ofstream fout;class KNN
{
private:tData dataSet[rowLen][colLen];tLabel labels[rowLen];tData testData[colLen];int k;map<int, double> map_index_dis;map<tLabel, int> map_label_freq;double get_distance(tData *d1, tData *d2);
public:KNN(int k);void get_all_distance();void get_max_freq_label();struct CmpByValue{bool operator() (const PAIR& lhs, const PAIR& rhs){return lhs.second < rhs.second;}};};KNN::KNN(int k)
{this->k = k;fin.open("C:\\Users\\zws\\Desktop\\K近邻\\data.txt");if (!fin){cout << "can not open the file data.txt" << endl;exit(1);}/* input the dataSet */for (int i = 0; i<rowLen; i++){for (int j = 0; j<colLen; j++){fin >> dataSet[i][j];}fin >> labels[i];}cout << "please input the test data :" << endl;/* inuput the test data */for (int i = 0; i<colLen; i++)cin >> testData[i];}/*
* calculate the distance between test data and dataSet[i]
*/
double KNN::get_distance(tData *d1, tData *d2)
{double sum = 0;for (int i = 0; i<colLen; i++){sum += pow((d1[i] - d2[i]), 2);}//    cout<<"the sum is = "<<sum<<endl;return sqrt(sum);
}/*
* calculate all the distance between test data and each training data
*/
void KNN::get_all_distance()
{double distance;int i;for (i = 0; i<rowLen; i++){distance = get_distance(dataSet[i], testData);//<key,value> => <i,distance>map_index_dis[i] = distance;}//traverse the map to print the index and distancemap<int, double>::const_iterator it = map_index_dis.begin();while (it != map_index_dis.end()){cout << "index = " << it->first << " distance = " << it->second << endl;it++;}
}/*
* check which label the test data belongs to to classify the test data
*/
void KNN::get_max_freq_label()
{//transform the map_index_dis to vec_index_disvector<PAIR> vec_index_dis(map_index_dis.begin(), map_index_dis.end());//sort the vec_index_dis by distance from low to high to get the nearest datasort(vec_index_dis.begin(), vec_index_dis.end(), CmpByValue());for (int i = 0; i<k; i++){cout << "the index = " << vec_index_dis[i].first << " the distance = " << vec_index_dis[i].second << " the label = " << labels[vec_index_dis[i].first] << " the coordinate ( " << dataSet[vec_index_dis[i].first][0] << "," << dataSet[vec_index_dis[i].first][1] << " )" << endl;//calculate the count of each labelmap_label_freq[labels[vec_index_dis[i].first]]++;}map<tLabel, int>::const_iterator map_it = map_label_freq.begin();tLabel label;int max_freq = 0;//find the most frequent labelwhile (map_it != map_label_freq.end()){if (map_it->second > max_freq){max_freq = map_it->second;label = map_it->first;}map_it++;}cout << "The test data belongs to the " << label << " label" << endl;
}int main()
{int k;cout << "please input the k value : " << endl;cin >> k;KNN knn(k);knn.get_all_distance();knn.get_max_freq_label();system("pause");return 0;
}

测试结果:

K=5时,待分类点为(5.0 ,5.0):

K=5时,待分类点为(4.5,1.6):
K=5时,待分类点为(-2.1,3.0):
四、K近邻算法的优缺点
优点:
1)原理简单,实现起来比较方便;
2)能够支持增量学习;
3)能够对超多边形的复杂决策空间建模。
使用数据类型: 数值型(目标变量可以从无限的数值集合中取值)和标称型(目标变量只有在有限目标集中取值)
缺点:
1)样本的不均衡性可能造成结果错误:如果一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新的样本时,该样本的K个邻居中大容量类的样本占多数。
2)计算量较大,需要有效的存储技术和并行硬件的支撑:因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得他的K个最近邻点。
五、遇到的问题以及想法
Q1、K值的选择问题
K值的选择很重要,选大选小都会影响预测的结果,那么K值应当怎样选择才合适?
Idea:
1)、先定义一个很小的值,然后通过交叉验证算出合适的值。
2)、根据样本的特征来决定K的值
3)、K的值一般选取为√q(q为训练样本的数目)。
以上几种方法是查找资料以及和同学讨论出的结果,个人认为第一种方法可靠性较高,但是可能计算量相比较其他两个会稍大一些。如何快速的定义K的值,依然是一个仍需讨论和研究的问题。
Q2、假设K为偶数,训练集中包含两个类别,得出的结果两个类别包含的数据一样,那么该测试样本应该从属于哪一个类?
Idea:
1)、可以选择距离该待分类点最近的样本点作为其类别,此时问题转化为K最近邻问题。
2)、当两个类别的数目相等时,可以算各个样本类别的平均值,平均值小的作为其类别。
Q3、K近邻算法中,需要存储所有的样本数据,而且需要计算每个训练样本与测试样本之间的距离,计算量很大,有没有什么好的改进方法?
Idea:
能否设置一个阈值,将距离待分类点很远的训练样本不考虑,减少计算每个训练样本与测试样本距离的计算量?
Q4、距离度量的计算方式选择不同时,所计算出来的结果也是不同的,到底应该采取怎么样的计算方法才合理?
以上只是我对K近邻算法的初步理解,如果存在错误的地方敬原谅,关于K近邻算法的实现kd树,学习的过程中存在不懂的地方,就没在文章中提起,等到把kd树问题理解了之后再写出来吧。谢谢大家的阅读,也请大家批评指正。

C++实现的简单k近邻算法(K-Nearest-Neighbour,K-NN)相关推荐

  1. python k近邻算法_python中的k最近邻居算法示例

    python k近邻算法 K最近邻居(KNN) (K-Nearest Neighbors (KNN)) KNN is a supervised machine learning algorithm t ...

  2. k近邻算法_图穷匕见:K近邻算法与手写数字识别

    机器学习算法是从数据中产生模型,也就是进行学习的算法.我们把经验提供给算法,它就能够根据经验数据产生模型.在面对新的情况时,模型就会为我们提供判断(预测)结果.例如,我们根据"个子高.腿长. ...

  3. k近邻算法_机器学习之K近邻分类算法的实现

    K近邻算法(k-nearest neighbors, KNN)是最基本的机器学习算法之一.所谓的K,就是距离最近的K个邻居的意思.其实,KNN在我们平常的生活中也会不自主的应用,比如,俗语说的&quo ...

  4. 通过交叉验证寻找K近邻算法的最优K值

    问题引出 之前我们使用K近邻算法尝试寻找用户年龄与预估薪资之间的某种相关性,以及他们是否有购买SUV的决定.主要代码如下: from sklearn.neighbors import KNeighbo ...

  5. SK-learn实现k近邻算法【准确率随k值的变化】-------莺尾花种类预测

    代码详解: from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split fr ...

  6. 机器学习入门笔记(三):K近邻算法

    文章目录 一.K近邻算法的基本概念 1.1 K近邻算法实现 二.K近邻分类三要素 2.1 距离度量 2.2 K值的选择 2.2.1 基于m-fold cross validation的 K值选择 2. ...

  7. 【机器学习】原理与实现k近邻算法

    文章目录 系列文章目录 前言 一.k近邻算法是什么? 二.使用步骤 1.引入库 2.读入数据 总结 前言 随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了 ...

  8. k近邻算法(k-Nearest Neighbors,kNN)

    k近邻算法 (k-Nearest Neighbors,kNN) 文章目录 k近邻算法 (k-Nearest Neighbors,kNN) 算法原理与思想 算法原理 手工实现 scikit−learns ...

  9. 机器学习第七章之K近邻算法

    K近邻算法(了解) 7.1 K近邻算法 7.1.1 K近邻算法的原理介绍 7.1.2 K近邻算法的计算步骤及代码实现 7.2 数据预处理之数据归一化 7.2.1 min-max标准化 7.2.2 Z- ...

最新文章

  1. 你还在 select * 吗?
  2. 谈谈我的移动端rem适配方案
  3. nginx tcp代理_nginx——TCP/UDP Load Balancing
  4. Mysql字符串截取 mysql将字符串字段转为数字排序或比大小
  5. CentOS安装yum 镜像 举例阿里云镜像
  6. Mac下搭建Cocos2d-x-3.2的开发环境详解
  7. NiFi-面向流程的大数据处理框架
  8. HttpClient 忽略证书直接访问https站点
  9. rdlc报表的制作步骤
  10. 物联网专用卡的优势有哪些
  11. Qt 使用vs调试的方法
  12. python输入输出基本点
  13. 几种开源许可协议(转载)
  14. Atitit. js mvc 总结(2)----angular 跟 Knockout o99 最佳实践
  15. 数值计算之第二期:误差分析
  16. APP测试和web测试有什么区别?
  17. uni-app获取屏幕高度和宽度
  18. 中国目前拥有的物种和人造卫星的作用
  19. JAVA 获取今天、昨天、上周等日期
  20. SAP中利用标准成本报表计算成品人工成本及组成实例

热门文章

  1. 传奇世界服务端WIN7简单安装教程
  2. 像素、分辨率、图片大小概念
  3. 模拟鼠标键盘操作,含硬件模拟技术。
  4. 传统营销与网络营销的整合
  5. android app 图片资源,巧用Android图片资源,打造更精致的APP
  6. 计算机电子表格制作教案,电子表格Excel教案设计
  7. excel怎么拆分表格
  8. 【转】Spring横切面(advice),增强(advisor),切入点(PointCut)(JAVA后端)
  9. (16)双目视觉的图像获取
  10. 小虎电商浏览器:拼多多怎么看单品实时数据