跳至主要內容

指南

教學:評估強化學習策略

一份針對兩類強化學習問題的可執行演練:一個您能執行的策略在各回合上表現如何;以及一個您無法在真實世界中試用的策略原本會表現如何,依據它將要取代的那個策略的日誌來評判。兩個範例都在本機執行,無需提供者憑證。

每個欄位和評估器的參考見強化學習;案例、評估器、指標、區間和閘門這些術語在核心概念中。本頁是貫穿它們的動手路線。

Oloproof 在這裡做什麼、不做什麼

Oloproof 不執行您的環境、不託管模擬器,也不訓練策略。您的系統在它自己的環境中執行每個回合(episode),並把它記錄為一個 rl_episode/v1 產物,每個回合指標都是從這份記錄中讀出來的。在第二部分中什麼都不執行:受測策略只說明它會給每個動作的機率。

把兩個問題分開:

問題您擁有什麼部分
這個策略在各回合上表現如何?一個您能執行的策略與環境1
這個策略在正式環境中原本會表現如何?一個較舊策略所做決策的日誌,以及它使用的機率2

事前準備

  • Python 3.11 或更高版本,並已安裝 Oloproof(pip install oloproof)。
  • 範例專案,它隨軟體套件一起提供。把它複製到一個新目錄:
oloproof init --example rl my-rl

它包含兩個專案:episodes/ 與 off_policy/。下面的每條命令都在其中一個專案內執行,證據儲存在該專案的 .oloproof/ 目錄中。

第 1 部分:一個您能執行的策略

cd my-rl/episodes

檔案

檔案它是什麼
env.py一個網格世界、兩個策略(wander 與 plan)以及執行它們的系統
data/tasks.jsonl24 個網格,每個是一個任務:牆壁、危險格、一個起點與一個目標
oloproof.yaml基準策略 wander 的套件
candidate.yaml候選策略 plan 的同一個套件
release.yaml發布政策
comparison.yaml候選版本相對於基準必須滿足的規則

一個回合每步移動一格,直到抵達目標或用完步數。每一步得 -1,抵達目標得 +10,因此報酬(return)介於 -30(30 步,未抵達目標)與 10 之間。進入危險格的成本為 1:這就是安全限制條件。十次移動中有一次會滑向隨機方向,無論策略選擇了什麼,因此同一個策略在同一個網格上可能表現不同。

記錄一個回合

系統自己執行回合,並把記錄交給案例記錄器:

@system(name="grid-agent", version="wander-v1", records=("rl_episode/v1",))
def run_baseline(task):
    return _run(task, wander)


def _run(task, policy):
    recorder = current_case()
    record = episode(task, policy, seed=task["seed"] * 1000 + recorder.replicate)
    recorder.rl_episode(record)
    return {"success": record["success"], "steps": len(record["steps"])}

記錄列出了每一步的獎勵與成本、回合是否抵達了目標(success),以及是否是步數上限結束了它(truncated)。

每個任務多個回合

oloproof.yaml 宣告了 replicates: 5,因此每個任務執行五個回合。current_case().replicate 說明是哪一個(0 到 4),環境用它為回合設定種子:同一個任務的同一個回合總是以同樣的方式重播,而第二次執行會重複使用已儲存的回合,而不是再次執行它們。

任務仍然是單位。每個準則都是 24 個任務上的平均值,而每個任務的值是它自己在五個回合上的平均值,因此區間計數的是 24 個任務,而不是 120 個回合。按回合計數,等於假裝一個網格的五個回合是五個獨立的網格。

評估器:

evaluators:
  - {type: episode_return, return_range: [-30, 10]}
  - {type: episode_success}
  - {type: episode_cost_within, budget: 0, criterion: hazard_free}
metrics:
  - {id: solved_every_time, type: every_replicate, criterion: episode_success}

return_range 是必需的:平均報酬上的區間只在每個報酬都落入的範圍內成立,而超出該範圍的報酬會停止執行。solved_every_time 只有在一個任務的全部五個回合都抵達目標時才計入該任務。

執行基準

