导航:首页 > 源码编译 > 基于数据挖掘的k近邻算法

基于数据挖掘的k近邻算法

发布时间:2023-07-22 13:34:30

A. K-近邻算法简介

1.K-近邻(KNearestNeighbor,KNN)算法简介 :对于一个未知的样本,我们可以根据离它最近的k个样本的类别来判断它的类别。

以下图为例,对于一个未知样本绿色小圆,我们可以选取离它最近的3的样本,其中包含了2个红色三角形,1个蓝色正方形,那么我们可以判断绿色小圆属于红色三角形这一类。
我们也可以选取离它最近的5个样本,其中包含了3个蓝色正方形,2个红色三角形,那么我们可以判断绿色小圆属于蓝色正方形这一类。

3.API文档

下面我们来对KNN算法中的参数项做一个解释说明:

'n_neighbors':选取的参考对象的个数(邻居个数),默认值为5,也可以自己指定数值,但不是n_neighbors的值越大分类效果越好,最佳值需要我们做一个验证。
'weights': 距离的权重参数,默认uniform。
'uniform': 均匀的权重,所有的点在每一个类别中的权重是一样的。简单的说,就是每个点的重要性都是一样的。
'distance':权重与距离的倒数成正比,距离近的点重要性更高,对于结果的影响也更大。
'algorithm':运算方法,默认auto。
'auto':根绝模型fit的数据自动选择最合适的运算方法。
'ball_tree':树模型算法BallTree
'kd_tree':树模型算法KDTree
'brute':暴力算法
'leaf_size':叶子的尺寸,默认30。只有当algorithm = 'ball_tree' or 'kd_tree',这个参数需要设定。
'p':闵可斯基距离,当p = 1时,选择曼哈顿距离;当p = 2时,选择欧式距离。
n_jobs:使用计算机处理器数目,默认为1。当n=-1时,使用所有的处理器进行运算。

4.应用案例演示
下面以Sklearn库中自带的数据集--手写数字识别数据集为例,来测试下kNN算法。上一章,我们简单的介绍了机器学习的一般步骤:加载数据集 - 训练模型 - 结果预测 - 保存模型。这一章我们还是按照这个步骤来执行。
[手写数字识别数据集] https://scikit-learn.org/stable/moles/generated/sklearn.datasets.load_digits.html#sklearn.datasets.load_digits

5.模型的方法
每一种模型都有一些它独有的属性方法(模型的技能,能做些什么事),下面我们来了解下knn算法常用的的属性方法。

6.knn算法的优缺点
优点:
简单,效果还不错,适合多分类问题
缺点:
效率低(因为要计算预测样本距离每个样本点的距离,然后排序),效率会随着样本量的增加而降低。

B. K-近邻算法(KNN)

简单地说,K-近邻算法采用测量不同特征值之间的距离方法进行分类。

欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:

身高、体重、鞋子尺码数据对应性别

导包,机器学习的算法KNN、数据鸢尾花

获取训练样本 datasets.load_iris()

画图研究前两个特征和分类之间的关系(二维散点图只能展示两个维度)

第二步预测数据:所预测的数据,自己创造,就是上面所显示图片的背景点

生成预测数据

对数据进行预测

ocr 光学字符识别(Optical Character Recognition) 我们先做一个基础班:识别数字

C. k近邻算法中关键的要素是

k近邻算法中关键的要素是:k值的选取、邻居距离的度量和分类决策的制订。

1.k值的选取:

k近邻算法优点很明显,简单易用,可解释性强,但也有其不足之处。例如,“多数表决”会在类别分布偏斜时浮现缺陷。也就是说,k值的选取非常重要,出现频率较多的样本将会主导测试点的预测结果。

3.分类决策的制订:

本质上,分类器就是一个由特征向量,到预测类别的映射函数。k近邻算法的分类流程大致如下三步走:(1)计算待测试样本与训练集合中每一个样本的欧式距离;(2)对每一个距离从小到大排序;(3)选择前k个距离最短的样本,分类任务采用“少数服从多数”的表决规则。回归任务则可采用k个近邻的平均值举茄作为预测值。

D. 使用Node.js如何实现K最近邻分类算法

