DEV Community

Cover image for Elixir для Machine Learning. Часть 1 - Теория
Artyom Molchanov
Artyom Molchanov

Posted on

Elixir для Machine Learning. Часть 1 - Теория

В последнее время роль искусственного интеллекта в различных сферах начинает набирать обороты. Многие компании уже внедряют ИИ для помощи пользователям на своих порталах, а некоторые разрабатывают собственные нейронные сети для решения специализированных задач

В то время как Python доминирует в ML-ландшафте, Elixir находит применение в особых нишах: системы обработки данных в реальном времени (Bumblebee), сервисы инференса моделей (Nx.Serving) и распределенные системы машинного обучения. Компании, такие как DockYard и Dashbit, уже успешно внедряют ML-решения на Elixir в промышленной среде

Данная статья разделена на 2 части — Теория и Практика. В первой части мы рассмотрим основы машинного обучения, познакомимся с ключевыми понятиями и библиотеками, которые помогут создавать нейронные сети с использованием Elixir


Что такое машинное обучение и нейронные сети?

Машинное обучение (Machine Learning, ML) — это подход к созданию систем, которые могут обучаться на данных и улучшать свою производительность с опытом без явного программирования. Вместо написания конкретных инструкций для решения задачи, мы создаем модель, которая может адаптироваться и "учиться" на основе опыта

Нейронные сети — один из наиболее популярных методов машинного обучения, вдохновленный принципами работы человеческого мозга. Они представляют собой системы взаимосвязанных узлов (нейронов), организованных в слои:

  1. Входной слой получает исходные данные (например, пиксели изображения)
  2. Скрытые слои обрабатывают информацию, выявляя все более сложные паттерны
  3. Выходной слой предоставляет итоговый результат (например, классификацию объекта)

Каждый нейрон получает входные сигналы, обрабатывает их, применяя активационную функцию к взвешенной сумме входов, и передает результат дальше по сети. Связи между нейронами имеют весовые коэффициенты, которые определяют важность сигнала

Процесс обучения нейронной сети заключается в настройке этих весовых коэффициентов таким образом, чтобы сеть выдавала правильные результаты. Это происходит путем:

  1. Подачи множества обучающих примеров
  2. Вычисления ошибки между предсказаниями сети и фактическими значениями
  3. Корректировки весов для минимизации этой ошибки с помощью алгоритма обратного распространения ошибки (backpropagation)

Ключевые концепции в машинном обучении

Модели и их типы

Модель — математическая или алгоритмическая конструкция, которая обучается на данных для выполнения определённой задачи. Модели бывают разных типов:

  • Линейные модели: Относительно простые модели, которые предполагают линейную зависимость между входными и выходными данными. Примеры: линейная регрессия, логистическая регрессия
  • Нейронные сети: Многослойные модели, которые могут выявлять сложные нелинейные зависимости. Применяются для задач компьютерного зрения, обработки естественного языка и других сложных проблем
  • Ансамбли моделей: Комбинации нескольких моделей для получения более точного результата. Примеры: случайные леса (Random Forests), градиентный бустинг (Gradient Boosting)

Тензоры и их роль в ML

Тензор — это обобщение понятий скаляра, вектора и матрицы на многомерные массивы данных. Тензоры являются фундаментальной структурой данных в современных системах машинного обучения:

  • Скаляр: Тензор ранга 0 (0-D). Пример: число 5
  • Вектор: Тензор ранга 1 (1-D). Пример: [1, 2, 3]
  • Матрица: Тензор ранга 2 (2-D). Пример: [[1, 2, 3], [4, 5, 6]]
  • Многомерный тензор: Тензор ранга 3+ (3-D и выше). Пример: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

Тензоры используются для представления и обработки различных типов данных в ML:

  • Изображения (тензоры размерности 4: [batch_size, height, width, channels])
  • Тексты (последовательности векторов, представляющих слова или токены)
  • Временные ряды (последовательности наблюдений с течением времени)

Типы обучения

