请用Java 实现聚类分析K-means算法
时间: 2023-11-16 22:08:01 浏览: 98
好的,以下是Java实现聚类分析K-means算法的示例代码:
```
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class KMeans {
private int k; // 聚类数
private int maxIter; // 最大迭代次数
private List<double[]> dataSet; // 数据集
private List<double[]> centroids; // 质心集合
public KMeans(int k, int maxIter, List<double[]> dataSet) {
this.k = k;
this.maxIter = maxIter;
this.dataSet = dataSet;
this.centroids = initCentroids();
}
// 初始化质心集合
private List<double[]> initCentroids() {
List<double[]> centroids = new ArrayList<>();
int dataSetSize = dataSet.size();
Random random = new Random();
for (int i = 0; i < k; i++) {
int randomIndex = random.nextInt(dataSetSize);
centroids.add(dataSet.get(randomIndex));
}
return centroids;
}
// 计算两个向量之间的距离
private double distance(double[] vec1, double[] vec2) {
double sum = 0;
for (int i = 0; i < vec1.length; i++) {
sum += Math.pow(vec1[i] - vec2[i], 2);
}
return Math.sqrt(sum);
}
// 将数据点分配到最近的质心
private int assignCluster(double[] dataPoint) {
int clusterIndex = -1;
double minDistance = Double.MAX_VALUE;
for (int i = 0; i < k; i++) {
double distance = distance(dataPoint, centroids.get(i));
if (distance < minDistance) {
minDistance = distance;
clusterIndex = i;
}
}
return clusterIndex;
}
// 更新质心
private void updateCentroids(List<List<double[]>> clusters) {
for (int i = 0; i < k; i++) {
double[] newCentroid = new double[dataSet.get(0).length];
for (double[] dataPoint : clusters.get(i)) {
for (int j = 0; j < dataPoint.length; j++) {
newCentroid[j] += dataPoint[j];
}
}
for (int j = 0; j < newCentroid.length; j++) {
newCentroid[j] /= clusters.get(i).size();
}
centroids.set(i, newCentroid);
}
}
// 聚类分析
public List<List<double[]>> cluster() {
List<List<double[]>> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(new ArrayList<>());
}
for (int iter = 0; iter < maxIter; iter++) {
// 分配数据点到最近的质心
for (double[] dataPoint : dataSet) {
int clusterIndex = assignCluster(dataPoint);
clusters.get(clusterIndex).add(dataPoint);
}
// 更新质心
updateCentroids(clusters);
// 清空聚类
for (int i = 0; i < k; i++) {
clusters.get(i).clear();
}
}
return clusters;
}
}
```
这段代码实现了K-means算法的核心部分,其中:
- `k`是聚类数,表示要将数据集分成多少类;
- `maxIter`是最大迭代次数,表示K-means算法的最大执行次数;
- `dataSet`是数据集,包含多个数据点,每个数据点是一个double类型数组;
- `centroids`是质心集合,表示每一类的质心,一开始随机初始化;
- `initCentroids`方法随机初始化质心集合;
- `distance`方法计算两个向量之间的距离;
- `assignCluster`方法将数据点分配到最近的质心;
- `updateCentroids`方法更新质心;
- `cluster`方法执行K-means算法,返回聚类结果,即每一类的数据点集合。
使用示例:
```
public static void main(String[] args) {
// 构造数据集
List<double[]> dataSet = new ArrayList<>();
dataSet.add(new double[]{1, 1});
dataSet.add(new double[]{1, 2});
dataSet.add(new double[]{2, 1});
dataSet.add(new double[]{2, 2});
dataSet.add(new double[]{5, 5});
dataSet.add(new double[]{5, 6});
dataSet.add(new double[]{6, 5});
dataSet.add(new double[]{6, 6});
// 执行K-means算法
KMeans kMeans = new KMeans(2, 100, dataSet);
List<List<double[]>> clusters = kMeans.cluster();
// 输出聚类结果
for (int i = 0; i < clusters.size(); i++) {
System.out.println("Cluster " + i + ":");
for (double[] dataPoint : clusters.get(i)) {
System.out.println(Arrays.toString(dataPoint));
}
}
}
```
这个示例将数据集分成了两类,输出的聚类结果如下:
```
Cluster 0:
[1.0, 1.0]
[1.0, 2.0]
[2.0, 1.0]
[2.0, 2.0]
Cluster 1:
[5.0, 5.0]
[5.0, 6.0]
[6.0, 5.0]
[6.0, 6.0]
```
这个结果比较符合我们的预期,将数据集分为了两个簇,一个簇包含了前四个数据点,另一个簇包含了后四个数据点。
阅读全文