如何在 Rust 中構建機器學習模型?


機器學習 (ML) 已成為科技領域發展最快的領域之一,使系統能夠從資料中學習、適應和改進。雖然 Python 在該領域佔據主導地位,但其他語言由於其效能、安全性以及併發特性而開始受到關注——其中一種語言就是 Rust。
Rust 以其無需垃圾回收器的記憶體安全性而聞名,為機器學習帶來了可觀的益處,尤其是在構建高效能和安全的系統時。在本文中,我們將探討如何在 Rust 中構建一個簡單的機器學習模型。無論您是 Rust 專家還是初學者,本指南都將提供有關在 Rust 中建立基本機器學習管道的分步說明。

為什麼選擇 Rust 進行機器學習?

雖然 Python 是機器學習中最常用的語言,但 Rust 提供了一些優勢

  • 效能:Rust 的速度與 C++ 媲美,並且與 Python 等解釋型語言相比,提供了更好的效能。
  • 安全性:Rust 透過其嚴格的借用和所有權模型確保記憶體安全,從而最大程度地減少了空指標取消引用和緩衝區溢位等執行時錯誤。
  • 併發性:Rust 提供了出色的併發程式設計工具,從而更輕鬆地有效地利用現代多核系統。
  • 不斷發展的生態系統:Rust 機器學習生態系統雖然仍在發展中,但正在隨著 Linfa 和 ndarray 等強大庫的出現而不斷壯大。

機器學習模型如何工作?

在較高層次上,機器學習 (ML) 模型旨在識別資料中的模式。最終目標是在無需明確程式設計執行這些任務的情況下進行預測或決策。要了解機器學習模型的工作原理,必須將其過程分解為核心元件

1. 資料

機器學習模型從資料中學習,資料是模型的基礎。資料通常包括

  1. 特徵(輸入):描述現象的屬性或變數。例如,在預測房價時,特徵可能是臥室數量、平方英尺或位置。
  2. 標籤(輸出):模型試圖預測的實際結果或目標值。在監督學習中,標籤在訓練階段是已知的(例如,房價)。

2. 學習演算法

機器學習的核心是用於從資料中學習的演算法。根據問題的性質使用不同的演算法

  1. 監督學習:在這種情況下,特徵和標籤都在訓練期間提供。模型透過最小化預測標籤和實際標籤之間的誤差來訓練將輸入對映到輸出。此處使用線性迴歸、決策樹和神經網路等演算法。
  2. 無監督學習:在這裡,模型僅提供輸入資料,沒有任何相應的標籤。目標是在資料中發現隱藏的模式、分組或結構。常見的演算法包括聚類(k 均值)和降維(PCA)。
  3. 強化學習:在這種情況下,模型從反饋而不是明確的資料中學習。它做出決策並獲得獎勵或懲罰,最終隨著時間的推移最佳化其策略。

3. 模型表示

每個機器學習演算法都有其模型的數學表示。例如
線性模型:線性迴歸模型可以表示為 y=wx + b,其中

  • y 是預測值(輸出)。
  • w 是權重(模型的引數)。
  • x 是特徵(輸入)。
  • b 是偏差項。模型的目標是找到最優的 ww 和 bb 值,以最小化預測值和實際值之間的差異。
更復雜的模型(如神經網路)將資料表示為相互連線的節點(神經元)層,每個節點都有其權重和啟用函式。

訓練過程:在訓練期間,模型透過根據輸入資料調整其內部引數來學習。步驟通常包括

  • 前向傳播:模型根據當前引數值進行預測。
  • 損失函式:損失或成本函式計算預測輸出與實際輸出之間的誤差或差異(對於監督學習)。常見的損失函式包括用於迴歸的均方誤差 (MSE) 和用於分類任務的交叉熵。
  • 反向傳播和最佳化:然後,模型使用梯度下降等最佳化演算法調整其引數,這些演算法旨在透過迭代改進模型的引數來最小化損失函式。

4. 評估

訓練後,模型將在未見資料(測試資料)上進行評估,以衡量其泛化能力。常見的評估指標包括

  • 準確率:正確預測的比例(主要用於分類問題)。
  • 均方誤差 (MSE):衡量預測值和實際值之間的平均平方差(用於迴歸問題)。
  • 精確率、召回率、F1 分數:這些指標評估分類任務中的效能,其中類的分佈不平衡(例如,檢測垃圾郵件)。

5. 推理

訓練後,模型用於對新的、未見的資料進行預測或分類。此階段稱為推理。此時,模型通常部署到生產環境中,在該環境中,它可以根據傳入的資料做出即時決策。

機器學習模型的型別

根據所使用的演算法,有各種型別的模型

  • 線性模型:這些模型假設輸入和輸出之間存線上性關係。線性迴歸是最簡單的形式,其中模型試圖找到最適合資料的直線。
  • 決策樹:決策樹是根據特徵值將資料分成子集的模型,建立樹狀結構,其中每個節點表示決策點,葉子表示預測結果。
  • 支援向量機 (SVM):SVM 試圖找到最能將資料分成不同類的超平面,最大化類之間的間隔。
  • 神經網路:神經網路受人腦啟發,由相互連線的神經元層組成。它們非常適合複雜的非線性問題,並且是深度學習的基礎。網路可以從簡單的淺層網路到具有許多隱藏層(每個隱藏層學習資料的不同方面)的深度網路。
  • 整合模型:這些模型結合多個模型以提高預測精度。隨機森林、提升和裝袋等方法是整合學習的例子。

機器學習中的通用概念

過擬合和欠擬合

  • 過擬合:當模型在訓練資料上表現良好但在新資料上表現不佳時,因為它已經學會記憶訓練資料而不是從中泛化。
  • 欠擬合:當模型過於簡單並且無法捕獲資料中的潛在模式時。
