机器学习模型评估与分类算法实现

立即解锁
发布时间: 2025-09-04 01:36:33 阅读量: 12 订阅数: 8 AIGC
PDF

Rust机器学习实战

### 机器学习模型评估与分类算法实现 在机器学习中,评估模型的性能以及选择合适的分类算法至关重要。下面将详细介绍回归模型的评估方法以及多种分类算法的实现。 #### 回归模型评估 在机器学习模型的代码中,我们使用了一些函数来评估模型的好坏,如 `neg_mean_squared_error` 或 `r_squared_score`。评估模型对于判断其在新数据和未来数据上的预测能力非常重要。由于未来数据的目标值未知,我们需要在已知数据上检查模型的准确率指标。因此,在训练前,我们会将数据集划分为训练集和测试集,以此来评估模型与实际应用场景的接近程度。 ##### MAE 和 MSE 对于连续变量,最常用的评估指标是平均绝对误差(MAE)和均方误差(MSE)。 - **MAE**:是预测值与观测值之间绝对差的平均值。公式如下: \[ MAE = \frac{1}{n} \sum_{i=1}^{n} |\hat{y}_i - y_i| \] - **MSE**:是预测值与观测值之间差异的平方和(也称为残差)。公式如下: \[ MSE = \frac{1}{n} \sum_{i=1}^{n} (\hat{y}_i - y_i)^2 \] 在很多情况下,还会取 MSE 的平方根,即均方根误差(RMSE)。RMSE 在处理高斯分布时是最好的误差估计器,但大多数实际应用场景并非严格的高斯分布,取残差的平方会过度关注异常值。MAE 更易于理解,对异常值的关注较少。然而,RMSE 是许多模型的默认指标,因为基于 RMSE 定义的损失函数具有平滑的可微性,便于进行机器学习所需的数学运算。 在 `rusty machine` 中,训练完成后,我们可以通过以下代码获取模型的均方误差: ```rust use rusty_machine::analysis::score::neg_mean_squared_error; pub fn run() -> Result<(), Box<dyn Error>> { // previous part ... let predictions = lin_model.predict(&boston_x_test).unwrap(); let predictions = Matrix::new(test_size, 1, predictions); let acc = neg_mean_squared_error(&predictions, &boston_y_test); println!("linear regression error: {:?}", acc); let predictions = gaus_model.predict(&boston_x_test).unwrap(); let predictions = Matrix::new(test_size, 1, predictions); let acc = neg_mean_squared_error(&predictions, &boston_y_test); println!("gaussian process regression error: {:?}", acc); // remaining code... } ``` ##### R - 平方误差 R - 平方用于评估数据点围绕拟合回归线的离散程度,也称为决定系数。对于同一数据集,较高的 R - 平方值表示观测值与拟合值之间的差异较小。R - 平方是线性模型解释的因变量变化的百分比,公式如下: \[ R^2 = \frac{Variance\ explained\ by\ the\ model}{Total\ variance} = 1 - \frac{\sum_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum_{i=1}^{n} (y_i - \bar{y})^2} \] 以下是在 Rust 中实现 R - 平方的代码: ```rust fn r_squared_score(y_test: &Vec<f64>, y_preds: &Vec<f64>) -> f64 { let mv: f64 = y_test.iter().zip(y_preds.iter()).fold( 0., |v, (y_i, y_i_hat)| { v + (y_i - y_i_hat).powi(2) } ); let mean = y_test.iter().sum::<f64>() as f64 / y_test.len() as f64; let var = y_test.iter().fold( 0., |v, &x| {v + (x - mean).powi(2)} ); let r2: f64 = 1.0 - (mv / var); r2 } ``` 在实际应用中,我们可以这样使用: ```rust pub fn run() -> Result<(), Box<dyn Error>> { // previous part of the function... println!("glm poisson R2 score: {:?}", r_squared_score( &boston_y_test.data(), &predictions.data())); } ``` #### 分类算法 当机器学习算法需要将输入变量分类到预定义的类别中时,这类问题被称为分类问题。下面将介绍如何在 Rust 中创建分类模型。 ##### Iris 数据集 为了展示分类算法的使用,我们将使用 Iris 数据集。该数据集是一个多变量数据集,包含以下特征: - 萼片长度(cm) - 萼片宽度(cm) - 花瓣长度(cm) - 花瓣宽度(cm) - 类别:setosa、versicolor 和 virginica 以下是相关代码的操作步骤: 1. 在 `rustlearn_classification_tasks` 文件夹中创建 `data` 文件夹,并将 `iris.csv` 文件放在其中。 2. 在 `Cargo.toml` 文件中添加依赖: ```toml [package] name = "rustlearn_classification_tasks" version = "0.1.0" edition = "2018" [dependencies] rustlearn = "0.5.0" csv = "1.0.5" serde = "1.0.89" serde_derive = "1.0.89" rand = "0.6" ml-utils = { path = "../ml-utils" } ``` 3. 创建 `Flower` 结构体: ```rust extern crate serde; #[macro_use] extern crate serde_derive; #[derive(Debug, Deserialize)] pub struct Flower { sepal_length: f32, sepal_width: f32, petal_length: f32, petal_width: f32, species: String, } ``` 4. 实现 `into_feature_vector` 和 `into_labels` 方法: ```rust use std::io; use std::vec::Vec; use csv; impl Flower { pub fn into_feature_vector(&self) -> Vec<f32> { vec![self.sepal_length, self.sepal_width, self.petal_length, self.petal_width] } pub fn into_labels(&self) -> f32 { match self.species.as_str() { "setosa" => 0., "versicolor" => 1., "virginica" => 2., some_other => panic!("Not able to parse the label. Some other label got passed. {:?}", some_other), } } } ``` 5. 读取数据并进行预处理: ```rust use ml_utils::datasets::Flower; use csv; use rand::thread_rng; use rand::seq::SliceRandom; pub fn run() -> Result<(), Box<dyn Error>> { let mut rdr = csv::Reader::from_reader(io::stdin()); let mut data = Vec::new(); for result in rdr.deserialize() { let r: Flower = result?; data.push(r); } data.shuffle(&mut thread_rng()); // rest of the code... } ``` 6. 分离训练集和测试集: ```rust use rustlearn::prelude::*; pub fn run() -> Result<(), Box<dyn Error>> { // previous part of the function ... // separate out to train and test datasets. let test_size: f32 = 0.2; let test_size: f32 = data.len() as f32 * test_size; let test_size = test_size.round() as usize; let (test_data, train_data) = data.split_at(test_size); let train_size = train_data.len(); let test_size = test_data.len(); // differentiate the features and the labels. let flower_x_train: Vec<f32> = train_data.iter() .flat_map(|r| r.into_feature_vector()).collect(); let flower_y_train: Vec<f32> = train_data.iter() .map(|r| r.into_labels()).collect(); let flower_x_test: Vec<f32> = test_data.iter() .flat_map(|r| r.into_feature_vector()).collect(); let flower_y_test: Vec<f32> = test_data.iter() .map(|r| r.into_labels()).collect(); // Convert the vectors to a dense matrix or a sparse matrix let mut flower_x_train = Array::from(flower_x_train); flower_x_train.reshape(train_size, 4); let flower_y_train = Array::from(flower_y_train); let mut flower_x_test = Array::from(flower_x_test); flower_x_test.reshape(test_size, 4); // rest of the function ... } ``` 以下是整个数据处理流程的 mermaid 流程图: ```mermaid graph LR A[读取 Iris 数据集] --> B[创建 Flower 结构体] B --> C[实现特征和标签提取方法] C --> D[读取数据并打乱] D --> E[分离训练集和测试集] E --> F[转换为矩阵] ``` 通过以上步骤,我们完成了回归模型的评估以及 Iris 数据集的预处理,为后续的分类算法实现奠定了基础。接下来,我们将介绍几种常见的分类算法及其在 Rust 中的实现。 ### 机器学习模型评估与分类算法实现 ##### 逻辑回归 逻辑回归是一种流行的分类技术,它使用对数几率函数来建模二元因变量,假设因变量服从伯努利分布。与普通最小二乘法(OLS)回归不同,逻辑回归使用最大似然法估计参数。由于无法找到最大化似然函数的封闭形式解,因此需要使用迭代方法,如随机梯度下降(SGD)。 在 Rust 中使用 `rustlearn` 实现逻辑回归的代码如下: ```rust pub fn run() -> Result<(), Box<dyn Error>> { // previous part of the fn .. let mut model = lr::new(4) .learning_rate(0.1).l2_penalty(0.5) .l1_penalty(0.0).one_vs_rest(); for _ in 0..100 { // for 100 epochs model.fit(&flower_x_train, &flower_y_train).unwrap(); } let prediction = model.predict(&flower_x_test).unwrap(); let acc1 = accuracy_score(&flower_y_test, &prediction); println!("Logistic Regression: accuracy: {:?}", acc1); Ok(()) } ``` 运行上述代码可能会得到类似以下的输出: ```plaintext $ cargo run lr < ../datasets/iris.csv Logistic Regression: accuracy: 0.36666667 ``` 逻辑回归的实现流程可以用以下 mermaid 流程图表示: ```mermaid graph LR A[初始化模型] --> B[设置超参数] B --> C[多次迭代训练] C --> D[进行预测] D --> E[计算准确率] ``` ##### 决策树 在分类问题中,我们的目标是找到一个模型,根据预测变量的值来预测类别变量的值。决策树通过递归地划分特征空间,将其划分为多个不相交的集合,使得每个集合对应一个类别。决策树的构建过程包括两个主要步骤: 1. **生长树**:使用前向选择方法生长一个过大的树,在每一步找到最佳分割点,直到所有终端节点满足以下条件之一: - 节点中的数据点少于 `n` 个。 - 节点中的所有数据点具有相同的结果(即节点为“纯”节点)。 2. **剪枝**:对生长的树进行剪枝,创建一系列嵌套的树,逐渐降低树的复杂度。 在 Rust 中使用 `rustlearn` 实现决策树的代码如下: ```rust use rustlearn::trees::decision_tree; pub fn run() -> Result<(), Box<dyn Error>> { // data loading and transformations part ... // similar to the logistic regression secion above ... let mut decision_tree_model = decision_tree::Hyperparameters::new( flower_x_train.cols()).one_vs_rest(); decision_tree_model.fit(&flower_x_train, &flower_y_train).unwrap(); let prediction = decision_tree_model.predict( &flower_x_test).unwrap(); let acc = accuracy_score( &flower_y_test, &prediction); println!("DecisionTree model accuracy: {:?}", acc); Ok(()) } ``` 运行上述代码可能会得到类似以下的输出: ```plaintext $ cargo run trees < ../datasets/iris.csv Finished dev [unoptimized + debuginfo] target(s) in 0.03s Running `target/debug/rustlearn_classification_tasks trees` DecisionTree model accuracy: 0.96666664 ``` 决策树的构建和预测流程可以用以下表格总结: | 步骤 | 操作 | | ---- | ---- | | 1 | 初始化决策树超参数 | | 2 | 使用训练数据拟合模型 | | 3 | 使用测试数据进行预测 | | 4 | 计算预测准确率 | ##### 随机森林 随机森林是决策树的改进算法,它通过生长多个决策树并进行投票来确定最终的分类结果。每个决策树依赖于一个独立采样的随机向量,并且森林中的所有树具有相同的分布。随着森林中树的数量增加,随机森林的泛化能力会收敛到一个极限。 在 Rust 中使用 `rustlearn` 实现随机森林的代码如下: ```rust use rustlearn::ensemble::random_forest::Hyperparameters as rf; pub fn run() -> Result<(), Box<dyn Error>> { // previous part of the fn ... let mut tree_params = decision_tree::Hyperparameters::new( flower_x_train.cols()); tree_params.min_samples_split(10) .max_features(4); let mut model = randomforest::new( tree_params, 10).one_vs_rest(); model.fit(&flower_x_train, &flower_y_train).unwrap(); let prediction = random_forest_model .predict(&flower_x_test).unwrap(); let acc = accuracy_score( &flower_y_test, &prediction); println!("Random Forest: accuracy: {:?}", acc); Ok(()) } ``` 运行上述代码可能会得到类似以下的输出: ```plaintext $ cargo run trees < ../datasets/iris.csv Finished dev [unoptimized + debuginfo] target(s) in 0.03s Running `target/debug/rustlearn_classification_tasks trees` DecisionTree model accuracy: 1.0 Random Forest: accuracy: 1.0 ``` 需要注意的是,在使用简单算法(如逻辑回归)时,准确率可能较低(约 30%),但随着使用基于树的模型(如决策树和随机森林),准确率可以达到 95% - 100%。不过,这些都是玩具数据集,在实际问题中,应谨慎对待如此高的准确率。 随机森林的实现流程可以用以下 mermaid 流程图表示: ```mermaid graph LR A[初始化决策树参数] --> B[设置随机森林超参数] B --> C[训练随机森林模型] C --> D[进行预测] D --> E[计算准确率] ``` ##### XGBoost XGBoost(Extreme Gradient Boosting)是一种强大的分类算法,它通过依次构建决策树,使得每棵后续树旨在减少前一棵树的误差。与随机森林不同,XGBoost 使用较浅的树,这些树具有较高的可解释性。在运行 XGBoost 之前,需要设置三种类型的参数:通用参数、提升器参数和任务参数。 在 Rust 中使用 `rust-xgboost` 库实现 XGBoost 的代码如下: ```rust use xgboost; use xgboost::{parameters, DMatrix, Booster}; fn read_csv() -> Result<(), Box<dyn Error>> { // previous data loading and splitting code ... let mut dtrain = DMatrix::from_dense(&flower_x_train, train_size).unwrap(); dtrain.set_labels(&flower_y_train).unwrap(); let mut dtest = DMatrix::from_dense(&flower_x_test, test_size).unwrap(); dtest.set_labels(&flower_y_test).unwrap(); let lps = parameters::learning::LearningTaskParametersBuilder::default() .objective(parameters::learning::Objective::MultiSoftmax(3)) .build().unwrap(); let tps = parameters::tree::TreeBoosterParametersBuilder::default() .max_depth(2).eta(1.0) .build().unwrap(); let bst_parms = parameters::BoosterParametersBuilder::default() .booster_type(parameters::BoosterType::Tree(tps)) .learning_params(learning_params) .verbose(true).build().unwrap(); let ev = &[(&dtrain, "train"), (&dtest, "test")]; let params = parameters::TrainingParametersBuilder::default() .dtrain(&dtrain).boost_rounds(2) .booster_params(bst_parms) .evaluation_sets(Some(ev)) .build().unwrap(); let booster = Booster::train(&params).unwrap(); let preds = booster.predict(&dtest).unwrap(); let labels = dtest.get_labels().unwrap(); // find the accuracy let mut hits = 0; let mut correct_hits = 0; for (predicted, actual) in preds.iter().zip(labels.iter()) { if predicted == actual { correct_hits += 1; } hits += 1; } assert_eq!(hits, preds.len()); println!("accuracy={} ({}/{} correct)", correct_hits as f32 / hits as f32, correct_hits, preds.len()); } ``` 运行上述代码可能会得到类似以下的输出: ```plaintext $ cd chapter2/iris_classification_xgboost $ cargo run < ../datasets/iris.csv Finished dev [unoptimized + debuginfo] target(s) in 0.05s Running `target/debug/iris_classification_xgboost` [08:26:11] DANGER AHEAD: You have manually specified `updater` parameter. The `tree_method` parameter will be ignored. Incorrect sequence of updaters will produce undefined behavior. For common uses, we recommend using `tree_method` parameter instead. [08:26:11] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 2 extra nodes, 0 pruned nodes, max_depth=1 [08:26:11] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 4 extra nodes, 0 pruned nodes, max_depth=2 [08:26:11] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 6 extra nodes, 0 pruned nodes, max_depth=2 [0] test-merror:0 train-merror:0.033333 [08:26:11] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 2 extra nodes, 0 pruned nodes, max_depth=1 [08:26:11] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 6 extra nodes, 0 pruned nodes, max_depth=2 [08:26:11] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 6 extra nodes, 0 pruned nodes, max_depth=2 [1] test-merror:0 train-merror:0.011111 ``` XGBoost 的实现步骤可以总结为以下表格: | 步骤 | 操作 | | ---- | ---- | | 1 | 数据预处理,转换为 `DMatrix` 并设置标签 | | 2 | 设置学习任务参数、树提升器参数和提升器参数 | | 3 | 设置训练参数,包括训练矩阵、迭代次数等 | | 4 | 训练提升器 | | 5 | 进行预测并计算准确率 | 通过以上介绍,我们详细了解了回归模型的评估方法以及多种分类算法在 Rust 中的实现。这些算法各有优缺点,在实际应用中,我们需要根据具体问题选择合适的算法。
corwn 最低0.47元/天 解锁专栏
买1年送3月
点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

