AP算法java实现
2015-07-14 16:41
681 查看
AP近邻传播算法,关于其原理网上有很多,这就不做过多的介绍,具体的可以参照 http://blog.sina.com.cn/s/blog_6617c8c201013v25.html 关于最终的终止条件设置是小于200,用于给出的例子可以很好地进行聚类,也可以按照原算法思想设置终止条件,算法结果输出的是最终的最佳n个中心,其他的点可以根据距离进行最终的归类划分,的以下是具体实现源代码:
package com.gxw;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* AP聚类算法
*
* @author gxw
*
*/
public class APMain {
public static void main(String[] args) {
List<List<Double>> data = getData(); // 获取文本数据
Double s[][] = getMatrix(data);
apOpreate(s);
}
private static void apOpreate(Double s[][]) {
double lam = 0.5;
int len = s.length;
//判定是否为中心点
int[] iscenter = new int[len];
Double r[][] = new Double[len][len];
Double a[][] = new Double[len][len];
Double oldr[][] = new Double[len][len];
Double olda[][] = new Double[len][len];
//初始化矩阵
for(int i = 0; i < len; i++)
{
for(int j = 0; j < len; j++)
{
olda[i][j] = 0.0;
a[i][j] = 0.0;
oldr[i][j] = 0.0;
r[i][j] = 0.0;
}
}
int times = 0;
while(times < 200)
{
//now to old
{
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
oldr[i][j] = r[i][j];
olda[i][j] = a[i][j];
}
}
}
//更新r.R(i,k)=S(i,k)- max{A(i,j)+S(i,j)}(j {1,2,……,N,但j≠k})
for(int i = 0; i < len; i++) {
for(int k = 0; k < len; k++) {
double max = -10000.0;
for(int j = 0; j < len; j++) {
if(j != k) {
max = max > (olda[i][j] + s[i][j]) ? max : (olda[i][j] + s[i][j] );
}
}
r[i][k] = s[i][k] - max;
}
}
//更新A(i,k)=min{0,R(k,k)+ (j {1,2,……,N,但j≠i且j≠k})
for(int i = 0; i < len; i++) {
for(int k = 0; k < len; k++) {
double sum = 0.0;
for(int j = 0; j < len; j++) {
if(j != i && j != k) {
if(oldr[j][k] > 0) {
sum += oldr[j][k];
}
}
}
if(i != k) {
a[i][k] = (0 < (oldr[k][k] + sum) ? 0 : (oldr[k][k] + sum));
}
else {
a[i][k] = sum;
}
}
}
// 加入阻尼系数
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
r[i][j] = (1 - lam) * r[i][j] + lam * oldr[i][j];
a[i][j] = (1 - lam) * a[i][j] + lam * olda[i][j];
}
}
//判断中心点
{
for (int k = 0; k < len; k++)
{
if (a[k][k] + r[k][k] > 0) //判定条件。。
{
System.out.println(k + 1 + " " + (a[k][k] + r[k][k]));
iscenter[k] = 1;
}
}
}
System.out.println();
times++;
}
}
/**
* 获取数据
* @return
*/
public static List<List<Double>> getData() {
List<List<Double>> ll = new ArrayList<List<Double>>();
try {
String path = System.getProperty("user.dir") + "/data1.txt";
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
String strs[] = line.split(" ");
List<Double> l = new ArrayList<Double>();
for (int i = 0; i < strs.length; i++) {
Double da = Double.parseDouble(strs[i]);
l.add(da);
}
ll.add(l);
line = br.readLine();
}
} catch (Exception e) {
System.out.println(e);
}
return ll;
}
/**
* 构建相似度矩阵
* @param data
* @return
*/
private static Double[][] getMatrix(List<List<Double>> data) {
int num = data.size(); // 数据个数
int dimen = data.get(0).size(); // 数据维度
Double s[][] = new Double[num][num];
Double tempData = 0.0;
int i = 0, j = 0, k = 0;
for (i = 0; i < num; i++) {
for (j = 0; j < num; j++) {
tempData = 0.0;
for (k = 0; k < dimen; k++) {
tempData += Math.pow(data.get(i).get(k)
- data.get(j).get(k), 2);
}
if(tempData == 0.0) {
s[i][j] = 0.0;
}
else {
s[i][j] = -Math.sqrt(tempData);
}
}
}
Double middleValue = getMiddle(s);
//重新设置 s[i][i] = middleValue;
for(i = 0; i < num; i++)
{
s[i][i] = middleValue;
}
return s;
}
/**
* 计算相似矩阵的中值
* @param s
* @return
*/
private static double getMiddle(Double s[][])
{
double res = 0.0;
int num = s.length;
List<Double> ld = new ArrayList<Double>();
for(int i = 0; i < num; i++)
{
for(int j = 0; j < num; j++)
{
ld.add(s[i][j]);
}
}
Collections.sort(ld, new Comparator<Double>() {
public int compare(Double a, Double b) {
return a.compareTo(b);
}
});
Double middleValue = 0.0;
if(num * num % 2 == 0)
middleValue = (ld.get(num * num / 2) + ld.get(num * num / 2 + 1)) / 2;
else
{
middleValue = ld.get(num * num / 2 + 1);
}
return middleValue;
}
}
//////原数据如下(二维坐标点), 在当前项目的根目录下新建data.txt,使用的eclipse创建的java项目:
0.02 0.61
0.18 0.46
0.23 0.35
0.40 0.43
0.41 0.20
0.45 0.19
0.46 0.19
0.48 0.01
0.62 0.02
0.61 0.82
0.74 0.93
0.79 0.74
0.93 0.85
0.89 0.67
0.91 0.53
0.92 0.44
0.76 0.20
0.82 0.28
0.89 0.14
0.95 0.05
package com.gxw;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* AP聚类算法
*
* @author gxw
*
*/
public class APMain {
public static void main(String[] args) {
List<List<Double>> data = getData(); // 获取文本数据
Double s[][] = getMatrix(data);
apOpreate(s);
}
private static void apOpreate(Double s[][]) {
double lam = 0.5;
int len = s.length;
//判定是否为中心点
int[] iscenter = new int[len];
Double r[][] = new Double[len][len];
Double a[][] = new Double[len][len];
Double oldr[][] = new Double[len][len];
Double olda[][] = new Double[len][len];
//初始化矩阵
for(int i = 0; i < len; i++)
{
for(int j = 0; j < len; j++)
{
olda[i][j] = 0.0;
a[i][j] = 0.0;
oldr[i][j] = 0.0;
r[i][j] = 0.0;
}
}
int times = 0;
while(times < 200)
{
//now to old
{
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
oldr[i][j] = r[i][j];
olda[i][j] = a[i][j];
}
}
}
//更新r.R(i,k)=S(i,k)- max{A(i,j)+S(i,j)}(j {1,2,……,N,但j≠k})
for(int i = 0; i < len; i++) {
for(int k = 0; k < len; k++) {
double max = -10000.0;
for(int j = 0; j < len; j++) {
if(j != k) {
max = max > (olda[i][j] + s[i][j]) ? max : (olda[i][j] + s[i][j] );
}
}
r[i][k] = s[i][k] - max;
}
}
//更新A(i,k)=min{0,R(k,k)+ (j {1,2,……,N,但j≠i且j≠k})
for(int i = 0; i < len; i++) {
for(int k = 0; k < len; k++) {
double sum = 0.0;
for(int j = 0; j < len; j++) {
if(j != i && j != k) {
if(oldr[j][k] > 0) {
sum += oldr[j][k];
}
}
}
if(i != k) {
a[i][k] = (0 < (oldr[k][k] + sum) ? 0 : (oldr[k][k] + sum));
}
else {
a[i][k] = sum;
}
}
}
// 加入阻尼系数
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
r[i][j] = (1 - lam) * r[i][j] + lam * oldr[i][j];
a[i][j] = (1 - lam) * a[i][j] + lam * olda[i][j];
}
}
//判断中心点
{
for (int k = 0; k < len; k++)
{
if (a[k][k] + r[k][k] > 0) //判定条件。。
{
System.out.println(k + 1 + " " + (a[k][k] + r[k][k]));
iscenter[k] = 1;
}
}
}
System.out.println();
times++;
}
}
/**
* 获取数据
* @return
*/
public static List<List<Double>> getData() {
List<List<Double>> ll = new ArrayList<List<Double>>();
try {
String path = System.getProperty("user.dir") + "/data1.txt";
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
String strs[] = line.split(" ");
List<Double> l = new ArrayList<Double>();
for (int i = 0; i < strs.length; i++) {
Double da = Double.parseDouble(strs[i]);
l.add(da);
}
ll.add(l);
line = br.readLine();
}
} catch (Exception e) {
System.out.println(e);
}
return ll;
}
/**
* 构建相似度矩阵
* @param data
* @return
*/
private static Double[][] getMatrix(List<List<Double>> data) {
int num = data.size(); // 数据个数
int dimen = data.get(0).size(); // 数据维度
Double s[][] = new Double[num][num];
Double tempData = 0.0;
int i = 0, j = 0, k = 0;
for (i = 0; i < num; i++) {
for (j = 0; j < num; j++) {
tempData = 0.0;
for (k = 0; k < dimen; k++) {
tempData += Math.pow(data.get(i).get(k)
- data.get(j).get(k), 2);
}
if(tempData == 0.0) {
s[i][j] = 0.0;
}
else {
s[i][j] = -Math.sqrt(tempData);
}
}
}
Double middleValue = getMiddle(s);
//重新设置 s[i][i] = middleValue;
for(i = 0; i < num; i++)
{
s[i][i] = middleValue;
}
return s;
}
/**
* 计算相似矩阵的中值
* @param s
* @return
*/
private static double getMiddle(Double s[][])
{
double res = 0.0;
int num = s.length;
List<Double> ld = new ArrayList<Double>();
for(int i = 0; i < num; i++)
{
for(int j = 0; j < num; j++)
{
ld.add(s[i][j]);
}
}
Collections.sort(ld, new Comparator<Double>() {
public int compare(Double a, Double b) {
return a.compareTo(b);
}
});
Double middleValue = 0.0;
if(num * num % 2 == 0)
middleValue = (ld.get(num * num / 2) + ld.get(num * num / 2 + 1)) / 2;
else
{
middleValue = ld.get(num * num / 2 + 1);
}
return middleValue;
}
}
//////原数据如下(二维坐标点), 在当前项目的根目录下新建data.txt,使用的eclipse创建的java项目:
0.02 0.61
0.18 0.46
0.23 0.35
0.40 0.43
0.41 0.20
0.45 0.19
0.46 0.19
0.48 0.01
0.62 0.02
0.61 0.82
0.74 0.93
0.79 0.74
0.93 0.85
0.89 0.67
0.91 0.53
0.92 0.44
0.76 0.20
0.82 0.28
0.89 0.14
0.95 0.05
相关文章推荐
- 类加载器--java静态方法静态变量
- POI导出JavaWeb中的table到excel下载
- 为什么我的eclipse按住ctrl点布局文件只能到R.java文件?
- android+eclipse 真机调试
- Spring中IoC的入门实例
- spring3.x/4.x 依赖包 详解
- java重载跟重写的用法
- 【Java基础学习笔记】Java中Socket+Swing设计简单通信
- Java创建以及读写xml文档(dom方式)
- Java防盗链机制
- java使用链栈实现迷宫求解
- java 生成excel
- Java ArrayList 源码分析
- 常见错误总结_1_对java类进行修改后,无法按修改的类型加载
- java文件处理测试
- Spring Quartz动态配置时间
- java执行cmd命令,返回结果中文乱码问题解决
- SpringMVC中的异步提交表单
- java集合体系与C#集合比较
- 如何在eclipse jee中创建Maven project并且转换为Dynamic web project