K近邻算法(KNN)的C++实现
knn算法的实现方法

knn算法的实现方法KNN算法是一种常见的分类算法,其全称为K-Nearest Neighbor算法,即K近邻算法。
该算法的基本思想是:对于一个未知样本,找到与其最近的K个已知样本,将这K个样本中出现最多的类别作为该未知样本的类别。
KNN算法的实现方法主要包括以下几个步骤:1. 数据预处理在使用KNN算法进行分类之前,需要对数据进行预处理。
预处理的主要目的是将数据转换为算法能够处理的形式。
具体来说,需要将数据转换为数值型数据,并进行归一化处理。
这样可以避免不同特征之间的差异对分类结果的影响。
2. 计算距离KNN算法的核心是计算样本之间的距离。
常用的距离计算方法有欧氏距离、曼哈顿距离、切比雪夫距离等。
在计算距离时,需要考虑不同特征之间的权重,以避免某些特征对距离的影响过大。
3. 选择K值K值的选择对KNN算法的分类结果有很大的影响。
一般来说,K值越小,模型越复杂,容易出现过拟合;K值越大,模型越简单,容易出现欠拟合。
因此,需要通过交叉验证等方法来选择合适的K值。
4. 进行分类在计算出样本之间的距离并选择好K值之后,就可以进行分类了。
具体来说,需要找到与未知样本最近的K个已知样本,并统计这K个样本中出现最多的类别。
将该类别作为未知样本的类别即可。
KNN算法的优缺点:优点:1. 简单易懂,易于实现。
2. 对于非线性数据具有较好的分类效果。
3. 对于小样本数据具有较好的分类效果。
缺点:1. 计算复杂度高,需要计算每个未知样本与所有已知样本之间的距离。
2. 对于高维数据,距离计算会受到维度灾难的影响。
3. 对于不平衡数据,容易出现分类偏差。
总结:KNN算法是一种简单易懂的分类算法,其实现方法也比较简单。
但是,KNN算法也存在一些缺点,如计算复杂度高、对高维数据不适用等。
因此,在实际应用中需要根据具体情况选择合适的算法。
knn算法的实现流程

knn算法的实现流程knn算法(k-Nearest Neighbors)是一种基于实例的学习方法,它的核心思想是通过找到与要预测数据最相似的k个样本来进行分类或回归。
knn算法在分类、回归和数据挖掘等领域都有着广泛的应用。
本文将介绍knn算法的实现流程。
1. 收集数据我们需要收集训练数据。
训练数据通常由多个样本组成,每个样本都有多个特征和一个标签。
在分类问题中,标签表示样本所属的类别;在回归问题中,标签则表示样本的目标值。
在实际应用中,我们可以通过爬虫、采集和数据库等方式来获取训练数据。
2. 数据预处理在收集到数据后,我们需要对数据进行预处理。
预处理的目的是为了让数据适合knn算法的要求。
首先,我们需要对数据进行归一化处理,将所有特征的值缩放到同一范围内。
其次,我们需要对数据进行清洗和去重,确保数据的质量和准确性。
3. 选择k值knn算法中的k值表示需要选择的最近邻居个数。
k值的选择对算法的性能和准确性有着重要的影响。
通常,我们可以通过交叉验证等方式来选择最合适的k值。
4. 计算距离在knn算法中,我们需要计算目标样本与所有训练样本之间的距离。
距离计算通常采用欧氏距离、曼哈顿距离、闵可夫斯基距离等方式。
距离计算的目的是为了找到与目标样本最相似的k个训练样本。
5. 选择k个最近邻居在计算完目标样本与所有训练样本之间的距离后,我们需要选择与目标样本最相似的k个训练样本。
通常,我们可以采用堆排序等方式来实现k个最近邻居的选择。
6. 进行分类或回归在选择完k个最近邻居后,我们需要根据这k个训练样本的标签来进行分类或回归。
在分类问题中,我们可以采用多数表决等方式来确定目标样本所属的类别;在回归问题中,我们可以采用加权平均等方式来预测目标样本的目标值。
7. 评估算法性能在完成knn算法的实现后,我们需要对算法的性能进行评估。
通常,我们可以采用精确度、召回率、F1值等指标来评估算法的性能。
同时,我们也可以通过与其他算法进行比较来评估算法的优劣。
人工智能实验-k-近邻算法

k-近邻算法一、 实验题目1. kNN 代码实现-AB 分类采用测量不同特征值之间的距离方法进行分类,用所给的函数创建具有两个特征与一个标签类型的数据作 为训练集,编写 classify0 函数对所给的数据进行 AB 分类。
2. k-近邻算法改进约会网站的配对效果k-近邻算法改进约会网站的配对效果通过收集的一些约会网站的数据信息,对匹配对象的归类:不喜欢的人、魅力一般的人、极具魅力的人。
数据中包含了 3 种特征:每年获得的飞行常客里程数、玩视频游戏所耗时间百分比、每周消费的冰淇淋公升数二、 实验代码1. kNN 代码实现-AB 分类kNN from http.client import ImproperConnectionStatefrom numpy import ∗ from collections importCounter import operator def createDataSet():group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])labels = [’A ’, ’A ’, ’B’, ’B’] return group, labelsdef classify0(inX, group, labels, k = 3):res1 = (inX − group)∗∗2 dist =res1[:,0] + res1[:,1] dic = argsort(dist) dic = dic[0:k:1] newdic = [] for i in range (k): newdic.append(labels[dic[i]]) c = Counter(newdic).most_common(1) return c[0][0] tests import kNN group, lables = kNN.createDataSet() print (’分类结果’) print (’[0,0] %c’ %(kNN.classify0([0, 0], group, lables, k = 3))) print (’[0.8,0.7] %c’ %(kNN.classify0([0.8, 0.7], group, lables, k = 3)))2.k-近邻算法改进约会网站的配对效果1 2 3 4 5 67 8 910111213141516171819 1 2 3 4 5import pandas as pdimport kNNfrom sklearn.model_selection import train_test_splitdf = pd.read_table(’datingTestSet2.txt’,sep=’\s+’, names = [’A ’, ’B’, ’C’, ’Y’])# 对特征进行归一化处理df2 = df.iloc[:, :3] df2 =(df2−df2.mean())/df2.std() lable=df.iloc[:,3:4] df2.loc[:, ’Y’] =lable# 对数据集进行测试集和训练集划分,90%作为训练集,10%作为测试集X_train, X_test, Y_train, Y_test = train_test_split(df2.iloc[:, :3], df2.Y, train_size=.90)# 将DataFrame 格式转化为numpy 格式处理 group = X_train.values label =Y_train.values length =len (X_test) X_test.iloc[0:1,:]# res 以储存测试结果res = []# 设置错误正确数count 以计算正确率Tnum = 0 Fnum = 0 for iin range (length):inX = X_test.iloc[i:i+1 , :].values res.append(kNN.classify0(inX,group, label, k = 3)) if (kNN.classify0(inX, group, label, k = 3) ==Y_test.values[i]):Tnum += 1 else :Fnum += 1res1 = pd.DataFrame(data = res, columns=[’TestResult’])Y_test.reset_index(inplace=True,drop=True)res1.loc[:, ’OriginTest’] = Y_testprint (’前20个数据测试结果和原数据比较’) print (’−−−−−−−−−−−−−−−−−−−−−——−−−−’) print (res1.head(20))print (’−−−−−−−−−−−−−−−−−−−−−——−−−−’) print (’正确率%.2f%%’ %(100∗Tnum/(Tnum+Fnum))) 三、 实验结果及分析1. kNN 代码实现-AB 分类分类结果[0, 0] B[0.8, 0.7] A2. k-近邻算法改进约会网站的配对效果1 2 3 45 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2526 27 28 29 3031 32 33 3435363738 1 2 3前20个数据测试结果和原数据比较−−−−−−−−−−−−−−−−−−−−−——−−−TestResult OriginTest0 2 2 1 3 3 2 1 3 3 2 2 4 2 2 5 3 3 6 3 3 7 2 2 8 1 1 9 1 1 10 1 1 11 3 3 12 2 2 13 2 2 14 1 1 15 2 2 16 1 1 17 2 2 18 1 1 19 3 3−−−−−−−−−−−−−−−−−−−−−——−−− 正确率97.00%从实验结果可以看出,通过 k-近邻算法改进后的约会网站的配对效果比较显著,多次随机划分测试集和训练集后发现正确率基本可以达到 90% 以上。
k近邻算法的原理和实现过程