Обучение — процесс, при котором модель настраивает свои параметры на основе данных:

  • Обучение с учителем (Supervised Learning): Модель обучается на размеченных данных, где для каждого входного примера известен правильный ответ. Примеры задач: классификация изображений, прогнозирование цен, распознавание речи
  • Обучение без учителя (Unsupervised Learning): Модель обучается на неразмеченных данных, выявляя скрытые структуры и паттерны. Примеры задач: кластеризация, уменьшение размерности, обнаружение аномалий
  • Обучение с подкреплением (Reinforcement Learning): Модель обучается через взаимодействие с окружающей средой, получая награды или штрафы за свои действия. Применяется в робототехнике, играх, автономных системах

Гиперпараметры и их настройка

Гиперпараметры — это настройки модели, которые задаются до начала обучения и не изменяются в его процессе:

  • Архитектурные гиперпараметры: Количество слоёв в нейронной сети, количество нейронов в каждом слое, типы активационных функций
  • Параметры оптимизации: Скорость обучения (learning rate), размер батча (batch size), количество эпох обучения
  • Регуляризационные параметры: Коэффициенты L1/L2 регуляризации, параметр dropout для предотвращения переобучения

Настройка гиперпараметров обычно выполняется с помощью методов, таких как поиск по сетке (grid search), случайный поиск (random search) или байесовская оптимизация

Метрики оценки моделей

Метрики — это количественные показатели, которые используются для оценки качества работы модели:

  • Для задач классификации:
    • Точность (Accuracy): Доля правильных предсказаний среди всех предсказаний
    • Точность и полнота (Precision & Recall): Показатели, отражающие баланс между ложноположительными и ложноотрицательными результатами
    • F1-мера: Гармоническое среднее между точностью и полнотой
    • ROC-AUC: Площадь под ROC-кривой, отражающая способность модели различать классы
  • Для задач регрессии:
    • Среднеквадратичная ошибка (MSE): Среднее значение квадратов разностей между предсказанными и фактическими значениями
    • Средняя абсолютная ошибка (MAE): Среднее значение абсолютных разностей между предсказанными и фактическими значениями
    • Коэффициент детерминации (R²): Показывает, насколько хорошо модель объясняет вариацию данных

Выбор метрики зависит от конкретной задачи и бизнес-контекста. Например, в медицинской диагностике важнее минимизировать количество ложноотрицательных результатов, а в рекомендательных системах может быть важнее качество верхних рекомендаций

Теперь, когда мы рассмотрели ключевые концепции машинного обучения, давайте перейдем к инструментам, которые делают возможным применение этих концепций в экосистеме Elixir


Инструменты Elixir для машинного обучения

Экосистема машинного обучения в Elixir быстро развивается, предлагая все более мощные и удобные инструменты для разработчиков. Рассмотрим ключевые библиотеки, которые делают возможным применение ML на платформе BEAM

Numerical Elixir (Nx): Фундамент для вычислений

Nx — это основа всей ML-экосистемы Elixir, разработанная командой Dashbit под руководством Жозе Валима (создателя Elixir). Эта библиотека предоставляет высокоэффективные числовые вычисления и поддержку многомерных тензоров, что критически важно для машинного обучения

Ключевые возможности Nx:

  • Тензорные операции: Полный набор функций для манипуляции многомерными массивами данных
  • Численная стабильность: Высокая точность вычислений с контролем численных ошибок
  • Компиляция вычислений: Преобразование кода Elixir в оптимизированный машинный код
  • Автоматическое дифференцирование: Необходимое для алгоритмов обратного распространения ошибки

Особенно мощной особенностью Nx является система defn (определяемых числовых функций), которая позволяет компилировать вычисления в эффективный низкоуровневый код:

defmodule MathOps do
  import Nx.Defn

  defn multiply_and_add(a, b, c) do
    a * b + c
  end
end

# Использование
x = Nx.tensor([1, 2, 3])
y = Nx.tensor([4, 5, 6])
z = Nx.tensor([7, 8, 9])
MathOps.multiply_and_add(x, y, z)
# Результат: Nx.tensor([11, 18, 27])
Enter fullscreen mode Exit fullscreen mode

