在当今数据驱动的世界中,Rust聚类算法正变得越来越重要。Rust作为一种内存安全、高性能的系统编程语言,不仅适用于底层开发,也能胜任Rust机器学习任务。本教程将手把手教你如何用Rust从零实现经典的k-means聚类算法,即使你是编程新手也能轻松上手!
聚类是一种Rust无监督学习技术,它将相似的数据点分组到同一簇中,而不依赖于预先标记的类别。k-means是最常用的聚类算法之一,其目标是将数据划分为k个簇,使得每个数据点到其所属簇中心的距离之和最小。
首先,确保你已安装Rust。如果尚未安装,请访问 Rust官网 并按照说明安装。
创建一个新的Rust项目:
cargo new rust_kmeanscd rust_kmeans 我们首先定义表示二维数据点和聚类中心的结构体:
// src/main.rs#[derive(Debug, Clone, Copy)]pub struct Point { pub x: f64, pub y: f64,}impl Point { // 计算两点之间的欧氏距离 pub fn distance_to(&self, other: &Point) -> f64 { let dx = self.x - other.x; let dy = self.y - other.y; (dx * dx + dy * dy).sqrt() }} 接下来,我们实现核心的k-means逻辑。算法步骤如下:
use rand::Rng;use std::collections::HashMap;pub struct KMeans { k: usize, max_iters: usize, centroids: Vec<Point>,}impl KMeans { pub fn new(k: usize, max_iters: usize) -> Self { Self { k, max_iters, centroids: Vec::new(), } } pub fn fit(&mut self, data: &[Point]) { // 随机初始化聚类中心 let mut rng = rand::thread_rng(); self.centroids = (0..self.k) .map(|_| { let x = rng.gen_range(data.iter().map(|p| p.x).fold(f64::INFINITY, f64::min)..=data.iter().map(|p| p.x).fold(f64::NEG_INFINITY, f64::max)); let y = rng.gen_range(data.iter().map(|p| p.y).fold(f64::INFINITY, f64::min)..=data.iter().map(|p| p.y).fold(f64::NEG_INFINITY, f64::max)); Point { x, y } }) .collect(); for _ in 0..self.max_iters { // 分配数据点到最近的聚类中心 let mut clusters: HashMap<usize, Vec<Point>> = HashMap::new(); for point in data { let mut min_dist = f64::INFINITY; let mut closest_centroid = 0; for (i, centroid) in self.centroids.iter().enumerate() { let dist = point.distance_to(centroid); if dist < min_dist { min_dist = dist; closest_centroid = i; } } clusters.entry(closest_centroid).or_default().push(*point); } // 更新聚类中心 let mut new_centroids = Vec::with_capacity(self.k); for i in 0..self.k { if let Some(cluster) = clusters.get(&i) { let sum_x: f64 = cluster.iter().map(|p| p.x).sum(); let sum_y: f64 = cluster.iter().map(|p| p.y).sum(); let count = cluster.len() as f64; new_centroids.push(Point { x: sum_x / count, y: sum_y / count, }); } else { // 如果簇为空,保留旧中心 new_centroids.push(self.centroids[i]); } } self.centroids = new_centroids; } } pub fn predict(&self, point: &Point) -> usize { self.centroids .iter() .enumerate() .min_by(|(_, a), (_, b)| point.distance_to(a).partial_cmp(&point.distance_to(b)).unwrap()) .map(|(i, _)| i) .unwrap() } pub fn centroids(&self) -> &[Point] { &self.centroids }} 在 Cargo.toml 中添加 rand 依赖:
[dependencies]rand = "0.8" 然后在 main 函数中测试我们的实现:
fn main() { // 创建示例数据 let data = vec![ Point { x: 1.0, y: 1.0 }, Point { x: 1.5, y: 2.0 }, Point { x: 3.0, y: 4.0 }, Point { x: 5.0, y: 7.0 }, Point { x: 3.5, y: 5.0 }, Point { x: 4.5, y: 5.0 }, Point { x: 3.5, y: 4.5 }, ]; // 创建并训练k-means模型 let mut kmeans = KMeans::new(2, 100); kmeans.fit(&data); println!("聚类中心:"); for (i, centroid) in kmeans.centroids().iter().enumerate() { println!("簇 {}: ({:.2}, {:.2})", i, centroid.x, centroid.y); } // 预测新点 let new_point = Point { x: 2.0, y: 2.0 }; let cluster = kmeans.predict(&new_point); println!("\n新点 ({:.2}, {:.2}) 属于簇 {}", new_point.x, new_point.y, cluster);} 在终端执行:
cargo run 你应该会看到类似如下的输出:
聚类中心:簇 0: (1.25, 1.50)簇 1: (4.00, 5.25)新点 (2.00, 2.00) 属于簇 0 恭喜!你已经成功用Rust实现了k-means聚类算法。通过这个教程,你不仅掌握了k-means Rust实现的核心思想,还学会了如何在Rust中处理数值计算和数据结构。Rust的安全性和性能使其成为构建高效机器学习库的理想选择。
下一步,你可以尝试:
希望这篇教程能帮助你在Rust机器学习的道路上迈出坚实的一步!
本文由主机测评网于2025-12-10发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025125821.html