算法描述

  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. es6+最佳入门实践(13)

    13.模块化 13.1.什么是模块化 模块化是一种处理复杂系统分解为更好的可管理模块的方式.通俗的讲就是把一个复杂的功能拆分成多个小功能,并且以一种良好的机制管理起来,这样就可以认为是模块化.就像作家 ...

  2. 使用FindBugs-IDEA插件找到代码中潜在的问题

    另一篇使用文档,参照:https://www.cnblogs.com/huaxingtianxia/p/6703315.html 我们通常都会在APP上线之后,发现各种错误,尤其是空指针异常,这些错误 ...

  3. [bzoj3231][SDOI2008]递归数列——矩阵乘法

    题目大意: 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj和 cj ...

  4. 【Python实例一】使用minidom读取xml文件

    前言:最近刚在廖雪峰老师的网站里学习了Python的基础内容,想着循序渐进地找点实例练练手,网上看到有很多相关资料,决定针对感兴趣的内容实际编码实践一下,昨天刚好看到有关使用Python来读取XML文 ...

  5. 无线路由器中WMM/Short GI/AP隔离各是什么功能, 开启时PC无法ping通手机.

      无线路由器的WMM功能和开启ap隔离,以及开启ShortGI有什么用 无线路由器中有开启WMM.开启Short GI和开启AP隔离分别代表什么呢?这是我在我的TP-LINK无线路由器TL-WR84 ...

  6. 【FIRST USE】第一次用git把代码上传到github

    第一次使用某个东西总是充满了伤痛,我第一次用sed的时候,毁掉了我的所有源代码,第一次用git的时候一直提示不正确,后来解决了问题,便记录下来. 首先说明我的环境,我用的是虚拟机,上面运行的64位的c ...

  7. Oracle基础 07 参数文件 pfile/spfile

    --查看数据库运行模式(spfile还是pfile)select decode(count(*),1,'spfile','pfile') from v$spparameterwhere rownum= ...

  8. 【 Zabbix 】— 基础知识

    zabbix基础 zabbix是一个高度集成的网络监控套件.通过一个软件包即可提供如下特性: 1.数据收集 (1)可用性及性能检测 (2)支持SNMP.IPMI.JMX监控 (3)自定义检测 (4)自 ...

  9. codevs 1085

    数字游戏 2003年NOIP全国联赛普及组 时间限制: s 空间限制: KB 题目等级 : 黄金 Gold 题解 题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但 ...

  10. Selenium2+python自动化74-jquery定位【转载】

    转至博客:上海-悠悠 前言 元素定位可以说是学自动化的小伙伴遇到的一道门槛,学会了定位也就打通了任督二脉,前面分享过selenium的18般武艺,再加上五种js的定位大法. 这些还不够的话,今天再分享 ...