赞
踩
本例中主要是对二维点进行距离计算,开始得时候选取两个心,最终聚为两簇。
结束条件的判断有很多种,这里采用的是最简单的:当两个心不再变化了,则停止聚类。
内部距离和可以不需要计算,这里输出来做结果评估用。
public class Km_w2 { //初始化二维数据 /* public static double[] x = {1, 2, 1, -1, -3, -2}; public static double[] y = {1, 1, 3, 2, -4, -1}; public static int n = 6;//一共有6个点 */ public static double[] x = {1, 2, 1, -1, -3, -2, 2, -1, 2}; public static double[] y = {1, 1, 3, 2, -4, -1, -1, -1, -5}; public static int n = 9; //手选两个点,这里选择下标为1和4的两个点,k为2 public static int i1 = 0;//1,1 public static int i2 = 3;//-1,2 public static double x1 = x[i1], x2 = x[i2], y1 = y[i1], y2 = y[i2]; public static void main(String[] args) { int count = 1; while (true) { System.out.println("-------------这是第"+count+"次聚类----------------"); // 定义两个簇 List<Integer> c1 = new ArrayList<>(); List<Integer> c2 = new ArrayList<>(); Map<Integer, Double> dist = new HashMap<>();// 用来记录所有点到它所属心的距离 for (int i = 0; i < n; i++) { //筛选当前遍历的点既不是心1,也不是心2 if (!(x[i] == x1 && y[i] == y1) && !(x[i] == x2 && y[i] == y2)) { double d1 = distance(x[i], y[i], x1, y1); double d2 = distance(x[i], y[i], x2, y2); System.out.println("点"+i+"("+x[i]+","+y[i]+")距离心1("+x1+","+y1+")和心2("+x2+","+y2+")的距离分别为:"+d1+","+d2); // 如果说这个点离簇1更加近,将它放到c1中,否则相反,并且在map中记录下距离 if (d1 <= d2) { c1.add(i); dist.put(i, d1); } else { c2.add(i); dist.put(i, d2); } } } // 算距离和 System.out.println("当前1簇内部距离和为:"+distSum(c1, dist)); System.out.println("当前2簇内部距离和为:"+distSum(c2, dist)); //因为心在计算后有可能是存在的点,有可能是不存在的点。 //如果是存在的点则放到所属的簇中 i1 = isExist(x1, y1); if(i1 != -1) { c1.add(i1); System.out.println("1簇添加了心1:"+x1+","+y1); } i2 = isExist(x2, y2); if(i2 != -1) { c2.add(i2); System.out.println("2簇添加了心2:"+x2+","+y2); } //备份并重新计算心的坐标 double t_x1 = x1; double t_x2 = x2; double t_y1 = y1; double t_y2 = y2; x1 = avg(c1, x); y1 = avg(c1, y); x2 = avg(c2, x); y2 = avg(c2, y); System.out.println("新的心1为"+x1+","+y1); System.out.println("新的心2为"+x2+","+y2); System.out.println("簇1的内容为"+c1.toString()); System.out.println("簇2的内容为"+c2.toString()); //如果心不再更新 if(t_x1==x1 && t_x2==x2 && t_y1==y1 && t_y2==y2) { System.out.println("======================================="); System.out.println("聚类结束,结果为:"); System.out.println("簇1:"+c1.toString()); System.out.println("簇2:"+c2.toString()); break; } count++; } } //该方法用于计算2维两点距离 public static double distance(double x1, double y1, double x2, double y2) { return Math.sqrt(Math.pow(x1 - x2, 2)+Math.pow(y1 - y2, 2)); } //该方法用于计算一个簇中所有点到心的距离和 public static double distSum(List<Integer> c, Map<Integer, Double> dist) { double sum = 0; for (int i : c) { sum += dist.get(i); } return sum; } //该方法用于计算簇中x或y的平均值 public static double avg(List<Integer> c, double[] xory) { int sum = 0; for (int i : c) { sum += xory[i]; } return sum/(c.size()*1.0); } //该方法用于判断心是否是一个存在于数据集的点 public static int isExist(double a, double b) { for(int i = 0; i < x.length; i++) { if(a == x[i] && b == y[i]) { return i; } } return -1; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。