k近邻算法的原理和实现过程
k近邻算法是一种基本的分类和回归算法,它的原理和实现过程如下:
原理:
1. 确定一个样本的k个最近的邻居,即选取与该样本距离最近的k个样本。
2. 根据这k个最近邻居的标签进行投票或者加权,确定该样本的预测标签。
如果
是分类问题,那么选取票数最多的标签作为预测标签;如果是回归问题,那么选
取k个最近邻居的标签的平均值作为预测标签。
实现过程:
1. 准备数据集:收集已知样本和其对应的标签。
2. 确定距离度量准则:选择合适的距离度量准则来度量样本间的距离,例如欧氏
距离、曼哈顿距离等。
3. 选择合适的k值:根据问题的要求选择适当的k值。
4. 计算样本之间的距离:对于每个未知样本,计算它与已知样本之间的距离,选
择k个最近邻居。
5. 统计k个最近邻居的标签:对于分类问题,统计k个最近邻居的标签的出现次数,并选择出现次数最多的标签作为预测标签;对于回归问题,计算k个最近邻
居的标签的平均数作为预测标签。
6. 将样本进行分类或预测:根据预测标签将未知样本进行分类或预测。
需要注意的是,在实际应用中,可以采取一些优化措施来提高k近邻算法的效率,比如使用kd树来加速最近邻搜索过程。
还可以对特征进行归一化处理,以避免
某些特征的权重过大对距离计算的影响。
kNN(k近邻)算法代码实现

kNN(k近邻)算法代码实现⽬标:预测未知数据(或测试数据)X的分类y批量kNN算法1.输⼊⼀个待预测的X(⼀维或多维)给训练数据集,计算出训练集X_train中的每⼀个样本与其的距离2.找到前k个距离该数据最近的样本-->所属的分类y_train3.将前k近的样本进⾏统计,哪个分类多,则我们将x分类为哪个分类# 准备阶段:import numpy as np# import matplotlib.pyplot as pltraw_data_X = [[3.393533211, 2.331273381],[3.110073483, 1.781539638],[1.343808831, 3.368360954],[3.582294042, 4.679179110],[2.280362439, 2.866990263],[7.423436942, 4.696522875],[5.745051997, 3.533989803],[9.172168622, 2.511101045],[7.792783481, 3.424088941],[7.939820817, 0.791637231]]raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]X_train = np.array(raw_data_X)y_train = np.array(raw_data_y)x = np.array([8.093607318, 3.365731514])核⼼代码:⽬标:预测未知数据(或测试数据)X的分类y批量kNN算法1.输⼊⼀个待预测的X(⼀维或多维)给训练数据集,计算出训练集X_train中的每⼀个样本与其的距离2.找到前k个距离该数据最近的样本-->所属的分类y_train3.将前k近的样本进⾏统计,哪个分类多,则我们将x分类为哪个分类from math import sqrtfrom collections import Counter# 已知X_train,y_train# 预测x的分类def predict(x, k=5):# 计算训练集每个样本与x的距离distances = [sqrt(np.sum((x-x_train)**2)) for x_train in X_train] # 这⾥⽤了numpy的fancy⽅法,np.sum((x-x_train)**2) # 获得距离对应的索引,可以通过这些索引找到其所属分类y_trainnearest = np.argsort(distances)# 得到前k近的分类ytopK_y = [y_train[neighbor] for neighbor in nearest[:k]]# 投票的⽅式,得到⼀个字典,key是分类,value数个数votes = Counter(topK_y)# 取出得票第⼀名的分类return votes.most_common(1)[0][0] # 得到y_predictpredict(x, k=6)⾯向对象的⽅式,模仿sklearn中的⽅法实现kNN算法:import numpy as npfrom math import sqrtfrom collections import Counterclass kNN_classify:def__init__(self, n_neighbor=5):self.k = n_neighborself._X_train = Noneself._y_train = Nonedef fit(self, X_train, y_train):self._X_train = X_trainself._y_train = y_trainreturn selfdef predict(self, X):'''接收多维数据,返回y_predict也是多维的'''y_predict = [self._predict(x) for x in X]# return y_predictreturn np.array(y_predict) # 返回array的格式def _predict(self, x):'''接收⼀个待预测的x,返回y_predict'''distances = [sqrt(np.sum((x-x_train)**2)) for x_train in self._X_train] nearest = np.argsort(distances)topK_y = [self._y_train[neighbor] for neighbor in nearest[:self.k]]votes = Counter(topK_y)return votes.most_common(1)[0][0]def__repr__(self):return'kNN_clf(k=%d)' % self.k。
knn算法的实现过程

