- 浏览: 234852 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
清林小篆:
引用[/col[size=xx-small][/size]or ...
tomcat ssl配置以及CAS单点登录探究 -
cyxy99:
u012534143 写道我用同样的方法,同样的节点关系,为什 ...
PageRank算法java实现版本 -
cyxy99:
schaha123 写道楼主还有一个问题想请教一下,下面这2段 ...
PageRank算法java实现版本 -
njthnet:
Participle 和 IkParticiple 这2个类找 ...
贝叶斯文本分类 java实现 -
u012534143:
我用同样的方法,同样的节点关系,为什么的得到的结果与您不一样呢 ...
PageRank算法java实现版本
聚类的意思很明确,物以类聚,把类似的事物放在一起。
聚类算法是web智能中很重要的一步,可运用在社交,新闻,电商等各种应用中,我打算专门开个分类讲解聚类各种算法的java版实现。
首先介绍kmeans算法。
kmeans算法的速度很快,性能良好,几乎是应用最广泛的,它需要先指定聚类的个数k,然后根据k值来自动分出k个类别集合。
举个例子,某某教练在得到全队的数据后,想把这些球员自动分成不同的组别,你得问教练需要分成几个组,他回答你k个,ok可以开始了,在解决这个问题之前有必要详细了解自己需要达到的目的:根据教练给出的k值,呈现出k个组,每个组的队员是相似的。
首先,我们创建球员类。
@KmeanField这个注解是自定义的,用来标示这个属性是否是算法需要的维度。
代码如下
接下来看看最核心的kmeans算法,具体实现过程如下:
1,初始化k个聚类中心
2,计算出每个对象跟这k个中心的距离(相似度计算,这个下面会提到),假如x这个对象跟y这个中心的距离最小(相似度最大),那么x属于y这个中心。这一步就可以得到初步的k个聚类
3,在第二步得到的每个聚类分别计算出新的聚类中心,和旧的中心比对,假如不相同,则继续第2步,直到新旧两个中心相同,说明聚类不可变,已经成功
实现代码如下:
最后咱们测试一下:
结果如下
。
这个里面涉及到相似度算法,事实证明欧几里得距离算法的实践效果是最优的。
最后说说kmeans算法的不足:可以看到只能针对数字类型的属性(维),对于其他类型的除非选定合适的数值度量。
By 阿飞哥 转载请说明
腾讯微博:http://t.qq.com/duyunfeiRoom
新浪微博:http://weibo.com/u/1766094735
聚类算法是web智能中很重要的一步,可运用在社交,新闻,电商等各种应用中,我打算专门开个分类讲解聚类各种算法的java版实现。
首先介绍kmeans算法。
kmeans算法的速度很快,性能良好,几乎是应用最广泛的,它需要先指定聚类的个数k,然后根据k值来自动分出k个类别集合。
举个例子,某某教练在得到全队的数据后,想把这些球员自动分成不同的组别,你得问教练需要分成几个组,他回答你k个,ok可以开始了,在解决这个问题之前有必要详细了解自己需要达到的目的:根据教练给出的k值,呈现出k个组,每个组的队员是相似的。
首先,我们创建球员类。
package kmeans; /** * 球员 * * @author 阿飞哥 * */ public class Player { private int id; private String name; private int age; /* 得分 */ @KmeanField private double goal; /* 助攻 */ //@KmeanField private double assists; /* 篮板 */ //@KmeanField private double backboard; /* 抢断 */ //@KmeanField private double steals; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getGoal() { return goal; } public void setGoal(double goal) { this.goal = goal; } public double getAssists() { return assists; } public void setAssists(double assists) { this.assists = assists; } public double getBackboard() { return backboard; } public void setBackboard(double backboard) { this.backboard = backboard; } public double getSteals() { return steals; } public void setSteals(double steals) { this.steals = steals; } }
@KmeanField这个注解是自定义的,用来标示这个属性是否是算法需要的维度。
代码如下
package kmeans; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 在对象的属性上标注此注释, * 表示纳入kmeans算法,仅支持数值类属性 * @author 阿飞哥 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface KmeanField { }
接下来看看最核心的kmeans算法,具体实现过程如下:
1,初始化k个聚类中心
2,计算出每个对象跟这k个中心的距离(相似度计算,这个下面会提到),假如x这个对象跟y这个中心的距离最小(相似度最大),那么x属于y这个中心。这一步就可以得到初步的k个聚类
3,在第二步得到的每个聚类分别计算出新的聚类中心,和旧的中心比对,假如不相同,则继续第2步,直到新旧两个中心相同,说明聚类不可变,已经成功
实现代码如下:
package kmeans; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * * @author 阿飞哥 * */ public class Kmeans<T> { /** * 所有数据列表 */ private List<T> players = new ArrayList<T>(); /** * 数据类别 */ private Class<T> classT; /** * 初始化列表 */ private List<T> initPlayers; /** * 需要纳入kmeans算法的属性名称 */ private List<String> fieldNames = new ArrayList<String>(); /** * 分类数 */ private int k = 1; public Kmeans() { } /** * 初始化列表 * * @param list * @param k */ public Kmeans(List<T> list, int k) { this.players = list; this.k = k; T t = list.get(0); this.classT = (Class<T>) t.getClass(); Field[] fields = this.classT.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Annotation kmeansAnnotation = fields[i] .getAnnotation(KmeanField.class); if (kmeansAnnotation != null) { fieldNames.add(fields[i].getName()); } } initPlayers = new ArrayList<T>(); for (int i = 0; i < k; i++) { initPlayers.add(players.get(i)); } } public List<T>[] comput() { List<T>[] results = new ArrayList[k]; boolean centerchange = true; while (centerchange) { centerchange = false; for (int i = 0; i < k; i++) { results[i] = new ArrayList<T>(); } for (int i = 0; i < players.size(); i++) { T p = players.get(i); double[] dists = new double[k]; for (int j = 0; j < initPlayers.size(); j++) { T initP = initPlayers.get(j); /* 计算距离 */ double dist = distance(initP, p); dists[j] = dist; } int dist_index = computOrder(dists); results[dist_index].add(p); } for (int i = 0; i < k; i++) { T player_new = findNewCenter(results[i]); T player_old = initPlayers.get(i); if (!IsPlayerEqual(player_new, player_old)) { centerchange = true; initPlayers.set(i, player_new); } } } return results; } /** * 比较是否两个对象是否属性一致 * * @param p1 * @param p2 * @return */ public boolean IsPlayerEqual(T p1, T p2) { if (p1 == p2) { return true; } if (p1 == null || p2 == null) { return false; } boolean flag = true; try { for (int i = 0; i < fieldNames.size(); i++) { String fieldName=fieldNames.get(i); String getName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Object value1 = invokeMethod(p1,getName,null); Object value2 = invokeMethod(p2,getName,null); if (!value1.equals(value2)) { flag = false; break; } } } catch (Exception e) { e.printStackTrace(); flag = false; } return flag; } /** * 得到新聚类中心对象 * * @param ps * @return */ public T findNewCenter(List<T> ps) { try { T t = classT.newInstance(); if (ps == null || ps.size() == 0) { return t; } double[] ds = new double[fieldNames.size()]; for (T vo : ps) { for (int i = 0; i < fieldNames.size(); i++) { String fieldName=fieldNames.get(i); String getName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Object obj=invokeMethod(vo,getName,null); Double fv=(obj==null?0:Double.parseDouble(obj+"")); ds[i] += fv; } } for (int i = 0; i < fieldNames.size(); i++) { ds[i] = ds[i] / ps.size(); String fieldName = fieldNames.get(i); /* 给对象设值 */ String setName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); invokeMethod(t,setName,new Class[]{double.class},ds[i]); } return t; } catch (Exception ex) { ex.printStackTrace(); } return null; } /** * 得到最短距离,并返回最短距离索引 * * @param dists * @return */ public int computOrder(double[] dists) { double min = 0; int index = 0; for (int i = 0; i < dists.length - 1; i++) { double dist0 = dists[i]; if (i == 0) { min = dist0; index = 0; } double dist1 = dists[i + 1]; if (min > dist1) { min = dist1; index = i + 1; } } return index; } /** * 计算距离(相似性) 采用欧几里得算法 * * @param p0 * @param p1 * @return */ public double distance(T p0, T p1) { double dis = 0; try { for (int i = 0; i < fieldNames.size(); i++) { String fieldName = fieldNames.get(i); String getName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); Double field0Value=Double.parseDouble(invokeMethod(p0,getName,null)+""); Double field1Value=Double.parseDouble(invokeMethod(p1,getName,null)+""); dis += Math.pow(field0Value - field1Value, 2); } } catch (Exception ex) { ex.printStackTrace(); } return Math.sqrt(dis); } /*------公共方法-----*/ public Object invokeMethod(Object owner, String methodName,Class[] argsClass, Object... args) { Class ownerClass = owner.getClass(); try { Method method=ownerClass.getDeclaredMethod(methodName,argsClass); return method.invoke(owner, args); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } return null; } }
最后咱们测试一下:
package kmeans; import java.util.ArrayList; import java.util.List; import java.util.Random; public class TestMain { public static void main(String[] args) { List<Player> listPlayers=new ArrayList<Player>(); for(int i=0;i<15;i++){ Player p1=new Player(); p1.setName("afei-"+i); p1.setAssists(i); p1.setBackboard(i); //p1.setGoal(new Random(100*i).nextDouble()); p1.setGoal(i*10); p1.setSteals(i); //listPlayers.add(p1); } Player p1=new Player(); p1.setName("afei1"); p1.setGoal(1); p1.setAssists(8); listPlayers.add(p1); Player p2=new Player(); p2.setName("afei2"); p2.setGoal(2); listPlayers.add(p2); Player p3=new Player(); p3.setName("afei3"); p3.setGoal(3); listPlayers.add(p3); Player p4=new Player(); p4.setName("afei4"); p4.setGoal(7); listPlayers.add(p4); Player p5=new Player(); p5.setName("afei5"); p5.setGoal(8); listPlayers.add(p5); Player p6=new Player(); p6.setName("afei6"); p6.setGoal(25); listPlayers.add(p6); Player p7=new Player(); p7.setName("afei7"); p7.setGoal(26); listPlayers.add(p7); Player p8=new Player(); p8.setName("afei8"); p8.setGoal(27); listPlayers.add(p8); Player p9=new Player(); p9.setName("afei9"); p9.setGoal(28); listPlayers.add(p9); Kmeans<Player> kmeans = new Kmeans<Player>(listPlayers,3); List<Player>[] results = kmeans.comput(); for (int i = 0; i < results.length; i++) { System.out.println("===========类别" + (i + 1) + "================"); List<Player> list = results[i]; for (Player p : list) { System.out.println(p.getName() + "--->" + p.getGoal() + "," + p.getAssists() + "," + p.getSteals() + "," + p.getBackboard()); } } } }
结果如下
。
这个里面涉及到相似度算法,事实证明欧几里得距离算法的实践效果是最优的。
最后说说kmeans算法的不足:可以看到只能针对数字类型的属性(维),对于其他类型的除非选定合适的数值度量。
By 阿飞哥 转载请说明
腾讯微博:http://t.qq.com/duyunfeiRoom
新浪微博:http://weibo.com/u/1766094735
评论
6 楼
ganminhui
2015-07-29
我把代码复制上去,怎么测试结果都在一个分类里,根本没有起到聚类的效果
5 楼
hyywlz
2013-05-18
小弟是新手 ,不知道怎么改,能具体告诉我怎么改吗?
4 楼
AngelAndAngel
2013-05-15
KmeanField
KmeanField 这个是自定义注解
hyywlz 写道
核心的Kmeans算法中
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
KmeanField 这个是自定义注解
3 楼
hyywlz
2013-05-15
核心的Kmeans算法中
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
2 楼
hyywlz
2013-05-15
核心的Kmeans算法中
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
1 楼
hyywlz
2013-05-15
核心的Kmeans算法中
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
58 Annotation kmeansAnnotation = fields[i]
59 .getAnnotation(KmeanField.class);
报这个错误:
Multiple markers at this line
- Type mismatch: cannot convert from KmeanField to Annotation
- Line breakpoint:Kmeans [line: 50] - Kmeans(List<T>, int)
- Bound mismatch: The generic method getAnnotation(Class<T>) of type AnnotatedElement is not applicable for the
arguments (Class<KmeanField>). The inferred type KmeanField is not a valid substitute for the bounded parameter <T extends Annotation>
求解 不胜感激
发表评论
-
招Java培训老师(还是论坛招人靠谱)
2015-05-10 13:39 556好久没来坛子了,一来就搞这么有目的的事儿。。。 好吧, ... -
动手开发自己的mvc-3----容器该帮我们做什么?(非常的重点)
2013-01-22 13:55 1824注解注入 我们知道,Spring只有一个角色:工厂。这个工厂可 ... -
动手开发自己的mvc-2----完善控制层,提供自动注入和注解上传等功能
2013-01-22 13:44 2586当表单提交的内容过多 ,让懒惰的程序员一个个getPara ... -
动手开发自己的mvc-1----实现初步的控制层,实现各种配置和资源获取
2013-01-22 13:28 2821mvc框架最基础的功能就是跳转,struts2支持注 ... -
动手开发自己的mvc (系列)
2013-01-22 14:08 1934到年尾了,整理了一下我Evernote藏的各种文档,打算把ys ... -
整合了一个小的爬取流程框架
2013-01-08 13:04 1312弄了一个小的爬取流程框架,把之前工作中用到的一些小经验 ... -
Mahout各种推荐器的主要特点
2012-12-06 15:17 2996Mahout有很多推荐的实现,各有特点,在这里一并记录 ... -
怎样通过词频得到这个词频的排序?
2012-12-03 14:35 2070在大规模检索中,我们怎样通过已经的词频得到词频的排序 ... -
drools实现自定义业务规则
2012-10-12 11:49 2851最近做财务相关的积分规则,由于这个功能以后涉及到方方面面 ... -
贝叶斯文本分类 java实现
2012-09-25 15:15 12688昨天实现了一个基于贝叶斯定理的的文本分类,贝叶斯定理假 ... -
前段时间做了一个小型的MVC
2012-07-20 13:23 0前端时间做了一个小型的MVC,麻雀虽小,五脏俱全,目前实现的功 ... -
聚类算法之MST算法 java实现版本
2012-07-17 14:20 2805在介绍最小生成树算法(MST)之前,简单说一下平均链接算 ... -
聚类算法之单链接算法java实现
2012-07-05 10:09 4310聚类算法中基于链接的算法大致有三种:单链接算法(s ... -
朴素贝叶斯分类器
2012-05-20 15:25 0NaiveBayes分类器的优点是能得到已知Y的条件下X的 ... -
PageRank算法java实现版本
2012-05-16 16:03 17476PageRank算法是Google的核心搜索算法,在所有 ... -
昨天做了个小工具DB转pojo,html,sql
2012-03-21 13:15 1778做dbutils时为了方便就做了个小工具,省点小事儿吧。 -
我这儿的讨论(项目小组)区可以进来了
2012-02-28 10:38 150java项目小组群,前几天清了几个破坏气氛者,和不发言 ... -
智能web探究群组建立了
2011-11-24 12:10 1634最近群组已申请成功 ,地址是http://web.gr ... -
Cas https方式改为http方式
2011-09-24 13:02 2351最近项目要测试,来不及申请等待证书,所以先把项目改为http的 ... -
jdk6原生态webservice
2011-06-30 13:38 8929近期做cas 单点登录的时候由于要同步用户信息,所以准备在 ...
相关推荐
K-means聚类算法是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象...
在Java中实现KMeans算法,我们可以利用编程语言的强大功能来处理大规模数据集,并将其应用于实际问题,如本例中的数据库字段分组。 1. **KMeans算法基本原理**: KMeans算法主要包含以下步骤: - 初始化:选择K个...
kMeans聚类算法是一种广泛应用的无监督机器学习方法,主要用于数据的分类和分组。它通过将数据点分配到最近的聚类中心来构建类别,然后更新这些中心以更好地反映其所属的数据点。这个过程会迭代进行,直到聚类中心...
《KMeans算法的C++实现解析》 KMeans算法是一种广泛应用的数据聚类方法,它以其简单易懂和高效性在机器学习...通过理解和实现这个过程,我们可以更好地掌握聚类算法的核心思想,并将其应用到实际的数据分析任务中。
### C# 实现简单的 K-means 聚类算法 #### 概述 K-means 是一种常用的无监督机器学习算法,主要用于数据聚类。它能够将数据集划分为K个簇(Cluster),使得每个数据点都属于离它最近的簇中心。在本文中,我们将...
在本实验中,我们将深入探讨两种常用的聚类算法——K-Means和DBSCAN,并了解如何在MATLAB环境中实现它们。聚类是无监督学习的一种方法,主要用于发现数据集中的自然群体或类别,无需事先知道具体的分类信息。 **K-...
机器学习领域涉及多种算法,其中聚类算法是一个重要分支,常见的聚类算法有kmeans,虽然原理简单,简单易用,但通常需要事先确定K值,k值选取与具体数据和业务场景紧密相关,一旦k值选取不合理会导致模型效果出现...
Java语言是实现k-means聚类算法的不二之选。 在学习k-means聚类算法之前,需要了解一些基本概念: 1. 聚类分析:聚类分析是指对数据进行分类,将相似的数据点聚类到一起,形成不同的簇。 2. 无监督学习:无监督...
首先,K-means是最广泛应用的聚类算法之一,其基本思想是通过迭代将数据分配到K个预设的聚类中,以最小化各聚类内部的平方误差总和。K-means的工作流程包括选择初始质心、分配数据点到最近的质心对应的聚类、重新...
KMeans算法作为最经典且广泛使用的无监督学习方法之一,是大数据聚类的首选工具。本文将深入探讨大数据聚类的概念、重要性以及KMeans算法的工作原理和应用。 大数据聚类是对大量、高维度数据进行分类的一种方法,...
kMeans聚类算法是数据挖掘领域中广泛应用的一种无监督学习方法,主要用于将数据集中的样本点按照相似性划分到不同的类别或簇中。这个算法基于一个简单的核心思想:通过迭代优化,使得每个簇内的样本点尽可能接近,而...
KMeans聚类算法是数据挖掘领域中广泛应用的一种无监督学习方法,主要用于将数据集划分成多个不重叠的类别或簇。它通过迭代的方式寻找数据的聚类中心,并将每个数据点分配到最近的聚类中心所在的簇。下面将详细介绍...
这里提到的“k-means聚类分析”是聚类算法中的一种经典方法,它通过迭代寻找最佳的k个簇来对数据进行分类。 k-means算法的基本步骤如下: 1. 初始化:选择k个数据点作为初始的质心(cluster centers)。 2. 分配:...
K-Means算法是其中最常用且理解简单的聚类算法之一。本篇将深入探讨K-Means算法及其代码实现,并对相关的Meanshift算法进行简单介绍。 ### K-Means算法原理 K-Means算法的目标是将数据集划分为K个不同的簇,使得每...
聚类算法要把M个数据点按照分布分成K类(很多算法的K是人为提前设定的)。我们希望通过聚类算法得到 K个中心点,以及每个数据点属于哪个中心点的划分。 中心点可以通过迭代算法来找到,满足条件:所有的数据点到...
Mahout 聚类算法可以分为多种类型,如 Canopy、KMeans、Fuzzy-KMeans、Spectral Clustering 等,每种算法都有其自己的特点和应用场景。 在 Mahout 聚类算法中,数据模型是数据的基本结构,它可以是 DenseVector、...