Перейти к содержанию

A3C (Asynchronous Advantage Actor‑Critic)

A3C сочетает преимущества policy‑based и value‑based подходов: несколько асинхронных рабочих агентов параллельно исследуют среду и обновляют общую (глобальную) сеть, используя функцию преимущества. Данная PyTorch реализация использует многопроцессность с общей глобальной сетью и оптимизатором SharedAdam.

A3C схема

Компоненты

  • Глобальная сеть: Общие параметры Actor (политики) и Critic (оценки V) в едином модуле Net
  • Воркеры: Независимые процессы, каждый со своей средой и локальной копией сети
  • SharedAdam: Оптимизатор с общим состоянием между процессами для согласованного обновления параметров
  • Advantage: TD-ошибка используется для взвешивания градиентов политики и обновления функции ценности

Теория (на базе реализации)

Архитектура сети

Модуль Net объединяет Actor и Critic:

Ветвь Actor: - Вход → Linear(s_dim, 256) → ReLU6 - → mu: Linear(256, a_dim) → Tanh → масштабирование *2 (диапазон действий: [-2, 2]) - → sigma: Linear(256, a_dim) → Softplus + 0.001 (для численной стабильности)

Ветвь Critic: - Вход → Linear(s_dim, 256) → ReLU6 - → value: Linear(256, 1)

Политика (Actor) — Гауссовское распределение

Актор выводит среднее \(\mu(s)\) и стандартное отклонение \(\sigma(s)\). Действия семплируются из:

\[ a \sim \mathcal{N}\big(\mu(s),\ \sigma^2(s)\big) \]

Для многомерных действий базовое нормальное распределение оборачивается в Independent распределение.

Лог-вероятность:

\[ \log \pi_\theta(a|s) = -\tfrac{1}{2}\,\frac{(a-\mu)^2}{\sigma^2} - \tfrac{1}{2}\,\log(2\pi\sigma^2) \]

Функция ценности (Critic)

Критик оценивает ценность состояния \(V_\phi(s)\). Temporal difference ошибка:

\[ \text{TD} = R_t^{(n)} - V_\phi(s_t) \]

Потеря ценности (среднеквадратичная ошибка):

\[ \mathcal{L}_\text{value} = \mathbb{E}[\text{TD}^2] \]

N-шаговые возвраты с бутстрэпом

Реализация использует правильные n-шаговые возвраты с бутстрэпом:

\[ R_t^{(n)} = \sum_{k=0}^{n-1} \gamma^k r_{t+k} + \gamma^n V_\phi(s_{t+n}) \]

Если эпизод завершается, \(V_\phi(s_{t+n}) = 0\).

Функция потерь

Потеря политики (с регуляризацией энтропии):

\[ \mathcal{L}_\text{policy} = -\mathbb{E}\big[\log \pi_\theta(a_t|s_t) \cdot \text{TD} + 0.005 \cdot H[\pi]\big] \]

где \(H[\pi]\) — энтропия политики.

Общая потеря:

\[ \mathcal{L}_\text{total} = \mathbb{E}[\mathcal{L}_\text{policy} + \mathcal{L}_\text{value}] \]

Advantage (TD-ошибка) отсоединяется при вычислении потери политики для предотвращения обратного распространения через функцию ценности.

Асинхронность и синхронизация

Реализация использует torch.multiprocessing для параллельного обучения:

  1. Вычисление градиентов: Каждый воркер вычисляет градиенты на своей локальной сети
  2. Отправка градиентов: Локальные градиенты передаются в параметры глобальной сети (gp._grad = lp.grad)
  3. Клиппинг градиентов: Глобальные градиенты обрезаются (max_norm=40.0) для стабильности
  4. Шаг оптимизатора: SharedAdam обновляет параметры глобальной сети
  5. Получение параметров: Локальная сеть загружает обновленные глобальные параметры (load_state_dict)

Эта процедура push-and-pull выполняется каждые update_global_iter шагов или при завершении эпизода.

