java简单实现聚类算法
第一个版本有一些问题,,(一段废话biubiu。。。),,我其实每次迭代之后(在达不到收敛标准之前,聚类中心的误差达不到指定小的时候),虽然重新算了聚类中心,但是其实我的那些点并没有变,可是这个程序不知道咋回事每次都把我原先随机指定的聚类中心给变成了我算的聚类中心;怎么用,按照指示来就行了,不用读文件(源码全都是可以运行,不足之处还望批评指正)输出的结果有一堆小数的那是新聚类中心和老的的误差值,在没有达到指定小的时候,是不会停的。
////////////////////
改好了。。。。。。Java对象直接赋值属于浅拷贝
修改后为创建一个对象,值来源于随机点,但是跟随机点已经没有任何关系了。。。。。
A a=b;浅拷贝
..............................
A a=new A();
a.x=b.x;
a.y=b.y;
a并没有引用b
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
题目如下:、
初始,有问题版本:
1 import java.sql.Array; 2 import java.util.ArrayList; 3 import java.util.Random; 4 import java.util.Scanner; 5 6 class point { 7 public float x = 0; 8 public float y = 0; 9 public int flage = -1; 10 11 public float getX() { 12 return x; 13 } 14 15 public void setX(float x) { 16 this.x = x; 17 } 18 19 public float getY() { 20 return y; 21 } 22 23 public void setY(float y) { 24 this.y = y; 25 } 26 } 27 28 public class Kcluster { 29 30 point[] ypo;// 点集 31 point[] pacore = null;// old聚类中心 32 point[] pacoren = null;// new聚类中心 33 34 // 初试聚类中心,点集 35 public void productpoint() { 36 Scanner cina = new Scanner(System.in); 37 System.out.print("请输入聚类中点的个数(随机产生):"); 38 int num = cina.nextInt(); 39 40 ypo = new point[num]; 41 // 随机产生点 42 for (int i = 0; i < num; i++) { 43 44 float x = (int) (new Random().nextInt(10)); 45 float y = (int) (new Random().nextInt(10)); 46 47 ypo[i] = new point();// 对象创建 48 ypo[i].setX(x); 49 ypo[i].setY(y); 50 51 } 52 53 // 初始化聚类中心位置 54 System.out.print("请输入初始化聚类中心个数(随机产生):"); 55 int core = cina.nextInt(); 56 this.pacore = new point[core];// 存放聚类中心 57 this.pacoren = new point[core]; 58 59 Random rand = new Random(); 60 int temp[] = new int[core]; 61 temp[0] = rand.nextInt(num); 62 pacore[0] = new point(); 63 pacore[0] = ypo[temp[0]]; 64 // 避免产生重复的中心 65 for (int i = 1; i < core; i++) { 66 int flage = 0; 67 int thistemp = rand.nextInt(num); 68 for (int j = 0; j < i; j++) { 69 if (temp[j] == thistemp) { 70 flage = 1;// 有重复 71 break; 72 73 } 74 } 75 if (flage == 1) { 76 i--; 77 } else { 78 pacore[i] = new point(); 79 pacore[i] = ypo[thistemp]; 80 pacore[i].flage = 0;// 0表示聚类中心 81 } 82 83 } 84 System.out.println("初始聚类中心:"); 85 for (int i = 0; i < pacore.length; i++) { 86 System.out.println(pacore[i].x + " " + pacore[i].y); 87 } 88 89 } 90 91 // ///找出每个点属于哪个聚类中心 92 public void searchbelong()// 找出每个点属于哪个聚类中心 93 { 94 95 for (int i = 0; i < ypo.length; i++) { 96 double dist = 999; 97 int lable = -1; 98 for (int j = 0; j < pacore.length; j++) { 99 100 double distance = distpoint(ypo[i], pacore[j]); 101 if (distance < dist) { 102 dist = distance; 103 lable = j; 104 // po[i].flage = j + 1;// 1,2,3...... 105 106 } 107 } 108 ypo[i].flage = lable + 1; 109 110 } 111 112 } 113 114 // 更新聚类中心 115 public void calaverage() { 116 117 for (int i = 0; i < pacore.length; i++) { 118 System.out.println("以<" + pacore[i].x + "," + pacore[i].y 119 + ">为中心的点:"); 120 int numc = 0; 121 point newcore = new point(); 122 for (int j = 0; j < ypo.length; j++) { 123 124 if (ypo[j].flage == (i + 1)) { 125 numc += 1; 126 newcore.x += ypo[j].x; 127 newcore.y += ypo[j].y; 128 System.out.println(ypo[j].x + "," + ypo[j].y); 129 } 130 } 131 // 新的聚类中心 132 pacoren[i] = new point(); 133 pacoren[i].x = newcore.x / numc; 134 pacoren[i].y = newcore.y / numc; 135 pacoren[i].flage = 0; 136 System.out.println("新的聚类中心:" + pacoren[i].x + "," + pacoren[i].y); 137 138 } 139 } 140 141 public double distpoint(point px, point py) { 142 143 return Math.sqrt(Math.pow((px.x - py.x), 2) 144 + Math.pow((px.y - py.y), 2)); 145 146 } 147 148 public void change_oldtonew(point[] old, point[] news) { 149 for (int i = 0; i < old.length; i++) { 150 old[i].x = news[i].x; 151 old[i].y = news[i].y; 152 old[i].flage = 0;// 表示为聚类中心的标志。 153 } 154 } 155 156 public void movecore() { 157 // this.productpoint();//初始化,样本集,聚类中心, 158 this.searchbelong(); 159 this.calaverage();// 160 double movedistance = 0; 161 int biao = -1;//标志,聚类中心点的移动是否符合最小距离 162 for (int i = 0; i < pacore.length; i++) { 163 movedistance = distpoint(pacore[i], pacoren[i]); 164 System.out.println("distcore:" + movedistance);//聚类中心的移动距离 165 if (movedistance < 0.01) { 166 biao = 0; 167 168 } else { 169 170 biao=1; 171 break; 172 173 } 174 } 175 if (biao == 0) { 176 System.out.print("迭代完毕!!!!!"); 177 } else { 178 change_oldtonew(pacore, pacoren); 179 movecore(); 180 } 181 182 } 183 184 public static void main(String[] args) { 185 // TODO Auto-generated method stub 186 187 Kcluster kmean = new Kcluster(); 188 kmean.productpoint(); 189 kmean.movecore(); 190 } 191 192 }
修稿版:在初始化聚类中心那里。有一些改动。。。。。。。。。。。嘤嘤嘤
1 import java.sql.Array; 2 import java.util.ArrayList; 3 import java.util.Random; 4 import java.util.Scanner; 5 6 class point { 7 public float x = 0; 8 public float y = 0; 9 public int flage = -1; 10 11 public float getX() { 12 return x; 13 } 14 15 public void setX(float x) { 16 this.x = x; 17 } 18 19 public float getY() { 20 return y; 21 } 22 23 public void setY(float y) { 24 this.y = y; 25 } 26 } 27 28 public class Kcluster { 29 30 point[] ypo;// 点集 31 point[] pacore = null;// old聚类中心 32 point[] pacoren = null;// new聚类中心 33 34 // 初试聚类中心,点集 35 public void productpoint() { 36 Scanner cina = new Scanner(System.in); 37 System.out.print("请输入聚类中点的个数(随机产生):"); 38 int num = cina.nextInt(); 39 40 ypo = new point[num]; 41 // 随机产生点 42 for (int i = 0; i < num; i++) { 43 44 float x = (int) (new Random().nextInt(10)); 45 float y = (int) (new Random().nextInt(10)); 46 47 ypo[i] = new point();// 对象创建 48 ypo[i].setX(x); 49 ypo[i].setY(y); 50 51 } 52 53 // 初始化聚类中心位置 54 System.out.print("请输入初始化聚类中心个数(随机产生):"); 55 int core = cina.nextInt(); 56 this.pacore = new point[core];// 存放聚类中心 57 this.pacoren = new point[core]; 58 59 Random rand = new Random(); 60 int temp[] = new int[core]; 61 temp[0] = rand.nextInt(num); 62 pacore[0] = new point(); 63 pacore[0].x = ypo[temp[0]].x; 64 pacore[0].y = ypo[temp[0]].y; 65 pacore[0].flage=0 ; 66 // 避免产生重复的中心 67 for (int i = 1; i < core; i++) { 68 int flage = 0; 69 int thistemp = rand.nextInt(num); 70 for (int j = 0; j < i; j++) { 71 if (temp[j] == thistemp) { 72 flage = 1;// 有重复 73 break; 74 75 } 76 } 77 if (flage == 1) { 78 i--; 79 } else { 80 pacore[i] = new point(); 81 pacore[i].x= ypo[thistemp].x; 82 pacore[i].y = ypo[thistemp].y; 83 pacore[i].flage = 0;// 0表示聚类中心 84 } 85 86 } 87 System.out.println("初始聚类中心:"); 88 for (int i = 0; i < pacore.length; i++) { 89 System.out.println(pacore[i].x + " " + pacore[i].y); 90 } 91 92 } 93 94 // ///找出每个点属于哪个聚类中心 95 public void searchbelong()// 找出每个点属于哪个聚类中心 96 { 97 98 for (int i = 0; i < ypo.length; i++) { 99 double dist = 999; 100 int lable = -1; 101 for (int j = 0; j < pacore.length; j++) { 102 103 double distance = distpoint(ypo[i], pacore[j]); 104 if (distance < dist) { 105 dist = distance; 106 lable = j; 107 // po[i].flage = j + 1;// 1,2,3...... 108 109 } 110 } 111 ypo[i].flage = lable + 1; 112 113 } 114 115 } 116 117 // 更新聚类中心 118 public void calaverage() { 119 120 for (int i = 0; i < pacore.length; i++) { 121 System.out.println("以<" + pacore[i].x + "," + pacore[i].y 122 + ">为中心的点:"); 123 int numc = 0; 124 point newcore = new point(); 125 for (int j = 0; j < ypo.length; j++) { 126 127 if (ypo[j].flage == (i + 1)) { 128 System.out.println(ypo[j].x + "," + ypo[j].y); 129 numc += 1; 130 newcore.x += ypo[j].x; 131 newcore.y += ypo[j].y; 132 133 } 134 } 135 // 新的聚类中心 136 pacoren[i] = new point(); 137 pacoren[i].x = newcore.x / numc; 138 pacoren[i].y = newcore.y / numc; 139 pacoren[i].flage = 0; 140 System.out.println("新的聚类中心:" + pacoren[i].x + "," + pacoren[i].y); 141 142 } 143 } 144 145 public double distpoint(point px, point py) { 146 147 return Math.sqrt(Math.pow((px.x - py.x), 2) 148 + Math.pow((px.y - py.y), 2)); 149 150 } 151 152 public void change_oldtonew(point[] old, point[] news) { 153 for (int i = 0; i < old.length; i++) { 154 old[i].x = news[i].x; 155 old[i].y = news[i].y; 156 old[i].flage = 0;// 表示为聚类中心的标志。 157 } 158 } 159 160 public void movecore() { 161 // this.productpoint();//初始化,样本集,聚类中心, 162 this.searchbelong(); 163 this.calaverage();// 164 double movedistance = 0; 165 int biao = -1;//标志,聚类中心点的移动是否符合最小距离 166 for (int i = 0; i < pacore.length; i++) { 167 movedistance = distpoint(pacore[i], pacoren[i]); 168 System.out.println("distcore:" + movedistance);//聚类中心的移动距离 169 if (movedistance < 0.01) { 170 biao = 0; 171 172 } else { 173 174 biao=1;//需要继续迭代, 175 break; 176 177 } 178 } 179 if (biao == 0) { 180 System.out.print("迭代完毕!!!!!"); 181 } else { 182 change_oldtonew(pacore, pacoren); 183 movecore(); 184 } 185 186 } 187 188 public static void main(String[] args) { 189 // TODO Auto-generated method stub 190 191 Kcluster kmean = new Kcluster(); 192 kmean.productpoint(); 193 kmean.movecore(); 194 } 195 196 }