Java实现聚类算法k-means

 

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 }
原文地址:https://www.cnblogs.com/8335IT/p/5635965.html