让我来详细讲解“K均值聚类算法的Java版实现代码示例”的完整攻略。
1. K均值聚类算法简介
K均值聚类算法是一种常用的无监督机器学习算法,常用于数据挖掘、图像分割以及客户分类等场景中。它的基本原理是:将n个数据点划分成k个簇,使得每个点都属于其最近的中心点所在的簇,这些中心点是通过簇内点的平均值计算而得。
2. Java代码示例说明
对于Java程序员来说,实现K均值聚类算法可能并不容易,因此我们来看一下下面的Java代码示例说明。
2.1 示例一
public class KMeans {
public static void main(String[] args) {
int k = 3; // 设置簇的数目
double[][] data = {{1.0, 1.0}, {1.5, 2.0}, {3.0, 4.0}, {5.0, 7.0}, {3.5, 5.0}, {4.5, 5.0}, {3.5, 4.5}}; // 将数据划分成2个簇
int[] labels = cluster(data, k); // 聚类操作
for (int i = 0; i < labels.length; i++) {
System.out.println(Arrays.toString(data[i]) + " belongs to cluster " + labels[i]);
}
}
public static int[] cluster(double[][] data, int k) {
int n = data.length;
int[] labels = new int[n];
boolean changed = true;
int[] centers = new int[k];
for (int i = 0; i < k; i++) {
centers[i] = (int) (Math.random() * n); // 随机生成聚类中心
}
while (changed) {
changed = false;
for (int i = 0; i < n; i++) {
double minDist = Double.MAX_VALUE;
for (int j = 0; j < k; j++) {
double dist = getDist(data[i], data[centers[j]]); // 计算数据点距离各聚类中心的距离
if (dist < minDist) {
labels[i] = j;
minDist = dist;
}
}
}
for (int j = 0; j < k; j++) {
double[] newCenter = new double[data[0].length];
int count = 0;
for (int i = 0; i < n; i++) {
if (labels[i] == j) {
for (int d = 0; d < newCenter.length; d++) {
newCenter[d] += data[i][d];
}
count++;
}
}
for (int d = 0; d < newCenter.length; d++) {
newCenter[d] /= count; // 更新聚类中心
}
if (getDist(data[centers[j]], newCenter) > 0.0001) {
changed = true;
}
centers[j] = findNearest(newCenter, data); // 找到数据中最近的点作为新的聚类中心
}
}
return labels;
}
private static double getDist(double[] a, double[] b) {
double dist = 0.0;
for (int i = 0; i < a.length; i++) {
dist += (a[i] - b[i]) * (a[i] - b[i]);
}
return Math.sqrt(dist);
}
private static int findNearest(double[] center, double[][] data) {
int index = 0;
double minDist = Double.MAX_VALUE;
for (int i = 0; i < data.length; i++) {
double dist = getDist(center, data[i]);
if (dist < minDist) {
index = i;
minDist = dist;
}
}
return index;
}
}
代码解析:
该示例中,我们首先定义了一个KMeans类,其中包含了聚类方法cluster、计算两点距离的方法getDist,以及找到离给定点最近的点的方法findNearest等。在main方法中我们设置数据点数目和簇的数目,然后调用cluster方法进行聚类操作。在聚类结束后,我们将每个数据点的标签以及对应的簇打印出来。
2.2 示例二
下面是一个更为完整的Java代码示例:
import java.util.ArrayList;
import java.util.List;
public class KMeans {
private final int k;
private final int maxIter;
private final List<double[]> data;
private final List<c> centers;
public KMeans(int k, int maxIter, List<double[]> data) {
this.k = k;
this.maxIter = maxIter;
this.data = data;
this.centers = new ArrayList<>();
}
public void run() {
initialCenters();
for (int i = 0; i < maxIter; i++) {
cluster();
updateCenter();
}
}
private void initialCenters() {
for (int i = 0; i < k; i++) {
centers.add(new c(data.get(i)));
}
}
private void cluster() {
for (double[] point : data) {
c nearestCenter = null;
double minDist = Double.MAX_VALUE;
for (c center : centers) {
double dist = center.dist(point);
if (dist < minDist) {
nearestCenter = center;
minDist = dist;
}
}
nearestCenter.addPoint(point);
}
}
private void updateCenter() {
for (c center : centers) {
center.update();
}
}
private static class c {
private final double[] center;
private final List<double[]> points;
public c(double[] center) {
this.center = center;
this.points = new ArrayList<>();
}
public void addPoint(double[] point) {
points.add(point);
}
public void update() {
for (int i = 0; i < center.length; i++) {
double sum = 0.0;
for (double[] point : points) {
sum += point[i];
}
if (points.size() > 0) {
center[i] = sum / points.size();
}
}
}
public double dist(double[] point) {
double dist = 0.0;
for (int i = 0; i < center.length; i++) {
dist += (center[i] - point[i]) * (center[i] - point[i]);
}
return Math.sqrt(dist);
}
}
public static void main(String[] args) {
List<double[]> data = new ArrayList<>();
data.add(new double[]{1.0, 1.0});
data.add(new double[]{1.5, 2.0});
data.add(new double[]{3.0, 4.0});
data.add(new double[]{5.0, 7.0});
data.add(new double[]{3.5, 5.0});
data.add(new double[]{4.5, 5.0});
data.add(new double[]{3.5, 4.5});
KMeans kMeans = new KMeans(2, 10, data);
kMeans.run();
for (int i = 0; i < kMeans.centers.size(); i++) {
System.out.println("Cluster " + (i + 1) + ": " + kMeans.centers.get(i));
}
}
}
代码解析:
在该示例中,我们首先定义了一个KMeans类,其中包含了计算两点距离的方法dist,以及代表中心点的类c。在main方法中我们设置数据点数目和簇的数目,然后调用KMeans类进行聚类操作。在聚类结束后,我们将每个簇的中心坐标打印出来。
3. 总结
综上所述,K均值聚类算法的Java版实现并不复杂,而且在Java中也有很多现成的工具库可以供我们使用,例如Apache Mahout、Weka等。但是为了更好地理解该算法的原理和实现思路,我们还是需要亲自动手写一下。
通过本文的讲解,我相信你已经对K均值聚类算法的Java版实现有了更深入的了解,希望对你有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:K均值聚类算法的Java版实现代码示例 - Python技术站