大三狗模式识别课后练手,仅供参考。若有不合理或是有待改进之处,希望能得到大神的指导与建议!
算法描述
- 任选一个样本作为聚类中心z1
- 选择离z1距离最大的样本作为第二个聚类中心z2
- 计算其余样本与{z1,z2}之间的距离,Di1=|Xi-z1|, Di2=|Xi-z2|,Di=min(Di1,Di2)
- 若max(Di,{i=1…2…}) >
θ|z1-z2|,即样本离两个中心太远,则取max(Di)中的Xi为新的聚类中心z3,
若没有新的聚类中心,则找聚类中心过程结束,直接将样本分到最近的中心。 - 重新回到第3步计算最小距离
算法思路
main(){
setDefaultCenter();
while(isEnd != true) {
calcMinDis();
selectNewCenter(theta);
}
printResult();
}
程序结构
public class MaxminAlgo(算法主题部分)
-public static double calcDis(Sample samp1, Sample samp2)
-public static void calcMinDis()
-public static void setDefaultCenter()
-public static void selectNewCenter(double theta)
-public static void printResult()
-public static void main(String[] args)
-class Sample (定义样本类)
代码段
- Sample类
class Sample{
private int posx, posy;//标记样本的坐标
private boolean isCenter;//是否为聚类中心
private double minDistance;//最小距离
private Sample nearestSamp; //记录距离最近的聚类中心
public Sample(int x, int y) {
this.posx = x;
this.posy = y;
this.isCenter = false; //缺省值为非聚类中心
}
public int getX() {
return this.posx;
}
public int getY() {
return this.posy;
}
public void setMinDistance(double temp_dis) {
this.minDistance = temp_dis;
}
public void setNearestSamp(Sample temp_samp) {
this.nearestSamp = temp_samp;
}
public Sample getNearestSamp() {
return this.nearestSamp;
}
public void setCenter() {
this.isCenter = true;
}
public boolean getCenter() {
return this.isCenter;
}
}
- public static double calcDis(Sample samp1, Sample samp2)
//封装计算两点距离方法
public static double calcDis(Sample samp1, Sample samp2) {
double temp_dis;
int temp_square;
temp_square = (int) ((int) Math.pow((samp1.getX() - samp2.getX()),2) + Math.pow((samp1.getY() - samp2.getY()),2));
temp_dis = Math.sqrt(temp_square);
return temp_dis;
}
- public static void calcMinDis()
//更新样本变量:minDistance, nearestSamp
public static void calcMinDis() {
double min_dis = 999.9;//暂时设置最大值,若不合理再议
for(int m = 0; m < unCenterSample.size(); m++) {
for(int n = 0; n < centerSample.size(); n++) {
double temp_dis = calcDis(centerSample.get(n), unCenterSample.get(m));
//若该距离短,则设置该样本的最短距离与最近样本
if(temp_dis < min_dis) {
min_dis = temp_dis;
unCenterSample.get(m).setNearestSamp(centerSample.get(n));
unCenterSample.get(m).setMinDistance(min_dis);
}
else {
//继续循环
}
}
//将该样本的最短距离加入Array中
minDistance.add(min_dis);
//最小距离重置
min_dis = 999.99;
}
}
- public static void setDefaultCenter()
public static void setDefaultCenter() {
//默认选取第一个样本点为第一个聚类中心, 从非聚类中心去除该样本
Sample defaultCenter_1 = unCenterSample.get(0);
defaultCenter_1.setCenter();
Sample defaultCenter_2 = null;
double temp_dis;
double max_dis = 0;
for(int i = 1; i < unCenterSample.size(); i++) {
temp_dis = calcDis(defaultCenter_1,unCenterSample.get(i));
if(temp_dis > max_dis) {
max_dis = temp_dis; //更新最大距离
defaultCenter_2 = unCenterSample.get(i);
}
else{
//继续循环
}
}
defaultCenter_2.setCenter();
centerSample.add(defaultCenter_1);
centerSample.add(defaultCenter_2);
standardDis = calcDis(defaultCenter_1,defaultCenter_2);
unCenterSample.remove(defaultCenter_1);
unCenterSample.remove(defaultCenter_2);
}
- public static void selectNewCenter(double theta)
public static void selectNewCenter(double theta) {
double max_temp_dis = 0;
int record = 0;
for(int i = 0; i< minDistance.size(); i ++) {
if(minDistance.get(i) > max_temp_dis) {
max_temp_dis = minDistance.get(i);
//为了获得该最大距离的Sample
record = i;
}
}
if(max_temp_dis > theta* standardDis) {
unCenterSample.get(record).setCenter();
centerSample.add(unCenterSample.get(record));
unCenterSample.remove(record);
isEnd = false;
}
else{
//循环结束 输出结果
isEnd = true;
}
}
- public static void printResult()
public static void printResult() {
System.out.println("聚类分类完毕!");
System.out.println("聚类中心有: ");
for(int i = 0; i< centerSample.size() - 1; i ++) {
System.out.print("(" + centerSample.get(i).getX() + "," + centerSample.get(i).getY()+") ");
}
System.out.println();
System.out.println("非聚类中心有:");
for (int i= 0 ; i<unCenterSample.size(); i++) {
System.out.println("(" +unCenterSample.get(i).getX()+"," + unCenterSample.get(i).getY()+") "+
" 的聚类中心是 : " +
"(" + unCenterSample.get(i).getNearestSamp().getX() + "," + unCenterSample.get(i).getNearestSamp().getY() +") ");
}
}
- public static void main(String[] args)
public static void main(String[] args) {
double theta = 0.5;
Sample s1 = new Sample(0,0);
Sample s2 = new Sample(1,1);
Sample s3 = new Sample(2,2);
Sample s4 = new Sample(3,7);
Sample s5 = new Sample(3,6);
Sample s6 = new Sample(4,6);
Sample s7 = new Sample(5,7);
Sample s8 = new Sample(6,3);
Sample s9 = new Sample(7,3);
Sample s10 = new Sample(7,4);
unCenterSample.add(s1);
unCenterSample.add(s2);
unCenterSample.add(s3);
unCenterSample.add(s4);
unCenterSample.add(s5);
unCenterSample.add(s6);
unCenterSample.add(s7);
unCenterSample.add(s8);
unCenterSample.add(s9);
unCenterSample.add(s10);
setDefaultCenter();
while(isEnd != true) {
//selectStandardDis();
calcMinDis();
selectNewCenter(theta);
minDistance.clear();
}
printResult();
System.out.println("Finish");
}