算法描述

  K-means算法是一种被广泛使用的基于划分的聚类算法,目的是将n个对象会分成k个簇。算法的具体描述如下:

随机选取k个对象作为簇中心;

Do

          计算所有对象到这k个簇中心的距离,将距离最近的归入相应的簇;

          重新计算每个簇的中心;

          计算准则函数V;

While 准则函数的值稳定(或变化小于某个阈值)

  其中准则函数V的定义如下:

         

  其中,ui表示第i个簇Si的中心。最终经过T次迭代获取到最终的分类结果,对于第t+1次迭代之后得到的中心,有如下定义:

          

算法的优缺点

  优点:

    1)         算法描述简单,高效;

    2)         适合用于处理大数据,得到的算法的复杂度大约为O(nkt),n表示对象的数量,k是划分的簇数量,t为迭代次数。通常情况下能够保证k<<n,算法的效率有一定的保障;

    3)         算法比较适合处理簇之间划分明确的对象集合;

  缺点:

    1)         k值必须手动的给出,选取k值就显得特别重要了;

    2)         不同的初始对象会带来不同的划分结果;

    3)         如果对象集合内部包含一些小范围孤立对象,这种基于局部最优的聚类划分算法可能会产生一些错误的划分;

    4)         通常判断对象之间远近的依据是欧拉距离,可以尽快得到结果,但同时也带来了一些缺点,比如采用K-means算法处理一下非凸面的簇时。

Kmeans算法的Java实现

 import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set; import ocr.algorithm.KMeans.Cluster;
