Создаем собственные окружения в Reinforcement Learning. Gymnasium.. Gymnasium. openai gym.. Gymnasium. openai gym. rl.. Gymnasium. openai gym. rl. Stable-Baselines3.. Gymnasium. openai gym. rl. Stable-Baselines3. агент.. Gymnasium. openai gym. rl. Stable-Baselines3. агент. кастомные окружения.. Gymnasium. openai gym. rl. Stable-Baselines3. агент. кастомные окружения. обучение с подкреплением.. Gymnasium. openai gym. rl. Stable-Baselines3. агент. кастомные окружения. обучение с подкреплением. пространство действий.. Gymnasium. openai gym. rl. Stable-Baselines3. агент. кастомные окружения. обучение с подкреплением. пространство действий. функция награды.

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

Обучение с подкреплением (Reinforcement Learning) сейчас переживает ренессанс. Мы видим впечатляющие демонстрации успехов искусственного интеллекта: алгоритмы, обыгрывающие чемпионов в го и StarCraft, управляющие роботами‑гуманоидами и оптимизирующие дата‑центры. Но за этими успехами часто стоит жесткая привязка к конкретному окружению. Стоит немного изменить правила игры, и агент теряется.

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

В этой статье мы разберем, как перейти от использования готовых окружений к созданию собственных — полностью контролируемых и настраиваемых.

Но для начала вспомним основы. Обучение с подкреплением — это парадигма машинного обучения, в которой агент обучается принимать решения путем проб и ошибок в интерактивной среде. Вместо того чтобы получать правильные ответы (как в обучении с учителем), агент совершает действия, за которые среда возвращает ему награду (скалярный сигнал) и новое состояние.

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

Если вы уже работали с Gym/Gymnasium или только разбираетесь в RL, имеет смысл быстро свериться с базой. Короткий бесплатный вступительный тест по Reinforcement Learning поможет понять, какие темы стоит подтянуть перед практикой с собственными окружениями.

Создаем собственные окружения в Reinforcement Learning - 1

Три кита архитектуры среды

Создание кастомной среды для обучения с подкреплением — это не магия, а строгое программирование интерфейса. Подавляющее большинство современных библиотек (начиная с классического OpenAI Gym и заканчивая его форком Gymnasium) следуют одному и тому же шаблону. Ваша среда — это класс, реализующий три ключевых метода:

  • init(): Конструктор. Здесь вы задаете «правила игры»: определяете, что может видеть агент (observation_space) и какие действия он может совершать (action_space). Пространства могут быть дискретными (например, «вверх», «вниз», «влево», «вправо») или непрерывными (например, угол поворота и сила тяги).

  • reset(): Функция перезапуска. Она возвращает среду в исходное состояние в начале новой «жизни» агента (эпизода) и отдает ему первое наблюдение.

  • step(action): Это сердце среды. Получив от агента действие, она просчитывает новое состояние, вычисляет награду (тот самый скаляр, который агент и пытается максимизировать), сигнализирует о завершении эпизода (done) и возвращает всю эту информацию обратно агенту.

Следование этому простому, но строгому интерфейсу — ваше главное преимущество. Оно делает вашу среду совместимой с мощнейшими библиотеками алгоритмов, такими как Stable‑Baselines3, позволяя использовать готовые реализации PPO, DQN и других алгоритмов «из коробки».

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

Создаем собственные окружения в Reinforcement Learning - 2

Также, во многих практических задачах необходимо уметь выходить за рамки «закрытых миров». И хотя традиционные RL‑задачи решаются в «закрытых» средах с четкими границами и правилами, но реальный мир открыт и непредсказуем. Гибкость кастомных сред позволяет приблизиться к этим условиям, создавая симуляции для открытых пространств с меняющимися условиями.

Примером служит российская разработка XLand‑MiniGrid, которая предоставляет среду для контекстного обучения, позволяя агентам мгновенно адаптироваться к новым сценариям.

Создаем собственные окружения в Reinforcement Learning - 3

От идеи к коду

Итак, с теорией обучения с подкреплением, полагаю, всё понятно, и теперь самое время перейти к практике. Итак, представьте, что нам нужно обучить агента проходить лабиринт, избегая ям‑ловушек. Вот как это может выглядеть на практике:

import gymnasium as gym
from gymnasium import spaces
import numpy as np

