Ray RLlib 提供了靈活的模型自定義和組態機制,以滿足不同強化學習任務的需求。開發者可以根據實際情況調整模型架構、組態訓練引數、選擇合適的探索策略,以及有效利用計算資源。理解 RLlib 的模型架構、前處理器、Q 值和動作分佈的取得方式,對於構建高效的強化學習模型至關重要。此外,RLlib 提供了豐富的組態選項,涵蓋訓練、環境、rollout workers 等方面,可以根據需求微調訓練過程。對於多代理環境,RLlib 提供了 MultiAgentEnv 和 ExternalEnv 等工具,方便定義和訓練多代理強化學習模型。

強化學習模型的自定義與組態

在前面的章節中,我們探討了使用Ray RLlib進行強化學習(RL)的基本原理和實踐方法。現在,我們將進一步討論如何自定義和組態RLlib模型,以滿足特定的實驗需求。

強化學習模型的架構

首先,讓我們回顧一下RLlib中模型的架構。以DQN模型為例,其輸出代表了狀態-動作對的Q值。模型的架構如下所示:

Model: "model"
________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
================================================================================
observations (InputLayer) [(None, 25)] 0
________________________________________________________________________________
fc_1 (Dense) (None, 256) 6656 observations[0][0]
________________________________________________________________________________
fc_out (Dense) (None, 256) 65792 fc_1[0][0]
________________________________________________________________________________
value_out (Dense) (None, 1) 257 fc_1[0][0]
================================================================================
Total params: 72,705
Trainable params: 72,705
Non-trainable params: 0
________________________________________________________________________________

內容解密:

此模型的架構包含一個輸入層、兩個密集層(Dense layers)和一個輸出層。輸入層接收觀察值,形狀為(None, 25),表示輸入資料的形狀是未知的,但每個樣本有25個特徵。第一個密集層(fc_1)有256個單元,使用ReLU啟用函式。第二個密集層(fc_out)同樣有256個單元。最後,輸出層(value_out)預測一個單一值,即Q值。

自定義模型

RLlib允許使用者自定義模型,以適應複雜的環境。例如,如果環境的觀察空間很大,您可能需要一個更大的模型來捕捉這種複雜性。然而,這需要深入瞭解底層的神經網路框架,例如TensorFlow。

from ray.rllib.models.preprocessors import get_preprocessor

env = GymEnvironment()
obs_space = env.observation_space
preprocessor = get_preprocessor(obs_space)(obs_space)
observations = env.reset()
transformed = preprocessor.transform(observations).reshape(1, -1)
model_output, _ = model({"obs": transformed})

內容解密:

這段程式碼展示瞭如何使用get_preprocessor來存取策略所使用的前處理器,並將原始觀察值轉換為模型可接受的格式。首先,我們建立了一個GymEnvironment例項,並取得其觀察空間。然後,我們使用get_preprocessor獲得前處理器,並將原始觀察值轉換為適合模型的格式。最後,我們將轉換後的觀察值輸入模型,獲得模型的輸出。

取得Q值和動作分佈

獲得模型輸出後,我們可以存取Q值和動作分佈:

q_values = model.get_q_value_distributions(model_output)
print(q_values)
action_distribution = policy.dist_class(model_output, model)
sample = action_distribution.sample()
print(sample)

內容解密:

這段程式碼展示瞭如何從模型輸出中取得Q值和動作分佈。首先,我們呼叫get_q_value_distributions方法獲得Q值。然後,我們使用策略的dist_class屬性建立一個動作分佈例項,並從中取樣一個動作。

組態RLlib實驗

現在,讓我們討論如何組態和執行RLlib實驗。RLlib提供了豐富的組態選項,以滿足不同的實驗需求。

組態類別

RLlib的組態選項分為以下類別:

  • training():組態訓練相關的選項。
  • environment():組態環境相關的選項。
  • rollouts():組態rollout workers的行為。
  • exploration():組態探索策略。
  • resources():組態計算資源。
  • offline_data():組態離線資料訓練。
  • multi_agent():組態多代理訓練。

這些類別涵蓋了RLlib實驗的大部分組態需求。透過鏈式呼叫這些方法,我們可以輕鬆地組態和執行RLlib實驗。

組態強化學習訓練的高階選項

一旦確定使用某種強化學習演算法並希望進一步最佳化其效能時,演算法特定的組態在訓練過程中變得尤為重要。在實際操作中,RLlib 提供了良好的預設值讓使用者能夠順利開始。

資源組態

無論是在本地端還是在叢集上使用 Ray RLlib,都可以指定用於訓練程式的資源。以下是一些重要的選項。以 DQN 演算法為例,但這些選項同樣適用於其他 RLlib 演算法:

from ray.rllib.algorithms.dqn import DQNConfig

config = DQNConfig().resources(
    num_gpus=1,
    num_cpus_per_worker=2,
    num_gpus_per_worker=0,
)

內容解密:

  • num_gpus=1:指定用於訓練的 GPU 數量。這個值也可以是小數,例如,若在 DQN 中使用四個 rollout workers (num_rollout_workers=4),可以設定 num_gpus=0.25 將所有四個 workers 放在同一個 GPU 上,以利用潛在的加速效果。
  • num_cpus_per_worker=2:設定每個 rollout worker 使用的 CPU 數量。
  • num_gpus_per_worker=0:設定每個 worker 使用的 GPU 數量。

Rollout Worker 組態

RLlib 允許使用者組態如何計算 rollout 以及如何分配它們:

from ray.rllib.algorithms.dqn import DQNConfig

config = DQNConfig().rollouts(
    num_rollout_workers=4,
    num_envs_per_worker=1,
    create_env_on_local_worker=True,
)

內容解密:

  • num_rollout_workers=4:指定使用的 Ray workers 數量。
  • num_envs_per_worker=1:指定每個 worker 評估的環境數量。這允許將環境評估進行「批次」處理,特別是在模型評估需要較長時間時,可以加速訓練。
  • create_env_on_local_worker=True:當 num_rollout_workers > 0 時,本地 worker 不需要環境。設定此選項為 True 可以在本地 worker 上建立環境。

環境組態

from ray.rllib.algorithms.dqn import DQNConfig

config = DQNConfig().environment(
    env="CartPole-v1",
    env_config={"my_config": "value"},
    observation_space=None,
    action_space=None,
    render_env=True,
)

內容解密:

  • env="CartPole-v1":指定用於訓練的環境,可以是已知的 Gym 環境或自定義環境的類別名稱。
  • env_config={"my_config": "value"}:可選地為環境指定組態字典,這些組態將傳遞給環境建構函式。
  • observation_space=Noneaction_space=None:可以指定環境的觀測空間和動作空間,如果未指定,將從環境中推斷。
  • render_env=True:允許渲染環境,需要實作環境的 render 方法。

與 RLlib 環境協作

RLlib 支援多種環境,包括 Gym 環境、VectorEnv、MultiAgentEnv 和 ExternalEnv。其中,MultiAgentEnv 允許訓練具有多個代理的模型,而 ExternalEnv 可以用於連線外部模擬器到 RLlib。

MultiAgentEnv

允許多個代理與環境互動,需要定義代理之間的介面和互動邏輯。

ExternalEnv

提供了一個簡單的客戶端-伺服器架構,用於與外部模擬器進行通訊,支援透過 REST API 進行通訊。

多代理環境下的強化學習:以Ray RLlib為例

在強化學習(RL)領域中,多代理環境(Multi-Agent Environment)是一個重要的研究方向。Ray RLlib是一個強大的強化學習框架,它提供了對多代理環境的原生支援。在本篇文章中,我們將探討如何在Ray RLlib中定義和訓練多代理環境。

多代理環境的基本概念

在多代理環境中,我們有多個代理(Agent)在同一環境中互動。每個代理都有自己的觀察(Observation)、動作(Action)和獎勵(Reward)。與單代理環境不同,多代理環境需要考慮多個代理之間的互動和協調。

定義多代理環境

在Ray RLlib中,定義多代理環境需要繼承MultiAgentEnv類別。以下是一個簡單的例子,定義了一個具有兩個代理的多代理迷宮環境:

from ray.rllib.env.multi_agent_env import MultiAgentEnv
from gym.spaces import Discrete

class MultiAgentMaze(MultiAgentEnv):
    def __init__(self, *args, **kwargs):
        self.action_space = Discrete(4)
        self.observation_space = Discrete(5*5)
        self.agents = {1: (4, 0), 2: (0, 4)}
        self.goal = (4, 4)
        self.info = {1: {'obs': self.agents[1]}, 2: {'obs': self.agents[2]}}

    def reset(self):
        self.agents = {1: (4, 0), 2: (0, 4)}
        return {1: self.get_observation(1), 2: self.get_observation(2)}

    def get_observation(self, agent_id):
        seeker = self.agents[agent_id]
        return 5 * seeker[0] + seeker[1]

    def get_reward(self, agent_id):
        return 1 if self.agents[agent_id] == self.goal else 0

    def is_done(self, agent_id):
        return self.agents[agent_id] == self.goal

    def step(self, action):
        agent_ids = action.keys()
        for agent_id in agent_ids:
            seeker = self.agents[agent_id]
            if action[agent_id] == 0: # move down
                seeker = (min(seeker[0] + 1, 4), seeker[1])
            elif action[agent_id] == 1: # move left
                seeker = (seeker[0], max(seeker[1] - 1, 0))
            elif action[agent_id] == 2: # move up
                seeker = (max(seeker[0] - 1, 0), seeker[1])
            elif action[agent_id] == 3: # move right
                seeker = (seeker[0], min(seeker[1] + 1, 4))
            else:
                raise ValueError("Invalid action")
            self.agents[agent_id] = seeker
        observations = {i: self.get_observation(i) for i in agent_ids}
        rewards = {i: self.get_reward(i) for i in agent_ids}
        done = {i: self.is_done(i) for i in agent_ids}
        done["__all__"] = all(done.values())
        return observations, rewards, done, self.info

程式碼解密:

此程式碼定義了一個多代理迷宮環境,具有兩個代理。reset方法重置環境,step方法根據代理的動作更新環境狀態。get_observationget_rewardis_done方法分別傳回代理的觀察、獎勵和完成狀態。

多代理環境的訓練

在定義好多代理環境後,我們可以使用Ray RLlib的訓練API來訓練代理。具體的訓練過程取決於所選擇的強化學習演算法和超引數。

# 以下是一個簡單的訓練範例
from ray import tune
from ray.rllib.agents.ppo import PPOTrainer

config = {
    "env": MultiAgentMaze,
    "num_gpus": 0,
    "num_workers": 1,
    "framework": "tf"
}

tune.run(PPOTrainer, config=config)

程式碼解密:

此程式碼使用Ray RLlib的PPO演算法訓練多代理迷宮環境。config字典定義了訓練組態,包括環境、GPU數量、worker數量和框架。