Поддерживаемые бэкенды Nx:

Nx работает через систему бэкендов, которые определяют, где и как будут выполняться вычисления:

  • EXLA: Интеграция с XLA (Accelerated Linear Algebra) от Google, обеспечивающая компиляцию для CPU, GPU и TPU
  • Torchx: Соединение с PyTorch, использующее его оптимизированные CUDA-операции
  • ONNX: Поддержка Open Neural Network Exchange для совместимости с широким спектром моделей
  • BinaryBackend: Нативная реализация на Elixir, не требующая внешних зависимостей

Выбор бэкенда зависит от задачи и доступного оборудования:

# Глобальное использование EXLA-бэкенда
Nx.global_default_backend(EXLA.Backend)

# Использование PyTorch для конкретной операции
Nx.backend_transfer(tensor, {Torchx.Backend, device: :cuda})
Enter fullscreen mode Exit fullscreen mode

Axon: Нейронные сети с функциональным подходом

Axon — это высокоуровневый фреймворк для определения, обучения и оценки нейронных сетей, построенный поверх Nx. Главная особенность Axon — функциональный дизайн, идеально соответствующий философии Elixir

Особенности Axon:

  • Декларативное определение моделей: Понятный пайплайн-подход к созданию архитектур
  • Встроенные оптимизаторы: Реализации Adam, SGD, RMSProp и других алгоритмов
  • Функции потерь: Широкий набор для различных задач (MSE, кросс-энтропия и др.)
  • Управление обучением: Инструменты для раннего останова, валидации, обратных вызовов

Пример создания и обучения модели классификации:

# Определение модели
model =
  Axon.input("input", shape: {nil, 784})
  |> Axon.dense(512)
  |> Axon.relu()
  |> Axon.dense(10)
  |> Axon.softmax()

# Компиляция и обучение
trained_model =
  model
  |> Axon.Loop.trainer(:categorical_cross_entropy, :adam)
  |> Axon.Loop.metric(:accuracy)
  |> Axon.Loop.run(train_data, epochs: 5, compiler: EXLA)
Enter fullscreen mode Exit fullscreen mode

Расширенные возможности Axon:

Axon поддерживает широкий спектр слоев и архитектур:

  • Сверточные слои: Для задач компьютерного зрения (Axon.conv)
  • Рекуррентные сети: LSTM, GRU для последовательных данных
  • Трансформеры: Внимание, мультиголовое внимание для NLP
  • Нормализация: BatchNorm, LayerNorm для стабилизации обучения
  • Регуляризация: Dropout, L1/L2 для борьбы с переобучением

Пример сверточной сети для классификации изображений:

model =
  Axon.input("input", shape: {nil, 1, 28, 28})
  |> Axon.conv(32, kernel_size: 3, padding: :same)
  |> Axon.relu()
  |> Axon.max_pool(kernel_size: 2)
  |> Axon.conv(64, kernel_size: 3, padding: :same)
  |> Axon.relu()
  |> Axon.max_pool(kernel_size: 2)
  |> Axon.flatten()
  |> Axon.dense(128)
  |> Axon.relu()
  |> Axon.dense(10)
  |> Axon.softmax()
Enter fullscreen mode Exit fullscreen mode

Explorer: Обработка и подготовка данных

Explorer — библиотека для работы с табличными данными, вдохновленная Pandas из Python. Она тесно интегрируется с Nx, позволяя легко преобразовывать данные в тензоры

Ключевые возможности Explorer:

  • DataFrame API: Мощный интерфейс для манипуляций с данными
  • Фильтрация и группировка: Эффективная работа с большими наборами данных
  • Загрузка/сохранение: Поддержка CSV, Parquet, JSON и других форматов
  • Визуализация: Интеграция с Vega-Lite для создания диаграмм

Пример работы с данными:

# Загрузка и обработка данных
df = Explorer.DataFrame.from_csv!("titanic.csv")
  |> Explorer.DataFrame.filter(age > 18)
  |> Explorer.DataFrame.select(["survived", "age", "sex", "fare"])
  |> Explorer.DataFrame.mutate(fare_category: apply(fare, fn fare -> 
    cond do
      fare < 20 -> "low"
      fare < 50 -> "medium"
      true -> "high"
    end
  end))

#### Преобразование в тензоры для ML
features = Explorer.DataFrame.to_nx(df, ["age", "sex", "fare"])
labels = Explorer.DataFrame.to_nx(df, ["survived"])
Enter fullscreen mode Exit fullscreen mode

Bumblebee: Готовые модели для практического применения

Bumblebee — это библиотека, предоставляющая предобученные модели и инструменты для их использования. Bumblebee значительно упрощает работу с современными моделями без необходимости обучать их с нуля

Ключевые возможности:

  • Предобученные модели: BERT, GPT-2, ResNet, CLIP, Stable Diffusion и другие
  • Встроенные пайплайны: Готовые решения для типовых задач
  • Интеграция с Hugging Face: Доступ к тысячам моделей
  • Оптимизированный инференс: Эффективное выполнение на различном оборудовании

Пример использования для анализа тональности текста:

{:ok, model_info} = Bumblebee.load_model({:hf, "distilbert-base-uncased-finetuned-sst-2-english"})
{:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, "distilbert-base-uncased"})

serving = Bumblebee.Text.sentiment(model_info, tokenizer, compile: [batch_size: 1])

Nx.Serving.run(serving, "I love Elixir, it's an amazing language!")
# => %{predictions: [%{label: "POSITIVE", score: 0.998}]}
Enter fullscreen mode Exit fullscreen mode

Nx.Serving: Развертывание моделей в продакшене

Nx.Serving — инструмент для эффективного развертывания ML-моделей в качестве сервисов. Он обеспечивает:

  • Батчинг запросов: Автоматическое группирование для эффективного выполнения
  • Очереди и приоритеты: Управление нагрузкой и распределение ресурсов
  • Горячая замена: Обновление моделей без простоя
  • Мониторинг: Отслеживание производительности и использования ресурсов

Пример создания сервиса для распознавания изображений:

model_info = Bumblebee.load_model({:hf, "microsoft/resnet-50"})
featurizer = Bumblebee.load_featurizer({:hf, "microsoft/resnet-50"})

serving =
  Bumblebee.Vision.image_classification(
    model_info,
    featurizer,
    compile: [batch_size: 8],  # Динамический батчинг
    defn_options: [compiler: EXLA]  # Использование GPU
  )

# Запуск как процесса OTP
{:ok, pid} = Nx.Serving.start_link(serving, name: ImageClassifier)

# Использование
{:ok, image} = Image.from_file("cat.jpg")
Nx.Serving.batched_run(ImageClassifier, image)
Enter fullscreen mode Exit fullscreen mode

LiveBook: Интерактивная разработка и эксперименты

LiveBook — это интерактивная среда для разработки и документирования кода Elixir, идеально подходящая для ML-экспериментов. Она предоставляет:

  • Jupyter-подобный интерфейс: Интерактивные ячейки кода
  • Встроенная визуализация: Диаграммы, графики, таблицы
  • Интеграция с ML-библиотеками: Специальные виджеты для Nx, Axon, Explorer
  • Совместная работа: Возможность делиться ноутбуками и работать над ними вместе
  • Выполнение на GPU: Поддержка аппаратного ускорения

LiveBook существенно упрощает обучение, экспериментирование и документирование ML-проектов на Elixir:

# Пример ячейки LiveBook
Mix.install([
  {:nx, "~> 0.5"},
  {:axon, "~> 0.5"},
  {:explorer, "~> 0.5"},
  {:kino, "~> 0.8"}
])

### Интерактивный ввод гиперпараметров
form = Kino.Control.form(
  [
    learning_rate: Kino.Input.text("Learning rate", default: "0.001"),
    epochs: Kino.Input.range(1..100, default: 10)
  ],
  submit: "Train model"
)
Enter fullscreen mode Exit fullscreen mode

Scholar: Традиционные алгоритмы машинного обучения

Scholar расширяет экосистему Elixir ML классическими алгоритмами, которые часто бывают более подходящими для определенных задач, чем глубокое обучение:

Пример использования линейной регрессии:

import Scholar.Linear.LinearRegression
import Nx.Defn

# Подготовка данных
x = Nx.tensor([[1.0, 1.0], [1.0, 2.0], [2.0, 2.0], [2.0, 3.0]])
y = Nx.tensor([6.0, 8.0, 9.0, 11.0])

# Обучение модели
model = fit(x, y)

# Предсказание
predict(model, Nx.tensor([[3.0, 5.0]]))
# => #Nx.Tensor
#  f32[1]
#  [17.0]
# >
Enter fullscreen mode Exit fullscreen mode

Практическое применение: Интеграция с Phoenix

Отдельно стоит отметить, насколько органично ML-модели интегрируются с веб-фреймворком Phoenix, создавая мощные интеллектуальные веб-приложения:

defmodule MyAppWeb.MLController do
  use MyAppWeb, :controller
  alias Nx.Serving

  # Инициализация модели при старте приложения
  @serving Bumblebee.Text.sentiment(model_info, tokenizer, compile: [batch_size: 4])
  Serving.start_link(@serving, name: SentimentAnalyzer)

  def analyze(conn, %{"text" => text}) do
    # Асинхронный анализ
    Task.async(fn ->
      Serving.batched_run(SentimentAnalyzer, text)
    end)
    |> Task.await()
    |> case do
      %{predictions: [%{label: label, score: score}]} ->
        json(conn, %{sentiment: label, confidence: score})
      _ ->
        conn
        |> put_status(422)
        |> json(%{error: "Analysis failed"})
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Такая интеграция позволяет легко создавать API для анализа текста, классификации изображений, рекомендательных систем и многих других ML-приложений, используя все преимущества BEAM для горизонтального масштабирования и высокой доступности

Экосистема ML в Elixir предлагает сбалансированное сочетание высокоуровневых инструментов и низкоуровневого контроля, позволяя выбрать подходящий уровень абстракции для конкретной задачи. Хотя она еще не так обширна, как Python-экосистема, уникальные преимущества BEAM делают Elixir привлекательным выбором для определенных сценариев машинного обучения, особенно связанных с высоконагруженными системами и обработкой данных в реальном времени

Пример кода для обучения и оценки модели

# Подготовка данных
train_images = train_images |> Nx.reshape({60000, 784}) |> Nx.divide(255.0)
test_images = test_images |> Nx.reshape({10000, 784}) |> Nx.divide(255.0)

# Создание батчей данных
batches =
  Stream.repeatedly(fn ->
    indices = Nx.random_uniform(shape: {32}, min: 0, max: 60000) |> Nx.as_type(:s64)
    x = Nx.take(train_images, indices)
    y = Nx.take(train_labels, indices)
    {x, y}
  end)

# Определение модели с регуляризацией и дропаутом
model =
  Axon.input("input", shape: {nil, 784})
  |> Axon.dense(256, activation: :relu, kernel_regularizer: :l2)
  |> Axon.dropout(rate: 0.4)
  |> Axon.dense(128, activation: :relu)
  |> Axon.dropout(rate: 0.3)
  |> Axon.dense(10, activation: :softmax)

# Обучение с ранним остановом и оптимизацией гиперпараметров
trained_model_state =
  model
  |> Axon.Loop.trainer(:categorical_cross_entropy, Axon.Optimizers.adam(learning_rate: 0.001))
  |> Axon.Loop.metric(:accuracy)
  |> Axon.Loop.validate(test_data)
  |> Axon.Loop.early_stopping("validation_loss", patience: 5)
  |> Axon.Loop.run(batches, epochs: 20, iterations: 1000)

# Оценка модели
test_data = Stream.repeatedly(fn -> {test_images, test_labels} end) |> Stream.take(1)
eval_results =
  model
  |> Axon.Loop.evaluator()
  |> Axon.Loop.metric(:accuracy)
  |> Axon.Loop.run(test_data, trained_model_state)
Enter fullscreen mode Exit fullscreen mode

Сравнение с Python-инструментами