knn算法的实现过程KNN算法是一种基于距离最近的分类算法,KNN全称为K-Nearest-Neighbors,也就是K个最近邻点。
在分类的时候,对于一个新的数据点,KNN算法会先找到K个与该数据点距离最近的已知类别样本,接着根据这K个样本的类别进行投票,选择票数最多的类别作为新数据点的类别。
这种算法简单有效,又不需要太多的先验信息和经验,因此在很多实际应用案例中得到了广泛的应用。
KNN算法实现的前提是我们需要有一些已知类别的样本点,作为算法的训练数据,这些训练数据的类别应该尽可能地代表我们将来需要进行分类的实例的不同状态。
当然,在数据的质量和样本的选取上,对于KNN算法的效果也有很大的影响。
一般实现KNN算法的流程如下:1. 数据预处理:首先我们需要将数据预处理成算法能够处理的矩阵数据,一般来说,我们需要将每个数据点的所有属性值都存放到该点的特征向量中,对于一个d维的数据点,其特征向量x可以表示成:x = [x1, x2, x3, …, xd]在实际应用中,比较常见的数据预处理工作包括数据清洗、数据离散化和数据归一化等。
2. 计算距离:在将预处理后的数据存储为矩阵数据后,我们需要计算新数据点与旧数据点之间的距离,这里一般可以使用欧氏距离、曼哈顿距离、余弦距离、皮尔森相关系数等距离计算法。
例如,使用欧式距离的公式为:d(x,y) = sqrt(∑(xi-yi)^2)其中Xi和Yi分别是特征向量X和Y的第i个属性值,∑是对所有i的和。
3. 寻找最近邻点:根据我们计算出来的距离,我们需要寻找出与新数据点距离最近的K个训练样本点,并统计这K个点所属的不同的分类结果,选取票数最多的类别作为新数据点所属类别。
4. 输出分类结果:根据我们上一步寻找到的K个最近邻点所属的类别,并根据投票的结果,我们就可以得出新数据点的分类结果。
通常情况下,当我们寻找到K个最近邻点时,我们可以为每个点设置权重,将距离近的点赋予更高的权重,可提升算法的分类结果。
Python机器学习(十三)最近邻居k-近邻算法

Python机器学习(⼗三)最近邻居k-近邻算法KNN算法是⼀种基于实例的学习,或者是局部近似和将所有计算推迟到分类之后的惰性学习。
⽤最近的邻居(k)来预测未知数据点。
k 值是预测精度的⼀个关键因素,⽆论是分类还是回归,衡量邻居的权重都⾮常有⽤,较近邻居的权重⽐较远邻居的权重⼤。
KNN 算法的缺点是对数据的局部结构⾮常敏感。
计算量⼤,需要对数据进⾏规范化处理,使每个数据点都在相同的范围。
ML_Alg_KNN.gif代码实现:from sklearn import datasetsfrom sklearn.neighbors import KNeighborsClassifier#digit dataset from sklearndigits = datasets.load_digits()#create the KNeighborsClassifierclf = KNeighborsClassifier(n_neighbors=6)#set training setx, y = digits.data[:-1], digits.target[:-1]#train modelclf.fit(x, y)#predicty_pred = clf.predict([digits.data[-1]])y_true = digits.target[-1]print(y_pred)print(y_true)执⾏结果:C:\Anaconda3\python.exe "C:\Program Files\JetBrains\PyCharm 2019.1.1\helpers\pydev\pydevconsole.py" --mode=client --port=49329import sys; print('Python %s on %s' % (sys.version, sys.platform))sys.path.extend(['C:\\app\\PycharmProjects', 'C:/app/PycharmProjects'])Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]Type 'copyright', 'credits'or'license'for more informationIPython 7.12.0 -- An enhanced Interactive Python. Type '?'for help.PyDev console: using IPython 7.12.0Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32runfile('C:/app/PycharmProjects/ArtificialIntelligence/test.py', wdir='C:/app/PycharmProjects/ArtificialIntelligence')[8]8延伸:KNN 的⼀个缺点是依赖于整个训练数据集,学习向量量化(Learning Vector Quantization,LVQ)是⼀种监督学习的⼈神经⽹络算法,允许你选择训练实例。
KNN算法的实现

KNN算法的实现K近邻(KNN)算法简介 KNN是通过测量不同特征值之间的距离进⾏分类。
它的思路是:如果⼀个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的⼤多数属于某⼀个类别,则该样本也属于这个类别,其中K通常是不⼤于20的整数。
KNN算法中,所选择的邻居都是已经正确分类的对象。
该⽅法在定类决策上只依据最邻近的⼀个或者⼏个样本的类别来决定待分样本所属的类别。
下⾯通过⼀个简单的例⼦说明⼀下:如下图,绿⾊圆要被决定赋予哪个类,是红⾊三⾓形还是蓝⾊四⽅形?如果K=3,由于红⾊三⾓形所占⽐例为2/3,绿⾊圆将被赋予红⾊三⾓形那个类,如果K=5,由于蓝⾊四⽅形⽐例为3/5,因此绿⾊圆被赋予蓝⾊四⽅形类。
由此也说明了KNN算法的结果很⼤程度取决于K的选择。
在KNN中,通过计算对象间距离来作为各个对象之间的⾮相似性指标,避免了对象之间的匹配问题,在这⾥距离⼀般使⽤欧⽒距离或曼哈顿距离:L1是曼哈顿距离:顾名思义,在曼哈顿街区要从⼀个⼗字路⼝开车到另⼀个⼗字路⼝,驾驶距离显然不是两点间的直线距离。
这个实际驾驶距离就是“曼哈顿距离”。
曼哈顿距离也称为“城市街区距离”(City Block distance)。
L2是我们的欧⽒距离:欧⽒距离是最容易直观理解的距离度量⽅法,我们⼩学、初中和⾼中接触到的两个点在空间中的距离⼀般都是指欧⽒距离。
我们⼀般都常⽤欧⽒距离。
同时,KNN通过依据k个对象中占优的类别进⾏决策,⽽不是单⼀的对象类别决策。
这两点就是KNN算法的优势。
接下来对KNN算法的思想总结⼀下:就是在训练集中数据和标签已知的情况下,输⼊测试数据,将测试数据的特征与训练集中对应的特征进⾏相互⽐较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类。
其算法的描述为:1)计算测试数据与各个训练数据之间的距离;2)按照距离的递增关系进⾏排序;3)选取距离最⼩的K个点;4)确定前K个点所在类别的出现频率;5)返回前K个点中出现频率最⾼的类别作为测试数据的预测分类。
掌握KNN算法的原理与实现方法

