最近邻算法
Ⅰ 什么叫做knn算法
在模式识别领域中,最近邻居法(KNN算法,又译K-近邻算法)是一种用于分类和回归的非参数统计方法。
在这两种情况下,输入包含特征空间(Feature Space)中的k个最接近的训练样本。
1、在k-NN分类中,输出是一个分类族群。一个对象的分类是由其邻居的“多数表决”确定的,k个最近邻居(k为正整数,通常较小)中最常见的分类决定了赋予该对象的类别。若k=1,则该对象的类别直接由最近的一个节点赋予。
2、在k-NN回归中,输出是该对象的属性值。该值是其k个最近邻居的值的平均值。
最近邻居法采用向量空间模型来分类,概念为相同类别的案例,彼此的相似度高,而可以借由计算与已知类别案例之相似度,来评估未知类别案例可能的分类。
K-NN是一种基于实例的学习,或者是局部近似和将所有计算推迟到分类之后的惰性学习。k-近邻算法是所有的机器学习算法中最简单的之一。
无论是分类还是回归,衡量邻居的权重都非常有用,使较近邻居的权重比较远邻居的权重大。例如,一种常见的加权方案是给每个邻居权重赋值为1/ d,其中d是到邻居的距离。
邻居都取自一组已经正确分类(在回归的情况下,指属性值正确)的对象。虽然没要求明确的训练步骤,但这也可以当作是此算法的一个训练样本集。
k-近邻算法的缺点是对数据的局部结构非常敏感。
K-均值算法也是流行的机器学习技术,其名称和k-近邻算法相近,但两者没有关系。数据标准化可以大大提高该算法的准确性。
参数选择
如何选择一个最佳的K值取决于数据。一般情况下,在分类时较大的K值能够减小噪声的影响,但会使类别之间的界限变得模糊。一个较好的K值能通过各种启发式技术(见超参数优化)来获取。
噪声和非相关性特征的存在,或特征尺度与它们的重要性不一致会使K近邻算法的准确性严重降低。对于选取和缩放特征来改善分类已经作了很多研究。一个普遍的做法是利用进化算法优化功能扩展,还有一种较普遍的方法是利用训练样本的互信息进行选择特征。
在二元(两类)分类问题中,选取k为奇数有助于避免两个分类平票的情形。在此问题下,选取最佳经验k值的方法是自助法。
Ⅱ 急求最近邻算法的半监督学习算法对vehicle数据分类的matlab程序
嗯嗯嗯
Ⅲ 使用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的门,会有点小小的成就感。
Ⅳ 机器学习中算法的优缺点之最近邻算法
机器学习中有个算法是十分重要的,那就是最近邻算法,这种算法被大家称为KNN。我们在学习机器学习知识的时候一定要学习这种算法,其实不管是什么算法都是有自己的优缺点的,KNN算法也不例外,在这篇文章中我们就详细的给大家介绍一下KNN算法的优缺点,大家一定要好好学起来哟。
说到KNN算法我们有必要说一下KNN算法的主要过程,KNN算法的主要过程有四种,第一就是计算训练样本和测试样本中每个样本点的距离,第二个步骤就是对上面所有的距离值进行排序(升序)。第三个步骤就是选前k个最小距离的样本。第四个步骤就是根据这k个样本的标签进行投票,得到最后的分类类别。
那么大家是否知道如何选择一个最佳的K值,这取决于数据。一般情况下,在分类时较大的K值能够减小噪声的影响,但会使类别之间的界限变得模糊。一般来说,一个较好的K值可通过各种启发式技术来获取,比如说交叉验证。另外噪声和非相关性特征向量的存在会使K近邻算法的准确性减小。近邻算法具有较强的一致性结果,随着数据趋于无限,算法保证错误率不会超过贝叶斯算法错误率的两倍。对于一些好的K值,K近邻保证错误率不会超过贝叶斯理论误差率。
那么KNN算法的优点是什么呢?KNN算法的优点具体体现在六点,第一就是对数据没有假设,准确度高,对outlier不敏感。第二就是KNN是一种在线技术,新数据可以直接加入数据集而不必进行重新训练。第三就是KNN理论简单,容易实现。第四就是理论成熟,思想简单,既可以用来做分类也可以用来做回归。第五就是可用于非线性分类。第六就是训练时间复杂度为O(n)。由此可见,KNN算法的优点是有很多的。
那么KNN算法的缺点是什么呢?这种算法的缺点具体体现在六点,第一就是样本不平衡时,预测偏差比较大。第二就是KNN每一次分类都会重新进行一次全局运算。第三就是k值大小的选择没有理论选择最优,往往是结合K-折交叉验证得到最优k值选择。第四就是样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少)效果差。第五就是需要大量内存。第六就是对于样本容量大的数据集计算量比较大。
正是由于这些优点和缺点,KNN算法应用领域比较广泛,在文本分类、模式识别、聚类分析,多分类领域中处处有KNN算法的身影。
在这篇文章中我们给大家介绍了很多关于KNN算法的相关知识,通过对这些知识的理解相信大家已经知道该算法的特点了吧,希望这篇文章能够帮助大家更好的理解KNN算法。
Ⅳ k近邻算法如何做回归分析
有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。也就是说,现在, 我们不知道中间那个绿色的数据是从属于哪一类(蓝色小正方形or红色小三角形),下面,我们就要解决这个问题:给这个绿色的圆分类。我们常说,物以类聚,人以群分,判别一个人是一个什么样品质特征的人,常常可以从他/她身边的朋友入手,所谓观其友,而识其人。我们不是要判别上图中那个绿色的圆是属于哪一类数据么,好说,从它的邻居下手。但一次性看多少个邻居呢?从上图中,你还能看到:
如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。 如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。 于此我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。
KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
KNN 算法本身简单有效,它是一种 lazy-learning 算法,分类器不需要使用训练集进行训练,训练时间复杂度为0。KNN 分类的计算复杂度和训练集中的文档数目成正比,也就是说,如果训练集中文档总数为 n,那么 KNN 的分类时间复杂度为O(n)。
KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
K 近邻算法使用的模型实际上对应于对特征空间的划分。K 值的选择,距离度量和分类决策规则是该算法的三个基本要素: K 值的选择会对算法的结果产生重大影响。K值较小意味着只有与输入实例较近的训练实例才会对预测结果起作用,但容易发生过拟合;如果 K 值较大,优点是可以减少学习的估计误差,但缺点是学习的近似误差增大,这时与输入实例较远的训练实例也会对预测起作用,是预测发生错误。在实际应用中,K 值一般选择一个较小的数值,通常采用交叉验证的方法来选择最优的 K 值。随着训练实例数目趋向于无穷和 K=1 时,误差率不会超过贝叶斯误差率的2倍,如果K也趋向于无穷,则误差率趋向于贝叶斯误差率。 该算法中的分类决策规则往往是多数表决,即由输入实例的 K 个最临近的训练实例中的多数类决定输入实例的类别 距离度量一般采用 Lp 距离,当p=2时,即为欧氏距离,在度量之前,应该将每个属性的值规范化,这样有助于防止具有较大初始值域的属性比具有较小初始值域的属性的权重过大。 KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成反比。该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。
该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
实现 K 近邻算法时,主要考虑的问题是如何对训练数据进行快速 K 近邻搜索,这在特征空间维数大及训练数据容量大时非常必要。
Ⅵ 最近邻法的java实现
packageKNN;
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileReader;
importjava.util.ArrayList;
importjava.util.List;
publicclassTestKNN{
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
TestKNNt=newTestKNN();
Stringdatafile="训练数据1.txt";
Stringtestfile="测试数据1.txt";
try{
List<List<Double>>datas=newArrayList<List<Double>>();
List<List<Double>>testDatas=newArrayList<List<Double>>();
t.read(datas,datafile);
t.read(testDatas,testfile);
KNNknn=newKNN();
for(inti=0;i<testDatas.size();i++){
List<Double>test=testDatas.get(i);
System.out.print("测试元组:");
for(intj=0;j<test.size();j++){
System.out.print(test.get(j)+"");
}
System.out.print("类别为:");
System.out.println(Math.round(Float.parseFloat((knn.knn(datas,
test,4)))));//返回最接近参数的int
}
}catch(Exceptione){
e.printStackTrace();
}
}
publicvoidread(List<List<Double>>datas,Stringpath){
try{
BufferedReaderbr=newBufferedReader(newFileReader(
newFile(path)));
Stringdata=br.readLine();
List<Double>l=null;
while(data!=null){
Stringt[]=data.split("");
l=newArrayList<Double>();
for(inti=0;i<t.length;i++){
l.add(Double.parseDouble(t[i]));
}
datas.add(l);
data=br.readLine();
}
}catch(Exceptione){
e.printStackTrace();
}
}
}
packageKNN;
importjava.util.ArrayList;
importjava.util.Comparator;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjava.util.PriorityQueue;
/**
*KNN算法主体类
*/
publicclassKNN{
/**
*设置优先级队列的比较函数,距离越大,优先级越高
*/
privateComparator<KNNNode>comparator=newComparator<KNNNode>(){
publicintcompare(KNNNodeo1,KNNNodeo2){
if(o1.getDistance()>=o2.getDistance()){
return1;
}else{
return0;
}
}
};
/**
*获取K个不同的随机数
*
*@paramk
*随机数的个数
*@parammax
*随机数最大的范围
*@return生成的随机数数组
*/
publicList<Integer>getRandKNum(intk,intmax){
List<Integer>rand=newArrayList<Integer>(k);
for(inti=0;i<k;i++){
inttemp=(int)(Math.random()*max);
if(!rand.contains(temp)){
rand.add(temp);
}else{
i--;
}
}
returnrand;
}
/**
*计算测试元组与训练元组之前的距离
*
*@paramd1
*测试元组
*@paramd2
*训练元组
*@return距离值
*/
publicdoublecalDistance(List<Double>d1,List<Double>d2){
doubledistance=0.00;
for(inti=0;i<d1.size();i++){
distance+=(d1.get(i)-d2.get(i))*(d1.get(i)-d2.get(i));
}
returnMath.sqrt(distance);
}
/**
*执行KNN算法,获取测试元组的类别
*
*@paramdatas
*训练数据集
*@paramtestData
*测试元组
*@paramk
*设定的K值
*@return测试元组的类别
*/
publicStringknn(List<List<Double>>datas,List<Double>testData,intk){
ArrayList<KNNNode>alKN=newArrayList<KNNNode>();
for(inti=0;i<k;i++){
List<Double>currData=datas.get(i);
Stringc=currData.get(currData.size()-1).toString();
KNNNodenode=newKNNNode(i,calDistance(testData,currData),c);
alKN.add(node);
}
for(inti=k;i<datas.size();i++){
List<Double>t=datas.get(i);
doubledistance=calDistance(testData,t);
for(intj=0;j<alKN.size();j++){
if((alKN.get(j).getDistance())>=distance){
alKN.remove(j);
alKN.add(newKNNNode(i,distance,t.get(t.size()-1)
.toString()));
break;
}
}
}
returngetMostClass(alKN);
}
/**
*获取所得到的k个最近邻元组的多数类
*
*@parampq
*存储k个最近近邻元组的优先级队列
*@return多数类的名称
*/
privateStringgetMostClass(ArrayList<KNNNode>alKN){
Map<String,Integer>classCount=newHashMap<String,Integer>();
for(inti=0;i<alKN.size();i++){
KNNNodenode=alKN.remove(i);
Stringc=node.getC();
if(classCount.containsKey(c)){
classCount.put(c,classCount.get(c)+1);
}else{
classCount.put(c,1);
}
}
intmaxIndex=-1;
intmaxCount=0;
Object[]classes=classCount.keySet().toArray();
for(inti=0;i<classes.length;i++){
if(classCount.get(classes[i])>maxCount){
maxIndex=i;
maxCount=classCount.get(classes[i]);
}
}
returnclasses[maxIndex].toString();
}
}
packageKNN;
/**
*KNN结点类,用来存储最近邻的k个元组相关的信息
*/
publicclassKNNNode{
privateintindex;//元组标号
privatedoubledistance;//与测试元组的距离
privateStringc;//所属类别
publicKNNNode(intindex,doubledistance,Stringc){
super();
this.index=index;
this.distance=distance;
this.c=c;
}
publicintgetIndex(){
returnindex;
}
publicvoidsetIndex(intindex){
this.index=index;
}
publicdoublegetDistance(){
returndistance;
}
publicvoidsetDistance(doubledistance){
this.distance=distance;
}
publicStringgetC(){
returnc;
}
publicvoidsetC(Stringc){
this.c=c;
}
}
Ⅶ 邻近算法的算法流程
1. 准备数据,对数据进行预处理
2. 选用合适的数据结构存储训练数据和测试元组
3. 设定参数,如k
4.维护一个大小为k的的按距离由大到小的优先级队列,用于存储最近邻训练元组。随机从训练元组中选取k个元组作为初始的最近邻元组,分别计算测试元组到这k个元组的距离,将训练元组标号和距离存入优先级队列
5. 遍历训练元组集,计算当前训练元组与测试元组的距离,将所得距离L 与优先级队列中的最大距离Lmax
6. 进行比较。若L>=Lmax,则舍弃该元组,遍历下一个元组。若L < Lmax,删除优先级队列中最大距离的元组,将当前训练元组存入优先级队列。
7. 遍历完毕,计算优先级队列中k 个元组的多数类,并将其作为测试元组的类别。
8. 测试元组集测试完毕后计算误差率,继续设定不同的k值重新进行训练,最后取误差率最小的k 值。
Ⅷ 邻近算法
k-Nearest Neighbor algorithm K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。因此,采用这种方法可以较好地避免样本的不平衡问题。另外,由于 KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。该方法的不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
Ⅸ 邻近算法的介绍
邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。
Ⅹ 如何结合pca算法和最近邻法进行人脸识别
%一个修改后的PCA进行人脸识别的Matlab代码
% calc xmean,sigma and its eigen decomposition
allsamples=[];%所有训练图像
for i=1:40
for j=1:5
a=imread(strcat('D:\rawdata\ORL\s',num2str(i),'\',num2str(j),'.pgm'));
% imshow(a);
b=a(1:112*92); % b是行矢量 1×N,其中N=10304,提取顺序是先列后行,即从上到下,从左到右
b=double(b);
allsamples=[allsamples; b]; % allsamples 是一个M * N 矩阵,allsamples 中每一行数据代表一张图片,其中M=200
end
end
samplemean=mean(allsamples); % 平均图片,1 × N
for i=1:200 xmean(i,:)=allsamples(i,:)-samplemean; % xmean是一个M × N矩阵,xmean每一行保存的数据是“每个图片数据-平均图片”
end;
sigma=xmean*xmean'; % M * M 阶矩阵
[v d]=eig(sigma);
d1=diag(d);
[d2 index]=sort(d1); %以升序排序
cols=size(v,2);% 特征向量矩阵的列数
for i=1:cols
vsort(:,i) = v(:,index(cols-i+1) ); % vsort 是一个M*col(注:col一般等于M)阶矩阵,保存的是按降序排列的特征向量,每一列构成一个特征向量
dsort(i) = d1( index(cols-i+1) ); % dsort 保存的是按降序排列的特征值,是一维行向量
end %完成降序排列
%以下选择90%的能量
dsum = sum(dsort);
dsum_extract = 0;
p = 0;
while( dsum_extract/dsum < 0.9)
p = p + 1;
dsum_extract = sum(dsort(1:p));
end
i=1;
% (训练阶段)计算特征脸形成的坐标系
while (i0)
base(:,i) = dsort(i)^(-1/2) * xmean' * vsort(:,i); % base是N×p阶矩阵,除以dsort(i)^(1/2)是对人脸图像的标准化,详见《基于PCA的人脸识别算法研究》p31
i = i + 1;
end
% add by wolfsky 就是下面两行代码,将训练样本对坐标系上进行投影,得到一个 M*p 阶矩阵allcoor
allcoor = allsamples * base;
accu = 0;
%
for i=1:40
for j=6:10 %读入40 x 5 副测试图像
a=imread(strcat('D:\rawdata\ORL\s',num2str(i),'\',num2str(j),'.pgm'));
b=a(1:10304);
b=double(b);
tcoor= b * base; %计算坐标,是1×p阶矩阵
for k=1:200
mdist(k)=norm(tcoor-allcoor(k,:));
end;
%三阶近邻
[dist,index2]=sort(mdist);
class1=floor( index2(1)/5 )+1;
class2=floor(index2(2)/5)+1;
class3=floor(index2(3)/5)+1;
if class1~=class2 && class2~=class3
class=class1;
elseif class1==class2
class=class1;
elseif class2==class3
class=class2;
end;
if class==i
accu=accu+1;
end;
end;
end;
accuracy=accu/200 %输出识别率
函数调用是定义函数,然后用函数名进行调用就可以了