Гиперпараметры

  • lr: Скорость обучения для SharedAdam (по умолчанию: 1e-4)
  • gamma: Коэффициент дисконтирования (по умолчанию: 0.99)
  • n_workers: Количество параллельных воркеров (по умолчанию: количество CPU)
  • max_episodes: Общее количество эпизодов (по умолчанию: 10)
  • max_ep_step: Максимум шагов в эпизоде (по умолчанию: 200)
  • update_global_iter: Частота глобальных обновлений (по умолчанию: 10)
  • Коэффициент энтропии: 0.005 (жестко задан в функции потерь)
  • Размер скрытого слоя: 256 (жестко задан в архитектуре Net)

Алгоритм обучения (псевдокод)

# Глобальная настройка
global_net = Net(s_dim, a_dim).share_memory()
optimizer = SharedAdam(global_net.parameters(), lr)

# Каждый воркер выполняется параллельно:
def worker_process(worker_id):
    local_net = Net(s_dim, a_dim)
    local_net.load_state_dict(global_net.state_dict())  # Начальная синхронизация
    env = env_function(worker_id)

    while global_episodes < max_episodes:
        s = env.reset()
        buffer_s, buffer_a, buffer_r = [], [], []
        episode_reward = 0

        for t in range(max_ep_step):
            # Выбор действия
            a = local_net.choose_action(s)
            s', r, done = env.step(clip(a, action_space))

            # Сохранение перехода
            buffer_s.append(s)
            buffer_a.append(a)
            buffer_r.append(r)
            episode_reward += r

            # Условие обновления
            if t % update_global_iter == 0 or done:
                # Вычисление n-шаговых возвратов с бутстрэпом
                if done:
                    v_s_ = 0
                else:
                    v_s_ = local_net.forward(s')[2]  # оценка ценности

                # Обратное накопление
                returns = []
                for r in reversed(buffer_r):
                    v_s_ = r + gamma * v_s_
                    returns.insert(0, v_s_)

                # Вычисление потерь
                loss = local_net.loss_func(buffer_s, buffer_a, returns)

                # Отправка градиентов в глобальную сеть, получение обновленных параметров
                optimizer.zero_grad()
                loss.backward()
                transfer_gradients(local_net, global_net)
                clip_grad_norm(global_net.parameters(), max_norm=40.0)
                optimizer.step()
                local_net.load_state_dict(global_net.state_dict())

                # Очистка буферов
                buffer_s, buffer_a, buffer_r = [], [], []

                if done:
                    record_episode(episode_reward)
                    break

            s = s'

Быстрый старт

Полный пример обучения A3C на окружении B747 для отслеживания синусоидального угла тангажа:

import numpy as np
import torch
from tensoraerospace.envs.b747 import ImprovedB747Env
from tensoraerospace.signals.standard import sinusoid_vertical_shift
from tensoraerospace.utils import convert_tp_to_sec_tp, generate_time_period
from tensoraerospace.agent.a3c import Agent, setup_global_params

# Установка random seed
SEED = 42
np.random.seed(SEED)
torch.manual_seed(SEED)

# Создание временной базы и опорного сигнала
dt = 0.1
_tp = generate_time_period(tn=20, dt=dt)
tps = convert_tp_to_sec_tp(_tp, dt=dt)
number_time_steps = len(_tp)

reference_signals = np.reshape(
    sinusoid_vertical_shift(
        tp=np.asarray(tps),
        frequency=0.05,
        amplitude=np.deg2rad(1.0),
        vertical_shift=0.0,
    ),
    [1, -1],
)

# Начальное состояние: [u, w, q, theta]
init_state = np.array([0.0, 0.0, 0.0, 0.0], dtype=np.float32)

# Настройка гиперпараметров
setup_global_params(
    max_episodes=3000,
    max_ep_step=number_time_steps,
    gamma=0.99,
    update_global_iter=10,
    lr=1e-4,
)

# Функция-фабрика окружения
def make_env(worker_id: int):
    return ImprovedB747Env(
        initial_state=init_state,
        reference_signal=reference_signals,
        number_time_steps=number_time_steps,
        dt=dt,
        initial_elevator_deg=0.0,
    )

# Создание и обучение агента
agent = Agent(
    env_function=make_env,
    gamma=0.99,
    n_workers=4,
    lr=1e-4,
    max_episodes=3000,
    max_ep_step=number_time_steps,
    update_global_iter=10,
    render=False,
    run_in_main=True,  # Установите False для многопроцессности
    log_dir="runs/a3c_b747",
)

# Обучение
agent.train()

# Оценка
eval_env = make_env(0)
obs, _ = eval_env.reset()
agent.gnet.eval()
episode_reward = 0.0

with torch.no_grad():
    terminated = truncated = False
    while not (terminated or truncated):
        obs_tensor = torch.from_numpy(np.array(obs).reshape(1, -1).astype(np.float32))
        mu, _, _ = agent.gnet.forward(obs_tensor)
        action = mu.cpu().numpy().reshape(-1)
        obs, reward, terminated, truncated, _ = eval_env.step(action)
        episode_reward += reward

print(f"Оценка награды: {episode_reward:.4f}")
eval_env.close()
agent.close()

Мониторинг с помощью TensorBoard

tensorboard --logdir=runs/a3c_b747

Метрики включают: - Loss/w*/total: Общая потеря для каждого воркера - Loss/w*/value: Потеря ценности (TD ошибка) - Loss/w*/policy: Потеря политики - Loss/w*/entropy: Энтропия политики - Performance/w*/episode_reward: Награды за эпизод - Performance/w*/moving_avg_reward: Скользящее среднее

Лучшие практики

  • Используйте run_in_main=True для notebook/отладки
  • Установите run_in_main=False и n_workers=8 для продакшн обучения
  • Действия автоматически обрезаются по env.action_space.low/high
  • Sigma имеет минимальное значение 0.001 для численной стабильности
  • Следите в TensorBoard за коллапсом энтропии или расхождением потери ценности

Продвинутый пример: Обучение на окружении B747

Полный пример демонстрирует обучение агента A3C на окружении ImprovedB747Env для отслеживания синусоидального опорного сигнала угла тангажа.

Настройка и создание окружения

import numpy as np
import torch
import matplotlib.pyplot as plt
from queue import Empty

from tensoraerospace.envs.b747 import ImprovedB747Env
from tensoraerospace.signals.standard import sinusoid_vertical_shift
from tensoraerospace.utils import convert_tp_to_sec_tp, generate_time_period
from tensoraerospace.agent.a3c import Agent, setup_global_params

# Установка random seed для воспроизводимости
SEED = 42
np.random.seed(SEED)
torch.manual_seed(SEED)

# Создание временной базы
dt = 0.1  # секунды
_tp = generate_time_period(tn=20, dt=dt)
tps = convert_tp_to_sec_tp(_tp, dt=dt)
number_time_steps = len(_tp)

print(f"Длина эпизода: {number_time_steps} шагов ({number_time_steps * dt:.1f} секунд)")

# Генерация синусоидального опорного сигнала для угла тангажа (theta)
reference_signals = np.reshape(
    sinusoid_vertical_shift(
        tp=np.asarray(tps),
        frequency=0.05,             # Гц
        amplitude=np.deg2rad(1.0),  # амплитуда 1 градус
        vertical_shift=0.0,
    ),
    [1, -1],
)

# Определение начального состояния: [u, w, q, theta]
init_state = np.array([0.0, 0.0, 0.0, 0.0], dtype=np.float32)

# Создание окружения
env = ImprovedB747Env(
    initial_state=init_state,
    reference_signal=reference_signals,
    number_time_steps=number_time_steps,
    dt=dt,
    initial_elevator_deg=0.0,
)

print(f"Пространство наблюдений: {env.observation_space}")
print(f"Пространство действий: {env.action_space}")

Настройка и создание агента

# Настройка гиперпараметров
setup_global_params(
    max_episodes=3000,
    max_ep_step=number_time_steps,
    gamma=0.99,
    update_global_iter=10,
    lr=1e-4,
)

# Функция-фабрика окружения
def make_env(worker_id: int):
    """Создает окружение для каждого воркера."""
    return ImprovedB747Env(
        initial_state=init_state,
        reference_signal=reference_signals,
        number_time_steps=number_time_steps,
        dt=dt,
        initial_elevator_deg=0.0,
    )

# Создание агента A3C
agent = Agent(
    env_function=make_env,
    gamma=0.99,
    n_workers=4,              # Используем 4 параллельных воркера
    lr=1e-4,
    max_episodes=3000,
    max_ep_step=number_time_steps,
    update_global_iter=10,
    render=False,
    run_in_main=True,         # Установите False для настоящей многопроцессности
    log_dir="runs/a3c_b747",
)

print("Агент A3C успешно создан!")

Обучение агента

import time

print("Запуск обучения A3C...\n")

episode_rewards = []
start_time = time.time()

# Запуск обучения (синхронный если run_in_main=True)
agent.train()

# Сбор наград из очереди
while True:
    try:
        r = agent.res_queue.get_nowait()
    except Empty:
        break
    if r is None:
        break
    episode_rewards.append(float(r))

training_time = time.time() - start_time
print(f"\nОбучение завершено за {training_time:.2f} секунд")
print(f"Всего эпизодов: {len(episode_rewards)}")
print(f"Финальная награда (скользящее среднее): {episode_rewards[-1]:.4f}")

График прогресса обучения

plt.figure(figsize=(12, 5))
plt.plot(episode_rewards, label='Скользящее среднее награды', alpha=0.7)

# Добавление сглаженного тренда
window = 50
if len(episode_rewards) >= window:
    smoothed = np.convolve(episode_rewards, np.ones(window)/window, mode='valid')
    plt.plot(range(window-1, len(episode_rewards)), smoothed, 
             'r-', linewidth=2, label=f'Сглаженное (MA{window})')

plt.grid(True, alpha=0.3)
plt.xlabel('Эпизод')
plt.ylabel('Награда (скользящее среднее)')
plt.title('Прогресс обучения A3C на окружении B747')
plt.legend()
plt.tight_layout()
plt.show()

Оценка обученной политики

# Детерминированная оценка с использованием среднего политики
eval_env = make_env(0)
obs, info = eval_env.reset()

agent.gnet.eval()
episode_reward = 0.0
terminated = False
truncated = False

with torch.no_grad():
    while not (terminated or truncated):
        obs_tensor = torch.from_numpy(np.array(obs).reshape(1, -1).astype(np.float32))
        mu, sigma, value = agent.gnet.forward(obs_tensor)

        # Используем среднее для детерминированной политики
        action = mu.cpu().numpy().reshape(-1)

        obs, reward, terminated, truncated, info = eval_env.step(action)
        episode_reward += float(reward)

print(f"Детерминированная оценка награды: {episode_reward:.4f}")

# График отслеживания угла тангажа
eval_env.unwrapped.model.plot_transient_process(
    'theta',
    tps,
    reference_signals[0],
    to_deg=True,
    figsize=(15, 4)
)

eval_env.close()
agent.close()

Мониторинг с помощью TensorBoard

tensorboard --logdir=runs/a3c_b747

Доступные метрики: - Loss/w*/total: Общая потеря для каждого воркера - Loss/w*/value: Потеря функции ценности (квадрат TD ошибки) - Loss/w*/policy: Потеря политики (отрицательное ожидаемое преимущество) - Loss/w*/entropy: Энтропия политики (мера исследования) - Performance/w*/episode_reward: Сырые награды за эпизод - Performance/w*/moving_avg_reward: Экспоненциально взвешенное скользящее среднее

Ожидаемые результаты

После 3000 эпизодов обучения: - Агент учится отслеживать синусоидальный опорный сигнал тангажа с амплитудой ~1° - Финальное скользящее среднее награды: примерно от -1.6 до -2.0 - Ошибка отслеживания тангажа: < 0.5° среднеквадратичное

Советы для улучшения производительности

  1. Увеличьте длительность обучения: 10000+ эпизодов для лучшей сходимости
  2. Настройте гиперпараметры:
  3. Уменьшите lr (5e-5) для более стабильного обучения
  4. Увеличьте update_global_iter (20-30) для более плавных градиентов
  5. Используйте больше воркеров: Установите run_in_main=False и n_workers=8 для более быстрого обучения
  6. Настройте опорный сигнал: Попробуйте разные частоты и амплитуды
  7. Следите за TensorBoard: Отслеживайте коллапс энтропии или расхождение потери ценности

Документация API

Agent

Agent(env_function, gamma=DEFAULT_GAMMA, n_workers=None, lr=DEFAULT_LR, max_episodes=DEFAULT_MAX_EP, max_ep_step=DEFAULT_MAX_EP_STEP, update_global_iter=DEFAULT_UPDATE_GLOBAL_ITER, render=False, run_in_main=False, log_dir='runs/a3c', wandb_project=None, wandb_entity=None, wandb_run_name=None, wandb_tags=None, wandb_config=None)

Simple A3C Agent wrapper around multiprocessing Workers.

Parameters:

Name Type Description Default
env_function Callable[[int], Env]

callable that returns a new env for a given worker id.

required
gamma float

discount factor.

DEFAULT_GAMMA
n_workers Optional[int]

number of worker processes.

None
lr float

learning rate for SharedAdam.

DEFAULT_LR
max_episodes int

total episodes to run per global counter.

DEFAULT_MAX_EP
max_ep_step int

max steps per episode.

DEFAULT_MAX_EP_STEP
update_global_iter int

frequency to push/pull.

DEFAULT_UPDATE_GLOBAL_ITER
render bool

render from worker w0 (optional).

False

Note: For unit tests or debugging, set run_in_main=True to avoid spawning processes. The single worker will run in the main process.

Configure A3C agent wrapper.

Parameters:

Name Type Description Default
env_function Callable[[int], Env]

Factory returning an environment per worker id.

required
gamma float

Discount factor.

DEFAULT_GAMMA
n_workers Optional[int]

Number of worker processes; defaults to CPU count.

None
lr float

Learning rate for optimizer.

DEFAULT_LR
max_episodes int

Total episodes to run.

DEFAULT_MAX_EP
max_ep_step int

Max steps per episode.

DEFAULT_MAX_EP_STEP
update_global_iter int

Sync frequency for global net updates.

DEFAULT_UPDATE_GLOBAL_ITER
render bool

Whether to render from worker 0.

False
run_in_main bool

If True, run worker inline for debugging/tests.

False
log_dir str

TensorBoard log directory.

'runs/a3c'

train(num_episodes=None, *, max_steps=None, save_best=False, save_path=None, verbose=True, **kwargs)

Launch training across worker processes (unified interface).

Parameters:

Name Type Description Default
num_episodes Optional[int]

Override for self.max_episodes; when None the value supplied at construction is used, preserving the original no-argument call style.

None
max_steps Optional[int]

Override for self.max_ep_step.

None
save_best bool

Reserved for API consistency.

False
save_path Optional[str]

Reserved for API consistency.

None
verbose bool

Reserved for symmetry.

True
**kwargs Any

Currently unused.

{}

Returns:

Name Type Description
dict dict

Summary dictionary (global_ep, global_step,

dict

global_ep_r).

close()

Close TensorBoard writer and cleanup resources.

get_param_env()

Return serializable configuration of the agent.

save(path=None, save_gradients=False)

Save A3C agent to the specified directory.

Saves the global actor-critic network and configuration. Optionally saves the shared optimizer state for resuming training.

Parameters:

Name Type Description Default
path str | Path | None

Base save directory. If None, saves to the current working directory.

None
save_gradients bool

If True, also save optimizer state dict.

False

Returns:

Name Type Description
Path Path

The directory where the model was saved.

load(path, env_function=None, load_gradients=False) classmethod

Load an A3C agent from a checkpoint directory.

Parameters:

Name Type Description Default
path Union[str, Path]

Directory containing saved model files.

required
env_function Optional[Callable[[int], Env]]

Factory returning an environment per worker id. Required because A3C needs environments for its workers.

None
load_gradients bool

If True, restore optimizer state.

False

Returns:

Name Type Description
Agent 'Agent'

Reconstructed agent.

from_pretrained(repo_name, env_function=None, access_token=None, version=None, load_gradients=False) classmethod

Load pretrained model from a local directory or Hugging Face Hub.

Parameters:

Name Type Description Default
repo_name str

Path to a local folder or a Hugging Face repo id (e.g. "namespace/repo_name").

required
env_function Optional[Callable[[int], Env]]

Factory returning an environment per worker id (required).

None
access_token Optional[str]

Hugging Face access token for private repos.

None
version Optional[str]

Revision / branch / tag on Hugging Face.

None
load_gradients bool

Restore optimizer state for continued training.

False

Returns:

Name Type Description
Agent 'Agent'

Initialized agent.

publish_to_hub(repo_name, folder_path, access_token=None)

Upload a saved model folder to Hugging Face Hub.

Parameters:

Name Type Description Default
repo_name str

Repository id on Hugging Face (e.g. "user/my-a3c").

required
folder_path Union[str, Path]

Local folder produced by :meth:save.

required
access_token Optional[str]

Hugging Face access token.

None

Worker

Worker(gnet, opt, global_ep, global_ep_r, res_queue, name, num_actions, num_observations, MAX_EP, MAX_EP_STEP, GAMMA, update_global_iter, env_function=None, env=None, render=False, writer=None, global_step=None, global_env_step=None)

Bases: Process

Worker process class for asynchronous agent training.

Parameters:

Name Type Description Default
env Env

Environment for agent training.

None
gnet Net

Global model for shared training.

required
opt SharedAdam

Optimizer for global network.

required
global_ep Value

Global episode counter.

required
global_ep_r Value

Global total reward counter across all processes.

required
res_queue Queue

Queue for storing results.

required
name int

Process number.

required
num_actions int

Number of possible actions in the environment.

required
num_observations int

Number of observations (state variables) in the environment.

required
MAX_EP int

Maximum number of episodes.

required
MAX_EP_STEP int

Maximum number of steps per episode.

required
GAMMA float

Discount factor for future rewards.

required
update_global_iter int

Frequency of global model updates.

required
render bool

Whether to render the environment. Defaults to False.

False
writer Optional[SummaryWriter]

TensorBoard writer. Defaults to None.

None
global_step Optional[Value]

Global step counter. Defaults to None.

None

Attributes:

Name Type Description
name str

Unique process name.

g_ep Value

Global episode counter.

g_ep_r Value

Global total reward counter.

res_queue Queue

Results queue.

gnet Net

Global neural network.

opt SharedAdam

Optimizer for updating global network.

lnet Net

Local neural network.

env Env

OpenAI Gym environment.

gamma float

Discount factor.

max_ep int

Maximum number of episodes.

max_ep_step int

Maximum number of steps per episode.

update_global_iter int

Frequency of global network updates.

render bool

Whether to render the environment.

writer Optional[SummaryWriter]

TensorBoard writer.

global_step Optional[Value]

Global step counter.

Initialize worker process.

Parameters:

Name Type Description Default
env_function Optional[Callable[[int], Env]]

Factory callable taking worker id and returning a fresh env. The env is created inside run() so that under fork multiprocessing each worker gets its own env (avoids sharing a single env object across processes). This is the preferred way to supply an env.

None
env Optional[Env]

Legacy/direct env instance. Provided for backward compatibility (and for single-process tests); DO NOT use this path with real multi-process training because a single env would be shared across forked workers.

None
gnet Net

Global shared network.

required
opt SharedAdam

Shared optimizer.

required
global_ep Any

Shared episode counter.

required
global_ep_r Any

Shared reward accumulator.

required
res_queue Queue

Queue for results.

required
name int

Worker id.

required
num_actions int

Action dimension.

required
num_observations int

Observation dimension.

required
MAX_EP int

Max episodes to run.

required
MAX_EP_STEP int

Max steps per episode.

required
GAMMA float

Discount factor.

required
update_global_iter int

Steps between syncs with global net.

required
render bool

Whether to render (only worker 0 typically).

False
writer Optional[MetricWriter]

TensorBoard writer for metrics.

None
global_step Any | None

Shared global update counter (push_and_pull count).

None
global_env_step Any | None

Shared global env-step counter (incremented once per env.step); used as the canonical TensorBoard X-axis for all scalar writes.

None

run()

Execute worker process containing agent training.

Network

Net(s_dim, a_dim)

Bases: Module

Neural network for policy and value function approximation in RL.

Parameters:

Name Type Description Default
s_dim int

State space dimension.

required
a_dim int

Action space dimension.

required

Attributes:

Name Type Description
s_dim int

State space dimension.

a_dim int

Action space dimension.

a1 Linear

First policy layer.

mu Linear

Mean layer of policy distribution.

sigma Linear

Standard deviation layer of policy distribution.

c1 Linear

First value function layer.

v Linear

Value function output layer.

distribution Distribution

Distribution for modeling agent actions.

Create network layers.

Parameters:

Name Type Description Default
s_dim int

State dimension.

required
a_dim int

Action dimension.

required

forward(x)

Perform one forward pass.

Parameters:

Name Type Description Default
x Tensor

Input data, environment state.

required

Returns:

Type Description
Tensor

Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: Predicted mu, sigma,

Tensor

and value for the given state.

choose_action(s)

Select agent action based on current state.

Parameters:

Name Type Description Default
s Tensor

Current environment state.

required

Returns:

Type Description
ndarray

np.ndarray: Selected action.

loss_func(s, a, v_t)

Compute loss function for network training.

Parameters:

Name Type Description Default
s Tensor

States.

required
a Tensor

Actions.

required
v_t Tensor

Target state value function values.

required

Returns:

Type Description
Tensor

torch.Tensor: Loss function value.

Optimizer

SharedAdam(params, lr=0.001, betas=(0.9, 0.99), eps=1e-08, weight_decay=0)

Bases: Adam

Adam optimizer with shared state for multi-process training.

This optimizer stores its internal state tensors (step counter, exp_avg, exp_avg_sq) in shared memory so multiple worker processes can update a single set of parameters consistently.

Parameters:

Name Type Description Default
params Iterable[Parameter]

Parameters to optimize.

required
lr float

Learning rate. Defaults to 1e-3.

0.001
betas Tuple[float, float]

Coefficients used for computing running averages of gradient and its square. Defaults to (0.9, 0.99).

(0.9, 0.99)
eps float

Term added to the denominator for numerical stability. Defaults to 1e-8.

1e-08
weight_decay float

Weight decay (L2 penalty). Defaults to 0.

0

Initialize shared Adam optimizer.

Parameters:

Name Type Description Default
params Iterable[Parameter]

Iterable of parameters to optimize.

required
lr float

Learning rate.

0.001
betas Tuple[float, float]

Beta coefficients for Adam moments.

(0.9, 0.99)
eps float

Numerical stability term.

1e-08
weight_decay float

L2 weight decay.

0

Утилиты

setup_global_params(*, max_episodes=DEFAULT_MAX_EP, max_ep_step=DEFAULT_MAX_EP_STEP, gamma=DEFAULT_GAMMA, update_global_iter=DEFAULT_UPDATE_GLOBAL_ITER, lr=DEFAULT_LR)

Update defaults used by Agent.

This matches the previous TF API name to ease migration.

Детали реализации

Ключевые особенности

  1. Единая сеть: Один модуль Net с общими слоями, снижающий потребление памяти
  2. Активация ReLU6: Более стабильные градиенты по сравнению со стандартным ReLU
  3. Клиппинг градиентов: Максимальная норма 40.0 предотвращает взрывающиеся градиенты
  4. Регуляризация энтропии: Коэффициент 0.005 поощряет исследование
  5. SharedAdam: Состояние оптимизатора разделяется между процессами для согласованных обновлений
  6. Правильный бутстрэп: N-шаговые возвраты включают ценность терминального состояния, когда эпизод продолжается

Преимущества перед синхронными методами

  • Параллельный сбор опыта: Несколько воркеров исследуют одновременно
  • Некоррелированные сэмплы: Разные воркеры в разных состояниях снижают корреляцию
  • Без буфера повторов: Онлайн обучение снижает требования к памяти
  • Естественное исследование: Асинхронность обеспечивает разнообразие без ε-greedy

Советы по отладке

  • Используйте run_in_main=True для запуска одного воркера без многопроцессности
  • Проверяйте TensorBoard на расхождение потерь или коллапс энтропии
  • Уменьшайте lr если обучение нестабильно
  • Увеличивайте update_global_iter для более стабильных градиентов
  • Убедитесь, что окружение правильно инициализировано для воспроизводимости

Источники

Протестированные окружения

  • Unity ML-Agents окружения
  • Gymnasium задачи непрерывного управления
  • TensorAeroSpace LinearLongitudinal* окружения
  • Кастомные аэрокосмические окружения управления