RLtools: быстрая портативная библиотека глубокого обучения с подкреплением для непрерывного управления

7.5/10

Jonas Eschmann · New York University · Dario Albani · Technology Innovation Institute · Giuseppe Loianno · New York University

Оригинал: Eschmann, J., Albani, D., Loianno, G. «RLtools: A Fast, Portable Deep Reinforcement Learning Library for Continuous Control», Journal of Machine Learning Research 25(301), 2024 — arxiv.org/abs/2306.03530 (PDF).

Код: github.com/rl-tools/rl-tools · документация и демо: rl.tools

Рисунки воспроизведены из оригинальной публикации. Оригинал распространяется по лицензии CC BY 4.0; перевод выполнен на её условиях, изменение по отношению к оригиналу — перевод на русский язык.

Ключевые слова: reinforcement learning, continuous control, deep learning, TinyRL.

Аннотация

Глубокое обучение с подкреплением (RL) способно давать эффективных агентов и управляющие политики в ряде предметных областей, но часто страдает от неприемлемо долгого обучения. Кроме того, в задачах непрерывного управления применимость выученных политик на реальных встраиваемых устройствах ограничена отсутствием real-time гарантий и портируемости существующих библиотек. Чтобы решить эти проблемы, мы представляем RLtools — библиотеку глубокого обучения с подкреплением и с учителем на чистом C++ без зависимостей, в формате header-only. Новая архитектура позволяет использовать RLtools на широком спектре платформ: от HPC-кластеров и рабочих станций до смартфонов, смарт-часов и микроконтроллеров. Благодаря плотной интеграции RL-алгоритмов со средой симуляции RLtools решает популярные RL-задачи до 76 раз быстрее других распространённых фреймворков. Мы также бенчмаркуем inference на разнообразном наборе микроконтроллеров и показываем, что в большинстве случаев наша оптимизированная реализация — самая быстрая. Наконец, RLtools демонстрирует первое в истории обучение алгоритма глубокого RL непосредственно на микроконтроллере, открывая область Tiny Reinforcement Learning (TinyRL). Исходный код, документация и live-демо доступны на странице проекта rl.tools.

1. Введение

Непрерывное управление — повсеместная задача в робототехнике, высокочастотном принятии решений на финансовых рынках, автоматизации химических производств и инфраструктуре smart grid. Используя прогресс глубокого обучения (DL), перетекающий в принятие решений в форме RL, агенты на базе deep RL уже достигли впечатляющих результатов в играх и особенно в непрерывном управлении. Несмотря на это, практическое внедрение RL для непрерывного управления сдерживают неприемлемо долгое обучение и отсутствие поддержки развёртывания обученных политик на встраиваемых устройствах.

Долгое обучение мешает быстрой итерации в пространстве задач (дизайн функции вознаграждения, подбор гиперпараметров и т.д.), а развёртывание на вычислительно ограниченных встраиваемых платформах необходимо для управления большинством физических систем: роботами, автомобильными компонентами, медицинскими приборами, smart grid и др. В нефизических системах, таких как финансовые рынки, потребность в высокочастотном принятии решений ведёт к схожим real-time требованиям, которые текущие deep RL библиотеки не выполняют.

Чтобы решить эти вызовы, мы представляем RLtools — header-only библиотеку на чистом C++ без зависимостей для глубокого обучения с учителем и с подкреплением, объединяющую следующие вклады:

2. Связанные работы