class MazeGameEnv(gym.Env):
    def init(self, config=None):
        super().__init__()
        # 1. Определяем действия (вверх, вниз, влево, вправо)
        self.action_space = spaces.Discrete(4)
        # 2. Определяем наблюдение (позиция агента [x, y])
        self.observation_space = spaces.Box(low=0, high=4, shape=(2,), dtype=int)
        # 3. Задаем карту (1 - стена, 2 - яма, 3 - цель)
        self.maze_map = self._build_maze()
        self.start_pos = np.array([0, 0])
        self.goal_pos = np.array([4, 4])
        self.state = self.start_pos.copy()

    def reset(self, seed=None, options=None):
        super().reset(seed=seed)
        self.state = self.start_pos.copy()
        return self.state, {}

    def step(self, action):
        # Логика перемещения...
        self.state +=... 



        # Рассчет награды и проверка на завершение
        reward = -1  # Каждый шаг стоит 1 очко, чтобы поощрять кратчайший путь
        terminated = False
        if np.array_equal(self.state, self.goal_pos):
            reward = 100
            terminated = True
        elif self._is_death_pit(self.state):
            reward = -100
            terminated = True
     
        return self.state, reward, terminated, False, {}

Рассмотрим ключевые моменты этого подхода. Прежде всего, это наследование: класс наследуется от gym.Env, что гарантирует его совместимость с экосистемой. Также важным моментом является документирование. У нас все методы должны быть четко документированы для ясности.

И наконец, упаковка. Для удобства использования вашу среду можно оформить как pip‑пакет, зарегистрировав её под уникальным ID (например, Maze‑v0).

Практические рекомендации

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

Прежде, чем писать step(), вам необходимо зафиксировать начальное значение seed для всех генераторов случайных чисел (NumPy, Random, PyTorch). Здесь важно помнить, что воспроизводимость это ваша страховка и баг в среде легче ловить, когда поведение детерминировано.

Затем вручную проиграйте 100 случайных эпизодов и запишите статистику (средняя длина, разброс наград). В результате вы увидите, не слишком ли редко агент получает награду (sparse reward). Если да, то агент рискует никогда не научиться.

Визуализируйте траекторию (хотя бы через matplotlib) на каждом шаге. Глаз мгновенно замечает неправильные перемещения или выход за границы.

И добавьте проверку на бесконечный цикл (max_steps в step() или через truncated), чтобы обучение не зависло на эпизоде‑зомби.

Отдельно хотелось бы остановиться на проектировании функции награды. Награда — это единственный канал обратной связи, и ее дизайн важнее выбора алгоритма. Поэтому начинать надо с плотной награды, а не со спарсенной. То есть вместо reward = 1 только на финише используйте в коде что‑то подобное:

# Плотная награда за приближение к цели
distance_old = np.linalg.norm(self.state - self.goal_pos)
distance_new = np.linalg.norm(new_state - self.goal_pos)
reward = (distance_old - distance_new) * 0.1  # положительно, если приблизился

Так агент получает сигнал на каждом шаге, а не только в конце эпизода. Помимо наград не забываем и о штрафах, но без фанатизма. Штраф -100 за смерть в яме — ок. Но если вы добавите -0.01 за каждый шаг, агент научится замирать. Лучше используйте reward = -1 за шаг — это поощряет кратчайший путь, но не убивает исследование.

Еще одно правило: нормируйте награду по шкале [-1, 1]. Большинство алгоритмов (особенно DQN и PPO) чувствительны к масштабу награды. Если ваша награда колеблется от -1000 до +1000, градиенты будут взрываться. Приводите её к диапазону [-1, 1] через деление на максимально возможное значение.

И не допускайте ошибку новичка: подавать сырые координаты, когда агенту важны относительные данные.

Так не очень хорошая идея передавать абсолютные координаты, так как агент не знает, где цель. Лучше передать ему относительное смещение до цели или полярные координаты + производные [distance_to_goal, angle_to_goal, velocity_x, velocity_y].

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

Итог

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

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

Если хотите разобрать создание RL‑окружений не только на уровне статьи, 7 июля в 20:00 на бесплатном открытом уроке «Обучение с подкреплением — гибкий подход для сложных задач. Создаем собственные окружения» покажем, как спроектировать среду под нестандартную задачу и обучить в ней агента. Можно будет сверить подход, задать вопросы и понять, какие темы стоит подтянуть дальше.

Больше открытых уроков июля смотрите в дайджесте.

Автор: Andrey_Biryukov

Источник