李_涛

知名公司架构师
拥有多年在大型科技公司的工作经验,曾在多个大厂担任技术主管和架构师一职。擅长设计和开发高效稳定的后端系统,熟练掌握多种后端开发语言和框架,包括Java、Python、Spring、Django等。精通关系型数据库和NoSQL数据库的设计和优化,能够有效地处理海量数据和复杂查询。
最低0.47元/天 解锁专栏
买1年送3月
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看

最新推荐

请你提供书中第37章的具体英文内容,以便我按照要求完成博客创作。

请你提供书中第37章的具体英文内容,以便我按照要求完成博客创作。 请你先提供书中第37章的具体英文内容,以及已经完成的博客上半部分内容,这样我才能按照要求输出下半部分。

Linux系统运维知识大揭秘

### Linux 系统运维知识大揭秘 #### 1. 标准输入、输出与错误 在 Linux 系统中,标准输入(STDIN)、标准输出(STDOUT)和标准错误(STDERR)是非常基础且重要的概念。 |名称|默认目标|重定向使用|文件描述符编号| | ---- | ---- | ---- | ---- | |STDIN|计算机键盘|< (等同于 0<)|0| |STDOUT|计算机显示器|> (等同于 1>)|1| |STDERR|计算机显示器|2>|2| 常见的 Bash 重定向器如下: |重定向器|解释| | ---- | ---- | |> (等同于 1>)|重定向 STDOUT。

