Java分布式数据聚类API怎么KMeans

wen java案例 4

本文目录导读:

Java分布式数据聚类API怎么KMeans

  1. 使用Apache Spark MLlib(推荐)
  2. 使用Apache Mahout(早已成熟)
  3. 自定义分布式KMeans(基于MapReduce)
  4. 性能优化建议
  5. 适用场景对比

在Java中实现分布式KMeans聚类,通常有两种主要方式:

使用Apache Spark MLlib(推荐)

Spark提供了开箱即用的分布式KMeans实现:

import org.apache.spark.ml.clustering.KMeans;
import org.apache.spark.ml.clustering.KMeansModel;
import org.apache.spark.ml.evaluation.ClusteringEvaluator;
import org.apache.spark.ml.linalg.Vectors;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
public class SparkKMeansExample {
    public static void main(String[] args) {
        // 1. 创建SparkSession
        SparkSession spark = SparkSession.builder()
                .appName("KMeansExample")
                .master("local[*]")  // 分布式部署时改为yarn/mesos等
                .getOrCreate();
        // 2. 准备数据(示例数据)
        Dataset<Row> dataset = spark.createDataFrame(
            Arrays.asList(
                RowFactory.create(Vectors.dense(0.0, 0.0)),
                RowFactory.create(Vectors.dense(1.0, 1.0)),
                RowFactory.create(Vectors.dense(9.0, 8.0)),
                RowFactory.create(Vectors.dense(8.0, 9.0)),
                RowFactory.create(Vectors.dense(5.0, 5.0))
            ),
            new StructType()
                .add("features", new VectorUDT(), false)
        );
        // 3. 训练KMeans模型
        KMeans kmeans = new KMeans()
                .setK(2)
                .setSeed(1L)
                .setMaxIter(20)
                .setFeaturesCol("features")
                .setPredictionCol("prediction");
        KMeansModel model = kmeans.fit(dataset);
        // 4. 评估模型(轮廓系数)
        Dataset<Row> predictions = model.transform(dataset);
        ClusteringEvaluator evaluator = new ClusteringEvaluator();
        double silhouette = evaluator.evaluate(predictions);
        System.out.println("轮廓系数: " + silhouette);
        // 5. 获取聚类中心
        Vector[] centers = model.clusterCenters();
        System.out.println("聚类中心:");
        for (Vector center : centers) {
            System.out.println(center);
        }
        // 6. 预测新数据
        Vector newPoint = Vectors.dense(0.5, 0.5);
        int cluster = model.predict(newPoint);
        System.out.println("点 " + newPoint + " 属于簇: " + cluster);
        spark.stop();
    }
}

Maven依赖:

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-mllib_2.12</artifactId>
    <version>3.4.0</version>
</dependency>

使用Apache Mahout(早已成熟)

Mahout与Hadoop集成,适合大规模数据:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.mahout.clustering.kmeans.KMeansDriver;
import org.apache.mahout.clustering.kmeans.Kluster;
import org.apache.mahout.common.distance.EuclideanDistanceMeasure;
import org.apache.mahout.math.VectorWritable;
public class MahoutKMeansExample {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        // 设置输入输出路径
        Path input = new Path("hdfs://localhost:9000/input/data");
        Path clusters = new Path("hdfs://localhost:9000/clusters");
        Path output = new Path("hdfs://localhost:9000/output");
        // 运行KMeans
        KMeansDriver.run(conf, input, clusters, output,
            new EuclideanDistanceMeasure(),  // 距离度量
            0.001,  // 收敛阈值
            10,     // 最大迭代次数
            true,   // 是否聚类
            0.0,    // 聚类中心阈值
            false); // 是否运行在本地
    }
}

自定义分布式KMeans(基于MapReduce)

import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.*;
import org.apache.hadoop.mapreduce.lib.output.*;
// Mapper类
public class KMeansMapper extends Mapper<LongWritable, Text, IntWritable, Text> {
    private List<Vector> centers = new ArrayList<>();
    @Override
    protected void setup(Context context) {
        // 从分布式缓存读取聚类中心
        // 初始化centers列表
    }
    @Override
    protected void map(LongWritable key, Text value, Context context) {
        // 1. 解析数据点
        Vector point = parsePoint(value.toString());
        // 2. 找到最近的聚类中心
        int nearestCenter = findNearestCenter(point, centers);
        // 3. 输出:中心索引和点向量
        context.write(new IntWritable(nearestCenter), 
                     new Text(point.toString()));
    }
}
// Reducer类
public class KMeansReducer extends Reducer<IntWritable, Text, IntWritable, Text> {
    @Override
    protected void reduce(IntWritable key, Iterable<Text> values, Context context) {
        // 1. 计算新的聚类中心(所有点的平均值)
        Vector sum = new DenseVector();
        int count = 0;
        for (Text value : values) {
            Vector point = parsePoint(value.toString());
            sum = sum.plus(point);
            count++;
        }
        Vector newCenter = sum.divide(count);
        // 2. 输出新的聚类中心
        context.write(key, new Text(newCenter.toString()));
    }
}
// Driver类
public class DistributedKMeansDriver {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "Distributed KMeans");
        job.setJarByClass(DistributedKMeansDriver.class);
        job.setMapperClass(KMeansMapper.class);
        job.setReducerClass(KMeansReducer.class);
        job.setOutputKeyClass(IntWritable.class);
        job.setOutputValueClass(Text.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        // 迭代执行直到收敛
        int iteration = 0;
        do {
            System.exit(job.waitForCompletion(true) ? 0 : 1);
            // 更新聚类中心
            // 检查是否收敛
            iteration++;
        } while (iteration < MAX_ITERATIONS && !converged);
    }
}

性能优化建议

  1. 数据分区:合理设置分区数(通常是集群CPU核心数的2-3倍)
// Spark分区优化
dataset.repartition(100); // 显式设置分区数
  1. 缓存中间结果

    Dataset<Row> cachedData = dataset.cache();
    // 或
    dataset.persist(StorageLevel.MEMORY_AND_DISK());
  2. 选择合适的K值

    // 使用肘部法则选择K
    double[] costs = new double[10];
    for (int k = 2; k <= 10; k++) {
     KMeans kmeans = new KMeans().setK(k);
     KMeansModel model = kmeans.fit(dataset);
     costs[k-2] = model.computeCost(dataset);
    }
  3. 并行度设置

    spark.conf().set("spark.sql.shuffle.partitions", "200");

适用场景对比

方案 适合场景 优势 劣势
Spark MLlib 大数据(GB-TB级) 内存计算,速度快,易用 需要Spark集群
Mahout 超大数据(TB+) 成熟稳定,支持Hadoop 配置复杂,较慢
自定义MR 学习/定制化需求 完全可控 开发工作量大

对于大多数生产环境,推荐使用Spark MLlib,它提供了最平衡的性能、易用性和功能完整性。

抱歉,评论功能暂时关闭!