源于数据挖掘的一个作业, 这里用Node.js技术来实现一下这个机器学习中最简单的算法之一k-nearest-neighbor算法(k最近邻分类法)。
k-nearest-neighbor-classifier
还是先严谨的介绍下。急切学习法(eager learner)是在接受待分类的新元组之前就构造了分类模型,学习后的模型已经就绪,急着对未知的元组进行分类,所以称为急切学习法,诸如决策树归纳,贝叶斯分类等都是急切学习法的例子。惰性学习法(lazy learner)正好与其相反,直到给定一个待接受分类的新元组之后,才开始根据训练元组构建分类模型,在此之前只是存储着训练元组,所以称为惰性学习法,惰性学习法在分类进行时做更多的工作。
本文的knn算法就是一种惰性学习法,它被广泛应用于模式识别。knn基于类比学习,将未知的新元组与训练元组进行对比,搜索模式空间,找出最接近未知元组的k个训练元组,这里的k即是knn中的k。这k个训练元祖就是待预测元组的k个最近邻。
balabala了这么多,是不是某些同学想大喊一声..speak Chinese! 还是来通俗的解释下,然后再来看上面的理论应该会明白很多。小时候妈妈会指着各种各样的东西教我们,这是小鸭子,这个红的是苹果等等,那我们哼哧哼哧的看着应答着,多次被教后再看到的时候我们自己就能认出来这些事物了。主要是因为我们在脑海像给这个苹果贴了很多标签一样,不只是颜色这一个标签,可能还有苹果的形状大小等等。这些标签让我们看到苹果的时候不会误认为是橘子。其实这些标签就对应于机器学习中的特征这一重要概念,而训练我们识别的过程就对应于泛化这一概念。一台iphone戴了一个壳或者屏幕上有一道划痕,我们还是能认得出来它,这对于我们人来说非常简单,但蠢计算机就不知道怎么做了,需要我们好好调教它,当然也不能过度调教2333,过度调教它要把其他手机也认成iphone那就不好了,其实这就叫过度泛化。
所以特征就是提取对象的信息,泛化就是学习到隐含在这些特征背后的规律,并对新的输入给出合理的判断。
我们可以看上图,绿色的圆代表未知样本,我们选取距离其最近的k个几何图形,这k个几何图形就是未知类型样本的邻居,如果k=3,我们可以看到有两个红色的三角形,有一个蓝色的三正方形,由于红色三角形所占比例高,所以我们可以判断未知样本类型为红色三角形。扩展到一般情况时,这里的距离就是我们根据样本的特征所计算出来的数值,再找出距离未知类型样本最近的K个样本,即可预测样本类型。那么求距离其实不同情况适合不同的方法,我们这里采用欧式距离。
综上所述knn分类的关键点就是k的选取和距离的计算。
2. 实现
我的数据是一个xls文件,那么我去npm搜了一下选了一个叫node-xlrd的包直接拿来用。
// node.js用来读取xls文件的包
var xls = require('node-xlrd');
然后直接看文档实例即可,把数据解析后插入到自己的数据结构里。
var data = [];// 将文件中的数据映射到样本的属性var map = ['a','b','c','d','e','f','g','h','i','j','k'];// 读取文件
xls.open('data.xls', function(err,bk){
if(err) {console.log(err.name, err.message); return;}
var shtCount = bk.sheet.count;
for(var sIdx = 0; sIdx < shtCount; sIdx++ ){
var sht = bk.sheets[sIdx],
rCount = sht.row.count,
cCount = sht.column.count;
for(var rIdx = 0; rIdx < rCount; rIdx++){
var item = {};
for(var cIdx = 0; cIdx < cCount; cIdx++){
item[map[cIdx]] = sht.cell(rIdx,cIdx);
}
data.push(item);
}
}
// 等文件读取完毕后 执行测试
run();
});
然后定义一个构造函数Sample表示一个样本,这里是把刚生成的数据结构里的对象传入,生成一个新的样本。
// Sample表示一个样本
var Sample = function (object) {
// 把传过来的对象上的属性克隆到新创建的样本上
for (var key in object)
{
// 检验属性是否属于对象自身
if (object.hasOwnProperty(key)) {
this[key] = object[key];
}
}
}
再定义一个样本集的构造函数
// SampleSet管理所有样本 参数k表示KNN中的kvar SampleSet = function(k) {
this.samples = [];
this.k = k;
};
// 将样本加入样本数组
SampleSet.prototype.add = function(sample) {
this.samples.push(sample);
}
然后我们会在样本的原型上定义很多方法,这样每个样本都可以用这些方法。
// 计算样本间距离 采用欧式距离
Sample.prototype.measureDistances = function(a, b, c, d, e, f, g, h, i, j, k) {
for (var i in this.neighbors)
{
var neighbor = this.neighbors[i];
var a = neighbor.a - this.a;
var b = neighbor.b - this.b;
var c = neighbor.c - this.c;
var d = neighbor.d - this.d;
var e = neighbor.e - this.e;
var f = neighbor.f - this.f;
var g = neighbor.g - this.g;
var h = neighbor.h - this.h;
var i = neighbor.i - this.i;
var j = neighbor.j - this.j;
var k = neighbor.k - this.k;
// 计算欧式距离
neighbor.distance = Math.sqrt(a*a + b*b + c*c + d*d + e*e + f*f + g*g + h*h + i*i + j*j + k*k);
}
};
// 将邻居样本根据与预测样本间距离排序
Sample.prototype.sortByDistance = function() {
this.neighbors.sort(function (a, b) {
return a.distance - b.distance;
});
};
// 判断被预测样本类别
Sample.prototype.guessType = function(k) {
// 有两种类别 1和-1
var types = { '1': 0, '-1': 0 };
// 根据k值截取邻居里面前k个
for (var i in this.neighbors.slice(0, k))
{
var neighbor = this.neighbors[i];
types[neighbor.trueType] += 1;
}
// 判断邻居里哪个样本类型多
if(types['1']>types['-1']){
this.type = '1';
} else {
this.type = '-1';
}
}
注意到我这里的数据有a-k共11个属性,样本有1和-1两种类型,使用truetype和type来预测样本类型和对比判断是否分类成功。
最后是样本集的原型上定义一个方法,该方法可以在整个样本集里寻找未知类型的样本,并生成他们的邻居集,调用未知样本原型上的方法来计算邻居到它的距离,把所有邻居按距离排序,最后猜测类型。
// 构建总样本数组,包含未知类型样本
SampleSet.prototype.determineUnknown = function() {

for (var i in this.samples)
{
// 如果发现没有类型的样本
if ( ! this.samples[i].type)
{
// 初始化未知样本的邻居
this.samples[i].neighbors = [];
// 生成邻居集
for (var j in this.samples)
{
// 如果碰到未知样本 跳过
if ( ! this.samples[j].type)
continue;
this.samples[i].neighbors.push( new Sample(this.samples[j]) );
}
// 计算所有邻居与预测样本的距离
this.samples[i].measureDistances(this.a, this.b, this.c, this.d, this.e, this.f, this.g, this.h, this.k);
// 把所有邻居按距离排序
this.samples[i].sortByDistance();
// 猜测预测样本类型
this.samples[i].guessType(this.k);
}
}
};
最后分别计算10倍交叉验证和留一法交叉验证的精度。
留一法就是每次只留下一个样本做测试集,其它样本做训练集。
K倍交叉验证将所有样本分成K份,一般均分。取一份作为测试样本,剩余K-1份作为训练样本。这个过程重复K次,最后的平均测试结果可以衡量模型的性能。
k倍验证时定义了个方法先把数组打乱随机摆放。
// helper函数 将数组里的元素随机摆放
function ruffle(array) {
array.sort(function (a, b) {
return Math.random() - 0.5;
})
}
剩余测试代码好写,这里就不贴了。
测试结果为
用余弦距离等计算方式可能精度会更高。
3. 总结
knn算法非常简单,但却能在很多关键的地方发挥作用并且效果非常好。缺点就是进行分类时要扫描所有训练样本得到距离,训练集大的话会很慢。
可以用这个最简单的分类算法来入高大上的ML的门,会有点小小的成就感。