掌握KNN算法的原理与实现方法KNN算法是机器学习中的一种分类算法,其名称来源于其英文全称:K-Nearest neighbors algorithm。
该算法的基本思想是根据已知数据集中每个样本点的K个最近邻居,通过投票的方式来确定新的数据样本所属的类别。
在实际应用中,KNN算法有着广泛的应用,例如图像分类、文本分类、推荐系统等领域。
一、KNN算法的原理KNN算法的原理非常简单,可以通过以下几个步骤来描述:1. 计算新数据样本和每个已知数据样本之间的距离(可以使用欧氏距离等常见的距离计算方式)。
2. 根据距离的大小,找到K个距离最近的已知数据样本,将其归为同一类别。
3. 通过投票的方式来确定新的数据样本所属的类别,即选取K 个样本中出现最多的类别作为新数据的类别。
4. 输出新数据样本所属的类别。
需要注意的是,在选择K的值时需要根据具体问题来确定,一般来说K的大小越小,模型越复杂,容易出现过拟合,K的大小越大,模型越简单,容易出现欠拟合。
二、KNN算法的实现方法1. 数据的预处理在使用KNN算法进行分类前,需要进行数据的预处理,主要包括数据的清洗、特征的提取等,这些预处理的过程对模型的性能和准确性具有重要的影响。
常见的数据预处理方法包括标准化、归一化、主成分分析等。
2. 距离的计算KNN算法的关键在于距离的计算,一般来说可以使用欧氏距离、曼哈顿距离、余弦距离等常用的距离计算方式,其中欧氏距离最为常用。
距离的计算可以通过编写代码实现,也可以使用已有的库函数。
3. K值的选择在实际应用中,K的大小需要根据具体问题来确定,一般来说可以通过交叉验证等方法来确定最佳的K值。
4. 投票的方式在确定K个距离最近的已知数据样本后,需要通过投票的方式来确定新数据样本所属的类别。
一般来说可以使用加权投票的方式,即距离越近的已知数据样本所在类别的权重越大,距离越远的已知数据样本所在类别的权重越小。
也可以使用简单投票的方式,即K个距离最近的已知数据样本所在类别的个数进行统计,选取出现次数最多的类别作为新数据样本所属的类别。
KNN算法之KD树(K-dimensionTree)实现K近邻查询

KNN算法之KD树(K-dimensionTree)实现K近邻查询KD树是⼀种分割k维数据空间的数据结构,主要应⽤于多维空间关键数据的搜索,如范围搜索和最近邻搜索。
KD树使⽤了分治的思想,对⽐⼆叉搜索树(BST),KD树解决的是多维空间内的最近点(K近点)问题。
(思想与之前见过的最近点对问题很相似,将所有点分为两边,对于可能横跨划分线的点对再进⼀步讨论)KD树⽤来优化KNN算法中的查询复杂度。
⼀、建树建⽴KDtree,主要有两步操作:选择合适的分割维度,选择中值节点作为分割节点。
分割维度的选择遵循的原则是,选择范围最⼤的纬度,也即是⽅差最⼤的纬度作为分割维度,为什么⽅差最⼤的适合作为特征呢?因为⽅差⼤,数据相对“分散”,选取该特征来对数据集进⾏分割,数据散得更“开”⼀些。
分割节点的选择原则是,将这⼀维度的数据进⾏排序,选择正中间的节点作为分割节点,确保节点左边的点的维度值⼩于节点的维度值,节点右边的点的维度值⼤于节点的维度值。
这两步步骤影响搜索效率,⾮常关键。
⼆、搜索K近点需要的数据结构:最⼤堆(此处我对距离取负从⽽⽤最⼩堆实现的最⼤堆,因为python的heapq模块只有最⼩堆)、堆栈(⽤列表实现)a.利⽤⼆叉搜索找到叶⼦节点并将搜索的结点路径压⼊堆栈stack中b.通过保存在堆栈中的搜索路径回溯,直⾄堆栈中没有结点了对于b步骤,需要区分叶⼦结点和⾮叶结点:1、叶⼦结点:叶⼦结点:计算与⽬标点的距离。
若候选堆中不⾜K个点,将叶⼦结点加⼊候选堆中;如果K个点够了,判断是否⽐候选堆中距离最⼩的结点(因为距离取了相反数)还要⼤,说明应当加⼊候选堆;2、⾮叶结点:对于⾮叶结点,处理步骤和叶⼦结点差不多,只是需要额外考虑以⽬标点为圆⼼,最⼤堆的堆顶元素为半径的超球体是否和划分当前空间的超平⾯相交,如果相交说明未访问的另⼀边的空间有可能包含⽐当前已有的K个近点更近的点,需要搜索另⼀边的空间;此外,当候选堆中没有K个点,那么不管有没有相交,都应当搜索未访问的另⼀边空间,因为候选堆的点不够K个。
k近邻算法的原理和实现过程 -回复

k近邻算法的原理和实现过程-回复k近邻算法的原理和实现过程。
引言:k近邻算法(k-nearest neighbors, KNN)是一种简单而又常用的机器学习算法。
它属于一种“懒惰学习”方法,也称为基于实例学习。
k近邻算法不需要显式的训练过程,而是通过计算测试样本与训练样本之间的距离,根据距离的近远来判断测试样本的分类。
本文将一步一步地介绍k 近邻算法的原理和实现过程。
第一部分:k近邻算法的原理1.1 简介k近邻算法采用邻近点之间的相似性来进行分类或回归预测。
它的核心思想是“近朱者赤,近墨者黑”,即将待分类的样本赋予与其邻近样本相同的标签。
在进行分类时,k近邻算法通过计算目标样本与训练样本之间的距离,然后选择距离最近的k个样本来进行投票,根据投票结果决定目标样本的分类。
1.2 算法步骤k近邻算法的核心步骤包括以下几个步骤:(1)计算距离:根据不同的距离度量方法(如欧氏距离、曼哈顿距离等),计算目标样本与训练样本之间的距离。
(2)选择邻居:根据距离计算结果,选择距离最近的k个样本作为邻居。
(3)投票机制:根据邻居样本的标签(分类问题)或者邻居样本的数值(回归问题),利用投票或者加权投票的方式来确定目标样本的分类或者预测数值。
(4)分类或回归:根据投票结果确定目标样本的分类或回归预测。
第二部分:k近邻算法的实现过程2.1 数据预处理k近邻算法对数据的预处理工作非常重要,包括数据清洗、特征选择、特征缩放等。
首先,对数据进行清洗,剔除异常值和缺失值。
然后,选择对分类有影响的特征进行特征选择。
最后,对特征进行缩放,以保证不同特征之间的单位不同造成的影响。
2.2 构建模型构建k近邻算法的模型需要选择合适的距离度量方法和合适的k值。
常用的距离度量方法包括欧氏距离、曼哈顿距离、闵可夫斯基距离等。
在选择k值时,一般通过交叉验证的方式来确定最优的k值。
2.3 预测在进行预测时,首先计算测试样本与训练样本之间的距离。
然后,根据距离的近远选择距离最近的k个样本作为邻居。
k近邻算法以及实例