请你提供书中第37章的具体内容,以便我按照要求为你创作博客。

请你提供书中第37章的具体内容,以便我按照要求为你创作博客。 请你先提供书中第37章的英文具体内容,我会先输出上半部分博客,再输出下半部分博客。

Terraform自动化与CI/CD实战指南

### Terraform自动化与CI/CD实战指南 #### 1. Azure DevOps中构建Terraform管道 在Azure DevOps中,我们可以借助Azure Pipelines服务来自动化执行Terraform。以下是具体步骤: 1. **创建新管道**:通过Web界面使用Azure Pipelines创建新管道,并在GitHub仓库中进行配置,选择从新的YAML文件开始配置。 2. **编写YAML代码**: - 下载Terraform二进制文件,并指定与Terraform配置兼容的版本,如1.4.4。即便使用已安装Terraform的Microsoft托管代理

Docker容器化应用入门与实践

### Docker 容器化应用入门与实践 #### 1. Docker 基础命令与操作 - **运行容器**:使用 `docker run` 命令运行容器,例如 `-d` 选项可让容器在后台运行。以 `nginx` 镜像为例: ```bash docker run -d nginx ``` 若要在 `http://localhost:80` 看到 HTML 内容,可在 `/tmp` 目录添加 `index.html` 文件: ```bash cat <<EOF > /tmp/index.html <!doctype html> <h1>Hello World</h1> <p>This is

