SAC с Unity ML-Agents¶
О чём пример¶
Этот пример демонстрирует обучение Soft Actor-Critic (SAC) агента из TensorAeroSpace в Unity ML-Agents окружении для непрерывного управления.
Репозиторий Unity окружения
Исходный код Unity окружения доступен по ссылке: TensorAeroSpace/UnityAirplaneEnvironment
Цели и требования¶
Что вы сделаете:
- Подключите Unity-среду к TensorAeroSpace (Editor или билд)
- Обучите SAC-агента на непрерывных действиях
- Оцените качество обученной политики
- Сохраните и загрузите модель
Требования:
- Unity + ML-Agents (Python package
mlagents==1.1.0) - Python 3.8+
- TensorAeroSpace
- GPU рекомендуется для обучения
Установка¶
Импорты¶
import gymnasium as gym
import numpy as np
from tensoraerospace.agent import SAC
from mlagents_envs.environment import UnityEnvironment
from mlagents_envs.envs.unity_gym_env import UnityToGymWrapper
Обёртка для Gymnasium API¶
Unity ML-Agents использует старый gym API. Нам нужна обёртка для преобразования в современный gymnasium API:
class UnityToGymnasiumWrapper(gym.Wrapper):
"""Обёртка для преобразования Unity ML-Agents gym в Gymnasium API.
Args:
env: Unity окружение, обёрнутое в UnityToGymWrapper
"""
def __init__(self, env):
super().__init__(env)
self.env = env
def reset(self, *, seed=None, options=None):
"""Сброс окружения."""
obs = self.env.reset()
return obs, {}
def step(self, action):
"""Выполнение шага в окружении."""
result = self.env.step(action)
obs, reward, done, info = result
# Gymnasium использует 5-tuple вместо 4-tuple
return obs, reward, done, False, info
def close(self):
"""Закрытие Unity окружения."""
self.env.close()
Подключение к Unity¶
# Обёртка для совместимости
gym_env = UnityToGymWrapper(unity_env, uint8_visual=True)
env = UnityToGymnasiumWrapper(gym_env)
print(f"Action space: {env.action_space}")
print(f"Observation space: {env.observation_space}")
Порт подключения
По умолчанию используется порт 5004. Если он занят — закройте другие процессы Unity.
Конфигурация SAC агента¶
agent = SAC(
env=env,
# Динамика обучения
updates_per_step=1,
batch_size=256,
memory_capacity=1_000_000,
# Скорости обучения
lr=3e-4, # Критик
policy_lr=3e-4, # Актёр
# RL гиперпараметры
gamma=0.99, # Коэффициент дисконтирования
tau=0.005, # Мягкое обновление
alpha=0.2, # Начальный коэффициент энтропии
# Конфигурация политики
policy_type="Gaussian",
target_update_interval=1,
automatic_entropy_tuning=True,
# Архитектура сети
hidden_size=256,
# Устройство и логирование
device="cuda", # Используйте "cpu" если нет GPU
verbose_histogram=False,
seed=42,
)
Таблица гиперпараметров¶
| Параметр | Значение | Описание |
|---|---|---|
batch_size |
256 | Размер мини-батча |
memory_capacity |
1,000,000 | Размер replay buffer |
lr |
3e-4 | Скорость обучения критиков |
policy_lr |
3e-4 | Скорость обучения актёра |
gamma |
0.99 | Коэффициент дисконтирования |
tau |
0.005 | Коэффициент мягкого обновления |
automatic_entropy_tuning |
True | Автоподстройка исследования |
hidden_size |
256 | Нейроны скрытого слоя |
Обучение¶
Оценка¶
def evaluate_agent(agent, env, num_episodes=5):
"""Оценка обученного агента."""
rewards = []
for episode in range(num_episodes):
state, info = env.reset()
done = False
total_reward = 0
while not done:
action = agent.select_action(state, evaluate=True)
state, reward, terminated, truncated, info = env.step(action)
done = terminated or truncated
total_reward += reward
rewards.append(total_reward)
print(f"Episode {episode + 1}: Reward = {total_reward:.2f}")
print(f"\nСредняя награда: {np.mean(rewards):.2f} ± {np.std(rewards):.2f}")
return np.mean(rewards), np.std(rewards), rewards
# Запуск оценки
mean_reward, std_reward, all_rewards = evaluate_agent(agent, env, num_episodes=5)
Сохранение и загрузка модели¶
# Сохранение
agent.save(path="./checkpoints")
# Загрузка
loaded_agent = SAC.from_pretrained("./checkpoints/Nov24_11-01-27_SAC")
Закрытие окружения¶
Решение проблем¶
| Проблема | Решение |
|---|---|
Port 5004 is busy |
Закройте другие Unity процессы |
allow_multiple_obs предупреждение |
Установите allow_multiple_obs=True или игнорируйте |
| Таймаут соединения | Запустите Unity сцену перед Python скриптом |
| CUDA out of memory | Уменьшите batch_size или hidden_size |
Типичный лог подключения¶
[INFO] Listening on port 5004...
[INFO] Connected to Unity environment with package version X.X.X
[INFO] Connected new brain: BehaviorName?team=0