E. K-近邻算法(K-NN)

给定一个训练数据集,对于新的输入实例, 根据这个实例最近的 k 个实例所属的类别来决定其属于哪一类 。所以相对于其它机器学习模型和算法,k 近邻总体上而言是一种非常简单的方法。

找到与该实例最近邻的实例,这里就涉及到如何找到,即在特征向量空间中,我们要采取 何种方式来对距离进行度量

距离的度量用在 k 近邻中我们也可以称之为 相似性度量 ,即特征空间中两个实例点相似程度的反映。在机器学习中,常用的距离度量方式包括欧式距离、曼哈顿距离、余弦距离以及切比雪夫距离等。 在 k 近邻算法中常用的距离度量方式是欧式距离,也即 L2 距离, L2 距离计算公式如下:

一般而言,k 值的大小对分类结果有着重大的影响。 当选择的 k 值较小的情况下,就相当于用较小的邻域中的训练实例进行预测,只有当与输入实例较近的训练实例才会对预测结果起作用。但与此同时预测结果会对实例点非常敏感,分类器抗噪能力较差,因而容易产生过拟合 ,所以一般而言,k 值的选择不宜过小。但如果选择较大的 k 值,就相当于在用较大邻域中的闷郑握训练实例进行预测,但相应的分类误差也会增大,模型整体变得简单,会产生一定程度的欠拟合。所以一般而言,我们需要 采用交叉验证的方式来选择合适的 k 值

k 个实例的多数属于哪丛裤个类,明显是多数表决的归类规则。当然还可能使用其他规则,所以第三个关键就是 分类决策规则。

回归:k个实例该属性值的平均值

它是一个二叉树的数据结构,方便存储 K 维空间的数据

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

如果是做分类,你需要引用:from sklearn.neihbors import KNeighborsClassifier
如果是回归, 需要引用:from sklearn.neighbors import KNeighborsRegressor

sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights='uniform', algorithm='auto', leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=None, **kwargs)

F. 邻近算法的介绍

邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。

阅读全文

与基于数据挖掘的k近邻算法相关的资料

热点内容
dvd光盘存储汉子算法 浏览:756
苹果邮件无法连接服务器地址 浏览:962
phpffmpeg转码 浏览:671
长沙好玩的解压项目 浏览:142
专属学情分析报告是什么app 浏览:564
php工程部署 浏览:833
android全屏透明 浏览:732
阿里云服务器已开通怎么办 浏览:803
光遇为什么登录时服务器已满 浏览:301
PDF分析 浏览:484
h3c光纤全工半全工设置命令 浏览:141
公司法pdf下载 浏览:381
linuxmarkdown 浏览:350
华为手机怎么多选文件夹 浏览:683
如何取消命令方块指令 浏览:349
风翼app为什么进不去了 浏览:778
im4java压缩图片 浏览:362
数据查询网站源码 浏览:150
伊克塞尔文档怎么进行加密 浏览:890
app转账是什么 浏览:163