掌握设计交接与UI/UX设计师面试准备

# 掌握设计交接与 UI/UX 设计师面试准备 ## 一、设计交接的重要性与流程 ### 1.1 设计交接概述 设计交接是 UX 设计师向开发团队提供数字资产和全面文档,以助力产品愿景实现的关键过程。除了文件传输,顺利的交接还需要设计师与开发者之间密切的协调与沟通。良好的合作能确保设计准确执行,提升用户体验,推动项目成功完成。 ### 1.2 理解设计交接 UX 设计师完成设计后,需创建包含开发团队所需所有要求和数字资源的综合文档。这一过程虽看似简单,但成功的交接需要深思熟虑。常见的问题是认为设计完成后责任就完全转移到了开发者身上,然而,设计师与开发者的紧密合作才是良好交接的第一步,它能保

使用Prometheus和Grafana监控分布式应用

### 使用 Prometheus 和 Grafana 监控分布式应用 #### 1. 架构概述 计划中的系统架构涉及微服务、Prometheus 服务器和 Grafana,并且所有组件都将部署到 Kubernetes 中。以下是它们之间的关系: ```mermaid graph LR classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px A(Kubernetes):::process -->|提供指标| B(Prometheus):::process C(Node.js 服务):::process

优化Kubernetes应用部署:亲和性、反亲和性与硬件资源管理

