Rust для машинного обучения: практика, возможности и ограничения

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Rust для машинного обучения: возможности и ограничения на практике

Мир машинного обучения (ML) долгое время был безраздельной вотчиной Python. Однако с ростом требований к производительности, безопасности и детерминированности кода, на сцену выходит Rust. Этот язык, известный своей скоростью, близкой к C/C++, и строгой системой типов, предлагает интересную альтернативу для задач, где Python "буксует". В этой статье мы разберем реальные возможности и ограничения использования Rust в ML, подкрепив теорию практическими примерами кода.

Почему Rust? Ключевые преимущества для ML

Прежде чем перейти к ограничениям, давайте посмотрим, зачем вообще использовать Rust в ML-пайплайнах. Основных причин три:

  • Производительность без GC (Garbage Collector): Rust компилируется в нативный код и не имеет сборщика мусора. Это дает предсказуемую и высокую скорость выполнения, что критично для инференса моделей в продакшене и обработки больших объемов данных в реальном времени.
  • Безопасность памяти на этапе компиляции: Ошибки сегментации и гонки данных (data races) — одна из самых частых проблем в C++ ML-фреймворках. Система владения (ownership) и заимствования (borrowing) в Rust гарантирует, что вы не сможете случайно испортить память, что повышает надежность продакшн-систем.
  • Бесшовная интеграция с другими языками: Rust легко встраивается в Python через PyO3 или maturin. Вы можете написать узкое место (bottleneck) на Rust, скомпилировать его в нативный модуль и импортировать в Python, получив прирост скорости в 10-100 раз.

Основные библиотеки и фреймворки: что работает прямо сейчас

Экосистема Rust для ML активно развивается. Вот три столпа, на которые стоит обратить внимание:

1. Burn: Современный фреймворк для глубокого обучения

Burn — это, пожалуй, самый амбициозный проект. Он написан на Rust и предлагает API, похожий на PyTorch, но с бонусами в виде безопасности и производительности. Burn поддерживает автоматическое дифференцирование, работу на CPU, CUDA (через wgpu или candle) и даже WebGPU.

Пример: Простая нейронная сеть на Burn

use burn::tensor::{Tensor, backend::Backend};
use burn::nn::{Linear, LinearConfig};
use burn::optim::Adam;
use burn::module::Module;

// Определяем модель
#[derive(Module, Debug)]
struct MyModel<B: Backend> {
    linear1: Linear<B>,
    linear2: Linear<B>,
}

impl<B: Backend> MyModel<B> {
    pub fn new(device: &B::Device) -> Self {
        Self {
            linear1: LinearConfig::new(10, 50).init(device),
            linear2: LinearConfig::new(50, 1).init(device),
        }
    }

    pub fn forward(&self, input: Tensor<B, 2>) -> Tensor<B, 2> {
        let x = self.linear1.forward(input).relu();
        self.linear2.forward(x)
    }
}

// Пример использования (псевдокод для демонстрации)
fn main() {
    type MyBackend = burn::backend::WgpuBackend; // Или CandleBackend, NdArrayBackend
    let device = MyBackend::Device::default();
    let model = MyModel::<MyBackend>::new(&device);
    let input = Tensor::<MyBackend, 2>::random([4, 10], burn::tensor::Distribution::Uniform(0.0, 1.0), &device);
    let output = model.forward(input);
    println!("Output shape: {:?}", output.dims());
}

2. Candle: Минималистичный и быстрый от Hugging Face

Candle — это фреймворк от создателей Hugging Face, ориентированный на инференс (вывод) без необходимости в CUDA. Он минималистичен, не использует unsafe код (кроме биндингов к CUDA), что делает его очень безопасным. Идеально подходит для запуска моделей на CPU или встраиваемых устройствах.

Пример: Загрузка и инференс модели BERT

use candle_core::{Device, Tensor};
use candle_nn::VarBuilder;
use hf_hub::api::sync::Api;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Api::new()?;
    let repo = api.model("bert-base-uncased".to_string());
    let model_path = repo.get("model.safetensors")?;

    let device = Device::Cpu;
    let vb = VarBuilder::from_safetensors(&std::fs::read(model_path)?, candle_core::DType::F32, &device);
    // Далее создаем конфиг и модель BERT, передаем тензоры
    // let model = bert::BertModel::new(vb, &config)?;
    // let embeddings = model.forward(&input_ids, &attention_mask)?;
    println!("Candle работает! Модель загружена.");
    Ok(())
}

3. Linfa: Экосистема для классического ML (Scikit-learn на Rust)

Если вам не нужны нейронные сети, а нужны линейная регрессия, SVM, кластеризация K-средних или Random Forest, то Linfa — ваш выбор. Это аналог scikit-learn, но на Rust.

Пример: Линейная регрессия с Linfa

use linfa::prelude::*;
use linfa_linear::LinearRegression;
use ndarray::Array2;

fn main() {
    // Данные: X (признаки) и y (целевая переменная)
    let x = Array2::from_shape_vec((5, 2), vec![1.0, 2.0, 2.0, 4.0, 3.0, 6.0, 4.0, 8.0, 5.0, 10.0]).unwrap();
    let y = Array2::from_shape_vec((5, 1), vec![5.0, 10.0, 15.0, 20.0, 25.0]).unwrap();

    let dataset = Dataset::new(x, y);
    let model = LinearRegression::fit(&dataset, Default::default()).unwrap();
    let pred = model.predict(&dataset);
    println!("Predictions: {:?}", pred.targets);
}

Ограничения Rust в ML: что нужно знать

Несмотря на все плюсы, Rust не заменит Python в ML полностью. Вот основные камни преткновения:

  • Зрелость экосистемы: В Python

Блоги

Рекомендаций по книгам