Предложено множество deep RL фреймворков и библиотек. Многие ориентированы на алгоритмические исследования — с абстракциями или без (Acme (Hoffman et al., 2020), skrl (Serrano-Muñoz et al., 2023) и CleanRL (Huang et al., 2022) соответственно). Другие фокусируются на полноте набора алгоритмов: RLlib (Liang et al., 2018), ReinforcementLearning.jl (Tian, 2020), MushroomRL (D'Eramo et al., 2021), Stable-Baselines3 (Raffin et al., 2021), ChainerRL (Fujita et al., 2021), Tianshou (Weng et al., 2022), TorchRL (Bou et al., 2024).

В отличие от них, RLtools нацелен на быструю итерацию в пространстве задач — например, дизайн функции вознаграждения (Eschmann, 2021) и оптимизацию гиперпараметров. В пространстве задач алгоритмические тонкости и разнообразие алгоритмов менее важны, чем робастность, скорость обучения, итоговая производительность и понимание того, как обучать их надёжно. Из перечисленных фреймворков RLlib (Liang et al., 2018) наиболее близок по миссии — быстрая итерация и развёртывание (ср. бенчмарки в разделе 4). Сосредоточившись на итерации в пространстве задач и последующем развёртывании на real-time платформах, мы проводим параллель между RLtools и ПО ACADOS (Verschueren et al., 2022) для синтеза MPC: RLtools стремится стать его RL-эквивалентом.

3. Подход

За последние годы в RL для непрерывного управления наиболее распространённые аппроксиматоры функций остаются относительно небольшими полносвязными нейросетями. В приложении A мы анализируем архитектуры из ключевых публикаций и обосновываем фокус RLtools на (небольших) MLP. Из этого следует, что гибкость фреймворков автоматического дифференцирования вроде TensorFlow или PyTorch может быть избыточной для многих задач непрерывного управления. Мы считаем выгодным обменять гибкость архитектуры аппроксиматора на общую скорость обучения. Сокращение времени обучения экономит энергию, упрощает воспроизводимость и демократизирует доступ к state-of-the-art RL. Быстрое обучение также облегчает систематический поиск гиперпараметров и улучшает сопоставимость результатов.

Архитектура

Архитектура ПО направлена на максимизацию эффективности обучения без потери returns. ПО должно работать на разных ускорителях и устройствах (CPU, GPU, микроконтроллеры и др.), чтобы обученные политики можно было напрямую развернуть на микроконтроллерах с device-specific инструкциями, обеспечивающими высокую частоту и жёсткие real-time гарантии. Это также означает отсутствие внешних зависимостей — они могут быть недоступны на целевых микроконтроллерах.

Для максимальной производительности компоненты интегрируются настолько плотно, насколько нужно, сохраняя модульность. Мы активно используем систему шаблонов C++. Template meta-programming даёт компилятору максимум информации о структуре кода для агрессивной оптимизации. Размеры всех циклов известны на этапе компиляции — компилятор может инлайнить и развернуть циклы (см. приложения B и F).

На чистом C++ без зависимостей реализованы: глубокое обучение (MLP, backpropagation, Adam и др.), RL (GAE, PPO, TD3, SAC) и симуляция (Pendulum, Acrobot, квадрокоптер, гоночный автомобиль, интерфейс MuJoCo). RLtools модульна благодаря новой парадигме статического multiple dispatch, вдохновлённой (динамическим) multiple dispatch из Julia (Bezanson et al., 2012). Рекомендуем пример кода в приложении B и ablation study в приложении F.

4. Результаты

Горизонтальный бенчмарк

На рисунках 1 и 2 — среднее время обучения PPO и SAC за десять запусков на ноутбуке на Intel (детали в таблице 6). RLtools опережает существующие библиотеки с большим отрывом: PPO в среднем 0,54 с (SAC — 2,59 с).

Рисунок 1
Рисунок 1. PPO: Pendulum-v1 (300 000 шагов). Время обучения [с] (меньше — лучше). Базовая линия RLtools: 1,0× = 0,54 с.
Рисунок 2
Рисунок 2. SAC: Pendulum-v1 (10 000 шагов). Сравнение wall-clock времени обучения с другими библиотеками.

Вертикальный бенчмарк

На рисунке 3 — результаты обучения RLtools на широком спектре устройств, несовместимых с другими RL-библиотеками. Важно, мы демонстрируем первое обучение deep RL агента для непрерывного управления на микроконтроллере Teensy 4.1.

Рисунок 3
Рисунок 3. SAC: Pendulum-v1 (10 000 шагов) на различных платформах — от ноутбука и MacBook до iPhone, Apple Watch и микроконтроллеров.

Inference на микроконтроллерах

Таблица 1 показывает время inference на микроконтроллерах разной вычислительной мощности (Crazyflie — 27-граммовый квадрокоптер с очень ограниченными ресурсами, см. приложение E). Generic-реализация уже даёт приемлемое время, но dispatch к DSP-библиотеке производителя улучшает производительность. Дополнительная оптимизация (например, fusion операторов активации) даёт значительное ускорение даже относительно DSP-библиотек производителя.

Таблица 1. Время inference на разных платформах (политика [64, 64], ReLU; см. таблицу 5).
ПлатформаRLtools: GenericDSP LibraryRLtools: Optimized
Crazyflie743 µs (1,3 kHz)478 µs (2,1 kHz)293 µs (3,4 kHz)
Pixhawk 6C133 µs (7,5 kHz)93 µs (10,8 kHz)53 µs (18,8 kHz)
Teensy 4.164 µs (15,5 kHz)45 µs (22,3 kHz)41 µs (24,3 kHz)
ESP32 (Xtensa)4282 µs (234 Hz)279 µs (3,6 kHz)333 µs (3 kHz)
ESP32-C3 (RISC-V)8716 µs (115 Hz)6950 µs (144 Hz)6645 µs (150 Hz)

5. Заключение

Мы считаем, что RLtools заполняет пробел: быстрая итерация в пространстве задач и последующее real-time развёртывание политик. Кроме того, RLtools впервые делает возможным обучение deep RL на микроконтроллере. Мы признаём более крутую кривую обучения C++ (по сравнению с Python), но по нашему опыту более быстрая итерация за счёт короткого обучения может перевесить начальные затраты. Сейчас RLtools ограничен плотными наблюдениями; планируем добавить vision. Снижая требования к вычислениям и будучи полностью open-source, RLtools демократизирует обучение state-of-the-art RL и ускоряет прогресс в непрерывном управлении.

Благодарности и раскрытие финансирования

Работа поддержана Technology Innovation Institute, NSF CAREER Award 2145277 и DARPA YFA Grant D22AP00156-00. Giuseppe Loianno консультирует Technology Innovation Institute. Эта договорённость проверена и одобрена New York University в соответствии с политикой объективности исследований.

Приложение A. Анализ ландшафта deep RL

В этом разделе мы анализируем модели аппроксиматоров функций из ключевых публикаций по deep RL для непрерывного управления (таблица 2 и таблица 7). Главное наблюдение: за все годы архитектура (небольшие полносвязные сети) не изменилась. В непрерывном управлении наблюдения — обычно плотные состояния системы без пространственной или временной структуры, как у изображений или временных рядов, что не требует CNN или RNN. Эта регулярность мотивирует фокус RLtools на оптимизации и плотной интеграции MLP как первый шаг; в будущем планируем recurrent и, возможно, свёрточные слои.

Таблица 2. Выборка работ, введших значимые алгоритмы, и размерности нейросетей для аппроксимации value function. Число параметров при входе 20 и выходе 1; TRPO = 1,0×.
ГодНазваниеHidden Dim#ParamsНелинейность
2015TRPO (Schulman et al.)[50, 50]1,0×tanh
2015GAE (Schulman et al.)[100, 50, 25]2,3×tanh
2016DDPG (Lillicrap et al.)[400, 300]35,3×ReLU
2017PPO (Schulman et al.)[64, 64]1,5×tanh
2018TD3 (Fujimoto et al.)[400, 300]35,3×ReLU
2018SAC (Haarnoja et al.)[256, 256]19,6×ReLU
2019SACv2 (Haarnoja et al.)[256, 256]19,6×ReLU
2020TQC (Kuznetsov et al.)[512, 512, 512]147,0×ReLU
2020D4PG&TD3 (Bach et al.)[256, 256]19,6×ReLU
2021PPO&RMA (Kumar et al.)[128, 128, 128]9,8×ReLU

Приложение B. Парадигма программирования

Для максимальной производительности мы избегаем lookup в таблице виртуальных методов C++ (VMT), не используя классическую ОО-парадигму, а опираясь на функциональный стиль с шаблонами и перегрузкой — статическую compile-time интерпретацию multiple dispatch.

// file: implementation_generic.h
template <typename DEVICE, auto M, auto N, auto K>
void multiply(DEVICE device, Matrix<M, K> a, Matrix<K, N> b, Matrix<M, N> result){
  // Generic code for matrix multiplication
  ...
}
// file: implementation_microcontroller.h
template <auto M, auto N, auto K>
void multiply(MICROCONTROLLER device, Matrix<M, K> a, Matrix<K, N> b, Matrix<M, N> result){
  // Optimized code for matrix multiplication on a particular microcontroller
  ...
}
// file: implementation_gpu.h
template <auto M, auto N, auto K>
void multiply(GPU device, Matrix<M, K> a, Matrix<K, N> b, Matrix<M, N> result){
  // Optimized GPU code for matrix multiplication
  ...
}
template<typename DEVICE, typename OBJECT_A, typename OBJECT_B, typename OBJECT_C>
void algorithm(DEVICE device, OBJECT_A a, OBJECT_B b, OBJECT_C c){
  ...
  multiply(device, a, b, c);
  ...
}
Рисунок 4
Рисунок 4. Упрощённый пример tag dispatch для разных реализаций элементарных матричных операций.

Multiple dispatch популяризован Julia (Bezanson et al., 2012) и основан на продвинутой перегрузке функций. Высокоуровневые функции (forward/backward pass MLP) задают действия на подкомпонентах, а конкретная реализация зависит от типов аргументов. Так легко делить код между GPU и CPU: достаточно реализовать низкоуровневые примитивы для каждого типа устройства и сигнализировать тип через tag dispatch. Если специализированной реализации нет, компилятор использует generic-версию (например, вложенные циклы) — чистый C++ без зависимостей. Размеры операндов проверяются на этапе компиляции. Для сложного dispatch используются static_assert и enable_if через SFINAE.

В Julia multiple dispatch разрешается в runtime, что даёт высокую композируемость (Flux (Innes, 2018) конкурирует с PyTorch при меньших ресурсах). Мы же разрешаем все вызовы на этапе компиляции. Julia не подходит для микроконтроллеров из-за размера runtime и недетерминированного GC-поведения. Тем не менее в наших бенчмарках Julia — один из ближайших конкурентов по скорости обучения.

Мы строим библиотеку, а не фреймворк. Фреймворки ограничивают свободу пользователя ради упрощения узкого набора задач; накладные расходы на крутую кривую обучения и обход ограничений не всегда оправданы. Фреймворки вызывают код пользователя из своего контекста; библиотеки — пользователь полностью контролирует вызов компонентов. Контексты фреймворков обычно несовместимы; библиотеки — совместимы по умолчанию.

В RLtools любой тип аппроксиматора функции задаётся пользователем на этапе компиляции через шаблоны — при условии, что предоставлены forward и backward. Установлена конвенция передавать device-контекст в каждую функцию через tag dispatch для упрощения работы с разными вычислительными устройствами.

Приложение C. Детали бенчмарков

Таблица 3. Гиперпараметры PPO для Pendulum-v1 (рисунок 1).
Структура актора / критика[64, 64]
Функция активацииReLU
Batch size256
Число сред4
Шагов на среду1024
Число эпох2
Всего шагов среды300 000
Discount factor $\gamma$0,9
GAE $\lambda$0,95
$\epsilon$ clip0,2
Коэффициент энтропии $\beta$0
Нормализация advantagetrue
Adam $\alpha$, $\beta_1$, $\beta_2$, $\epsilon$$10^{-3}$, 0,9, 0,999, $10^{-7}$
Таблица 4. Гиперпараметры SAC для Pendulum-v1 (рисунок 2).
Структура актора / критика[64, 64], ReLU
Batch size100
Всего шагов10 000
Размер replay buffer10 000
$\gamma$0,99
Entropy bonus $\alpha$ (обучаемый, нач.)0,5
Polyak $\beta$0,99
Adamкак в таблице 3
Таблица 5. Параметры on-device inference (таблица 1).
Размерность входа13
Структура политики[64, 64]
Размерность выхода4
АктивацияReLU
Таблица 6. Платформы для SAC Pendulum-v1 (рисунок 3).
МеткаДетали
Laptop (CPU) / Laptop (Web)Intel i9-10885H
Laptop (GPU)Intel i9-10885H + Nvidia T2000
MacBook (CPU) / MacBook (Web)MacBook Pro (M3 Pro)
iPhone (Native) / iPhone (Web)iPhone 14
Apple Watch (Native)Apple Watch Series 4
RLtools / Baselineсм. горизонтальный бенчмарк

Приложение D. Фреймворки и библиотеки deep RL

Таблица 7. Обзор RL-библиотек: платформа DL, популярность (GitHub stars / цитирования, данные на 2024-02-07).
НазваниеПлатформаStars / Citations
Acme (Hoffman et al., 2020)JAX3316 / 219
CleanRL (Huang et al., 2022)PyTorch4030 / 86
MushroomRL (D'Eramo et al., 2021)TF/PyTorch749 / 61
PFRL / ChainerRL (Fujita et al., 2021)PyTorch1125 / 122
ReinforcementLearning.jl (Tian, 2020)Flux.jl (Julia)543 / n/a
RLlib + ray (Liang et al., 2018)PyTorch29 798 / 828
Stable Baselines3 (Raffin et al., 2021)PyTorch7396 / 1149
Stable Baselines JAX (SBX)JAX223 / n/a
Tianshou (Weng et al., 2022)PyTorch7139 / 133
TorchRL (Bou et al., 2024)PyTorch1691 / 5

Приложение E. Встраиваемые платформы

  1. Crazyflie — небольшой open-source квадрокоптер массой 27 г с батареей. Основной процессор STM32F405 (ARM Cortex-M4), 192 KB RAM, 168 MHz.
  2. Pixhawk 6C — используем Pixracer Pro (FCU семейства Pixhawk, стандарт Pixhawk 6C), поддерживает прошивку PX4 (Meier et al., 2015) для разных типов аппаратов. Процессор STM32H743 (ARM Cortex-M7), 460 MHz, 1024 KB RAM.
  3. Teensy 4.1 — универсальное встраиваемое устройство на i.MX RT1060 (ARM Cortex-M7), 1024 KB on-chip и 16 MB off-chip RAM, 600 MHz.
  4. ESP32 — один из самых распространённых IoT/edge микроконтроллеров со встроенными Wi-Fi и Bluetooth; продано около миллиарда устройств на этой и предыдущей версии чипа (~$5 за dev kit). Процессор Xtensa LX7; также оцениваем ESP32-C3 на RISC-V.

Приложение F. Ablation study

Мы проводим ablation study, чтобы оценить вклад компонентов и оптимизаций в быстрое wall-clock обучение RLtools. На рисунке 5 — время обучения после удаления разных компонент. «Baseline» — та же конфигурация, что в эксперименте SAC Pendulum-v1 в разделе 4.

Мы симулируем медлительность Python-среды, замедляя C++-реализацию на среднее время шага Python-версии. C++-реализация динамики Pendulum-v1 даёт измеримый, но не доминирующий вклад. Аблируем уровни оптимизации компилятора -O0-O3 (baseline использует -O3): при -O0 RLtools примерно между ACME и CleanRL (рисунок 2). Конфигурация «No Fast Math» убирает -ffast-math; «BLAS» — Intel oneMKL для умножения матриц; «AVX/AVX2» отключает векторные расширения.

Благодаря дизайну RLtools (приложение B), когда размеры циклов и структур данных известны на этапе компиляции, компилятор активно использует SIMD. Из 11 243 машинных инструкций 2276 + 1430 = 3706 (AVX + SSE) относятся к векторным регистрам. При отключении AVX компилятор заменяет инструкции на SSE (5406 из 11 243), что демонстрирует «дружелюбность» архитектуры к компилятору.

Рисунок 5
Рисунок 5. Ablation study. «Baseline» включает все оптимизации.

Приложение G. Исследование сходимости

Чтобы убедиться в корректности реализаций PPO, TD3 и SAC, мы сравниваем кривые обучения с другими реализациями на одинаковых гиперпараметрах. Для Pendulum-v1 — 100 seeds, для Hopper-v4 — 30; на каждом шаге оценки — 100 эпизодов со случайными начальными состояниями.

Даже при большом числе seeds выбросы существенно влияют на средний финальный return. По рекомендации Agarwal et al. (2021) мы отчитываем Inter Quantile Mean (IQM), отбрасывая нижний и верхний квантили (по 5 %). Для идентичности сред вместо переимплементации в C++ построен Python-обёртка RLtools для сред Gymnasium (Towers et al.). Обёртка упрощает использование, но снижает производительность, если среда на Python (см. приложение F).

Рисунок 6
Рисунок 6. PPO Pendulum-v1 — сравнение сходимости с другими библиотеками.
Рисунок 7
Рисунок 7. PPO Hopper-v4.
Рисунок 8
Рисунок 8. PPO Ant-v4.
Рисунок 9
Рисунок 9. SAC Pendulum-v1.
Рисунок 10
Рисунок 10. SAC Hopper-v4.
Рисунок 11
Рисунок 11. SAC Ant-v4.
Рисунок 12
Рисунок 12. TD3 Pendulum-v1.
Рисунок 13
Рисунок 13. TD3 Hopper-v4.
Рисунок 14
Рисунок 14. TD3 Ant-v4.

Литература

Оригинал статьи: Eschmann, J., Albani, D., Loianno, G., «RLtools: A Fast, Portable Deep Reinforcement Learning Library for Continuous Control», JMLR 25(301), 2024 · код: rl-tools/rl-tools · лицензия CC BY 4.0