Ray 提供了 Actor 模型和 RLlib 函式庫,讓開發者能更輕鬆地建構和執行分散式強化學習應用。透過 Ray Actor,可以將模擬環境分佈到不同的節點上,大幅提升訓練速度。RLlib 則簡化了強化學習演算法的實作,並提供高度可擴充套件的訓練環境。開發者只需專注於定義環境和調整引數,即可將訓練規模擴充套件到多個節點,而無需處理底層的分散式計算細節。此外,RLlib 也支援 PyTorch 和 TensorFlow 等主流深度學習框架,方便開發者整合現有模型和工具。文章中的程式碼範例展示瞭如何使用 Ray Actor 建立分散式模擬環境,以及如何使用 RLlib 訓練 DQN 模型,並透過評估函式驗證訓練結果。
強化學習在 Ray 上的分散式訓練實作
使用 Ray Actor 進行分散式模擬
class SimulationActor(Simulation):
"""Ray actor for a Simulation."""
def __init__(self):
env = Environment()
super().__init__(env)
內容解密:
SimulationActor繼承自Simulation類別,並使用 Ray 的actor機制進行分散式處理。- 在建構函式中,初始化一個
Environment物件,並呼叫父類別的建構函式。 - 這樣的設計使得
SimulationActor可以在不同的 Ray worker 上執行,從而實作分散式模擬。
分散式訓練函式實作
def train_policy_parallel(env, num_episodes=1000, num_simulations=4):
"""Parallel policy training function."""
policy = Policy(env)
simulations = [SimulationActor.remote() for _ in range(num_simulations)]
policy_ref = ray.put(policy)
for _ in range(num_episodes):
experiences = [sim.rollout.remote(policy_ref) for sim in simulations]
while len(experiences) > 0:
finished, experiences = ray.wait(experiences)
for xp in ray.get(finished):
update_policy(policy, xp)
return policy
內容解密:
train_policy_parallel函式負責在多個 Ray actor 上平行訓練強化學習策略。- 首先初始化一個
Policy物件和多個SimulationActor例項,並將策略物件放入 Ray 的物件儲存中。 - 在每個訓練回合中,平行呼叫各個
SimulationActor的rollout方法來收集經驗資料。 - 使用
ray.wait等待部分任務完成,並更新策略。 - 重複此過程直到所有回合完成,最終傳回訓練好的策略。
分散式訓練與評估
parallel_policy = train_policy_parallel(environment)
evaluate_policy(environment, parallel_policy)
內容解密:
- 呼叫
train_policy_parallel函式進行分散式訓練,獲得訓練好的策略。 - 使用
evaluate_policy函式評估訓練好的策略在特定環境中的表現。
強化學習關鍵概念回顧
- 環境(Environment):定義了強化學習問題中的動態系統,包含狀態、獎勵和終止條件。
- 代理(Agent):根據當前狀態選擇動作,與環境互動並學習。
- 策略(Policy):決定代理在給定狀態下選擇動作的機制。
- Q-Learning:一種更新策略的演算法,根據狀態-動作值(Q值)進行學習。
分散式強化學習的優勢
- 使用 Ray 可以輕鬆將強化學習訓練過程分散式化,提高訓練效率。
- 無需大幅修改應用程式碼,即可實作分散式計算。
Ray 分散式訓練流程圖示
圖表翻譯:
此圖示展示了使用 Ray 進行分散式強化學習訓練的流程。首先初始化環境和策略,接著建立多個 SimulationActor 進行平行模擬。然後收集經驗資料並更新策略,重複此過程直到訓練完成。最後評估最終得到的策略。
強化學習在 Ray RLlib 的應用
在前一章中,我們使用純 Python 實作了一個簡單的迷宮問題,並利用基本的強化學習演算法解決了該任務。接著,我們將這個解決方案移植到分散式的 Ray 應用程式中,程式碼行數約為 25 行。這個例子展示了 Ray 如何讓你專注於應用程式碼,而無需預先規劃如何與 Ray 協同工作。同時,它也證明瞭如何使用 Ray 高效地實作和分散式處理使用進階技術(如強化學習)的自定義工作負載。
使用 Ray RLlib 進行強化學習
大多數情況下,在訓練強化學習演算法時,你真正需要做的只有指定自定義環境,即你想要執行的“遊戲”。大多數工作將花費在選擇合適的演算法、設定引數以及最佳化訓練策略上。
Ray RLlib 是一個業界級的強化學習函式庫,用於大規模構建強化學習演算法。作為 Ray 生態系統的一部分,RLlib 繼承了 Ray 的所有效能和可擴充套件性優勢。特別是,RLlib 預設是分散式的,因此你可以將強化學習訓練擴充套件到任意數量的節點。
RLlib 的優勢
RLlib 緊密整合了其他 Ray 函式庫。例如,任何 RLlib 演算法的超引數都可以使用 Ray Tune 進行調優。此外,你還可以無縫地使用 Ray Serve 佈署 RLlib 模型。
RLlib 同時支援 PyTorch 和 TensorFlow 兩大主流深度學習框架。你可以輕鬆地在兩者之間切換,通常只需更改一行程式碼。
主要功能和特點
- 豐富的進階強化學習演算法函式庫
- 高度靈活的環境指定和處理方式
- 多代理人支援
- 根據歷史資料的經驗回放機制
使用 RLlib 的 CLI 和 Python API
本章將首先概述 RLlib 的功能,接著重新審視第三章中的迷宮遊戲,並展示如何使用 RLlib 的 CLI 和 Python API 在幾行程式碼內解決該問題。你將瞭解 RLlib 的關鍵概念,如環境和演算法,並學習如何建立課程表來引導代理人逐步學習,從簡單場景過渡到更複雜的場景。
程式碼範例:
# 匯入必要的函式庫
import ray
from ray import tune
# 初始化 Ray
ray.init()
# 設定訓練引數
config = {
"env": "CartPole-v0",
"num_gpus": 0,
"num_workers": 4,
"framework": "torch"
}
# 使用 Tune 進行訓練
results = tune.run("PPO", config=config)
# 結束 Ray
ray.shutdown()
內容解密:
這段程式碼首先匯入必要的函式庫並初始化 Ray。然後,它設定了訓練引數,包括使用的環境(CartPole-v0)、GPU 數量、工作執行緒數量以及深度學習框架(PyTorch)。接著,使用 Tune 進行 PPO 演算法的訓練。最後,關閉 Ray。
圖表說明
以下是一個簡單的 Plantuml 圖表,用於展示 RLlib 的架構:
圖表翻譯:
此圖表展示了 RLlib 在 Ray 生態系統中的位置。RLlib 建立在 Ray Core 之上,提供 Trainers 和 Policies 等元件。Trainers 負責管理工作執行緒,而 Policies 則與模型互動。這種架構使得 RLlib 能夠高效地進行分散式強化學習訓練。
使用RLlib的起步
要使用RLlib,請確保已經在電腦上安裝了它:
pip install "ray[rllib]==2.2.0"
如果不想自己輸入程式碼,可以參考本章節附帶的Jupyter Notebook。
每個強化學習(RL)問題都始於一個有趣的環境。在第1章中,我們探討了經典的倒立擺平衡問題(cart-pole balancing problem)。我們並沒有實作這個倒立擺環境,而是直接使用了RLlib提供的環境。
建立Gym環境
Gym是一個由OpenAI開發的開源Python專案,用於建立強化學習環境。如果檢視Gym的gym.Env環境介面,你會發現實作這個介面需要兩個必備的類別變數和三個方法。
簡而言之,Gym環境的介面如下所示:
import gym
class Env:
action_space: gym.spaces.Space
observation_space: gym.spaces.Space
def step(self, action):
...
def reset(self):
...
def render(self, mode="human"):
...
Gym環境具有一個動作空間(action space)和一個觀測空間(observation space)。Env可以執行一步並傳回觀測值、獎勵、完成條件和其他資訊。Env可以重置自己,傳回新回合的初始觀測值。我們可以以不同方式呈現Env,例如以人類可讀的方式或字串表示。
將迷宮環境轉換為Gym環境
在第3章中,我們實作了一個簡單的迷宮遊戲(maze game)。要使其與RLlib相容,需要將其轉換為Gym環境。我們可以透過繼承gym.Env並實作必要的方法來實作這一點。
以下是範例程式碼:
# maze_gym_env.py
import gym
from gym.spaces import Discrete
class GymEnvironment(Environment, gym.Env):
def __init__(self, *args, **kwargs):
"""將原始的Environment轉換為Gym `Env`。"""
super().__init__(*args, **kwargs)
gym_env = GymEnvironment()
內容解密:
- 我們定義了一個新的類別
GymEnvironment,它繼承自原始的Environment和gym.Env。 - 在
__init__方法中,我們呼叫了父類別的建構函式。 - 透過這種方式,我們將原始的
Environment轉換為Gym環境,使其與RLlib相容。
使用RLlib CLI訓練模型
現在我們已經將GymEnvironment實作為Gym環境,可以使用RLlib CLI來訓練模型。
首先,我們需要定義一個組態檔案,指定要使用的RLlib演算法和環境。在本例中,我們使用DQN演算法和GymEnvironment環境。
# maze.py
from ray.rllib.algorithms.dqn import DQNConfig
config = DQNConfig().environment("maze_gym_env.GymEnvironment")\
.rollouts(num_rollout_workers=2)
內容解密:
- 我們從
ray.rllib.algorithms.dqn匯入了DQNConfig類別。 - 我們建立了一個
DQNConfig例項,並設定了環境為maze_gym_env.GymEnvironment。 - 我們設定了rollout worker的數量為2。
接下來,我們可以使用以下命令來訓練模型:
rllib train file maze.py --stop '{"timesteps_total": 10000}'
這個命令會使用maze.py中的組態來訓練模型,直到總時間步數達到10,000為止。
RLlib訓練流程
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Ray 分散式強化學習訓練實作
package "機器學習流程" {
package "資料處理" {
component [資料收集] as collect
component [資料清洗] as clean
component [特徵工程] as feature
}
package "模型訓練" {
component [模型選擇] as select
component [超參數調優] as tune
component [交叉驗證] as cv
}
package "評估部署" {
component [模型評估] as eval
component [模型部署] as deploy
component [監控維護] as monitor
}
}
collect --> clean : 原始資料
clean --> feature : 乾淨資料
feature --> select : 特徵向量
select --> tune : 基礎模型
tune --> cv : 最佳參數
cv --> eval : 訓練模型
eval --> deploy : 驗證模型
deploy --> monitor : 生產模型
note right of feature
特徵工程包含:
- 特徵選擇
- 特徵轉換
- 降維處理
end note
note right of eval
評估指標:
- 準確率/召回率
- F1 Score
- AUC-ROC
end note
@enduml
圖表翻譯: 此圖表呈現了使用RLlib訓練模型的流程。首先,載入組態檔案並建立RLlib演算法。然後,開始訓練模型並檢查停止條件。如果滿足停止條件,則停止訓練;否則,繼續訓練模型。
探討Ray RLlib的強化學習應用
Ray RLlib是一個強大的強化學習框架,能夠簡化複雜的訓練過程並提供高效的演算法實作。在本章中,我們將探討如何使用RLlib來解決強化學習問題,特別是在自定義環境中的應用。
使用RLlib命令列介面
首先,我們來看看如何使用RLlib的命令列介面(CLI)來訓練模型。RLlib的CLI提供了一種簡便的方式來啟動訓練過程,無需深入瞭解底層的Python程式碼。
訓練DQN模型
使用以下命令可以啟動DQN模型的訓練:
rllib train file maze.yml
這個命令會自動處理以下事項:
- 執行更先進的Q-Learning版本(DQN)
- 自動擴充套件到多個工作節點(在此例中為兩個)
- 自動建立演算法的檢查點
訓練結果將被寫入~/ray_results/maze_env目錄。如果訓練成功完成,您將獲得一個檢查點和一個可複製的rllib evaluate命令。
評估訓練好的策略
使用以下命令可以評估訓練好的策略:
rllib evaluate ~/ray_results/maze_env/<checkpoint>\
--algo DQN\
--env maze_gym_env.Environment\
--steps 100
這個命令將評估訓練好的演算法在自定義環境中的表現,總共進行100步。
使用RLlib Python API
雖然RLlib CLI提供了一種方便的方式來啟動訓練過程,但大多數情況下,您需要使用Python API來編寫自己的強化學習實驗。
建立DQN演算法
以下是建立DQN演算法的示例程式碼:
from ray.tune.logger import pretty_print
from maze_gym_env import GymEnvironment
from ray.rllib.algorithms.dqn import DQNConfig
config = (DQNConfig()
.environment(GymEnvironment)
.rollouts(num_rollout_workers=2, create_env_on_local_worker=True)
)
algo = config.build()
for i in range(10):
result = algo.train()
print(pretty_print(result))
這段程式碼建立了一個DQN演算法,並使用兩個rollout workers進行訓練。訓練結果將被列印預出來。
訓練結果分析
訓練結果包含了詳細的資訊,例如獎勵、迭代次數等。以下是輸出結果的示例:
episode_reward_max: 1.0
episode_reward_mean: 1.0
episode_reward_min: 1.0
episodes_this_iter: 15
episodes_total: 19
...
training_iteration: 10
...
這個輸出結果表明,代理在每次迭代中都達到了最大獎勵(1.0),這意味著它已經學會瞭解決迷宮問題。
使用RLlib儲存、載入與評估模型
在簡單範例中達到目標並不困難,但讓我們看看評估訓練好的演算法是否能以最佳方式完成任務,也就是說,只需最少的8個步驟就能到達目標。為此,我們利用了RLlib CLI中另一個機制:檢查點(checkpointing)。建立演算法檢查點有助於確保在發生當機時能夠還原工作,或者只是為了持續跟蹤訓練進度。您可以透過呼叫algo.save()在訓練過程中的任何時候建立RLlib演算法的檢查點。一旦有了檢查點,就可以輕鬆地使用它來還原Algorithm。評估模型就像呼叫algo.evaluate(checkpoint)一樣簡單。
from ray.rllib.algorithms.algorithm import Algorithm
checkpoint = algo.save()
print(checkpoint)
evaluation = algo.evaluate()
print(pretty_print(evaluation))
algo.stop()
restored_algo = Algorithm.from_checkpoint(checkpoint)
內容解密:
algo.save():儲存演算法的當前狀態到檢查點。algo.evaluate():評估當前演算法的效能。algo.stop():停止演算法,釋放所有資源。Algorithm.from_checkpoint(checkpoint):從指定的檢查點還原演算法。
檢視此範例的輸出,我們現在可以確認訓練好的RLlib演算法確實收斂到了迷宮問題的良好解決方案,如評估中長度為8的劇集所示。
計算動作
RLlib演算法的功能遠不止於我們迄今為止所見的train、evaluate、save和from_checkpoint方法。例如,您可以直接根據環境的當前狀態計算動作。在第3章中,我們透過逐步執行環境並收集獎勵來實作劇集展開。我們可以輕鬆地使用RLlib對我們的GymEnvironment做同樣的事情:
env = GymEnvironment()
done = False
total_reward = 0
observations = env.reset()
while not done:
action = algo.compute_single_action(observations)
observations, reward, done, info = env.step(action)
total_reward += reward
內容解密:
algo.compute_single_action(observations):根據給定的觀察結果計算單個動作。env.step(action):在環境中執行給定的動作,並傳回新的觀察結果、獎勵、完成狀態和額外資訊。
如果您需要一次計算多個動作,而不僅僅是一個,您可以使用compute_actions方法,它接受觀察結果的字典作為輸入,並產生具有相同字典鍵的動作字典作為輸出:
action = algo.compute_actions(
{"obs_1": observations, "obs_2": observations}
)
print(action)
# {'obs_1': 0, 'obs_2': 1}
內容解密:
algo.compute_actions({"obs_1": observations, "obs_2": observations}):根據多個觀察結果計算多個動作。
存取策略和模型狀態
每個強化學習演算法都根據一個策略,該策略根據代理對環境的當前觀察結果選擇下一個動作。每個策略反過來又根據一個底層模型。在我們討論的 vanilla Q-Learning 的情況下,模型是一個簡單的狀態-動作值查詢表,也稱為Q值。而該策略使用此模型來預測下一個動作,以防它決定利用模型迄今為止所學到的知識,或者以其他方式隨機探索環境。
policy = algo.get_policy()
print(policy.get_weights())
model = policy.model
內容解密:
algo.get_policy():取得演算法使用的策略。policy.get_weights():取得底層模型的權重。policy.model:取得策略使用的模型。
workers = algo.workers
workers.foreach_worker(
lambda remote_trainer: remote_trainer.get_policy().get_weights()
)
內容解密:
algo.workers:取得演算法使用的所有工作者。workers.foreach_worker():對每個工作者執行給定的函式,以取得其策略的權重。
每個從策略獲得的RLlib模型都有一個base_model,它有一個簡潔的summary方法來描述自己:
model.base_model.summary()
內容解密:
model.base_model.summary():輸出模型的摘要資訊。