📄 fcm.java
字号:
/**
*
*/
package fcm;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author 吴春江 2007-4-23
*
*/
public class FCM {
private static final String FILE_DATA_IN = "data_in.txt";//输入的样本数据
private static final String FILE_PAR = "parameters.txt";//参数配置
private static final String FILE_CENTER = "center.txt";//聚类中心
private static final String FILE_MATRIX = "matrix.txt";//隶属度矩阵
private static final int SIZE = 10;
public int numpattern;//样本数
public int dimension;//每个样本点的维数
public int cata;//要聚类的类别数
public int maxcycle;//最大的迭代次数
public double m;//参数m
public double limit;//误差限
public FCM() {
super();
}
public FCM(int numpattern, int dimension, int cata, int maxcycle, double m, double limit) {
this.numpattern = numpattern;
this.dimension = dimension;
this.cata = cata;
this.maxcycle = maxcycle;
this.m = m;
this.limit = limit;
}
/**
* 读取配置文件
* @return
*/
public boolean getPar() {
//打开配置文件
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(FILE_PAR));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//读取配置文件
String line = null;
for (int i = 0; i < 6; i++) {
try {
line = br.readLine();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
switch(i) {
case 0: numpattern = Integer.valueOf(line); break;
case 1: dimension = Integer.valueOf(line); break;
case 2: cata = Integer.valueOf(line); break;
case 3: m = Double.valueOf(line); break;
case 4: maxcycle = Integer.valueOf(line); break;
case 5: limit = Double.valueOf(line); break;
}
}
return true;
}
/**
* 读取样本
* @param pattern
* @return
*/
public boolean getPattern(double[] pattern) {
//打开样本文件
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(FILE_DATA_IN));
} catch (FileNotFoundException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
//读取样本文件
String line = null;
String regex = ",";
int index = 0;
while (true) {
try {
line = br.readLine();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
if (line == null)
break;
String[] split = line.split(regex);
for (int i = 0; i < split.length; i++)
pattern[index++] = Double.valueOf(split[i]);
}
return true;
}
/**
* 本函数完成FCM聚类算法
* 参数分为三组:基本聚类样本的信息、算法的参数信息、算法控制信息、输出信息。
* @param pattern 为样本点向量 指标为:样本指标*维数=维数指标
* @param dimension 每个样本的维数
* @param numpattern 样本的个数
* @param cata 分类的数目
* @param m fcm的重要控制参数m
* @param maxcycle 最大循环次数
* @param limit 算法结束迭代的阈值
* @param umatrix 输出的划分矩阵 指标为:聚类指标*样本数=样本指标
* @param rescenter 输出的样本的聚类中心向量 指标为:聚类指标*维数=维数指标
* @param result 目标函数的值
*/
public boolean FCM_fun(double[] pattern, int dimension, int numpattern, int cata, double m,
int maxcycle, double limit, double[] umatrix, double[] rescenter, double result) {
int j, i, k, t, count;
int n_cycle;
int n_selnum;
int flagtemp;
double f_temp, lastv, delta, t_temp;
double[] v1 = new double[SIZE];
double[] v2 = new double[SIZE];
double min_dis = 0.001;//距离的最小值
//验证输入参数的有效性
if (cata >= numpattern || m <= 1)
return false;
//随机选取初始迭代点作为初始的聚类中心
for (j = 0; j < cata; j++) {
t_temp = Math.random();
n_selnum = (int) (Math.random() * numpattern / cata + j * numpattern / cata);
n_selnum = j * numpattern / cata;
while (n_selnum * dimension > numpattern * dimension)
n_selnum -= numpattern;
for (i = 0; i < dimension; i++)
rescenter[j * dimension + i] = pattern[n_selnum * dimension + i];
}
//开始主循环
n_cycle = 0;
lastv = 0;
do{
//计算划分矩阵
for(i = 0; i < numpattern; i++) {
flagtemp = 0;
count = 0;
for(j = 0;j < cata; j++) {
f_temp = 0;
for(t = 0;t < cata; t++) {
for(k = 0; k < dimension; k++) {
v1[k] = pattern[i * dimension + k];
v2[k] = rescenter[t * dimension + k];
}
if (distance(v1, v2, dimension) > min_dis){
f_temp += Math.pow(distance(v1, v2, dimension), -2 / (m - 1));
}else{
flagtemp = 1;
}
}
for(k = 0; k < dimension; k++){
v1[k] = pattern[i * dimension + k];
v2[k] = rescenter[j * dimension + k];
}
if(flagtemp == 1){
umatrix[j * numpattern + i] = 0;
flagtemp = 0;
}
//如果存在使得||Xk-Vi||=0的点置标志-1
if(distance(v1, v2, dimension) > min_dis) {
double shit1 = distance(v1, v2, dimension);
double shit2 = Math.pow(shit1, -2 / (m - 1)) / f_temp;
int shit3 = j * numpattern + i;
umatrix[shit3] = shit2;
}else{
count++;
umatrix[j * numpattern + i] = -1;
}
}//end for j
// 如果存在使得||Xk-Vi||=0就让所有的与Xk不为零的类的隶属度为零。
if(count > 0){
for(j = 0; j < cata; j++){
if(umatrix[j * numpattern + i] == -1){
umatrix[j * numpattern + i] = 1 / (double)(count);
}else
umatrix[j * numpattern +i]=0;
}
}
}//end for i
f_temp = objectfun(umatrix, rescenter, pattern, cata, numpattern, dimension, m);
delta = Math.abs(f_temp - lastv);
lastv = f_temp;
//计算聚类中心的坐标
for(i = 0; i < cata; i++){
for(j = 0; j < dimension; j++){
f_temp = 0;
for(k = 0; k < numpattern; k++){
f_temp += Math.pow(umatrix[i * numpattern + k], m) * pattern[k * dimension + j];
}
rescenter[i * dimension + j] = f_temp;
f_temp = 0;
for(k = 0; k < numpattern; k++){
f_temp += Math.pow(umatrix[i * numpattern + k], m);
}
rescenter[i * dimension + j] /= f_temp;
}
}
n_cycle++;
} while(n_cycle < maxcycle && delta > limit);
return true;
}
/**
* 计算欧氏距离
* @param v1
* @param v2
* @param dimension
* @return
*/
public double distance(double v1[],double v2[],double dimension) {
//这个函数计算欧氏距离
int i;
double result;
result = 0;
for(i = 0; i < dimension; i++){
result += (v1[i] - v2[i]) * (v1[i] - v2[i]);
}
result = Math.sqrt(result);
return result;
}
/**
* 计算优化的目标函数
* @param u
* @param v
* @param x
* @param c
* @param pattern
* @param dimension
* @param m
* @return
*/
public double objectfun(double u[],double v[],double x[],int c,int pattern,int dimension,double m) {
//此函数计算优化的目标函数
int i,j,k;
double[] v1 = new double[SIZE];
double[] v2 = new double[SIZE];
double object;
object = 0;
for(i = 0; i < c; i++) {
for(j = 0; j < pattern; j++) {
for(k = 0; k < dimension; k++) {
v1[k] = x[j * dimension + k];
v2[k] = v[i * dimension + k];
}
object += Math.pow(u[i * pattern+j], m) * distance(v1, v2, dimension) * distance(v1, v2, dimension);
}
}
return object;
}
/**
* 运行FCM算法
*
*/
public void runFCM() {
double[] pattern = new double[numpattern * dimension];
double[] umatrix = new double[numpattern * cata];
double[] rescenter = new double[cata * dimension];
double result=0;
//获取样本
getPattern(pattern);
//执行FCM_fun
FCM_fun(pattern, dimension, numpattern, cata, m, maxcycle, limit, umatrix, rescenter, result);
//输出结果
Export(umatrix, rescenter);
}
/**
* 输出隶属度矩阵和聚类的中心
* @param umatrix
* @param rescenter
*/
public void Export(double[] umatrix, double[] rescenter) {
String str = null;
String tab = " ";
//输出隶属度矩阵
try {
FileWriter matrixFileWriter = new FileWriter(FILE_MATRIX);
for (int i = 0; i < numpattern; i++) {
str = "";
for (int j = 0; j < cata; j++) {
str += umatrix[j * numpattern + i] + tab;
}
str += "\n";
matrixFileWriter.write(str);
}
matrixFileWriter.close();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
//输出聚类的中心
try {
FileWriter centerFileWriter = new FileWriter(FILE_CENTER);
for (int i = 0; i < cata; i++) {
str = "";
for (int j = 0; j < dimension; j++) {
str += rescenter[i*dimension + j] + tab;
}
str += "\n";
centerFileWriter.write(str);
}
centerFileWriter.close();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
}
/**
* 主函数
* @param args
*/
public static void main(String[] args) {
FCM fcm = new FCM();
fcm.getPar();
fcm.runFCM();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -