算法--K均值聚类算法(Java实现)

【转】算法——K均值聚类算法(Java实现)

1、用途:聚类算法通常用于数据挖掘,将相似的数组进行聚簇

2、原理:网上比较多,可以百度或者google一下

3、实现:Java代码如下

package org.algorithm;

import java.util.ArrayList;

import java.util.Random;

/**

* K均值聚类算法

*/

public class Kmeans {

private int k;// 分成多少簇

private int m;// 迭代次数

private int dataSetLength;// 数据集元素个数,即数据集的长度

private ArrayList dataSet;// 数据集链表

private ArrayList center;// 中心链表

private ArrayList> cluster; // 簇

private ArrayList jc;// 误差平方和,k越接近dataSetLength,误差越小

private Random random;

/**

* 设置需分组的原始数据集

*

* @param dataSet

*/

public void setDataSet(ArrayList dataSet) {

this.dataSet = dataSet;

}

/**

* 获取结果分组

*

* @return 结果集

*/

public ArrayList> getCluster() {

return cluster;

}

/**

* 构造函数,传入需要分成的簇数量

*

* @param k

*            簇数量,若k

*/

public Kmeans(int k) {

if (k

k = 1;

}

this.k = k;

}

/**

* 初始化

*/

private void init() {

m = 0;

random = new Random();

if (dataSet == null || dataSet.size() == 0) {

initDataSet();

}

dataSetLength = dataSet.size();

if (k > dataSetLength) {

k = dataSetLength;

}

center = initCenters();

cluster = initCluster();

jc = new ArrayList();

}

/**

* 如果调用者未初始化数据集,则采用内部测试数据集

*/

private void initDataSet() {

dataSet = new ArrayList();

// 其中{6,3}是一样的,所以长度为15的数据集分成14簇和15簇的误差都为0

float[][] dataSetArray = new float[][] { { 8, 2 }, { 3, 4 }, { 2, 5 },

{ 4, 2 }, { 7, 3 }, { 6, 2 }, { 4, 7 }, { 6, 3 }, { 5, 3 },

{ 6, 3 }, { 6, 9 }, { 1, 6 }, { 3, 9 }, { 4, 1 }, { 8, 6 } };

for (int i = 0; i

dataSet.add(dataSetArray[i]);

}

}

/**

* 初始化中心数据链表,分成多少簇就有多少个中心点

*

* @return 中心点集

*/

private ArrayList initCenters() {

ArrayList center = new ArrayList();

int[] randoms = new int[k];

boolean flag;

int temp = random.nextInt(dataSetLength);

randoms[0] = temp;

for (int i = 1; i

flag = true;

while (flag) {

temp = random.nextInt(dataSetLength);

int j = 0;

// 不清楚for循环导致j无法加1

// for(j=0;j

// {

// if(temp==randoms[j]);

// {

// break;

// }

// }

while (j

if (temp == randoms[j]) {

break;

}

j++;

}

if (j == i) {

flag = false;

}

}

randoms[i] = temp;

}

// 测试随机数生成情况

// for(int i=0;i

// {

// System.out.println("test1:randoms["+i+"]="+randoms[i]);

// }

// System.out.println();

for (int i = 0; i

center.add(dataSet.get(randoms[i]));// 生成初始化中心链表

}

return center;

}

/**

* 初始化簇集合

*

* @return 一个分为k簇的空数据的簇集合

*/

private ArrayList> initCluster() {

ArrayList> cluster = new ArrayList>();

for (int i = 0; i

cluster.add(new ArrayList());

}

return cluster;

}

/**

* 计算两个点之间的距离

*

* @param element

*            点1

* @param center

*            点2

* @return 距离

*/

private float distance(float[] element, float[] center) {

float distance = 0.0f;

float x = element[0] - center[0];

float y = element[1] - center[1];

float z = x * x + y * y;

distance = (float) Math.sqrt(z);

return distance;

}

/**

* 获取距离集合中最小距离的位置

*

* @param distance

*            距离数组

* @return 最小距离在距离数组中的位置

*/

private int minDistance(float[] distance) {

float minDistance = distance[0];

int minLocation = 0;

for (int i = 1; i

if (distance[i]

minDistance = distance[i];

minLocation = i;

} else if (distance[i] == minDistance) // 如果相等,随机返回一个位置

{

if (random.nextInt(10)

minLocation = i;

}

}

}

return minLocation;

}

/**

* 核心,将当前元素放到最小距离中心相关的簇中

*/

private void clusterSet() {

float[] distance = new float[k];

for (int i = 0; i

for (int j = 0; j

distance[j] = distance(dataSet.get(i), center.get(j));

// System.out.println("test2:"+"dataSet["+i+"],center["+j+"],distance="+distance[j]);

}

int minLocation = minDistance(distance);

// System.out.println("test3:"+"dataSet["+i+"],minLocation="+minLocation);

// System.out.println();

cluster.get(minLocation).add(dataSet.get(i));// 核心,将当前元素放到最小距离中心相关的簇中

}

}

/**

* 求两点误差平方的方法

*

* @param element

*            点1

* @param center

*            点2

* @return 误差平方

*/

private float errorSquare(float[] element, float[] center) {

float x = element[0] - center[0];

float y = element[1] - center[1];

float errSquare = x * x + y * y;

return errSquare;

}

/**

* 计算误差平方和准则函数方法

*/

private void countRule() {

float jcF = 0;

for (int i = 0; i

for (int j = 0; j

jcF += errorSquare(cluster.get(i).get(j), center.get(i));

}

}

jc.add(jcF);

}

/**

* 设置新的簇中心方法

*/

private void setNewCenter() {

for (int i = 0; i

int n = cluster.get(i).size();

if (n != 0) {

float[] newCenter = { 0, 0 };

for (int j = 0; j

newCenter[0] += cluster.get(i).get(j)[0];

newCenter[1] += cluster.get(i).get(j)[1];

}

// 设置一个平均值

newCenter[0] = newCenter[0] / n;

newCenter[1] = newCenter[1] / n;

center.set(i, newCenter);

}

}

}

/**

* 打印数据,测试用

*

* @param dataArray

*            数据集

* @param dataArrayName

*            数据集名称

*/

public void printDataArray(ArrayList dataArray,

String dataArrayName) {

for (int i = 0; i

System.out.println("print:" + dataArrayName + "[" + i + "]={"

+ dataArray.get(i)[0] + "," + dataArray.get(i)[1] + "}");

}

System.out.println("===================================");

}

/**

* Kmeans算法核心过程方法

*/

private void kmeans() {

init();

// printDataArray(dataSet,"initDataSet");

// printDataArray(center,"initCenter");

// 循环分组,直到误差不变为止

while (true) {

clusterSet();

// for(int i=0;i

// {

// printDataArray(cluster.get(i),"cluster["+i+"]");

// }

countRule();

// System.out.println("count:"+"jc["+m+"]="+jc.get(m));

// System.out.println();

// 误差不变了,分组完成

if (m != 0) {

if (jc.get(m) - jc.get(m - 1) == 0) {

break;

}

}

setNewCenter();

// printDataArray(center,"newCenter");

m++;

cluster.clear();

cluster = initCluster();

}

// System.out.println("note:the times of repeat:m="+m);//输出迭代次数

}

/**

* 执行算法

*/

public void execute() {

long startTime = System.currentTimeMillis();

System.out.println("kmeans begins");

kmeans();

long endTime = System.currentTimeMillis();

System.out.println("kmeans running time=" + (endTime - startTime)

+ "ms");

System.out.println("kmeans ends");

System.out.println();

}

}

4、说明:具体代码是从网上找的,根据自己的理解加了注释和进行部分修改,若注释有误还望指正

5、测试

package org.test;

import java.util.ArrayList;

import org.algorithm.Kmeans;

public class KmeansTest {

public  static void main(String[] args)

{

//初始化一个Kmean对象,将k置为10

Kmeans k=new Kmeans(10);

ArrayList dataSet=new ArrayList();

dataSet.add(new float[]{1,2});

dataSet.add(new float[]{3,3});

dataSet.add(new float[]{3,4});

dataSet.add(new float[]{5,6});

dataSet.add(new float[]{8,9});

dataSet.add(new float[]{4,5});

dataSet.add(new float[]{6,4});

dataSet.add(new float[]{3,9});

dataSet.add(new float[]{5,9});

dataSet.add(new float[]{4,2});

dataSet.add(new float[]{1,9});

dataSet.add(new float[]{7,8});

//设置原始数据集

k.setDataSet(dataSet);

//执行算法

k.execute();

//得到聚类结果

ArrayList> cluster=k.getCluster();

//查看结果

for(int i=0;i

{

k.printDataArray(cluster.get(i), "cluster["+i+"]");

}

}

}

6、总结:测试代码已经通过。并对聚类的结果进行了查看,结果基本上符合要求。至于有没有更精确的算法有待发现。具体的实践还有待挖掘

【转】算法——K均值聚类算法扩展应用(Java实现)

1、前面一篇文章算法——K均值聚类算法(Java实现)简单的实现了一下K均值分类算法,这节我们对于他的应用进行一个扩展应用

2、目标为对对象的分类

3、具体实现如下

1)首先建立一个基类KmeansObject,目的为继承该类的子类都可以应用我们的k均值算法进行分类,代码如下

package org.cyxl.util.algorithm;

/**

* 所有使用k均值分类算法的对象都必须继承自该对象

* @author cyxl

* @version 1.0 2012-05-24

* @since 1.0

*

*/

public class KmeansObject {

public float compare; //比较因子

}

2)算法实现,代码如下

package org.cyxl.util.algorithm;

import java.util.ArrayList;

import java.util.Random;

/**

* K均值聚类算法

*/

public class CommonKmeans {

private int k;// 分成多少簇

private int m;// 迭代次数

private int dataSetLength;// 数据集元素个数,即数据集的长度

private ArrayList dataSet;// 数据集链表

private ArrayList center;// 中心链表

private ArrayList> cluster; // 簇

private ArrayList jc;// 误差平方和,k越接近dataSetLength,误差越小

private Random random;

/**

* 设置需分组的原始数据集

*

* @param dataSet

*/

public void setDataSet(ArrayList dataSet) {

this.dataSet = dataSet;

}

/**

* 获取结果分组

*

* @return 结果集

*/

public ArrayList> getCluster() {

return cluster;

}

/**

* 构造函数,传入需要分成的簇数量

*

* @param k

*            簇数量,若k

*/

public CommonKmeans(int k) {

if (k

k = 1;

}

this.k = k;

}

/**

* 初始化

*/

private void init() {

m = 0;

random = new Random();

if (dataSet == null || dataSet.size() == 0) {

initDataSet();

}

dataSetLength = dataSet.size();

if (k > dataSetLength) {

k = dataSetLength;

}

center = initCenters();

cluster = initCluster();

jc = new ArrayList();

}

/**

* 如果调用者未初始化数据集,则采用内部测试数据集

*/

private void initDataSet() {

dataSet = new ArrayList();

for(int i=0;i

{

int temp = random.nextInt(100);

KmeansObject ko=new KmeansObject();

ko.compare=temp;

dataSet.add(ko);

}

}

/**

* 初始化中心数据链表,分成多少簇就有多少个中心点

*

* @return 中心点集

*/

private ArrayList initCenters() {

ArrayList center = new ArrayList();

int[] randoms = new int[k];

boolean flag;

int temp = random.nextInt(dataSetLength);

randoms[0] = temp;

for (int i = 1; i

flag = true;

while (flag) {

temp = random.nextInt(dataSetLength);

int j = 0;

// 不清楚for循环导致j无法加1

// for(j=0;j

// {

// if(temp==randoms[j]);

// {

// break;

// }

// }

while (j

if (temp == randoms[j]) {

break;

}

j++;

}

if (j == i) {

flag = false;

}

}

randoms[i] = temp;

}

for (int i = 0; i

center.add(dataSet.get(randoms[i]));// 生成初始化中心链表

}

return center;

}

/**

* 初始化簇集合

*

* @return 一个分为k簇的空数据的簇集合

*/

private ArrayList> initCluster() {

ArrayList> cluster = new ArrayList>();

for (int i = 0; i

cluster.add(new ArrayList());

}

return cluster;

}

/**

* 计算两个点之间的距离

*

* @param element

*            点1

* @param center

*            点2

* @return 距离

*/

private float distance(KmeansObject element, KmeansObject center) {

float distance = 0.0f;

distance=Math.abs(element.compare-center.compare);

return distance;

}

/**

* 获取距离集合中最小距离的位置

*

* @param distance

*            距离数组

* @return 最小距离在距离数组中的位置

*/

private int minDistance(float[] distance) {

float minDistance = distance[0];

int minLocation = 0;

for (int i = 1; i

if (distance[i]

minDistance = distance[i];

minLocation = i;

} else if (distance[i] == minDistance) // 如果相等,随机返回一个位置

{

if (random.nextInt(10)

minLocation = i;

}

}

}

return minLocation;

}

/**

* 核心,将当前元素放到最小距离中心相关的簇中

*/

private void clusterSet() {

float[] distance = new float[k];

for (int i = 0; i

for (int j = 0; j

distance[j] = distance(dataSet.get(i), center.get(j));

}

int minLocation = minDistance(distance);

cluster.get(minLocation).add(dataSet.get(i));// 核心,将当前元素放到最小距离中心相关的簇中

}

}

/**

* 求两点误差平方的方法

*

* @param element

*            点1

* @param center

*            点2

* @return 误差平方

*/

private float errorSquare(KmeansObject element, KmeansObject center) {

float x = Math.abs(element.compare-center.compare);

float errSquare = x * x;

return errSquare;

}

/**

* 计算误差平方和准则函数方法

*/

private void countRule() {

float jcF = 0;

for (int i = 0; i

for (int j = 0; j

jcF += errorSquare(cluster.get(i).get(j), center.get(i));

}

}

jc.add(jcF);

}

/**

* 设置新的簇中心方法

*/

private void setNewCenter() {

for (int i = 0; i

int n = cluster.get(i).size();

if (n != 0) {

KmeansObject newCenter = new KmeansObject();

for (int j = 0; j

newCenter.compare += cluster.get(i).get(j).compare;

}

// 设置一个平均值

newCenter.compare=newCenter.compare/n;

center.set(i, newCenter);

}

}

}

/**

* 打印数据,测试用

*

* @param dataArray

*            数据集

* @param dataArrayName

*            数据集名称

*/

public void printDataArray(ArrayList dataArray,

String dataArrayName) {

for (int i = 0; i

System.out.println("print:" + dataArrayName + "[" + i + "]={"

+ dataArray.get(i) + "}");

}

System.out.println("===================================");

}

/**

* Kmeans算法核心过程方法

*/

private void kmeans() {

init();

// 循环分组,直到误差不变为止

while (true) {

clusterSet();

countRule();

// 误差不变了,分组完成

if (m != 0) {

if (jc.get(m) - jc.get(m - 1) == 0) {

break;

}

}

setNewCenter();

m++;

cluster.clear();

cluster = initCluster();

}

}

/**

* 执行算法

*/

public void execute() {

long startTime = System.currentTimeMillis();

System.out.println("kmeans begins");

kmeans();

long endTime = System.currentTimeMillis();

System.out.println("kmeans running time=" + (endTime - startTime)

+ "ms");

System.out.println("kmeans ends");

System.out.println();

}

}

3)测试算法,首先建立一个Person类,目标在于对人进行分类

package org.cyxl.util.algorithm;

public class Person extends KmeansObject {

String name="";

int age=0;

float qz=1; //权重

public Person(){}

public Person(String name,int age,float qz)

{

this.name=name;

this.age=age;

this.qz=qz;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public float getQz() {

return qz;

}

public void setQz(float qz) {

this.qz = qz;

}

public String toString()

{

return "name:"+this.name+";age:"+this.age+";qz:"+this.qz+";compare:"+super.compare;

}

}

4)客户端测试代码

CommonKmeans k=new CommonKmeans(5);

ArrayList list=new ArrayList();

for(int i=0;i

{

float qz=(float)(new Random().nextInt(10))/10;

Person p=new Person("name"+i,i,qz);

p.compare=new Random().nextInt(100)*p.getQz();

list.add(p);

}

k.setDataSet(list);

k.printDataArray(k.dataSet, "before");

k.execute();

ArrayList> cluster=k.getCluster();

//查看结果

for(int i=0;i

{

k.printDataArray(cluster.get(i), "cluster["+i+"]");

}

5)输出结果

print:before[0]={name:name0;age:0;qz:0.0;compare:0.0}

print:before[1]={name:name1;age:1;qz:0.9;compare:48.6}

print:before[2]={name:name2;age:2;qz:0.9;compare:57.6}

print:before[3]={name:name3;age:3;qz:0.4;compare:28.4}

print:before[4]={name:name4;age:4;qz:0.0;compare:0.0}

print:before[5]={name:name5;age:5;qz:0.4;compare:33.600002}

print:before[6]={name:name6;age:6;qz:0.5;compare:2.0}

print:before[7]={name:name7;age:7;qz:0.2;compare:14.6}

print:before[8]={name:name8;age:8;qz:0.6;compare:5.4}

print:before[9]={name:name9;age:9;qz:0.9;compare:52.199997}

===================================

kmeans begins

kmeans running time=0ms

kmeans ends

print:cluster[0][0]={name:name3;age:3;qz:0.4;compare:28.4}

print:cluster[0][1]={name:name5;age:5;qz:0.4;compare:33.600002}

===================================

print:cluster[1][0]={name:name7;age:7;qz:0.2;compare:14.6}

===================================

print:cluster[2][0]={name:name2;age:2;qz:0.9;compare:57.6}

===================================

print:cluster[3][0]={name:name1;age:1;qz:0.9;compare:48.6}

print:cluster[3][1]={name:name9;age:9;qz:0.9;compare:52.199997}

===================================

print:cluster[4][0]={name:name0;age:0;qz:0.0;compare:0.0}

print:cluster[4][1]={name:name4;age:4;qz:0.0;compare:0.0}

print:cluster[4][2]={name:name6;age:6;qz:0.5;compare:2.0}

print:cluster[4][3]={name:name8;age:8;qz:0.6;compare:5.4}

===================================

4、说明及总结。

1)基类KmeansObject定义了一个compare,我们把它叫做比较因子,分类时只要就是对分类因子进行分类计算的。所以这个分类因子很重要,每个对象的分类因子可以具体的根据业务进行计算设置。比如我们客户端测试代码中的比较因子的计算方法是,首先给每个对象赋予一个权值qz,然后根据权值和年龄的乘积(具体计算方法根据业务定)来对人群进行分类

2)该算法中对于比较因子compare的计算是影响该算法准确性的一个很重要方面,具体表现在距离(distance方法)和误差(errorSquare方法)计算中。想要改善该算法可以从这两个方法中进行修改

3)当然,我对于这个算法的实现和应用都还是很浅。如果有什么不对或者可以改善的地方请不吝赐教

【转】算法——K均值聚类算法(Java实现)

1、用途:聚类算法通常用于数据挖掘,将相似的数组进行聚簇

2、原理:网上比较多,可以百度或者google一下

3、实现:Java代码如下

package org.algorithm;

import java.util.ArrayList;

import java.util.Random;

/**

* K均值聚类算法

*/

public class Kmeans {

private int k;// 分成多少簇

private int m;// 迭代次数

private int dataSetLength;// 数据集元素个数,即数据集的长度

private ArrayList dataSet;// 数据集链表

private ArrayList center;// 中心链表

private ArrayList> cluster; // 簇

private ArrayList jc;// 误差平方和,k越接近dataSetLength,误差越小

private Random random;

/**

* 设置需分组的原始数据集

*

* @param dataSet

*/

public void setDataSet(ArrayList dataSet) {

this.dataSet = dataSet;

}

/**

* 获取结果分组

*

* @return 结果集

*/

public ArrayList> getCluster() {

return cluster;

}

/**

* 构造函数,传入需要分成的簇数量

*

* @param k

*            簇数量,若k

*/

public Kmeans(int k) {

if (k

k = 1;

}

this.k = k;

}

/**

* 初始化

*/

private void init() {

m = 0;

random = new Random();

if (dataSet == null || dataSet.size() == 0) {

initDataSet();

}

dataSetLength = dataSet.size();

if (k > dataSetLength) {

k = dataSetLength;

}

center = initCenters();

cluster = initCluster();

jc = new ArrayList();

}

/**

* 如果调用者未初始化数据集,则采用内部测试数据集

*/

private void initDataSet() {

dataSet = new ArrayList();

// 其中{6,3}是一样的,所以长度为15的数据集分成14簇和15簇的误差都为0

float[][] dataSetArray = new float[][] { { 8, 2 }, { 3, 4 }, { 2, 5 },

{ 4, 2 }, { 7, 3 }, { 6, 2 }, { 4, 7 }, { 6, 3 }, { 5, 3 },

{ 6, 3 }, { 6, 9 }, { 1, 6 }, { 3, 9 }, { 4, 1 }, { 8, 6 } };

for (int i = 0; i

dataSet.add(dataSetArray[i]);

}

}

/**

* 初始化中心数据链表,分成多少簇就有多少个中心点

*

* @return 中心点集

*/

private ArrayList initCenters() {

ArrayList center = new ArrayList();

int[] randoms = new int[k];

boolean flag;

int temp = random.nextInt(dataSetLength);

randoms[0] = temp;

for (int i = 1; i

flag = true;

while (flag) {

temp = random.nextInt(dataSetLength);

int j = 0;

// 不清楚for循环导致j无法加1

// for(j=0;j

// {

// if(temp==randoms[j]);

// {

// break;

// }

// }

while (j

if (temp == randoms[j]) {

break;

}

j++;

}

if (j == i) {

flag = false;

}

}

randoms[i] = temp;

}

// 测试随机数生成情况

// for(int i=0;i

// {

// System.out.println("test1:randoms["+i+"]="+randoms[i]);

// }

// System.out.println();

for (int i = 0; i

center.add(dataSet.get(randoms[i]));// 生成初始化中心链表

}

return center;

}

/**

* 初始化簇集合

*

* @return 一个分为k簇的空数据的簇集合

*/

private ArrayList> initCluster() {

ArrayList> cluster = new ArrayList>();

for (int i = 0; i

cluster.add(new ArrayList());

}

return cluster;

}

/**

* 计算两个点之间的距离

*

* @param element

*            点1

* @param center

*            点2

* @return 距离

*/

private float distance(float[] element, float[] center) {

float distance = 0.0f;

float x = element[0] - center[0];

float y = element[1] - center[1];

float z = x * x + y * y;

distance = (float) Math.sqrt(z);

return distance;

}

/**

* 获取距离集合中最小距离的位置

*

* @param distance

*            距离数组

* @return 最小距离在距离数组中的位置

*/

private int minDistance(float[] distance) {

float minDistance = distance[0];

int minLocation = 0;

for (int i = 1; i

if (distance[i]

minDistance = distance[i];

minLocation = i;

} else if (distance[i] == minDistance) // 如果相等,随机返回一个位置

{

if (random.nextInt(10)

minLocation = i;

}

}

}

return minLocation;

}

/**

* 核心,将当前元素放到最小距离中心相关的簇中

*/

private void clusterSet() {

float[] distance = new float[k];

for (int i = 0; i

for (int j = 0; j

distance[j] = distance(dataSet.get(i), center.get(j));

// System.out.println("test2:"+"dataSet["+i+"],center["+j+"],distance="+distance[j]);

}

int minLocation = minDistance(distance);

// System.out.println("test3:"+"dataSet["+i+"],minLocation="+minLocation);

// System.out.println();

cluster.get(minLocation).add(dataSet.get(i));// 核心,将当前元素放到最小距离中心相关的簇中

}

}

/**

* 求两点误差平方的方法

*

* @param element

*            点1

* @param center

*            点2

* @return 误差平方

*/

private float errorSquare(float[] element, float[] center) {

float x = element[0] - center[0];

float y = element[1] - center[1];

float errSquare = x * x + y * y;

return errSquare;

}

/**

* 计算误差平方和准则函数方法

*/

private void countRule() {

float jcF = 0;

for (int i = 0; i

for (int j = 0; j

jcF += errorSquare(cluster.get(i).get(j), center.get(i));

}

}

jc.add(jcF);

}

/**

* 设置新的簇中心方法

*/

private void setNewCenter() {

for (int i = 0; i

int n = cluster.get(i).size();

if (n != 0) {

float[] newCenter = { 0, 0 };

for (int j = 0; j

newCenter[0] += cluster.get(i).get(j)[0];

newCenter[1] += cluster.get(i).get(j)[1];

}

// 设置一个平均值

newCenter[0] = newCenter[0] / n;

newCenter[1] = newCenter[1] / n;

center.set(i, newCenter);

}

}

}

/**

* 打印数据,测试用

*

* @param dataArray

*            数据集

* @param dataArrayName

*            数据集名称

*/

public void printDataArray(ArrayList dataArray,

String dataArrayName) {

for (int i = 0; i

System.out.println("print:" + dataArrayName + "[" + i + "]={"

+ dataArray.get(i)[0] + "," + dataArray.get(i)[1] + "}");

}

System.out.println("===================================");

}

/**

* Kmeans算法核心过程方法

*/

private void kmeans() {

init();

// printDataArray(dataSet,"initDataSet");

// printDataArray(center,"initCenter");

// 循环分组,直到误差不变为止

while (true) {

clusterSet();

// for(int i=0;i

// {

// printDataArray(cluster.get(i),"cluster["+i+"]");

// }

countRule();

// System.out.println("count:"+"jc["+m+"]="+jc.get(m));

// System.out.println();

// 误差不变了,分组完成

if (m != 0) {

if (jc.get(m) - jc.get(m - 1) == 0) {

break;

}

}

setNewCenter();

// printDataArray(center,"newCenter");

m++;

cluster.clear();

cluster = initCluster();

}

// System.out.println("note:the times of repeat:m="+m);//输出迭代次数

}

/**

* 执行算法

*/

public void execute() {

long startTime = System.currentTimeMillis();

System.out.println("kmeans begins");

kmeans();

long endTime = System.currentTimeMillis();

System.out.println("kmeans running time=" + (endTime - startTime)

+ "ms");

System.out.println("kmeans ends");

System.out.println();

}

}

4、说明:具体代码是从网上找的,根据自己的理解加了注释和进行部分修改,若注释有误还望指正

5、测试

package org.test;

import java.util.ArrayList;

import org.algorithm.Kmeans;

public class KmeansTest {

public  static void main(String[] args)

{

//初始化一个Kmean对象,将k置为10

Kmeans k=new Kmeans(10);

ArrayList dataSet=new ArrayList();

dataSet.add(new float[]{1,2});

dataSet.add(new float[]{3,3});

dataSet.add(new float[]{3,4});

dataSet.add(new float[]{5,6});

dataSet.add(new float[]{8,9});

dataSet.add(new float[]{4,5});

dataSet.add(new float[]{6,4});

dataSet.add(new float[]{3,9});

dataSet.add(new float[]{5,9});

dataSet.add(new float[]{4,2});

dataSet.add(new float[]{1,9});

dataSet.add(new float[]{7,8});

//设置原始数据集

k.setDataSet(dataSet);

//执行算法

k.execute();

//得到聚类结果

ArrayList> cluster=k.getCluster();

//查看结果

for(int i=0;i

{

k.printDataArray(cluster.get(i), "cluster["+i+"]");

}

}

}

6、总结:测试代码已经通过。并对聚类的结果进行了查看,结果基本上符合要求。至于有没有更精确的算法有待发现。具体的实践还有待挖掘

【转】算法——K均值聚类算法扩展应用(Java实现)

1、前面一篇文章算法——K均值聚类算法(Java实现)简单的实现了一下K均值分类算法,这节我们对于他的应用进行一个扩展应用

2、目标为对对象的分类

3、具体实现如下

1)首先建立一个基类KmeansObject,目的为继承该类的子类都可以应用我们的k均值算法进行分类,代码如下

package org.cyxl.util.algorithm;

/**

* 所有使用k均值分类算法的对象都必须继承自该对象

* @author cyxl

* @version 1.0 2012-05-24

* @since 1.0

*

*/

public class KmeansObject {

public float compare; //比较因子

}

2)算法实现,代码如下

package org.cyxl.util.algorithm;

import java.util.ArrayList;

import java.util.Random;

/**

* K均值聚类算法

*/