### 优化Kubernetes应用部署:亲和性、反亲和性与硬件资源管理 #### 1. 引言 在Kubernetes集群中部署应用时,我们常常需要平衡应用的性能、可扩展性和弹性。理想的应用简单易设计、开发和部署,组件无状态,便于扩展。然而,现实世界的应用往往需要存储状态、处理数据安全和授权问题,还可能需要访问特殊硬件。因此,我们需要一些策略来指导Kubernetes集群更高效地调度容器,而亲和性(Affinity)和反亲和性(Anti-affinity)以及硬件资源管理就是这样的重要策略。 #### 2. 亲和性与反亲和性概述 在管理Pod调度时,我们可能希望控制多个容器是否在同一节点上

Linux认证考试全解析

### Linux认证考试全解析 #### 1. 命令行的强大功能 在学习Linux相关知识时,命令行是一个非常重要的部分。以下是学习此领域需要了解的十大要点: - **输入输出重定向**:标准输入(stdin)传统上是键盘,标准输出(stdout)传统上是显示器,标准错误(stderr)也可以重定向,使用符号 `>`、`>>`、`<` 和 `|` 即可实现。 - **命令连接**:命令可以在命令行用分号(;)连接,每个命令独立运行,也可以使用管道(|)将一个命令的输出作为另一个命令的输入。 - **文件字段操作**:`cut` 命令可从文件中提取字段,使用 `paste` 或 `join`