正則化:正則化技術(例如 L1 和 L2 正則化)透過懲罰模型中較大的權重來幫助防止過擬合,鼓勵模型保持簡單和可泛化。

交叉驗證:此技術將資料分成多個子集(摺疊),並在這些子集的不同組合上訓練模型,確保模型在不同的資料樣本中都能很好地泛化。

在 Rust 中逐步構建 ML 模型

讓我們在 Rust 中構建一個簡單的線性迴歸模型。我們將使用linfa crate,這是一個為 Rust 設計的機器學習庫。線性迴歸是一種簡單的監督學習演算法,它根據輸入變數預測連續輸出。

步驟 1:設定開發環境

首先確保 Rust 已安裝在您的系統上並正常工作,然後我們將透過cargo建立一個新的 Rust 專案

cargo new rustml && cd rustml

這將建立一個新的 Rust 專案,但我們需要將所需的依賴項新增到cargo.toml檔案中

[dependencies]
csv = "1.1.6"
linfa = "0.5.0"
ndarray = "0.15.0"
ndarray-csv = "0.3.0"
  1. Linfa:它是 Rust 中的一個機器學習 crate,提供各種演算法和工具來使用。
  2. ndarray :此 crate 廣泛用於處理矩陣和陣列以及資料操作。
  3. ndarry-csv:此庫幫助我們將 CSV 檔案轉換為矩陣格式。

步驟 2:載入資料集

為了簡單起見,我們將使用加州房價資料集,您可以在此處找到它。

接下來,我們將編寫此 Rust 程式碼

use csv::ReaderBuilder;
use ndarray::Array2;
use ndarray_csv::Array2Reader;
use ndarray::Axis;
use std::error::Error;
use linfa::Dataset;
use linfa::prelude::*;
use linfa_linear::LinearRegression;
use ndarray_stats::QuantileExt;

fn load_data() -> Result<(Array2, Array2), Box> {
    // Load the CSV file
    let mut rdr = ReaderBuilder::new()
        .has_headers(true)
        .from_path("{your_file_name}.csv")?;

    // Read the CSV into an ndarray
    let array: Array2 = rdr.deserialize_array2_dynamic()?;

    // Assume the last column is the target (house prices), split it from the rest
    let (x, y) = array.view().split_at(Axis(1));

    Ok((x.to_owned(), y.to_owned()))
}

此 Rust 程式碼建立了一個新的 CSV 讀取器,此外,此程式碼將 CSV 資料反序列化為 2D ndarray 的形式,在程式碼的最後一部分,我們透過假設最後一列是房價,而前面的列是房屋的特徵來拆分資料。還要確保 CSV 檔案的路徑和名稱正確。

步驟 3:預處理資料

預處理資料只需涉及清理、規範化和編碼從 CSV 檔案獲取的資料。我們現在將規範化資料

fn normalize_data(data: &Array2) -> Array2 {
    let min = data.min().unwrap();
    let max = data.max().unwrap();
    (data - min) / (max - min)
}

normalize_data 函式用於使用最小-最大規範化將資料規範化到 0 和 1 之間的值。

步驟 4:構建機器學習模型

由於我們已經載入併成功預處理了資料,因此我們現在可以繼續構建機器學習模型。為此,我們將使用線性迴歸來預測僅基於可用特徵的房價。

fn build_model(x: Array2, y: Array2) {
    let dataset = Dataset::new(x, y);

    let model = LinearRegression::default()
        .fit(&dataset)
        .expect("Failed to train linear regression model");

    model
}

此函式用於將線性迴歸模型擬合到訓練資料。

步驟 5:訓練機器學習模型

現在,我們機器學習模型開發的最後一個階段包括載入資料集、對其進行歸一化,然後訓練模型。

fn main() -> Result<(), Box> {
    let (x, y) = load_data()?;

    let x_normalized = normalize_data(&x);

    let model = build_model(x_normalized, y);

    let new_data = array![[5000.0, 3.0, 1500.0]];
    let prediction = model.predict(new_data);
    println!("Predicted house price: {:?}", prediction);

    Ok(())
}

由於我們已經成功訓練了機器學習模型,現在是時候評估模型的效能了。

步驟 6:評估模型

現在,由於我們的模型已成功訓練,我們將透過將資料集分成兩個部分(訓練集和測試集)來評估模型的效能,然後計算R平方或均方誤差(也稱為MSE)等指標。

use linfa::metrics::MeanAbsoluteError;

fn evaluate_model(model: &LinearRegression, test_x: Array2, test_y: Array2) {
    let predictions = model.predict(test_x);
    let mse = predictions.mean_absolute_error(&test_y).unwrap();
    println!("Mean Absolute Error: {}", mse);
}

結論

總而言之,對於需要在應用程式中兼顧效能和安全性的機器學習工程師而言,Rust 提供了一個引人注目的選擇。儘管在資料科學領域,Rust 的採用率可能尚未達到 Python 那樣高,但 Rust 快速發展的機器學習庫生態系統使其成為一個可行的替代方案,特別是對於已經熟悉該語言或希望在生產環境中利用 Rust 的優勢的工程師而言。
透過遵循本指南,您學習瞭如何使用 Rust 和 Linfa 庫載入、預處理和訓練機器學習模型。雖然我們專注於一項相對簡單的任務——線性迴歸預測房價,但此處概述的步驟可以擴充套件到更復雜的模型和資料集。隨著 Rust 生態系統不斷發展,值得關注其發展,因為它有可能在未來的機器學習專案中提供效能、安全性和可擴充套件性方面的巨大優勢。

更新於: 2024年10月9日

0 次瀏覽

開啟您的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.