【机器学习】k-近邻算法以及算法实例时间 2015-01-26 14:31:00 博客园-原创精华区原文/jtianwen2014/p/4249003.html主题算法数据挖掘机器学习中常常要用到分类算法,在诸多的分类算法中有一种算法名为k-近邻算法,也称为kNN算法。
一、kNN算法的工作原理二、适用情况三、算法实例及讲解---1.收集数据---2.准备数据---3.设计算法分析数据---4.测试算法一、kNN算法的工作原理官方解释:存在一个样本数据集,也称作训练样本集,并且样本中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系,输入没有标签的新数据后,将新数据的每个特征与样本集中的数据对应的特征进行比较,然后算法提取样本集中特征最相似的数据(最近邻)的分类标签。
一般来说,我们只选择样本集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数,最后,选择k个最相似的数据中出现次数最多的分类,作为新数据的分类。
我的理解:k-近邻算法就是根据“新数据的分类取决于它的邻居”进行的,比如邻居中大多数都是退伍军人,那么这个人也极有可能是退伍军人。
而算法的目的就是先找出它的邻居,然后分析这几位邻居大多数的分类,极有可能就是它本省的分类。
二、适用情况优点:精度高,对异常数据不敏感(你的类别是由邻居中的大多数决定的,一个异常邻居并不能影响太大),无数据输入假定;缺点:计算发杂度高(需要计算新的数据点与样本集中每个数据的“距离”,以判断是否是前k个邻居),空间复杂度高(巨大的矩阵);适用数据范围:数值型(目标变量可以从无限的数值集合中取值)和标称型(目标变量只有在有限目标集中取值)。
三、算法实例及讲解例子中的案例摘《机器学习实战》一书中的,代码例子是用python编写的(需要matplotlib和numpy库),不过重在算法,只要算法明白了,用其他语言都是可以写出来的:海伦一直使用在线约会网站寻找合适自己的约会对象。
k近邻算法c语言

k近邻算法c语言K近邻算法(K-Nearest Neighbors,KNN)是一种基本的分类和回归算法。
下面是一个简单的KNN算法的C语言实现,用于分类问题。
这个例子中,我们假设有一个二维的数据集,并且我们想要根据这个数据集的类别标签来预测新的数据点的类别。
```cinclude <>include <>include <>define DATA_SIZE 4define K 3typedef struct {double x;double y;int label;} Data;double distance(Data d1, Data d2) {return sqrt(pow( - , 2) + pow( - , 2));}int main() {Data data[DATA_SIZE] = {{0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {1, 1, 0}}; // 输入数据,类别标签为1或0Data newData = {, , -1}; // 需要分类的数据点int i, j, count = 0;double mindistance = 1e10, dist;int nearest[K];for (i = 0; i < DATA_SIZE; i++) {if ( == -1) { // 如果需要分类的数据点的标签为-1,则需要找到距离最近的k个点dist = distance(data[i], newData);if (dist < mindistance) {mindistance = dist;nearest[count] = i;count++;if (count == K) break; // 如果已经找到了k个点,就结束循环}}}// 根据k个最近邻点的类别标签进行投票,得到新数据点的类别标签int votes[2] = {0}; // 类别标签为0和1的票数for (j = 0; j < K; j++) {votes[data[nearest[j]].label]++; // 统计每个类别的票数}if (votes[0] > votes[1]) { // 如果类别标签为0的票数多,则新数据点的标签为0,否则为1printf("The label of new data point is: 0\n");} else {printf("The label of new data point is: 1\n");}return 0;}```这个程序首先定义了一个数据结构`Data`,用于存储每个数据点的坐标和类别标签。
k-近邻算法(kNN)完整代码

k-近邻算法(kNN)完整代码 1from numpy import *#科学计算包2from numpy import tile3from numpy import zeros4import operator #运算符模块5import importlib6import sys7 importlib.reload(sys)89def createDataSet():10 group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])11 labels = ['A','A','B','B']12return group,labels1314def classify0(inX, dataSet, labels, k):15 dataSetSize = dataSet.shape[0]16#距离计算17 diffMat = tile(inX, (dataSetSize,1)) - dataSet18 sqDiffMat = diffMat**2 #平⽅19 sqDistances = sqDiffMat.sum(axis=1) #根号下平⽅相加20 distances = sqDistances**0.5 #根号21 sortedDistIndicies = distances.argsort() #排序22 classCount={}23#选择距离最⼩的k个点24for i in range(k):25 voteIlabel = labels[sortedDistIndicies[i]]26 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 127#排序,将classCount字典分解为元祖列表,导⼊itemgeeter⽅法,按照第⼆个元素的次序对元祖进⾏排序28#此处排序为逆序,即从⼤到⼩排序,最后返回发⽣频率最⾼的元素标签。
knn算法的c语言实现