oloproof run
Gate: BLOCK (exit 3)
                                        Decisions
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Rule          ┃ Metric          ┃ State                 ┃ Reasons                     ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ success-floor │ episode_success │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ safety-floor  │ hazard_free     │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
└───────────────┴─────────────────┴───────────────────────┴─────────────────────────────┘
                                                           Metrics
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Metric            ┃ Estimate ┃ Interval        ┃ N                                                                         ┃
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ episode_return    │ -10.51   │ [-16.44, -5.11] │ mean of 24 observed · 0 missing · 0 excluded                              │
│ episode_success   │ 76.7%    │ [55.4%, 89.6%]  │ 24 cases observed · 0 missing · 0 excluded · 5 replicates each · 14 flaky │
│ hazard_free       │ 29.2%    │ [10.3%, 54.0%]  │ 24 cases observed · 0 missing · 0 excluded · 5 replicates each · 9 flaky  │
│ solved_every_time │ 37.5%    │ [18.7%, 59.5%]  │ 9 / 24 observed · 0 missing · 0 excluded · 5 replicates each · 14 flaky   │
└───────────────────┴──────────┴─────────────────┴───────────────────────────────────────────────────────────────────────────┘
Cache: execution 0 hit/120 miss; judgment 0 hit/360 miss

逐列閱讀:

  • 漫遊策略在 76.7% 的回合中抵達目標,但區間從 55.4% 到 89.6%,因此 75% 的下限既沒有被達到,也沒有被錯過:INSUFFICIENT_EVIDENCE。
  • 它只在 24 個任務中的 9 個上做到五個回合每次都解決。「通常有效」與「每次都有效」是不同的主張,而一個將在無人看管下執行的代理需要的是後者。
  • 14 個任務不穩定:它們的成功與否在完全相同的回合之間有所變動。每個任務只跑一個回合是無法顯示這一點的。
  • 它在 29.2% 的回合中避開了危險格。區間的上端 54.0% 高於 50% 的下限,因此即使是這樣糟糕的紀錄,也還不能證明這個策略不安全。

檢視一個任務:

oloproof inspect RUN_ID --case grid_03
output: {
  "success": false,
  "steps": 30
}
judgments:
  episode_return: score -30
  episode_success: failed
  hazard_free: passed

grid_03 的第一個回合用完了步數:報酬 -30,沒有抵達目標,沒有進入危險格。

執行候選版本

oloproof run --config candidate.yaml
│ success-floor │ episode_success │ PASS                  │ lower_bound_meets_minimum   │
│ safety-floor  │ hazard_free     │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ episode_return    │ 0.42     │ [-5.78, 2.59]   │ mean of 24 observed · 0 missing · 0 excluded                             │
│ episode_success   │ 100.0%   │ [79.9%, 100.0%] │ 24 cases observed · 0 missing · 0 excluded · 5 replicates each           │
│ hazard_free       │ 57.5%    │ [29.3%, 81.5%]  │ 24 cases observed · 0 missing · 0 excluded · 5 replicates each · 6 flaky │
│ solved_every_time │ 100.0%   │ [85.7%, 100.0%] │ 24 / 24 observed · 0 missing · 0 excluded · 5 replicates each            │

規劃策略在每個回合中都抵達目標,因此成功率下限通過。它仍然會進入危險格:有些網格沒有安全路徑,濕滑的地面又會把它推進其他危險格。它 57.5% 的安全率高於下限,但 24 個任務還不能證明它高於 50%。

比較兩個策略

oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy comparison.yaml
episode_return: +10.92 [+0.21, +17.74] · 24 paired · 0 missing · 0 excluded
episode_success: +23.3 points [-3.2, +44.6] · 24 paired · 0 missing · 0 excluded
hazard_free: +28.3 points [-2.4, +54.7] · 24 paired · 0 missing · 0 excluded
solved_every_time: +62.5 points [+24.3, +87.7] · 24 paired · 0 missing · 0 excluded
Decisions
  return-better  episode_return  superiority  PASS  difference_above_zero
  safety-no-worse  hazard_free  non-inferiority, margin 5.0 points  PASS  lower_bound_above_margin
Gate: ALLOW (exit 0)

比較把每個任務與它自己配對,每一側取它在五個回合上的平均值。報酬的差異以報酬本身的單位表示:規劃策略每個回合大約多得 10.9,至少多得 0.21。在相同的網格上配對後,5 個百分點的差距(margin)就足以表明規劃策略的安全性不比基準差,儘管兩次執行單獨都無法確定各自的安全下限。

第 2 部分:依據日誌評判的策略

cd ../off_policy

一個客服台把每張工單路由到一個小模型或一個大模型。目前的路由器隨機地在 70% 的時間裡選擇小模型,30% 的時間裡選擇大模型。您寫了一條新規則:技術類工單以及較長的帳務類工單交給大模型。您還不能在真實工單上試用它,但舊路由器的日誌可以替它作答。這就是離策略評估(off-policy evaluation)。

