Не удалось достичь такой же хорошей производительности PPO с MAPPO.

Вопрос или проблема

У меня есть многопользовательская среда, основанная на боидов, использующая gymnasium. Я использовал PPO с политикой Mlp и сетью из 8 слоев по 512 нейронов в каждом слое. Хотя я достиг объединения, это было централизованное решение.

Результаты:
Объединение (Централизованный PPO)

Сеть:

policy_kwargs = dict(
    activation_fn=th.nn.Tanh,  # Использование функции активации ReLU
    net_arch=[dict(pi=[512, 512, 512, 512, 512, 512, 512, 512], 
                   vf=[512, 512, 512, 512, 512, 512, 512, 512])]  # Отдельные сети для политики (pi) и функции ценности (vf)
)

Код обучения:

model = PPO("MlpPolicy", env, kwargs=policy_kwargs tensorboard_log="./ppo_Agents_tensorboard/", verbose=1, device=device)
model.set_random_seed(SimulationVariables["ModelSeed"])

Моя цель, однако, состоит в том, чтобы создать децентрализованную версию Это по сути MAPPO (PPO с децентрализованными акторами, но с общим критиком, как утверждается, это хорошо для группового поведения, в отличие от IPPO — полностью децентрализованного). Вот почему я создал индивидуальную политику сети следующим образом с SB3:

class CustomMultiAgentPolicy(ActorCriticPolicy):  # Убедитесь, что наследуетесь от правильного родительского класса
    def __init__(self, observation_space, action_space, lr_schedule, **kwargs):
        super(CustomMultiAgentPolicy, self).__init__(observation_space, action_space, lr_schedule, **kwargs)

        self.obs_size = observation_space.shape[0] # только это в соответствии с вашей структурой наблюдения
        self.hidden_size = 128  # Вы можете изменить это в зависимости от ваших потребностей
        self.action_space = action_space

        self.actor = CustomActor(observation_space, action_space)
        self.critic = SharedCritic(observation_space)

    def forward(self, obs, **kwargs):
        action_mean = self.actor(obs)  # Это среднее нормального распределения

        # Создайте нормальное распределение со средним значением и log_std (преобразованным в std)
        # action_std = th.exp(self.log_std)  # Преобразуйте log_std в std
        action_std = th.clamp(th.exp(self.log_std), min=1e-3, max=1.0)  # Стабилизируйте std

        action_distribution = th.distributions.Normal(action_mean, action_std)

        # Выбор действий и получение логарифмических вероятностей
        actions = action_distribution.sample()
        log_probs = action_distribution.log_prob(actions).sum(dim=-1)  # Сумма по измерениям действия

        values = self.critic(obs)

        # Убедитесь, что действия соответствуют ожидаемой форме для среды (в вашем случае, [1, 6])
        return actions, values, log_probs

Независимый актор и общий критик:

class CustomActor(th.nn.Module):
    def __init__(self, observation_space, action_space):
        super(CustomActor, self).__init__()
        self.device = th.device("cuda" if th.cuda.is_available() else "cpu")

        # Создайте 8 слоев с 512 нейронами каждый
        self.layers = th.nn.ModuleList()
        input_size = observation_space.shape[0]

        for _ in range(8):
            layer = th.nn.Linear(input_size, 512).to(self.device)  # Переместите слой на устройство
            self.layers.append(layer)
            input_size = 512  # Обновите размер ввода для следующего слоя

        # Обновите голову действия в зависимости от типа пространства действий
        if isinstance(action_space, spaces.Box):  # Непрерывное пространство действий
            self.action_head = th.nn.Linear(512, action_space.shape[0]).to(self.device)
        elif isinstance(action_space, spaces.Discrete):  # Дискретное пространство действий
            self.action_head = th.nn.Linear(512, action_space.n).to(self.device)
        else:
            raise NotImplementedError("Тип пространства действий не поддерживается")

    def forward(self, x):
        # Преобразуйте ввод в тензор torch, если это массив numpy, и переместите его на правильное устройство
        if isinstance(x, np.ndarray):
            x = th.tensor(x, dtype=th.float32).to(self.device)  # Переместите на устройство здесь

        # Пропустите ввод через слои сети
        for layer in self.layers:
            # print(f"layer weight device: {layer.weight.device}")  # Печать внутри цикла
            x = F.relu(layer(x))  # Все слои должны уже находиться на self.device

        # Получите логиты действий из головы действия
        action_logits = self.action_head(x)  # action_head также должен находиться на том же устройстве

        return action_logits
class SharedCritic(th.nn.Module):
    def __init__(self, observation_space):
        super(SharedCritic, self).__init__()

        # Создайте 8 слоев с 512 нейронами каждый
        self.layers = th.nn.ModuleList()
        input_size = observation_space.shape[0]

        for _ in range(8):
            self.layers.append(th.nn.Linear(input_size, 512))  # Переместите на устройство в методе forward, если это необходимо
            input_size = 512  # Обновите размер ввода для следующего слоя

        self.value_head = th.nn.Linear(512, 1)

    def forward(self, x):
        # Преобразуйте ввод в тензор torch, если это массив numpy
        if isinstance(x, np.ndarray):
            x = th.tensor(x, dtype=th.float32)

        for layer in self.layers:
            x = F.relu(layer(x))
        value = self.value_head(x)
        return value