public class CommonKmeans {

private int k;// 分成多少簇

private int m;// 迭代次数

private int dataSetLength;// 数据集元素个数,即数据集的长度

private ArrayList dataSet;// 数据集链表

private ArrayList center;// 中心链表

private ArrayList> cluster; // 簇

private ArrayList jc;// 误差平方和,k越接近dataSetLength,误差越小

private Random random;

/**

* 设置需分组的原始数据集

*

* @param dataSet

*/

public void setDataSet(ArrayList dataSet) {

this.dataSet = dataSet;

}

/**

* 获取结果分组

*

* @return 结果集

*/

public ArrayList> getCluster() {

return cluster;

}

/**

* 构造函数,传入需要分成的簇数量

*

* @param k

*            簇数量,若k

*/

public CommonKmeans(int k) {

if (k

k = 1;

}

this.k = k;

}

/**

* 初始化

*/

private void init() {

m = 0;

random = new Random();

if (dataSet == null || dataSet.size() == 0) {

initDataSet();

}

dataSetLength = dataSet.size();

if (k > dataSetLength) {

k = dataSetLength;

}

center = initCenters();

cluster = initCluster();

jc = new ArrayList();

}

/**

* 如果调用者未初始化数据集,则采用内部测试数据集

*/

private void initDataSet() {

dataSet = new ArrayList();

for(int i=0;i

{

int temp = random.nextInt(100);

KmeansObject ko=new KmeansObject();

ko.compare=temp;

dataSet.add(ko);

}

}

/**

* 初始化中心数据链表,分成多少簇就有多少个中心点

*

* @return 中心点集

*/

private ArrayList initCenters() {

ArrayList center = new ArrayList();

int[] randoms = new int[k];

boolean flag;

int temp = random.nextInt(dataSetLength);

randoms[0] = temp;

for (int i = 1; i

flag = true;

while (flag) {

temp = random.nextInt(dataSetLength);

int j = 0;

// 不清楚for循环导致j无法加1

// for(j=0;j

// {

// if(temp==randoms[j]);

// {

// break;

// }

// }

while (j

if (temp == randoms[j]) {

break;

}

j++;

}

if (j == i) {

flag = false;

}

}

randoms[i] = temp;

}

for (int i = 0; i

center.add(dataSet.get(randoms[i]));// 生成初始化中心链表

}

return center;

}

/**

* 初始化簇集合

*

* @return 一个分为k簇的空数据的簇集合

*/

private ArrayList> initCluster() {

ArrayList> cluster = new ArrayList>();

for (int i = 0; i

cluster.add(new ArrayList());

}

return cluster;

}

/**

* 计算两个点之间的距离

*

* @param element

*            点1

* @param center

*            点2

* @return 距离

*/

private float distance(KmeansObject element, KmeansObject center) {

float distance = 0.0f;

distance=Math.abs(element.compare-center.compare);

return distance;

}

/**

* 获取距离集合中最小距离的位置

*

* @param distance

*            距离数组

* @return 最小距离在距离数组中的位置

*/

private int minDistance(float[] distance) {

float minDistance = distance[0];

int minLocation = 0;

for (int i = 1; i

if (distance[i]

minDistance = distance[i];

minLocation = i;

} else if (distance[i] == minDistance) // 如果相等,随机返回一个位置

{

if (random.nextInt(10)

minLocation = i;

}

}

}

return minLocation;

}

/**

* 核心,将当前元素放到最小距离中心相关的簇中

*/

private void clusterSet() {

float[] distance = new float[k];

for (int i = 0; i

for (int j = 0; j

distance[j] = distance(dataSet.get(i), center.get(j));

}

int minLocation = minDistance(distance);

cluster.get(minLocation).add(dataSet.get(i));// 核心,将当前元素放到最小距离中心相关的簇中

}

}

/**

* 求两点误差平方的方法

*

* @param element

*            点1

* @param center

*            点2

* @return 误差平方

*/

private float errorSquare(KmeansObject element, KmeansObject center) {

float x = Math.abs(element.compare-center.compare);

float errSquare = x * x;

return errSquare;

}

/**

* 计算误差平方和准则函数方法

*/

private void countRule() {

float jcF = 0;

for (int i = 0; i

for (int j = 0; j

jcF += errorSquare(cluster.get(i).get(j), center.get(i));

}

}

jc.add(jcF);

}

/**

* 设置新的簇中心方法

*/

private void setNewCenter() {

for (int i = 0; i

int n = cluster.get(i).size();

if (n != 0) {

KmeansObject newCenter = new KmeansObject();

for (int j = 0; j

newCenter.compare += cluster.get(i).get(j).compare;

}

// 设置一个平均值

newCenter.compare=newCenter.compare/n;

center.set(i, newCenter);

}

}

}

/**

* 打印数据,测试用

*

* @param dataArray

*            数据集

* @param dataArrayName

*            数据集名称

*/

public void printDataArray(ArrayList dataArray,

String dataArrayName) {

for (int i = 0; i

System.out.println("print:" + dataArrayName + "[" + i + "]={"

+ dataArray.get(i) + "}");

}

System.out.println("===================================");

}

/**

* Kmeans算法核心过程方法

*/

private void kmeans() {

init();

// 循环分组,直到误差不变为止

while (true) {

clusterSet();

countRule();

// 误差不变了,分组完成

if (m != 0) {

if (jc.get(m) - jc.get(m - 1) == 0) {

break;

}

}

setNewCenter();

m++;

cluster.clear();

cluster = initCluster();

}

}

/**

* 执行算法

*/

public void execute() {

long startTime = System.currentTimeMillis();

System.out.println("kmeans begins");

kmeans();

long endTime = System.currentTimeMillis();

System.out.println("kmeans running time=" + (endTime - startTime)

+ "ms");

System.out.println("kmeans ends");

System.out.println();

}

}

3)测试算法,首先建立一个Person类,目标在于对人进行分类

package org.cyxl.util.algorithm;

public class Person extends KmeansObject {

String name="";

int age=0;

float qz=1; //权重

public Person(){}

public Person(String name,int age,float qz)

{

this.name=name;

this.age=age;

this.qz=qz;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public float getQz() {

return qz;

}

public void setQz(float qz) {

this.qz = qz;

}

public String toString()

{

return "name:"+this.name+";age:"+this.age+";qz:"+this.qz+";compare:"+super.compare;

}

}

4)客户端测试代码

CommonKmeans k=new CommonKmeans(5);

ArrayList list=new ArrayList();