Elixir для ML не стремится полностью заменить Python, а скорее дополняет существующую экосистему:

Критерий Elixir (Nx/Axon) Python (TensorFlow/PyTorch)
Зрелость экосистемы Развивающаяся Зрелая
Производительность Высокая (распределенные системы) Оптимизирована под GPU/TPU
Поддержка железа CPU/GPU (через EXLA) Широкая (CUDA, TPU, ROCm)
Параллелизм Встроенный (BEAM VM) Зависит от библиотек
Доступные модели Ограниченный набор (Bumblebee) Обширные репозитории моделей
Интеграция с веб Нативная (Phoenix LiveView) Через Flask/FastAPI/Django
Развертывание Простое (микс релизы + OTP) Комплексное (Docker/K8s)
Сообщество Растущее Огромное
Документация Качественная (hexdocs) Обширная (но фрагментированная)
Использование в продакшене Erlang-экосистема (WhatsApp, Discord) Лидер индустрии (Google, Meta)

Лучшая стратегия часто заключается в использовании гибридного подхода: обучение моделей на Python и их интеграция в Elixir-системы для инференса

Преимущества Elixir в ML

  1. Распределённые вычисления. BEAM позволяет легко распределять задачи обучения между узлами кластера
  2. Обработка в реальном времени. Благодаря акторам и OTP, Elixir эффективен для потоковой обработки данных (например, в IoT)
  3. Надёжность. Модели могут работать в продакшене с минимальным временем простоя

Ограничения и вызовы

Несмотря на быстрое развитие, экосистема ML в Elixir имеет ряд ограничений:

  • Отсутствие некоторых специализированных алгоритмов и методов оптимизации
  • Меньшая производительность для очень больших моделей по сравнению с оптимизированными Python-библиотеками
  • Ограниченная поддержка TPU
  • Меньше документации и обучающих материалов
  • Не все современные архитектуры (например, некоторые виды трансформеров) имеют эффективные реализации

Практические применения

Когда стоит использовать Elixir для ML:

  • Для интеграции ML в существующие Elixir/Phoenix-приложения
  • В системах, требующих высокой отказоустойчивости и масштабируемости
  • Для обработки данных в реальном времени и онлайн-обучения
  • В распределенных системах, где важен параллелизм

Когда лучше использовать Python:

  • Для исследовательской работы и прототипирования
  • При работе с очень большими моделями (например, большими языковыми моделями)
  • Когда требуются специализированные алгоритмы, доступные только в Python-библиотеках
  • При ограниченном времени на разработку и необходимости использовать готовые решения

Будущее нейросетей на Elixir

Экосистема Elixir для ML ещё молода, но перспективна. Усилия сообщества направлены на:

  • Улучшение интеграции с аппаратным ускорением (GPU/TPU)
  • Расширение списка готовых моделей в Axon
  • Развитие инструментов для обработки данных (Explorer, Scholar)

Заключение

Экосистема ML в Elixir активно развивается благодаря усилиям компаний, таких как Dashbit, и сообщества разработчиков. Для тех, кто хочет глубже погрузиться в тему, рекомендуем следующие ресурсы:


От автора

Благодарю вас за внимание к этой статье! Надеюсь, она помогла вам лучше понять возможности Elixir в сфере машинного обучения и вдохновила на собственные эксперименты с этой мощной комбинацией технологий =)

Экосистема ML в Elixir активно развивается, и я буду рад обсудить любые вопросы, предложения или замечания. Если вы обнаружили неточности в материале или у вас есть интересные дополнения — пожалуйста, напишите об этом в комментариях. Конструктивная обратная связь всегда ценна 😎

Для тех, кому интересно глубже погрузиться в мир технологий, архитектуры и разработки, приглашаю заглянуть в мой телеграм-канал 🖥, где я делюсь рецензиями на технические книги, полезными материалами по Elixir и не только 🤤

Во второй части статьи мы перейдем к практике и создадим полноценный ML-проект на Elixir, так что не пропустите продолжение!

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

If this article connected with you, consider tapping ❤️ or leaving a brief comment to share your thoughts!

Okay