关闭

数据挖掘---分类算法之K近邻(KNN)算法

标签: 分类算法机器学习knnK最近邻距离
893人阅读 评论(0) 收藏 举报
分类:
        K近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
        算法的步骤如下:
        1,计算已知类别数据集中的点与当前点之间的距离;
        2,按照距离递增次序排序;
        3,选取与当前点距离最小的K个点;
        4,确定前K个点所在类别的出现频率;
        5,返回前K个点出现频率最高的类别作为当前点的预测分类。

        KNN 算法本身简单有效,它是一种 lazy-learning 算法,分类器不需要使用训练集进行训练,训练时间复杂度为0。KNN 分类的计算复杂度和训练集中的文档数目成正比,也就是说,如果训练集中文档总数为 n,那么 KNN 的分类时间复杂度为O(n)。

        KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。

        K 近邻算法使用的模型实际上对应于对特征空间的划分。K 值的选择,距离度量和分类决策规则是该算法的三个基本要素:
1. K 值的选择会对算法的结果产生重大影响。K值较小意味着只有与输入实例较近的训练实例才会对预测结果起作用,但容易发生过拟合;如果 K 值较大,优点是可以减少学习的估计误差,但缺点是学习的近似误差增大,这时与输入实例较远的训练实例也会对预测起作用,是预测发生错误。在实际应用中,K 值一般选择一个较小的数值,通常采用交叉验证的方法来选择最优的 K 值。随着训练实例数目趋向于无穷和 K=1 时,误差率不会超过贝叶斯误差率的2倍,如果K也趋向于无穷,则误差率趋向于贝叶斯误差率。

2. 该算法中的分类决策规则往往是多数表决,即由输入实例的 K 个最临近的训练实例中的多数类决定输入实例的类别

3. 距离度量一般采用 Lp 距离,当p=2时,即为欧氏距离,在度量之前,应该将每个属性的值规范化,这样有助于防止具有较大初始值域的属性比具有较小初始值域的属性的权重过大。
       KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成反比。 该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。

       该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。

       说了这么多理论,咱来点实际的,下面用代码实现了简单的KNN。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

public class KNN {
	public static java.text.DecimalFormat df = new java.text.DecimalFormat("#0.00");
	/**K Nearest Neighbour
	 * 计算给定点到每个点的距离,选择距离最近的K个点,看K个点属于哪个类别最多,则该给定点也属于该类别
	 * */
	public static String CLS_SFX = "类";
	public int K;
	public List<KPoint> allData;

	@SuppressWarnings("rawtypes")
	public void knn(KPoint xpoint) {
		TreeSet<KPoint> ts = new TreeSet<KPoint>();
		//1.计算xpoint到每个点的距离,放到TreeSet中根据距离排序
		for (int i = 0; i < allData.size(); i++) {
			KPoint p = allData.get(i);
			double dis = getDistance(p, xpoint);
			p.dis = dis;
			ts.add(p);
		}
		for (Iterator it = ts.iterator(); it.hasNext();) {
			System.out.println(df.format(((KPoint) it.next()).dis));
		}
		KPoint ps[] = (KPoint[]) ts.toArray(new KPoint[0]);
		Map<String,Integer> voteMap = new TreeMap<String,Integer>();
		//2.选择K个最近的,类别投票
		for (int i = 0; i < K; i++) {
			System.out.println((i + 1) + "---" + ps[i]);
			int cnt = 1;
			if (voteMap.containsKey(ps[i].label)) {
				cnt = ((Integer) voteMap.get(ps[i].label)).intValue() + 1;
			}
			voteMap.put(ps[i].label, cnt);
		}
		//3.得到最多投票
		String votes[] = (String[]) voteMap.keySet().toArray(new String[0]);
		TreeSet<VoteResult> result = new TreeSet<VoteResult>();
		for (String vote : votes) {
			result.add(new VoteResult(vote, (int) voteMap.get(vote)));
		}
		System.out.println("Result=" + ((VoteResult) result.first()).label);

	}

	//简单计算距离
	public static double getDistance(KPoint a, KPoint b) {
		return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
	}

	public static void main(String[] args) {
		KNN kn = new KNN();
		kn.K = 3;
		List<KPoint> data = new ArrayList<KPoint>();
		data.add(new KPoint(1, 1, CLS_SFX + "A"));
		data.add(new KPoint(1.1, 1.1, CLS_SFX + "A"));
		data.add(new KPoint(10, 10, CLS_SFX + "B"));
		data.add(new KPoint(10.1, 10.1, CLS_SFX + "B"));
		data.add(new KPoint(10.1, 10.13, CLS_SFX + "B"));
		 for (int i = 0; i < 10; i++) {
		// data.add(new KPoint(Math.random(),Math.random()));
		 }
		kn.allData = data;

		kn.knn(new KPoint(0.1, 0.4));
	}

}

class VoteResult implements java.lang.Comparable<VoteResult> {
	public String label;
	public int count;

	public VoteResult(String label, int count) {
		super();
		this.label = label;
		this.count = count;
	}
        //比较得票数量
	@Override
	public int compareTo(VoteResult kp) {
		if (this.count > kp.count) {
			return -1;
		} else if (this.count < kp.count) {
			return 1;
		} else
			return 0;
	}

}

