Я хотел попробовать QMIX-реализацию библиотеки Ray / Rllib, но должно быть что-то не так в том, как я ее использую, потому что она, кажется, ничего не изучает. Поскольку я новичок в Ray / Rllib, я начал с примера «TwoStepGame», который библиотека предоставляет в качестве примера на репозитории github (https://github.com/ray-project/ray/blob/master/rllib/examples/twostep_game.py), пытаясь понять, как его использовать. Поскольку для начала этот пример был немного сложным для меня, я настроил его так, чтобы сделать пример максимально простым. Проблема: Qmix, кажется, не учится, означает, что полученное вознаграждение в значительной степени соответствует ожидаемому значению случайной политики.
Позвольте мне объяснить идею моего очень простого эксперимента. У нас есть 2 агента. Каждый агент может совершить 3 действия (Discrete(3)
). Если он выполняет действие 0, он получает вознаграждение 0,5, а не 0. Так что это должно быть очень простым заданием, поскольку лучшая политика - это просто выполнение действия 0.
Вот моя реализация:
from gym.spaces import Tuple, MultiDiscrete, Dict, Discrete
import numpy as np
import ray
from ray import tune
from ray.tune import register_env, grid_search
from ray.rllib.env.multi_agent_env import MultiAgentEnv
from ray.rllib.agents.qmix.qmix_policy import ENV_STATE
class TwoStepGame(MultiAgentEnv):
action_space = Discrete(3)
def __init__(self, env_config):
self.counter = 0
def reset(self):
return {0: {'obs': np.array([0]), 'state': np.array([0])},
1: {'obs': np.array([0]), 'state': np.array([0])}}
def step(self, action_dict):
self.counter += 1
move1 = action_dict[0]
move2 = action_dict[1]
reward_1 = 0
reward_2 = 0
if move1 == 0:
reward_1 = 0.5
if move2 == 0:
reward_2 = 0.5
obs = {0: {'obs': np.array([0]), 'state': np.array([0])},
1: {'obs': np.array([0]), 'state': np.array([0])}}
done = False
if self.counter > 100:
self.counter = 0
done = True
return obs, {0: reward_1, 1: reward_2}, {"__all__": done}, {}
if __name__ == "__main__":
grouping = {"group_1": [0, 1]}
obs_space = Tuple([
Dict({
"obs": MultiDiscrete([2]),
ENV_STATE: MultiDiscrete([3])
}),
Dict({
"obs": MultiDiscrete([2]),
ENV_STATE: MultiDiscrete([3])
}),
])
act_space = Tuple([
TwoStepGame.action_space,
TwoStepGame.action_space,
])
register_env("grouped_twostep",
lambda config: TwoStepGame(config).with_agent_groups(
grouping, obs_space=obs_space, act_space=act_space))
config = {
"mixer": grid_search(["qmix"]),
"env_config": {
"separate_state_space": True,
"one_hot_state_encoding": True
},
}
ray.init(num_cpus=1)
tune.run(
"QMIX",
stop={
"timesteps_total": 100000,
},
config=dict(config, **{
"env": "grouped_twostep",
}),
)
и вот результат вывода, когда я запускаю его для 100 000 временных шагов
+----------------------------+------------+-------+---------+--------+------------------+--------+----------+
| Trial name | status | loc | mixer | iter | total time (s) | ts | reward |
|----------------------------+------------+-------+---------+--------+------------------+--------+----------|
| QMIX_grouped_twostep_00000 | TERMINATED | | qmix | 100 | 276.796 | 101000 | 33.505 |
+----------------------------+------------+-------+---------+--------+------------------+--------+----------+
Process finished with exit code 0
Как видите, политика кажется случайной, поскольку ожидаемое значение равно 1/3, а итоговое вознаграждение составляет 33.505 (потому что я перезагружаю среду каждые 100 шагов). Мой вопрос: что я не понимаю? Должно быть что-то не так с моей конфигурацией или, возможно, моим пониманием того, как работает rllib. Но поскольку лучшая политика очень проста (просто всегда выполняйте действие 0), мне кажется, что этот алгоритм не может выучить.