日誌及其檔案

檔案它是什麼
data/decisions.jsonl目前的路由器做出的 600 筆決策
make_log.py寫出該日誌的模擬程式,讓您能看到它是如何產生的
router.py新規則,也就是受測系統
oloproof.yaml套件
release.yaml發布政策

日誌的每一行是一筆決策:

{"id":"t001","input":{"topic":"technical","length":"short"},"expected":{"action":"small","logging_probabilities":{"small":0.7,"large":0.3},"reward":1}}

input 是路由器看到的內容,action 是它的選擇,logging_probabilities 是它在那一刻給每個模型的機率,reward 表示工單是否獲得解決。新規則只以它自己的機率作答:

@system(name="ticket-router", version="by-topic-v1")
def route_by_topic(ticket):
    large = ticket["topic"] == "technical" or (
        ticket["topic"] == "billing" and ticket["length"] == "long"
    )
    return {"probabilities": {"small": 0.0 if large else 1.0, "large": 1.0 if large else 0.0}}

評估器:

evaluators:
  - {type: off_policy_value, reward_range: [0, 1], propensity_floor: 0.3}
  - {type: off_policy_improvement, reward_range: [0, 1], propensity_floor: 0.3}

每筆已記錄的決策,都按新規則做出它的可能性比舊路由器高多少或低多少來重新加權:一張舊路由器以 0.3 的機率送往大模型、而新規則總會送往那裡的工單,計為 1 / 0.3 次;一筆新規則永遠不會做出的決策計為零。propensity_floor 是舊路由器給它可能選擇的任何模型的最小機率。它限制了該權重,而沒有限制,任何區間都不成立。

執行

oloproof run
│ resolution-floor    │ off_policy_value       │ PASS                  │ lower_bound_meets_minimum                                                          │
│ better-than-current │ off_policy_improvement │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold                                                        │
│                     │                        │                       │ about 2633 more cases would decide it, if the observed values hold (3233 in total) │
│ off_policy_value       │ 0.775    │ [0.632, 0.921]  │ mean of 600 observed · 0 missing · 0 excluded │
│ off_policy_improvement │ 0.060    │ [-0.064, 0.188] │ mean of 600 observed · 0 missing · 0 excluded │

新規則估計能解決 77.5% 的工單,在 95% 信賴水準下至少為 63.2%:60% 的下限通過。它是否勝過目前的路由器尚無定論。估計值好 6 個百分點,但區間從差 6.4 個百分點到好 18.8 個百分點,而引擎會說明大約還需要多少筆已記錄的決策才能作出決定。

這個寬度就是從別人的選擇中學習的代價。只有舊路由器碰巧送往大模型的那 30% 工單能說明大模型的情況,而且每一張都被計入三次以上。有兩件事能讓它變窄:更長的日誌,以及探索更多的舊路由器。

從您自己的系統記錄決策

  • 在路由器做決策時記錄機率,而不是事後記錄;並記錄每個選項的機率,而不只是被選中的那個。Oloproof 不估計它們:猜測的機率會讓區間建立在這個猜測之上。
  • 在 input 中只放入路由器做決策時看到的內容,絕不放入被選中的選項或結果:受測策略不得看到它們。
  • 如果您的新策略以抽樣做出選擇,請回傳它抽樣所依據的機率,而不是它抽到的那一個選項。每個選項的名稱要與日誌中的完全一致:拼寫不同的選項會被視為舊路由器從未選擇過的選項。
  • 在正式環境的路由中保留一定的隨機性。一個從不選擇某個選項的策略,不會在日誌中留下任何東西來評判一個會選擇它的規則。
  • 答案描述的是與已記錄工單相似的工單,範圍是日誌所涵蓋的期間。您的流量發生的變化不在其中。
  • 格式錯誤的行(機率總和不為 1、被選中選項的機率為 0、獎勵超出 reward_range)會停止執行。新規則會選擇一個舊路由器所給機率低於下限之選項的決策,或獎勵缺失的決策,都計為缺失,並會使區間變寬。

尚未建置的功能

  • 對一連串決策的離策略評估,其中每一步的選擇都會改變接下來發生的事。只支援每個案例一筆決策。
  • 路由器在時間範圍內一邊學習一邊改變機率的日誌。
  • 託管或重設環境、模擬器或機器人。

下一步