class KPoint implements java.lang.Comparable<KPoint> {
	public double x;
	public double y;
	public String label;
	public double dis;

	public KPoint() {
		this.x = 0.0;
		this.y = 0.0;
	}

	public KPoint(double x, double y) {
		super();
		this.x = x;
		this.y = y;
	}

	public KPoint(double x, double y, String label) {
		super();
		this.x = x;
		this.y = y;
		this.label = label;
	}

	public String toString() {
		return "(" + KNN.df.format(x) + "," + KNN.df.format(y) + "," + label + ","
				+ KNN.df.format(dis) + ")";
	}
        //比较距离
	@Override
	public int compareTo(KPoint kp) {
		if (this.dis > kp.dis) {
			return 1;
		} else if (this.dis < kp.dis) {
			return -1;
		} else
			return 0;
	}

}



0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

数据挖掘十大算法翻译——8kNN(k邻近分类)

1 算法描述机械分级器,记录了所有的数据,而且仅当测试的对象吻合训练对象的所有属性时才能进行分类,他是目前最简单的分类器之一,也是最琐碎的分类器之一。这样做的明显的缺点之一就是很多数据无法进行分类,因为他们不能精确的匹配训练数据。一个更加高明的手电,k邻近分类(KNN),找到k个相互最接近的对象的群...
  • u010293844
  • u010293844
  • 2015-12-22 23:43
  • 620

【JAVA实现】K-近邻(KNN)分类算法

KNN算法属于监督学习算法,是一种用于分类的非常简单的算法。简单的说,KNN算法采用测量不同特征值之间的距离方法进行分类。具体算法如下:        1)计算已知类别数据集中的点与当前点之间的距离        2...
  • C_son
  • C_son
  • 2015-02-26 21:43
  • 4812

k-近邻算法(详细代码注释与调参性能分析)

kNN是数据挖掘分类技术中最简单的技术之一。 工作原理: 1、监督学习训练样本集(包含label); 2、输入新数据,将每个特征与样本集中数据对应的特征进行比较,提取特征最相似数据(最近邻)的分类标签; 3、一般指选择样本数据集中前 k 个最相似的数据。 算法实现: 1、初始化训练样本集,输入待测数...
  • AI_lalaland
  • AI_lalaland
  • 2017-07-02 19:46
  • 162

机器学习之K-近邻算法(kNN算法)

k-近邻算法是根据不同特征值之间的距离来进行分类的一种简单的机器学习方法。本文简单介绍下kNN算法,并用其实现手写数字的识别。
  • xiong452980729
  • xiong452980729
  • 2016-02-26 22:08
  • 1456

[机器学习]K近邻算法及其应用--WEKA工具

K邻近算法 weka
  • u010536377
  • u010536377
  • 2015-12-16 14:27
  • 3626

K近邻法算法(KNN)及其R实现

1. K近邻算法输入:训练数据集 T={(x1,y1),(x2,y2),⋯,(xN,yN)}T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)\} 其中,xi∈χ⊆Rnx_i \in \chi \subseteq R^n为实例的特征向量,yi∈Y={c1,c2,⋯,...
  • littlely_ll
  • littlely_ll
  • 2016-12-21 20:50
  • 1310

关于K最近邻分类算法(KNN)的综述

摘要 作为一种非参数的分类算法, K近邻(KNN)算法是非常有效和容易实现的。 它已经广泛应用于分类、回归和模式识别等 。在应用 KNN 算法解决问题的时候, 要注意两个方面的问题:—样本权重和特征权重。针对传统的KNN分类算法的不足,出现了很多改进的KNN算法。本文对当前改进KNN的文本分类...
  • hyf_1967
  • hyf_1967
  • 2016-11-30 16:59
  • 6123

KNN(K近邻)算法的简单入门

机器学习实战(第二章:k-近邻算法) 今天学习了第二章,在此就我理解做一下简单的总结,算是加深我的理解和用我自己的语言描述出这个算法吧。 基于向量空间的欧几里得距离的计算。 简单点来说就是 在一个具有大量样本集中,每一个实例都具有3个或以上的特征属性,其中有一个属性必然是分类属性,其余属性为...
  • lht_okk
  • lht_okk
  • 2017-04-18 23:05
  • 949

机器学习实战笔记(Python实现)-02-k近邻算法(kNN)

机器学习实战笔记(Python实现)-02-k近邻算法(kNN) -- 下面来看一下书上对这个算法的原理介绍:存在一个训练样本集,并且每个样本都存在标签(有监督学习)。输入没有标签的新样本数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取出与样本集中特征最相似的数据(最近邻)的...
  • niuwei22007
  • niuwei22007
  • 2015-11-07 17:27
  • 7138

《机器学习实战》k最近邻算法(K-Nearest Neighbor,Python实现)

一、什么是看KNN算法? 二、KNN算法的一般流程 三、KNN算法的Python代码实现 一:什么是看KNN算法?         kNN算法全称是k-最近邻算法(K-Nearest Neighbor)   ...
  • Gamer_gyt
  • Gamer_gyt
  • 2015-08-11 12:35
  • 9566
    个人资料
    • 访问:85435次
    • 积分:1361
    • 等级:
    • 排名:千里之外
    • 原创:63篇
    • 转载:3篇
    • 译文:0篇
    • 评论:14条
    最新评论