for(int i=0;i

{

float qz=(float)(new Random().nextInt(10))/10;

Person p=new Person("name"+i,i,qz);

p.compare=new Random().nextInt(100)*p.getQz();

list.add(p);

}

k.setDataSet(list);

k.printDataArray(k.dataSet, "before");

k.execute();

ArrayList> cluster=k.getCluster();

//查看结果

for(int i=0;i

{

k.printDataArray(cluster.get(i), "cluster["+i+"]");

}

5)输出结果

print:before[0]={name:name0;age:0;qz:0.0;compare:0.0}

print:before[1]={name:name1;age:1;qz:0.9;compare:48.6}

print:before[2]={name:name2;age:2;qz:0.9;compare:57.6}

print:before[3]={name:name3;age:3;qz:0.4;compare:28.4}

print:before[4]={name:name4;age:4;qz:0.0;compare:0.0}

print:before[5]={name:name5;age:5;qz:0.4;compare:33.600002}

print:before[6]={name:name6;age:6;qz:0.5;compare:2.0}

print:before[7]={name:name7;age:7;qz:0.2;compare:14.6}

print:before[8]={name:name8;age:8;qz:0.6;compare:5.4}

print:before[9]={name:name9;age:9;qz:0.9;compare:52.199997}

===================================

kmeans begins

kmeans running time=0ms

kmeans ends

print:cluster[0][0]={name:name3;age:3;qz:0.4;compare:28.4}

print:cluster[0][1]={name:name5;age:5;qz:0.4;compare:33.600002}

===================================

print:cluster[1][0]={name:name7;age:7;qz:0.2;compare:14.6}

===================================

print:cluster[2][0]={name:name2;age:2;qz:0.9;compare:57.6}

===================================

print:cluster[3][0]={name:name1;age:1;qz:0.9;compare:48.6}

print:cluster[3][1]={name:name9;age:9;qz:0.9;compare:52.199997}

===================================

print:cluster[4][0]={name:name0;age:0;qz:0.0;compare:0.0}

print:cluster[4][1]={name:name4;age:4;qz:0.0;compare:0.0}

print:cluster[4][2]={name:name6;age:6;qz:0.5;compare:2.0}

print:cluster[4][3]={name:name8;age:8;qz:0.6;compare:5.4}

===================================

4、说明及总结。

1)基类KmeansObject定义了一个compare,我们把它叫做比较因子,分类时只要就是对分类因子进行分类计算的。所以这个分类因子很重要,每个对象的分类因子可以具体的根据业务进行计算设置。比如我们客户端测试代码中的比较因子的计算方法是,首先给每个对象赋予一个权值qz,然后根据权值和年龄的乘积(具体计算方法根据业务定)来对人群进行分类

2)该算法中对于比较因子compare的计算是影响该算法准确性的一个很重要方面,具体表现在距离(distance方法)和误差(errorSquare方法)计算中。想要改善该算法可以从这两个方法中进行修改

3)当然,我对于这个算法的实现和应用都还是很浅。如果有什么不对或者可以改善的地方请不吝赐教


相关文章

  • 算法--K均值聚类算法扩展应用(Java实现)
  • 1.前面一篇文章算法--K均值聚类算法(Java实现)简单的实现了一下K均值分类算法,这节我们对于他的应用进行一个扩展应用 2.目标为对对象的分类 3.具体实现如下 1)首先建立一个基类KmeansObject,目的为继承该类的子类都可以应 ...查看


  • K-means算法的Java实现 聚类分析681个三国武将
  • 一,k-means算法介绍: k-means算法接受输入量 k :然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高:而不同聚类中的对象相似度较小.聚类相似度是利用各聚类中对象的均值所获得一个" ...查看


  • 数据挖掘聚类算法课程设计报告
  • 数据挖掘聚类问题(Plants Data Set)实验报告 1. 数据源描述 1.1数据特征 本实验用到的是关于植物信息的数据集,其中包含了每一种植物(种类和科属) 以及它们生长的地区.数据集中总共有68个地区,主要分布在美国和加拿大.一条 ...查看


  • 7网络与信息安全课程设计报告
  • <网络与信息安全>课程设计报告班级:07网络工程(3)班学号:[1**********]8姓名:韩立伟 题目: 评阅:加密软件的设计 成绩: 2010-1-07 RSA算法加密软件的设计 摘要:分析RSA算法的应用现状,论证文件 ...查看


  • 蚁群优化算法的JAVA实现
  • 蚁群优化算法的JAVA实现 一.蚁群算法简介 蚁群算法是群智能算法的一种,所谓的群智能是一种由无智能或简单智能的个体通过任何形式的聚集协同而表现出智能行为,它为在没有集中控制且不提供全局模型的前提下寻找复杂的分布式问题求解方案提供了基础,比 ...查看


  • 基于本体的案例推理模型研究
  • 第26卷第4期2009年4月 计算机应用研究 ApplicationResearchofComputers V01.26No.4 Apr.2009 基于本体的案例推理模型研究 谢红薇,李建伟 (太原理工大学计算机与软件学院,太原030024 ...查看


  • 历年程序员试题真题档(3)
  • 2007年下半年 程序员 上午试卷 ● 在Word编辑状态下,有些英文单词和汉字下面会自动加上红色或绿色的波浪型细下划线.以下叙述中,"波浪型细下划线 (1) "是错误的:按 (2) 键与工具栏上的按钮功能相同. (1) ...查看


  • 数据结构课程设计 马踏棋盘
  • 学习数据结构的最终目的是解决实际的应用问题,特别是非数值计算类型的应用问题,数据结构课程设计就是为此目的一次实际训练.要求我们在对题目进行独立分析的基础上,完成设计和开发,并最终接受严格的测试考核.以深化对数据结构课程中基本概念.理论和方法 ...查看


  • 09级计科专业毕业设计题目
  • 09级计算机科学与技术专业毕业设计题目指南 说明:1. 每个题目的选择人数最多不能超过2名同学,否则将退回重选.(如题目要求可多 人合作,则以题目要求为准),请各班级同学自行协调解决选题冲突问题. 2.学习委员上报题目请用EXCEL 表格, ...查看


热门内容