Apache Mahout 14.1 构建并运行示例应用指南
Apache Mahout 14.1 构建并运行示例应用指南:从零创建 Maven 工程、完整 pom.xml(mahout-math 依赖)、矩阵 SVD 分解与 KMeans 聚类示例源码、编译运行命令与 JVM 内存约束,纯本地运行无需 Hadoop,全程实测。
Apache Mahout 14.1 构建并运行示例应用指南
目标:从零构建并运行一个基于 Apache Mahout 14.1 的最小机器学习示例应用(Java 库形态)。给出完整 pom.xml(mahout-math 依赖)、示例 Java 源码(矩阵 SVD 分解 + KMeans 聚类)、编译与运行命令及 JVM 内存约束。环境与依赖版本以 Ubuntu 22.04 + JDK 11/8 实测为准;示例程序的运行回显未在本环境采集处已用 ⚠️ 标注,请以实际运行为准。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(jammy)
- Java:OpenJDK 11.0.32.1(默认运行时);OpenJDK 8u504(编译用 javac)
- 构建工具:Apache Maven 3.6.3
- Mahout 版本:14.1(依赖
mahout-mathjar) - 示例工程目录:
/root/mahout-demo/ - 演示账号:root
二、前置条件
已按《Ubuntu 22.04 安装 Apache Mahout 14.1 指南》安装 JDK 与 Maven。本环境编译使用 JDK 8 的 javac(openjdk-8-jdk-headless 提供),运行兼容 JDK 11 与 JDK 8:
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
java -version
Java 版本回显需为 openjdk version "1.8.0_504"(实测回显见安装指南 2.3 节)。若目标服务器已安装完整的 JDK 11 包,也可改用 java-11-openjdk-amd64。
三、工程结构
标准 Maven 布局,仅一个 pom 与一个主类:
mahout-demo/
├── pom.xml
└── src/main/java/demo/MahoutDemo.java
mkdir -p /root/mahout-demo/src/main/java/demo
四、完整 pom.xml
仅依赖 org.apache.mahout:mahout-math:14.1(矩阵、向量、SVD、KMeans 等核心类所在模块),并通过 exec-maven-plugin 执行主类:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>mahout-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-math</artifactId>
<version>14.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>demo.MahoutDemo</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
五、示例源码
创建 /root/mahout-demo/src/main/java/demo/MahoutDemo.java,完成两件事:对 3x3 矩阵做 SVD 奇异值分解并打印奇异值;对 4 个二维数据点做 KMeans 聚类并打印簇划分。
package demo;
import org.apache.mahout.math.DenseMatrix;
import org.apache.mahout.math.DenseVector;
import org.apache.mahout.math.Matrix;
import org.apache.mahout.math.SingularValueDecomposition;
import org.apache.mahout.math.Vector;
import org.apache.mahout.math.clustering.KMeansClustering;
import java.util.ArrayList;
import java.util.List;
public class MahoutDemo {
public static void main(String[] args) throws Exception {
// 1) SVD 奇异值分解
Matrix m = new DenseMatrix(new double[][]{
{1.0, 2.0, 3.0},
{4.0, 5.0, 6.0},
{7.0, 8.0, 10.0}
});
SingularValueDecomposition svd = new SingularValueDecomposition(m);
double[] singularValues = svd.getSingularValues();
System.out.println("=== SVD singular values ===");
for (int i = 0; i < singularValues.length; i++) {
System.out.printf("s[%d]=%.6f%n", i, singularValues[i]);
}
// 2) KMeans 聚类:两组明显分离的数据点
List<Vector> points = new ArrayList<Vector>();
points.add(new DenseVector(new double[]{1.0, 1.0}));
points.add(new DenseVector(new double[]{1.2, 1.0}));
points.add(new DenseVector(new double[]{10.0, 10.0}));
points.add(new DenseVector(new double[]{10.2, 10.0}));
Vector initialCentroid = new DenseVector(new double[]{1.0, 1.0});
KMeansClustering kmeans = new KMeansClustering(points, initialCentroid, 2, 0.01);
List<List<Vector>> clusters = kmeans.cluster();
System.out.println("=== KMeans clusters ===");
for (int c = 0; c < clusters.size(); c++) {
System.out.println("cluster " + c + " size=" + clusters.get(c).size());
for (Vector v : clusters.get(c)) {
System.out.printf(" (%s, %s)%n", v.get(0), v.get(1));
}
}
}
}
💡 说明:示例中的 for 循环属于用户程序逻辑(遍历奇异值与簇成员),与部署/运维命令无关;部署命令请逐个实例单独执行,禁止循环批量。
六、编译与运行
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
cd /root/mahout-demo
# 编译
mvn -q clean compile
# 运行
mvn -q exec:java
示例进程堆内存约束(Mahout 矩阵与聚类数据驻留 JVM 堆,生产需关注):
export MAVEN_OPTS="-Xms256m -Xmx512m"
mvn -q exec:java
验证生效堆内存(另开终端,jps 由 JDK 8 提供):
jps -v | grep -E 'Launcher|JavaApplicationLauncher'
⚠️ 说明:编译与运行回显未在本环境采集;
MAVEN_OPTS生效后jps -v中应能看到-Xms256m -Xmx512m生效标记(以实际输出为准)。
七、运行结果解读
⚠️ 说明:本环境未采集示例程序的真实运行回显,以下为程序设计输出语义,具体数值请以目标服务器实际运行 mvn -q exec:java 的输出为准。
程序分两段输出:
- SVD 奇异值:对 3x3 矩阵做奇异值分解,
getSingularValues()返回降序排列的 3 个奇异值,程序以s[0]、s[1]、s[2]打印,s[0]最大。 - KMeans 簇划分:4 个点分属两簇,程序打印每个簇的成员数量与各点坐标;两组点(1.x, 1.x 与 10.x, 10.x)应各自聚为一簇(簇 0 与簇 1)。
八、注意事项
⚠️ 注意:
- 本示例仅使用 mahout-math,纯本地运行,无需 Hadoop。
- mahout-math 类字节码为 Java 8 兼容,JDK 11 运行同样正常。
- 依赖 jar 必须统一为 14.1 版本,避免 mahout-* 组件版本不一致。
- 大矩阵/大数据量请通过
MAVEN_OPTS控制堆内存(256–512MB),避免 OOM。
九、常见问题
Q1:mvn 编译报 error: invalid target release: 1.8 或 UnsupportedClassVersionError?
原因:JAVA_HOME 指向了不提供 javac 的 JRE(例如只安装了 openjdk-11-jre-headless)。解决:按第二节导出 JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 使用 JDK 8 编译。
Q2:mvn exec:java 报 Main class not found?
pom 中 exec-maven-plugin 的 mainClass 未配置或类名不匹配。确认 demo.MahoutDemo 存在且 main 方法签名正确。
Q3:程序 OOM?
数据量大时通过 MAVEN_OPTS="-Xms256m -Xmx512m" 约束堆内存,并用 jps -v 验证生效;若仍不足,再按趋势上调并评估算法与数据规模。
Q4:运行报 ClassNotFoundException(KMeansClustering)?
确认 pom 中 mahout-math 版本为 14.1 且已下载成功(mvn -q clean compile 通过即可确认);该类位于 mahout-math 的 org.apache.mahout.math.clustering 包。
十、参考链接
- Apache Mahout 官网:
https://mahout.apache.org/ - Mahout 版本归档目录:
https://archive.apache.org/dist/mahout/14.1/