• 文件 >
  • 模型最佳化入門
捷徑

模型最佳化入門

作者: Vincent Moens

注意

若要在 notebook 中執行此教學課程,請在開頭新增一個包含以下內容的安裝儲存格

!pip install tensordict
!pip install torchrl

在 TorchRL 中,我們嘗試像在 PyTorch 中一樣處理最佳化,使用專用的損失模組,這些模組的設計目的僅在於最佳化模型。 這種方法有效地將策略的執行與其訓練分離,並允許我們設計類似於傳統監督式學習範例中的訓練迴圈。

因此,典型的訓練迴圈看起來像這樣

>>> for i in range(n_collections):
...     data = get_next_batch(env, policy)
...     for j in range(n_optim):
...         loss = loss_fn(data)
...         loss.backward()
...         optim.step()

在這個簡潔的教學課程中,您將收到損失模組的簡要概述。 由於基本使用的 API 通常很簡單,因此本教學課程將保持簡短。

RL 目標函數

在 RL 中,創新通常涉及探索最佳化策略的新方法(即新演算法),而不是像在其他領域中看到的那樣,專注於新架構。 在 TorchRL 中,這些演算法被封裝在損失模組中。 損失模組協調您演算法的各種元件,並產生一組可以反向傳播的損失值,以訓練相應的元件。

在本教學課程中,我們將以一個流行的離策略演算法為例,DDPG

要建構損失模組,唯一需要的是一組定義為 :class:`~tensordict.nn.TensorDictModule`s 的網路。 在大多數情況下,其中一個模組將是策略。 也可能需要其他輔助網路,例如 Q 值網路或某種評論家。 讓我們看看這在實踐中是什麼樣子的:DDPG 需要從觀察空間到動作空間的確定性映射,以及一個預測狀態-動作對值的價值網路。 DDPG 損失將嘗試找到輸出動作的策略參數,這些動作可以最大化給定狀態的值。

為了建立損失函數,我們需要 actor 和 value 網路。如果它們是依照 DDPG 的期望所建立的,那麼我們就擁有了一個可訓練的損失模組。

from torchrl.envs import GymEnv

env = GymEnv("Pendulum-v1")

from torchrl.modules import Actor, MLP, ValueOperator
from torchrl.objectives import DDPGLoss

n_obs = env.observation_spec["observation"].shape[-1]
n_act = env.action_spec.shape[-1]
actor = Actor(MLP(in_features=n_obs, out_features=n_act, num_cells=[32, 32]))
value_net = ValueOperator(
    MLP(in_features=n_obs + n_act, out_features=1, num_cells=[32, 32]),
    in_keys=["observation", "action"],
)

ddpg_loss = DDPGLoss(actor_network=actor, value_network=value_net)

就是這樣!我們的損失模組現在可以使用來自環境的資料來運行(我們省略了探索、儲存和其他功能,以便專注於損失函數的功能)。

rollout = env.rollout(max_steps=100, policy=actor)
loss_vals = ddpg_loss(rollout)
print(loss_vals)
TensorDict(
    fields={
        loss_actor: Tensor(shape=torch.Size([]), device=cpu, dtype=torch.float32, is_shared=False),
        loss_value: Tensor(shape=torch.Size([]), device=cpu, dtype=torch.float32, is_shared=False),
        pred_value: Tensor(shape=torch.Size([100]), device=cpu, dtype=torch.float32, is_shared=False),
        pred_value_max: Tensor(shape=torch.Size([]), device=cpu, dtype=torch.float32, is_shared=False),
        target_value: Tensor(shape=torch.Size([100]), device=cpu, dtype=torch.float32, is_shared=False),
        target_value_max: Tensor(shape=torch.Size([]), device=cpu, dtype=torch.float32, is_shared=False),
        td_error: Tensor(shape=torch.Size([100]), device=cpu, dtype=torch.float32, is_shared=False)},
    batch_size=torch.Size([]),
    device=None,
    is_shared=False)

LossModule 的輸出

正如您所看到的,從損失函數收到的 value 並非單一的純量,而是一個包含多個損失的字典。

原因很簡單:由於可能一次訓練多個網路,並且由於某些使用者可能希望在不同的步驟中分離每個模組的優化,因此 TorchRL 的目標將會返回包含各種損失成分的字典。

這種格式也允許我們傳遞與損失值相關的 metadata。一般來說,我們會確保只有損失值是可微分的,這樣您就可以簡單地對字典的值進行加總以獲得總損失。如果您想確保完全掌控發生的一切,您可以只對鍵以 "loss_" 前綴開頭的項目進行加總。

total_loss = 0
for key, val in loss_vals.items():
    if key.startswith("loss_"):
        total_loss += val

訓練 LossModule

鑑於以上所有內容,訓練模組與在任何其他訓練迴圈中所做的並沒有太大的不同。由於它封裝了模組,因此取得可訓練參數列表的最簡單方法是查詢 parameters() 方法。

我們需要一個最佳化器(或每個模組一個最佳化器,如果那是您的選擇)。

from torch.optim import Adam

optim = Adam(ddpg_loss.parameters())
total_loss.backward()

以下項目通常可以在您的訓練迴圈中找到

進一步的考量:目標參數

另一個需要考慮的重要方面是在 off-policy 演算法(如 DDPG)中 target 參數的存在。Target 參數通常代表參數隨時間推移的延遲或平滑版本,它們在 policy 訓練期間的 value 估計中起著至關重要的作用。與使用 value 網路參數的目前配置相比,使用 target 參數進行 policy 訓練通常被證明效率更高。通常,target 參數的管理由損失模組處理,從而免除了使用者直接的擔憂。但是,根據特定需求,使用者仍然有責任根據需要更新這些值。TorchRL 提供了幾個更新器,即 HardUpdateSoftUpdate,它們可以輕鬆地被實例化,而無需深入了解損失模組的底層機制。

from torchrl.objectives import SoftUpdate

updater = SoftUpdate(ddpg_loss, eps=0.99)

在您的訓練迴圈中,您需要在每個優化步驟或每個收集步驟更新 target 參數

updater.step()

這就是開始使用損失模組所需知道的一切!

要進一步探索該主題,請查看

腳本總執行時間: (0 分鐘 26.921 秒)

預估記憶體用量: 320 MB

由 Sphinx-Gallery 產生

文件

存取 PyTorch 的完整開發者文件

檢視文件

教學

取得適用於初學者和進階開發人員的深入教學

檢視教學

資源

尋找開發資源並取得您問題的解答

檢視資源