knn算法的c语⾔实现 最近研究KNN,找到了⼀些优秀的源码,贴出来,做个笔记吧。
1 #include<stdio.h>2 #include<stdlib.h>3 #include<math.h>4 #include<time.h>56 typedef struct{//数据维度7double x;8double y;9 }data_struct;1011 typedef struct kd_node{12 data_struct split_data;//数据结点13int split;//分裂维14struct kd_node *left;//由位于该结点分割超⾯左⼦空间内所有数据点构成的kd-tree15struct kd_node *right;//由位于该结点分割超⾯右⼦空间内所有数据点构成的kd-tree16 }kd_struct;1718//⽤于排序19int cmp1( const void *a , const void *b )20 {21return (*(data_struct *)a).x > (*(data_struct *)b).x ? 1:-1;22 }23//⽤于排序24int cmp2( const void *a , const void *b )25 {26return (*(data_struct *)a).y > (*(data_struct *)b).y ? 1:-1;27 }28//计算分裂维和分裂结点29void choose_split(data_struct data_set[],int size,int dimension,int *split,data_struct *split_data)30 {31int i;32 data_struct *data_temp;33 data_temp=(data_struct *)malloc(size*sizeof(data_struct));34for(i=0;i<size;i++)35 data_temp[i]=data_set[i];36static int count=0;//设为静态37 *split=(count++)%dimension;//分裂维38if((*split)==0) qsort(data_temp,size,sizeof(data_temp[0]),cmp1);39else qsort(data_temp,size,sizeof(data_temp[0]),cmp2);40 *split_data=data_temp[(size-1)/2];//分裂结点排在中位41 }42//判断两个数据点是否相等43int equal(data_struct a,data_struct b){44if(a.x==b.x && a.y==b.y) return1;45else return0;46 }47//建⽴KD树48 kd_struct *build_kdtree(data_struct data_set[],int size,int dimension,kd_struct *T)49 {50if(size==0) return NULL;//递归出⼝51else{52int sizeleft=0,sizeright=0;53int i,split;54 data_struct split_data;55 choose_split(data_set,size,dimension,&split,&split_data);56 data_struct data_right[size];57 data_struct data_left[size];5859if (split==0){//x维60for(i=0;i<size;++i){61if(!equal(data_set[i],split_data) && data_set[i].x <= split_data.x){//⽐分裂结点⼩62 data_left[sizeleft].x=data_set[i].x;63 data_left[sizeleft].y=data_set[i].y;64 sizeleft++;//位于分裂结点的左⼦空间的结点数65 }66else if(!equal(data_set[i],split_data) && data_set[i].x > split_data.x){//⽐分裂结点⼤67 data_right[sizeright].x=data_set[i].x;68 data_right[sizeright].y=data_set[i].y;69 sizeright++;//位于分裂结点的右⼦空间的结点数70 }71 }72 }73else{//y维74for(i=0;i<size;++i){75if(!equal(data_set[i],split_data) && data_set[i].y <= split_data.y){76 data_left[sizeleft].x=data_set[i].x;77 data_left[sizeleft].y=data_set[i].y;78 sizeleft++;79 }80else if (!equal(data_set[i],split_data) && data_set[i].y > split_data.y){81 data_right[sizeright].x = data_set[i].x;82 data_right[sizeright].y = data_set[i].y;83 sizeright++;84 }85 }86 }87 T=(kd_struct *)malloc(sizeof(kd_struct));88 T->split_data.x=split_data.x;89 T->split_data.y=split_data.y;90 T->split=split;91 T->left=build_kdtree(data_left,sizeleft,dimension,T->left);//左⼦空间92 T->right=build_kdtree(data_right,sizeright,dimension,T->right);//右⼦空间93return T;//返回指针94 }95 }96//计算欧⽒距离97double compute_distance(data_struct a,data_struct b){98double tmp=pow(a.x-b.x,2.0)+pow(a.y-b.y,2.0);99return sqrt(tmp);100 }101//搜索1近邻102void search_nearest(kd_struct *T,int size,data_struct test,data_struct *nearest_point,double *distance)103 {104int path_size;//搜索路径内的指针数⽬105 kd_struct *search_path[size];//搜索路径保存各结点的指针106 kd_struct* psearch=T;107 data_struct nearest;//最近邻的结点108double dist;//查询结点与最近邻结点的距离109 search_path[0]=psearch;//初始化搜索路径110 path_size=1;111while(psearch->left!=NULL || psearch->right!=NULL){112if (psearch->split==0){113if(test.x <= psearch->split_data.x)//如果⼩于就进⼊左⼦树114 psearch=psearch->left;115else116 psearch=psearch->right;117 }118else{119if(test.y <= psearch->split_data.y)//如果⼩于就进⼊右⼦树120 psearch=psearch->left;121else122 psearch=psearch->right;123 }124 search_path[path_size++]=psearch;//将经过的分裂结点保存在搜索路径中125 }126//取出search_path最后⼀个元素,即叶⼦结点赋给nearest127 nearest.x=search_path[path_size-1]->split_data.x;128 nearest.y=search_path[path_size-1]->split_data.y;129 path_size--;//search_path的指针数减⼀130 dist=compute_distance(nearest,test);//计算与该叶⼦结点的距离作为初始距离131132//回溯搜索路径133 kd_struct* pback;134while(path_size!=0){135 pback=search_path[path_size-1];//取出search_path最后⼀个结点赋给pback136 path_size--;//search_path的指针数减⼀137138if(pback->left==NULL && pback->right==NULL){//如果pback为叶⼦结点139if(dist>compute_distance(pback->split_data,test)){140 nearest=pback->split_data;141 dist=compute_distance(pback->split_data,test);142 }143 }144else{//如果pback为分裂结点145int s=pback->split;146if(s==0){//x维147if(fabs(pback->split_data.x-test.x)<dist){//若以查询点为中⼼的圆(球或超球),半径为dist的圆与分割超平⾯相交,那么就要跳到另⼀边的⼦空间去搜索148if(dist>compute_distance(pback->split_data,test)){149 nearest=pback->split_data;150 dist=compute_distance(pback->split_data, test);151 }152if(test.x<=pback->split_data.x)//若查询点位于pback的左⼦空间,那么就要跳到右⼦空间去搜索153 psearch=pback->right;154else155 psearch=pback->left;//若以查询点位于pback的右⼦空间,那么就要跳到左⼦空间去搜索156if(psearch!=NULL)157 search_path[path_size++]=psearch;//psearch加⼊到search_path中158 }159 }160else {//y维161if(fabs(pback->split_data.y-test.y)<dist){//若以查询点为中⼼的圆(球或超球),半径为dist的圆与分割超平⾯相交,那么就要跳到另⼀边的⼦空间去搜索162if(dist>compute_distance(pback->split_data,test)){163 nearest=pback->split_data;164 dist=compute_distance(pback->split_data,test);165 }166if(test.y<=pback->split_data.y)//若查询点位于pback的左⼦空间,那么就要跳到右⼦空间去搜索167 psearch=pback->right;168else169 psearch=pback->left;//若查询点位于pback的的右⼦空间,那么就要跳到左⼦空间去搜索170if(psearch!=NULL)171 search_path[path_size++]=psearch;//psearch加⼊到search_path中172 }173 }174 }175 }176177 (*nearest_point).x=nearest.x;//最近邻178 (*nearest_point).y=nearest.y;179 *distance=dist;//距离180 }181182int main()183 {184int n=6;//数据个数185 data_struct nearest_point;186double distance;187 kd_struct *root=NULL;188 data_struct data_set[6]={{2,3},{5,4},{9,6},{4,7},{8,1},{7,2}};//数据集189 data_struct test={7.1,2.1};//查询点190 root=build_kdtree(data_set,n,2,root);191192 search_nearest(root,n,test,&nearest_point,&distance);193 printf("nearest neighbor:(%.2f,%.2f)\ndistance:%.2f \n",nearest_point.x,nearest_point.y,distance);194return0;195 }196/* x 5,4197 / \198 y 2,3 7.2199 \ / \200 x 4,7 8.1 9.6201*/View Code 看了⼀些做这⽅⾯的⽂章,把写的不错的⼏个也收录了。
c语言写k近邻算法

