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 }