大三狗模式识别课后练手,仅供参考。若有不合理或是有待改进之处,希望能得到大神的指导与建议!

算法描述

  1. 任选一个样本作为聚类中心z1
  2. 选择离z1距离最大的样本作为第二个聚类中心z2
  3. 计算其余样本与{z1,z2}之间的距离,Di1=|Xi-z1|, Di2=|Xi-z2|,Di=min(Di1,Di2)
  4. 若max(Di,{i=1…2…}) >
    θ|z1-z2|,即样本离两个中心太远,则取max(Di)中的Xi为新的聚类中心z3,
    若没有新的聚类中心,则找聚类中心过程结束,直接将样本分到最近的中心。
  5. 重新回到第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");
	}

运行结果

在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