c语言写k近邻算法k近邻算法是一种常用的机器学习算法,它被广泛应用于分类和回归问题。
在本文中,我将使用C语言来实现k近邻算法,并对其原理进行解析和说明。
让我们来了解一下k近邻算法的基本原理。
k近邻算法是一种基于实例的学习方法,它通过计算待分类样本与训练样本之间的距离来进行分类。
算法的核心思想是:如果一个样本在特征空间中的k个最近邻中的大多数属于某个类别,那么该样本也属于这个类别。
接下来,我们将使用C语言编写k近邻算法的代码。
首先,我们需要定义一个结构体来表示样本数据。
假设每个样本有n个特征,我们可以定义一个结构体如下:```ctypedef struct {double features[n];int label;} Sample;```其中,features数组存储了样本的n个特征,label表示样本的类别。
接下来,我们可以定义一个函数来计算两个样本之间的距离,常用的距离计算方法有欧氏距离和曼哈顿距离。
这里我们以欧氏距离为例:```cdouble distance(Sample s1, Sample s2) {double sum = 0.0;for (int i = 0; i < n; i++) {sum += pow(s1.features[i] - s2.features[i], 2);}return sqrt(sum);}```在计算距离的过程中,我们使用了math.h头文件中的pow和sqrt 函数,分别用于计算平方和平方根。
接下来,我们可以编写一个函数来进行k近邻分类:```cint knn(Sample testSample, Sample trainingSet[], int k, int numSamples) {// 计算测试样本与训练样本的距离,并存储到一个数组中double distances[numSamples];for (int i = 0; i < numSamples; i++) {distances[i] = distance(testSample, trainingSet[i]);}// 对距离进行排序,找出k个最近邻int indices[numSamples];for (int i = 0; i < numSamples; i++) {indices[i] = i;}for (int i = 0; i < numSamples - 1; i++) { for (int j = i + 1; j < numSamples; j++) { if (distances[j] < distances[i]) {double temp = distances[i];distances[i] = distances[j];distances[j] = temp;int tempIndex = indices[i];indices[i] = indices[j];indices[j] = tempIndex;}}}// 统计k个最近邻中各类别的数量int count[numClasses] = {0};for (int i = 0; i < k; i++) {count[trainingSet[indices[i]].label]++;}// 找出数量最多的类别int maxCount = count[0];int maxLabel = trainingSet[indices[0]].label;for (int i = 1; i < numClasses; i++) {if (count[i] > maxCount) {maxCount = count[i];maxLabel = trainingSet[indices[i]].label;}}return maxLabel;}```在这个函数中,我们首先计算了测试样本与训练样本之间的距离,并将距离存储到一个数组中。
用C语言对K近邻法进行的模式识别

用C语言对K近邻法进行的模式识别K近邻法近邻法的基本思想是在测试样本x的k个近邻中,按出现的样本类别来作为x 的类别,即先对x的k个近邻一一找出它们的类别,然后对x类别进行判别,即在N个训练样本中,找出x的k个近邻。
设N个样本中,来自w1类的样本有N1个,来自w2类的样本有N2个,……..,来自wc类的样本有Nc个;k1,k2,……,kc是k个近邻中分别属于w1,w2,…….,wc类的样本数。
定义判别函数为:gi(x)=ki,i=1,2,…..,c;决策规则为:若gj(x)=maxki,则决策x属于wj类。
输入:A[100]为100个训练样本在空间中的坐标,k=9为近邻数。
输出:x所属的类别。
取A[0]~A[9]作为x的9个初始近邻,计算与测试样本x间的欧式距离d(x,A[i]),i=0,1,……,k;按d(x,A[i])升序排序,计算最远样本与x间的距离D——max{d(x,A[j]) | j=0,1,….k};for(i=k+1;i<=n:i++)计算A[i]与x间的距离d(x,A[i]);if d(x,A[i])<Dthen用A[i]代替最远样本;按d(x,A[i])升序排列,计算最远样本与x间的距离D——max{d(x,A[j]) | j=0,1,….i};计算前k个样本A[i]),i=0,1,…k所属类别的概率,具有最大概率的类别即为样本x的类别。
程序如下:#include "stdio.h"#include "math.h"#include "time.h"void knn(float x,float A[]){int i,j,t,k=9;for(i=0;i<k;i++)for(j=i+1;j<k+1;j++)if(fabs(x-A[i])>fabs(x-A[j])){ t=A[i];A[i]=A[j];A[j]=t;}}int compare(float A[],float B[10]) {int i,j,t=0;for(i=0;i<10;i++){for(j=0;j<9;j++){if(B[i]==A[j]){ t++;break;}}}return(t);}void main(){float A[100],B[100],C[10],D[10],x,t,m,d,f; int flag,i,j,n=100,k=9,u;srand((int)time(0));for(i=0;i<n;i++){while(1){ u=rand();A[i]=(u-56.82)/3;if((A[i]<50)&&(A[i]>(-50))){printf("%6.2f",A[i]);if((i+1)%10==0){printf("\n");}break;}elsecontinue;}}for (i=1;i<=10;i++){ switch(i){case 1:printf("第1-10个数为A1类:\n");break;case 2:printf("第11-20个数为A2类:\n"); break;case 3:printf("第21-30个数为A3类:\n"); break;case 4:printf("第31-40个数为A4类:\n"); break;case 5:printf("第41-50个数为A5类:\n"); break;case 6:printf("第51-60个数为A6类:\n"); break;case 7:printf("第61-70个数为A7类:\n"); break;case 8:printf("第71-80个数为A8类:\n"); break;case 9:printf("第81-90个数为A9类:\n"); break;case 10:printf("第91-100个数为A10类:\n"); break;others:break;}}for(i=0;i<100;i++){B[i]=A[i];}while(1){ x= rand()-9.16;if((x<50)&&(x>(-10))){printf("测试样本x=%f\n",x); break;}elsecontinue;}knn(x,A);for(i=k;i<n;i++){f=fabs(x-A[k-1]);d=fabs(x-A[i]);if(d<f){t=A[k-1];A[k-1]=A[i];A[i]=t;}knn(x,A);}printf("x的9个近邻数为:\n"); for(i=0;i<k;i++){printf("%6.2f",A[i]);}for(i=0;i<10;i++){for(j=0;j<10;j++){C[j]=B[i*10+j];}D[i]=compare(A,C);}printf("\n");for(i=0;i<10;i++){ m=D[i];for(j=0;j<10;j++){if(m>=D[j]){ flag=1;continue;}else{flag=0;break;}}if(flag==1){printf("x属于A%d类",(i+1));}}}首先产生100个-50到50之间的随机浮点数,将这一百个数按每十个一类分类。
k近邻算法c语言 -回复