Мои результаты с этим, несмотря на то что я абсолютно ничего не изменил, кроме сети, составляют 180 к тому, что должно быть (пробовал с аналогичным количеством временных шагов и меньшим тоже).

Результаты (MAPPO) Они движутся в совершенно разные стороны, несмотря на то, что моя функция вознаграждения осталась неизменной.

Функция вознаграждения:

CohesionReward = 0
        AlignmentReward = 0
        total_reward = 0
        outofflock = False
        midpoint = (SimulationVariables["SafetyRadius"] + SimulationVariables["NeighborhoodRadius"]) / 2

        if len(neighbor_positions) > 0:
            for neighbor_position in neighbor_positions:
                distance = np.linalg.norm(agent.position - neighbor_position)

                if distance <= SimulationVariables["SafetyRadius"]:
                    CohesionReward -= 10
                elif SimulationVariables["SafetyRadius"] < distance <= midpoint:
                    CohesionReward += 20 - (20 / (midpoint - SimulationVariables["SafetyRadius"])) * (distance - SimulationVariables["SafetyRadius"])
                elif midpoint < distance <= SimulationVariables["NeighborhoodRadius"]:
                    CohesionReward += 10 - (10 / (SimulationVariables["NeighborhoodRadius"] - midpoint)) * (distance - midpoint)

                average_velocity = np.mean(neighbor_velocities, axis = 0)
                dot_product = np.dot(average_velocity, agent.velocity)
                norm_product = np.linalg.norm(average_velocity) * np.linalg.norm(agent.velocity)

                if norm_product == 0:
                    cos_angle = 1.0
                else:
                    cos_angle = dot_product / norm_product

                cos_angle = np.clip(cos_angle, -1.0, 1.0)
                orientation_diff = np.arccos(cos_angle)
                alignment = (orientation_diff / np.pi)
                AlignmentReward = -20 * alignment + 10  

        else:
            CohesionReward -= 20
            outofflock = True

        total_reward = CohesionReward + AlignmentReward
return total_reward, outofflock

Ответ или решение

Проблема с производительностью MAPPO по сравнению с PPO в окружении многоместного боидного роя

Введение

Работа с многопользовательскими средами в области обучения с подкреплением (RL) требует тонкой настройки как алгоритмов обучения, так и архитектуры нейронных сетей. В вашем случае вы столкнулись с проблемой снижения производительности при переходе от централизованного метода PPO к многопользовательскому MAPPO, что является довольно распространенной проблемой. Давайте подробно разберем возможные причины этого поведения и предложим пути их решения.

Архитектура нейронной сети

Вы используете глубокую нейронную сеть с 8 скрытыми слоями по 512 нейронов в каждом, что является значительной архитектурой. Однако при переходе к MAPPO необходимо обратить внимание на распределение нагрузки и потребности в параметрах:

  1. Параметры сети: Обратите внимание, что использование большого количества параметров может привести к переобучению, особенно в децентрализованной среде. Для MAPPO вам может потребоваться настройка размера сети, чтобы избежать переобучения.

  2. Адаптация сети: Убедитесь, что ваша CustomMultiAgentPolicy и ее компоненты (CustomActor и SharedCritic) имеют соответствующую архитектуру для децентрализованного обучения. Проверка корректности передачи тензоров между устройствами также важна, чтобы избежать неожиданного поведения.

Обеспечение совместного критика

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

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

  2. Совместное состояние: Проверьте, что ваши наблюдения передаются корректно, и структура состояния (например, наличие информации о других агентах) выглядит так же, как и в PPO.

Проверьте стратегию наград

Вы используете фиксированную функцию награды, но в контексте децентрализованного обучения её стоит дополнительно протестировать:

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

  2. Награда за "выход из стаи": Проверка на разные ситуации может быть полезной для устранения проблем, связанных с поведением, когда агент оказывается вне группы. Возможно, стоит более жестко наказывать за это, или модель должна иметь четкие сигналы, когда «выход из роя» заслуживает поощрения.

Обучение и гиперпараметры

Переход с PPO на MAPPO часто требует пересмотра гиперпараметров:

  1. Learning Rate: Настройка параметров обучения в децентрализованной среде может потребовать более тонкой настройки learning rate.

  2. Масштабируемость: Проверьте batch size и количество временных шагов (timesteps), которые вы используете для обучения. Для MAPPO может потребоваться больше или меньше данных для достижения приемлемой производительности.

  3. Частота обновления: Подумайте о том, как часто обновляется общий критик по сравнению с индивидуальными акторами. Настройка этого параметра может существенно повлиять на обучение.

Заключение

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

Предлагаем вам тщательно пересмотреть свою реализацию с учетом данной информации и провести дополнительные эксперименты для нахождения оптимальных параметров и архитектуры. Успехов в ваших исследованиях!

Оцените материал
Добавить комментарий

Капча загружается...