import ocr.algorithm.KMeans.KMeansNode; /**
* 这是一个简单的Kmeans算法实现
* 假设前提包括:
* 1.集合中每个对象都是一个位于二维平面的点
* 2.对象之间的距离判定以欧氏距离为标准
* 3.这只是一个样例程序,主要用于叙述K-means算法的主干部分,一些特殊的情况未曾考虑(数据溢出,性能优化)
* @author yahokuma
* @email Hazin.lu@gmail.com
*/
public class KMeans { private List<KMeansNode> datas = new ArrayList<KMeans.KMeansNode>(); public static class KMeansNode {
private double x;
private double y; public double getX() {
return x;
} public double getY() {
return y;
} public KMeansNode(double x,double y){
this.x = x;
this.y = y;
} public double distance(KMeansNode n){
return
Math.pow( x - n.x , 2 ) + Math.pow( y - n.y , 2 );
} } public static class Cluster{
private List<KMeansNode> nodes = new ArrayList<KMeans.KMeansNode>();
private KMeansNode center = null;
public KMeansNode getCenter() {
return center;
}
public void addNode(KMeansNode n){
this.nodes.add(n);
}
public Cluster(KMeansNode c){
this.center = c;
}
public void calculateCenter(){
double x = 0,y = 0;
for (KMeansNode n : nodes) {
x += n.x;
y += n.y;
}
this.center = new KMeansNode( x / nodes.size(), y / nodes.size());
} public double criterion(){
double criterion = 0;
calculateCenter();
for (KMeansNode n : nodes) {
criterion += center.distance(n);
} return criterion;
} public void clear(){
this.nodes.clear();
} public List<KMeansNode> getNodes(){
return this.nodes;
} public void print(){
System.out.println("Contains "+ nodes.size() + " Nodes !");
System.out.println("Center Node is ( "+ getCenter().x + "," + getCenter().y + " )");
}
} public KMeans(List<KMeansNode> datas){
this.datas = datas;
} private List<KMeansNode> findRandNodes(int k){
List<KMeansNode> rNodes = new ArrayList<KMeans.KMeansNode>();
Set<Integer> rIndexes = new HashSet<Integer>();
Random r = new Random();
Integer rInt = null;
for (int i = 0; i < k; i++) {
rInt = r.nextInt(datas.size());
while(rIndexes.contains(rInt))
rInt = r.nextInt(datas.size()); rIndexes.add(rInt);
rNodes.add( datas.get(rInt));
} return rNodes;
} private double calculateCriterion(List<Cluster> clusters){
double res = 0;
for (Cluster c : clusters) {
res += c.criterion();
}
return res;
} public List<Cluster> partition(int k){
List<KMeansNode> centerNodes = findRandNodes(k);
List<Cluster> clusters = new ArrayList<KMeans.Cluster>();
for (KMeansNode c : centerNodes) {
clusters.add(new Cluster(c));
} double minDistance = Double.MAX_VALUE , distance;
Cluster minCluster = null;
double lastCriterion , criterion= Double.MAX_VALUE; do{
for (Cluster c : clusters) {
c.clear();
}
lastCriterion = criterion; for (KMeansNode n : datas) {
minDistance = Double.MAX_VALUE;
for (Cluster c : clusters) {
distance = c.getCenter().distance(n);
if( distance < minDistance ){
minDistance = distance;
minCluster = c;
}
}
minCluster.addNode(n);
}
criterion = calculateCriterion(clusters); }while( criterion != lastCriterion); return clusters; } /**
*随机生成了1000个平面点,将其划分为4个簇(k=4)
*由于点的坐标都是随机生成的,在空间上分布均匀;
*从结果中可以看出K-means对于处理这种边界不分明的对象集合时并不能很好的进行区分;
*但是一般情况,经过处理还是会将整个平面均匀得划分成四个部分
**/
public static void main(String args[]){
Random r = new Random();
List<KMeansNode> nodes = new ArrayList<KMeans.KMeansNode>();
for (int i = 0; i < 1000; i++) {
nodes.add(new KMeansNode(r.nextDouble() * 1000, r.nextDouble() * 1000));
} KMeans kmeans = new KMeans(nodes);
List<Cluster> clusters = kmeans.partition(4);
for( Cluster c : clusters){
c.print();
} Frame frame = new Frame("K-means Test!");
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.add(new KMeansCanvas(clusters),BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
} } /**
*
* @author yahokuma
* @email Hazin.lu@gmail.com
*/
class KMeansCanvas extends Canvas {
public final static Paint[] PAINT_COLOR = {Color.BLUE,Color.RED, Color.ORANGE, Color.BLACK}; private List<Cluster> clusters = null;
public KMeansCanvas(List<Cluster> clusters) {
this.setBackground(Color.WHITE);
this.clusters = clusters;
}
@Override
public void paint(Graphics g) {
drawKarel(g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1000,1000);
} private void drawKarel(Graphics g) { Random r = new Random();
int i = 0 ;
for (Cluster c : clusters) {
Graphics2D g2d= (Graphics2D) g;
g2d.setPaint(PAINT_COLOR[i++]);
for (KMeansNode n : c.getNodes()) {
g2d.drawRect((int)n.getX(), (int)n.getY() , 2, 2);
g2d.fillRect((int)n.getX(), (int)n.getY() , 2, 2);
}
}
}
private static final long serialVersionUID = 1L;
}

参考资料

http://en.wikipedia.org/wiki/K-means_clustering

http://blog.csdn.net/aladdina/article/details/4141177

http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006910.html

http://zh.wikipedia.org/wiki/K%E5%B9%B3%E5%9D%87%E7%AE%97%E6%B3%95

数据挖掘经典算法——K-means算法的更多相关文章

  1. 第4章 最基础的分类算法-k近邻算法

    思想极度简单 应用数学知识少 效果好(缺点?) 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 distances = [] for x_train in X_train ...

  2. 聚类算法:K-means 算法(k均值算法)

    k-means算法:      第一步:选$K$个初始聚类中心,$z_1(1),z_2(1),\cdots,z_k(1)$,其中括号内的序号为寻找聚类中心的迭代运算的次序号. 聚类中心的向量值可任意设 ...