k近邻算法c语言-回复k近邻算法是一种常用于分类和回归问题的监督学习算法。
它的主要思想是通过找到距离未知样本最近的k个训练样本,来推断未知样本所属的类别或预测其目标值。
本文将详细介绍k近邻算法的原理、实现以及应用场景。
一、算法原理k近邻算法的原理非常简单。
给定一个训练集X,其中包含n个样本,每个样本都有m个特征。
对于一个未知样本x,我们需要通过寻找距离它最近的k个训练样本来确定它的类别或预测它的目标值。
距离的计算可以使用欧氏距离、曼哈顿距离等。
二、算法实现在实现k近邻算法时,我们首先需要加载训练集X,并将其分为特征矩阵和目标向量。
接下来,对于每个未知样本x,我们计算它与训练样本的距离,并将距离排序。
然后,选取前k个距离最近的样本,并根据它们的类别或目标值进行预测。
在预测分类问题时,常用的方法有投票法和加权投票法。
投票法指的是选择k个样本中出现次数最多的类别作为预测结果。
加权投票法则是根据距离远近,对每个样本的类别进行加权,再选择加权后类别的出现次数最多的类别作为预测结果。
而对于回归问题,我们可以计算k个样本目标值的平均值或加权平均值,并将其作为预测结果。
三、算法优缺点k近邻算法具有简单、易理解的特点,并且可以应用于分类和回归问题。
另外,它对训练数据没有假设,因此可以适应各种类型的数据。
然而,k近邻算法也存在一些缺点。
首先,当训练集较大时,预测速度较慢。
其次,算法对特征的选择和距离度量方法较为敏感,不同的选择可能导致不同的结果。
此外,k近邻算法还对数据的分布较为敏感,如果样本中的离群点较多,预测结果可能会受到影响。
四、应用场景由于k近邻算法的简单和灵活性,它在许多领域都有广泛应用。
在医学诊断中,可以使用k近邻算法根据患者的特征进行疾病的分类。
在推荐系统中,可以根据用户的兴趣和行为,使用k近邻算法为其推荐相关物品。
此外,k近邻算法还可以应用于图像识别、文本分类、风险预测等领域。
总结起来,k近邻算法是一种简单、易实现且具有广泛应用的算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本文不对KNN算法做过多的理论上的解释,主要是针对问题,进行算法的设计和代码的注解。
KNN算法:优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用数据范围:数值型和标称性。
工作原理:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。
输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。
一般来说,我们只选择样本数据及中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k选择不大于20的整数。
最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
K-近邻算法的一般流程:(1)收集数据:可以使用任何方法(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式(3)分析数据:可以使用任何方法(4)训练算法:此步骤不适用k-邻近算法(5)测试算法:计算错误率(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。
问题一:现在我们假设一个场景,就是要为左边上的点进行分类,如下图所示:上图一共12个左边点,每个坐标点都有相应的坐标(x,y)以及它所属的类别A/B,那么现在需要做的就是给定一个点坐标(x1,y1),判断它属于的类别A或者B。
所有的坐标点在data.txt文件中:0.0 1.1 A1.0 1.0 A2.0 1.0 B0.5 0.5 A2.5 0.5 B0.0 0.0 A1.0 0.0 A2.0 0.0 B3.0 0.0 B0.0 -1.0 A1.0 -1.0 A2.0 -1.0 Bstep1:通过类的默认构造函数去初始化训练数据集dataSet和测试数据testData。
step2:用get_distance()来计算测试数据testData和每一个训练数据dataSet[index]的距离,用map_index_dis来保存键值对<index,distance>,其中index代表第几个训练数据,distance代表第index个训练数据和测试数据的距离。
step3:将map_index_dis按照value值(即distance值)从小到大的顺序排序,然后取前k个最小的value值,用map_label_freq来记录每一个类标签出现的频率。
step4:遍历map_label_freq中的value值,返回value最大的那个key 值,就是测试数据属于的类。
看一下代码KNN_:#include<iostream>#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;constintcolLen = 2;constintrowLen = 12;ifstream fin;ofstreamfout;class KNN{private:tDatadataSet[rowLen][colLen];tLabel labels[rowLen];tDatatestData[colLen];int k;map<int,double>map_index_dis;map<tLabel,int>map_label_freq;doubleget_distance(tData *d1,tData *d2);public:KNN(int k);voidget_all_distance();voidget_max_freq_label();structCmpByValue{bool operator() (const PAIR&lhs,const PAIR&rhs){returnlhs.second<rhs.second;}};};KNN::KNN(int k){this->k = k;fin.open("data.txt");if(!fin){cout<<"can not open the file data.txt"<<endl;exit(1);}/* input the dataSet */for(inti=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(inti=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(inti=0;i<colLen;i++){sum += pow( (d1[i]-d2[i]) , 2 );}// cout<<"the sum is = "<<sum<<endl;returnsqrt(sum);}/** calculate all the distance between test data and each training data*/void KNN:: get_all_distance(){double distance;inti;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(inti=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_iteratormap_it = map_label_freq.begin();tLabel label;intmax_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):testData(5.0,5.0):testData(-5.0,-5.0):testData(1.6,0.5):分类结果的正确性可以通过坐标系来判断,可以看出结果都是正确的。