<jupyter_start><jupyter_text>Meta-Learning-Shared-HieariesВ [статье](https://arxiv.org/pdf/1710.09767.pdf) рассматривается подход к обучению иерархический политики.Основная цель данного метода - быстрое дообучение политики под новую задачу (модель не видела их в процессе обучения). ИдеяМодель имеет иерархическую структуру и состоит из *мастер политики* обучаемой отдельно для каждой задачи,и набора *подполитик*, общих для всего набора задач.Мастер политика рассматривается как политика над подполитиками, т.е. отвечает за переключение между подполитикамив процессе работы алгоритма.Подполитики, в свою очередь, отвечают за обучение некоторых примитивов работы, т.е. каждая полполитика отвечает заспецифичный сценарий. ФормализацияЗадача рассматривается как марковси процесс $ P(s',r | s, a) $, где$s', s$ - следующее и текущее состояние, $a$ действие, $r$ - ревард на данном шаге.Есть распределение над задачами (над марковскики процессами) $P_{M}$.Агент описывается двумя наборами параметров: $\theta, \phi$, тогда политика агента $\pi_{\theta, \phi}(a|s)$.Здесь* $\theta$ - набор параметров мастер-политики, обучаемый заново для каждой задачи;* $\phi$ - параметры подполитик, общие для всех для всех задач и обучаемые на наборе задач.Задача в *meta-learning* задаче - оптимизировать награду на протяжении жизни агента.Т.е в процессе обучения агента на выбранной задаче. АрхитектураВ работе предлагается иерархическая структура политики.Общие параметры $\phi = (\phi_1, \dots, \phi_k)$, где каждый вектор параметров $\phi_k$ соответствует отдельнойподполитике $\pi_{\phi_k}(a|s)$.Вектор параметров $\theta$ задает мастер-политику $\pi_{\theta}(a|s)$, задающую распределение над подполитиками.В предлагаемом метода переключение между подполитиками происходит каждые $N$ шагов $(0, N, 2N, \dots)$.![Мотивирующая картинка: схема работы](../resources/motivation_picture_1.png)Актор и критик для мастер-политики и подполитик представлены двухслойными feed-forward сетями. Алгоритм обученияПредлагается итеративно учить множество подполитик, при этом уча на каждом итерации мастер-политику.Обучение на каждой $m ~ P_M$ происходит в два этапа: WarmupПредварительное обучение мастер политики. На этом этапе учатся только параметры $\theta$.Сыгранные шаги рассматриваются сгруппированными по $N$. То есть, действие - выбор подполитики, награда - суммарнаянаграда за $N$ шагов. JointСовместное обучение мастер политики и подполитик. Делается $T$ шагов агента, затем оптимизируем $\theta$ группируя шагипо $N$. Затем оптимизируем $\phi$ обычным способом.Оптимизация проводилась с помощью A2C. Эксперимент: WIPВ ходе эксперимента проверялось:* возможность метода к обучению. для этого сравнивался график среднего ревардра на проэмлированной задаче для    обученного MLSH и для необученного MLSH (т.е. для каждой задачи тренируем заново.)* преимущество иерархического подхода перед одной shared политикой. Для этого сравнивался средний ревард для MLSH c     среднем ревардом для одной политики, обучаемой тем же способом, т.е. по задачам.Тестирование проводиться в средах Minigrid: DoorKey5x5, Empty, FourRoom.На **Графике 1** изображена зависимость среднего реварда от итерации обучения (номера просэмлированной задачи).По оси  $x$ изображен номер задачи*100 *(TODO: надо поправить, извиняюсь, рудимент)*.На **Графике 2** изображен зависимость среднего реварда по 5 играм после каждой итерации обучения.Желтой линией обозначен MLSH, зеленой - Shared Policy, бежевой - необученная MLSH. Все графики построены для среды DoorKey.![График 1](../resources/mean_rewards.png)![График 2](../resources/seen_rewards.png)На текущем этапе эксперимент подтверждает только первый пункт: средний reward для MLSH растет.Похожие графики показываются на других небольших средах, но их не превожу, так как результаты не однозначные.При этом колебания награды при обучении очень велики.Возможно, это обусловлено выбранным методом обучения (A2C) и малым размером батча.Хотя, в случае обучения обычной политики в обычном режиме (не "эпоха - одна задача"), алгоритм сходиться.Далее планируется проверить ещё раз A2C на наличие ошибок, произвести эксперименты c PPO, как в оригинальной статье. OtherЗапуски данных экспериментов на wandb:* [MLSH reset](https://app.wandb.ai/morgachev/mlsh/runs/2d4etdkz?workspace=user-morgachev)* [MLSH](https://app.wandb.ai/morgachev/mlsh/runs/2jeevlst?workspace=user-morgachev)* [Shared Policy](https://app.wandb.ai/morgachev/mlsh/runs/2vi3styx?workspace=user-morgachev)Соответствующие ноутбуки лежат в репозитории.<jupyter_code>import sys
import wandb
import torch
from tqdm import tqdm
sys.path.append("..")

%load_ext autoreload
%autoreload 2
import numpy as np
from gym import wrappers
from torch import nn

from matplotlib import pyplot as plt
from src import utils as utils
env_name = "MiniGrid-DoorKey-5x5-v0"
# env_name = "MiniGrid-Empty-Random-5x5-v0"
# env_name = "MiniGrid-DoorKey-8x8-v0"
env = utils.make_env(env_name)

obs_space_shape = env.observation_space.shape
n_actions = env.action_space.n

plt.title('Game image')
plt.imshow(env.render('rgb_array'))
plt.show()
from src.a2c import A2CAlgo

config = {
    "max_reward": 0.99,
    "device": "cpu",
    "env": env_name,
    "hidden_dim": 128,
    "emb_dim": 128,
    "n_env": 8,
    "gamma": 0.99,

    "max_grad_norm": 0.5,
    "lr": 0.001,
    "value_loss_coef": 0.5,
    "entropy_coef": 0.01,

    "n_sub": 4,
    "sub_n_iter": 100,
    "sub_n_steps": 3,
    "sub_lr": 1e-4,

    "master_n_iter": 30,
    "master_step_size": 3,
    "master_n_steps": 3,
    "master_lr": 1e-3,

    "n_iter_epoch": 50,
    "n_steps_sub": 16
}

# import os
# os.environ["WANDB_MODE"] = "dryrun"
from src.mlsh_model import MLSHAgent
from src.env_pool import MLSHPool

agent = MLSHAgent(
    config["n_sub"],
    n_actions,
    obs_space_shape[1]
)
for p in agent.parameters():
    nn.init.uniform_(p, -0.1, 0.1)

pool = MLSHPool(agent,
                lambda : utils.make_env(env_name),
                config["n_env"],
                random_reset=False)

wandb.init(project="mlsh",
           monitor_gym=True,
           name=f"mlsh_{env_name[9:]}+{config['n_sub']}_fixed",
           config=config,
           dir="..",
           magic=True,
           group="tests")
wandb.watch(agent)
a2c_subpolicies = \
    A2CAlgo(agent.subpolicies.parameters(),
            config["device"],
            n_actions,
            config["gamma"],
            config["max_grad_norm"],
            config["entropy_coef"],
            config["sub_lr"],
            config["value_loss_coef"])

ac2_master = \
    A2CAlgo(list(agent.master_policy.parameters()),
            config["device"],
            config["n_sub"],
            config["gamma"],
            config["max_grad_norm"],
            config["entropy_coef"],
            config["master_lr"],
            config["value_loss_coef"])
from src import mlsh_algo
for i in tqdm(range(300)):
    pool.update_seeds()
    for seed, env in zip(pool.seeds, pool.envs):
        env.seed(seed)
        env.reset()

    for p in agent.master_policy.parameters():
        nn.init.uniform_(p, -0.1, 0.1)

    mlsh_algo.warmup(ac2_master, pool,
                     config["master_n_iter"],
                     config["master_step_size"],
                     config["master_n_steps"],
                     config["n_env"])
    epoch_rew = mlsh_algo.joint_train(
        ac2_master,
        a2c_subpolicies,
        pool,
        config["sub_n_iter"],
        config["master_step_size"],
        config["sub_n_steps"],
        config["n_env"])[0]

    with torch.no_grad():
        wandb.log({
            "mean_rewards_epoch": epoch_rew,
            "seen_evaluate_reward":
                np.mean(utils.evaluate_mlsh(agent, env, 5,
                    config["master_step_size"],
                    last_env=pool.seeds[0])[0]),
            "unseen_evaluate_reward":
                np.mean(utils.evaluate_mlsh(agent, env, 5,
                    config["master_step_size"],
                    last_env=None)[0])
        })<jupyter_output>82%|████████▏ | 245/300 [2:24:47<29:29, 32.17s/it]