  3. 分类算法----k近邻算法

    K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一.该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的 ...

  4. 机器学习(四) 机器学习(四) 分类算法--K近邻算法 KNN (下)

    六.网格搜索与 K 邻近算法中更多的超参数 七.数据归一化 Feature Scaling 解决方案:将所有的数据映射到同一尺度 八.scikit-learn 中的 Scaler preprocess ...

  5. 机器学习(四) 分类算法--K近邻算法 KNN (上)

    一.K近邻算法基础 KNN------- K近邻算法--------K-Nearest Neighbors 思想极度简单 应用数学知识少 (近乎为零) 效果好(缺点?) 可以解释机器学习算法使用过程中 ...

  6. python 机器学习(二)分类算法-k近邻算法

      一.什么是K近邻算法? 定义: 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别. 来源: KNN算法最早是由Cover和Hart提 ...

  7. KNN 与 K - Means 算法比较

    KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...

  8. 分类算法——k最近邻算法(Python实现)(文末附工程源代码)

    kNN算法原理 k最近邻(k-Nearest Neighbor)算法是比较简单的机器学习算法.它采用测量不同特征值之间的距离方法进行分类,思想很简单:如果一个样本在特征空间中的k个最近邻(最相似)的样 ...

  9. 【学习笔记】分类算法-k近邻算法

    k-近邻算法采用测量不同特征值之间的距离来进行分类. 优点:精度高.对异常值不敏感.无数据输入假定 缺点:计算复杂度高.空间复杂度高 使用数据范围:数值型和标称型 用例子来理解k-近邻算法 电影可以按 ...

  10. 【机器学习】聚类算法——K均值算法(k-means)

    一.聚类 1.基于划分的聚类:k-means.k-medoids(每个类别找一个样本来代表).Clarans 2.基于层次的聚类:(1)自底向上的凝聚方法,比如Agnes (2)自上而下的分裂方法,比 ...

随机推荐

  1. HTML5学习之新增标签

    转自:http://www.cnblogs.com/fly_dragon/archive/2012/05/25/2516142.html 作者:FlyDragon 一.引言 在本节中,笔者将向大家讲述 ...

  2. mybatis基本流程、jdbc连接、ps:附mybatis(乐观锁)实现

    一.前言 Mybatis和Hibernate一样,是一个优秀的持久层框架.已经说过很多次了,原生的jdbc操作存在大量的重复性代码(如注册驱动,创建连接,创建statement,结果集检测等).框架的 ...

  3. Spring发展史

    https://www.cnblogs.com/RunForLove/p/4641672.html

  4. HASHMAP 深入解析

    http://blog.csdn.net/ghsau/article/details/16843543/

  5. 【uva11468-Substring】AC自动机+dp

    http://acm.hust.edu.cn/vjudge/problem/31655 题意:给定k个模板串,n个字符以及选择它的概率pro[i],要构造一个长度问L的字符串s,问s不包含任意一个模板 ...

  6. noip2016 普及组

    T1 买铅笔 题目传送门 #include<cstdio> #include<cstring> #include<algorithm> using namespac ...

  7. Unordered load/store queue

    A method and processor for providing full load/store queue functionality to an unordered load/store  ...

  8. camera驱动框架分析(下)

    sensor的驱动 v4l2_i2c_new_subdev_board先用client = i2c_new_device(adapter, info);创建info对应的i2c_client对象(代表 ...

  9. linux tomcat 乱码

    使用vi编辑器编辑长文件时,常常是头昏眼花,也找不到需要更改的内容. 这时,使用查找功能尤为重要. 方法如下: 1.命令模式下输入“/字符串”,例如“/Section 3”. 2.如果查找下一个,按“ ...

  10. dependencyManagement和dependencies的区别

    参考:http://zhaoshijie.iteye.com/blog/2094478http://blog.csdn.net/cpf2016/article/details/45674377 还有一 ...