一個行動現在只拿到 −0.1,另一個卻能立刻結束。只看當下數字,你可能會做出和長期目標不同的選擇:那個小小的代價,也許是走向後面 +1 報酬的必要一步。
上一篇 bandit把問題簡化成每次選一臂、只收當次回饋。本篇把「下一個狀態」放回來。行動除了決定現在收到的 reward,也會改變之後能做什麼、可能拿到什麼。這是 Markov Decision Process,簡稱 MDP,用來描述的事情。
我們用一個只有三個非終止狀態、六個轉移的小世界,真正執行 2000 回合 Q-learning。你可以從手算右路報酬,一路對到程式的六個 Q 值;也能看出為何「真的終止」和「收集到步數上限」不能用同一個 target。
MDP 的狀態,要足以描述接下來會發生什麼
MDP 裡有 agent、environment、state、action 和 reward。Agent 在狀態 s 選行動 a;環境產生下一狀態 s′ 和獎勵 r;agent 再根據新狀態做下一次決定。
「Markov」不是說過去不重要,而是說我們選的狀態已經包含了預測未來轉移所需的過去資訊。在給定目前狀態和行動後,下一狀態與獎勵的條件分布不再需要更早的歷史:
p(s′, r | s, a)
例如,機器是否過熱會影響下一步是否故障;若 state 只記機器位置、不記必要的溫度資訊,就不能因為寫成 state 這個變數名,便當它自動具有 Markov 性質。同樣地,畫面中的同一個位置若可能有不同的庫存、剩餘時間或其他隱藏狀態,後續行為也未必相同。
本篇的小世界刻意沒有這些隱藏因素。非終止狀態是 0、1、2,行動只有 L 與 R;goal 為狀態 3、trap 為狀態 4。每個狀態—行動對都確定得到以下結果:
| 當前狀態 | L,action 0 | R,action 1 |
|---|---|---|
| 0 | 到 trap 4;reward −1;終止 | 到 1;reward −0.1 |
| 1 | 到 0;reward −0.1 | 到 2;reward −0.1 |
| 2 | 到 1;reward −0.1 | 到 goal 3;reward +1;終止 |
這張表是讀者與環境設計者知道的模型。Q-learning agent 不會拿整張表先算路線,只會收到實際執行後的狀態、動作、獎勵、下一狀態與真正終止旗標。環境確定,不表示學習者一開始已經知道所有結果。
Reward 是一步的回饋,return 才是沿路的目標
從狀態 0 一路向右,會依序得到:
0 --R, −0.1--> 1 --R, −0.1--> 2 --R, +1--> goal
Reward 是每一步收到的 −0.1、−0.1、+1。Undiscounted return 把它們相加,得到 .8。若採折扣 γ=.9,則從起點看的 return 是:
G₀ = R₁ + γR₂ + γ²R₃
= −0.1 + 0.9×(−0.1) + 0.9²×1
= 0.62
後面才收到的獎勵,被乘上更多次 γ。一般寫法是:
G_t = R_(t+1) + γR_(t+2) + γ²R_(t+3) + ...
= R_(t+1) + γG_(t+1)
真正終止後沒有後續報酬,因此 terminal state 的 continuation value 為 0。到 goal 那一步的 +1 已經是這次轉移的 reward,不能到終止狀態後再加一次。
γ 在這裡定義我們要優化的折扣目標,不是「未來獎勵真的有 90% 機率存在」的保證。若換折扣、換每步成本,最佳策略或價值都可能改變。不要把 .8 和 .62 當成程式互相矛盾:它們分別回答未折扣與折扣後的總報酬。
價值函數再把隨機性和後續策略納入。vπ(s) 是從 s 開始、之後依策略 π 行動的期望 return;qπ(s,a) 則指定第一步先做 a,再依 π 行動。Q-learning 想估的是最優的 action-value q*,而不是某個行動當下 reward 的平均。
Bellman 關係:下一個狀態的價值,接回現在這一步
如果完整轉移模型已知,可以把下一狀態和獎勵的所有可能性加權,寫出最優 Q 的 Bellman 關係:
Q*(s,a) = Σ_(s′,r) p(s′,r | s,a)
× [r + γ max_b Q*(s′,b)]
若該轉移真正終止,方括號只剩 r。
這裡的加總是一個期望;max 表示走到下一狀態之後,按最優 continuation 選行動。它不是說當前所有行動都會執行一次,也不是讓 agent 同時看見全部反事實回饋。
例如圖中的 S₁ 做 a₀,會以 .7/.1/.2 分別到 S₀/S₁/S₂,合計為 1。這類模型需要對可能結果加權;不能看見標著 +5 的線,就當成做了某行動必然拿到 +5,或直接把那裡當成終點。
本例是確定性模型,每個 (s,a) 只有一個結果,所以加權加總縮成單一項。從 goal 前面往回算右路:
V*(2) = 1
V*(1) = −0.1 + 0.9×1 = 0.8
V*(0) = −0.1 + 0.9×0.8 = 0.62
再算三個左行動的 Q:
Q*(0,L) = −1 (進 trap,終止)
Q*(1,L) = −0.1 + 0.9×0.62 = 0.458
Q*(2,L) = −0.1 + 0.9×0.8 = 0.62
注意 Q*(1,L) 不是一路永遠向左的總報酬。它的定義是「這一步先 L,到 0 後再按最優策略繼續」,所以會重新向右走。
完整程式另外用已知模型做 synchronous Bellman iteration,作為訓練後的 oracle 對照。每輪先從舊 Q 表算出整張新表,不在同一輪中混用剛寫入的新值。這個已知模型的計算是 model-based 參考答案,與下面只從 transition 學習的 model-free 更新分開。
Q-learning 的 TD target,與實際選動作的策略不同
圖中的多個綠箭頭提醒我們:一個狀態可能不只一個 action 達到最大 Q;選哪個要有 tie-breaking 規則。本篇固定同分選較小 ID,並不要求所有最優策略只有一條路。
Q-learning 不需要每次列出全部轉移分布。收到一筆實際經驗後,它使用單筆 reward,加上目前估計的下一狀態最大 Q,形成 sampled TD target:
target = r + γ max_b Q(s′,b) (非終止)
TD error = target − Q(s,a)
Q(s,a) ← Q(s,a) + α × TD error
最重要的是最後那個加號:當 target 高於舊 Q,更新往上走;低於舊 Q,更新往下走。本篇固定 α=.2,所以每次只把目前的 Q 往 target 移動差距的 20%。Target 使用的下一狀態 Q 也是當前估計,並不是老師直接給的正確長期報酬。
例如最初整張 Q 表都是 0。第一次在 0 選 L,觀察到 reward −1 並進入 trap,target 只剩 −1:
Q(0,L) = 0 + 0.2×(−1−0) = −0.2
第一次從 2 選 R 到 goal,則從 Q(2,R)=0 更新成 .2。後續回來觀察時,這些估計又會讓更前面的狀態得到不同 target,報酬的影響逐漸向前傳。
那探索在哪裡?它位於 behavior policy,也就是決定實際執行哪個 action 的規則。本例用 ε=.2:80% 選當前 Q 最大者,20% 均勻抽兩個動作。同分選較小 ID;唯一最佳動作的總機率為 .8+.2/2=.9,另一個為 .1。
但 Q-learning 的 target 沒有把下一步 behavior 抽到的 action 放進去,它仍用 max。用已知最優表做一個獨立算術例:0 選 R 後到 1、reward −.1,當前下一狀態 Q(L/R)=[.458,.8]。
後兩列只比較 target 定義,本篇沒有額外訓練 SARSA 或 Expected SARSA。它們說明 off-policy 的意義:behavior 影響會走到哪裡、更新哪些 pair,Q-learning 卻用 greedy continuation 估計最優 Q。Off-policy 不代表不必探索,也不代表可以用完全沒覆蓋的資料自動推得所有行動的價值。
真正終止與步數截斷,不能都把 continuation 清成零
本篇只有進入 goal 或 trap 才是 MDP 的真正終止。這時 target=r,不讀 terminal Q,也不把下一回合重置到 0 當成這個 terminal 的下一狀態。
另外,collector 為了避免一次回合收集太久,最多走 20 步。假如第 20 步仍在非終止狀態,收集器會停止這次 rollout,下回合再從 0 開始;這叫 truncation。它不表示該 MDP 狀態的未來報酬消失。
所以在這個合約裡:
terminated = True:target只用r
truncated,但terminated = False:仍用r + γ maxQ(next_state)
保存程式把 terminated 傳給 learner 的更新;步數上限由外層 collector 控制。沒有為了方便做一個「只要停止就設 done=True」的合併旗標。
這次 seed 的 2000 回合全都在 20 步內進入 goal 或 trap,實際 truncated 數為 0。輸出另外保留非訓練的 controlled 算術例:假設收集器在 0R→1 後停止,並使用非零的 Q(1,R)=.8,正確 target 是 −.1+.9×.8=.62;誤當真正終止會只剩 −.1。這是用來核對更新規則,不冒充實際發生的訓練截斷。
如果你的任務本來就規定「20 步後世界結束」,情況又不同:剩餘時間會影響價值,通常需要納入狀態,建立有限 horizon 的問題。不能把本篇為收集方便設定的上限,當成所有時間限制的標準答案。
實際跑完後:Q 表接近答案,探索期間仍可能掉進 trap
這張表幫助我們看清資料結構:一列是一個 state,一欄是一個 action,格子存的是估計值,不是轉移機率。來源的六個 action 包含移動與接送;本篇只有 L/R,因此使用六格而非 500×6 格。初始化為 0 是本例選擇,不表示初始就知道真正價值等於 0。
固定 γ=.9、α=.2、ε=.2、seed 7,從狀態 0 開始執行 2000 回合。環境沒有隨機轉移,隨機性只來自 ε-greedy 的行動選擇;參數並未根據保留資料反覆挑選。
實際總共觀察 6318 次轉移:1753 回合到 goal、247 回合到 trap、0 回合截斷。每個 pair 的訪次和最終 Q 如下:
| State | L 訪次 | R 訪次 | 最終 Q(L) | 最終 Q(R) |
|---|---|---|---|---|
| 0 | 247 | 1968 | −1.000 | .620 |
| 1 | 215 | 1944 | .458 | .800 |
| 2 | 191 | 1753 | .620 | 1.000 |
六個 pair 都有更新;訪次合計等於總轉移數。訓練後,已知模型的同步 Bellman iteration 在 5 次 sweep 達到設定容許誤差,與 learned Q 的最大絕對差約 7.78×10⁻¹⁶。
這個結果說明程式在此小型確定模型上學到了可手算的值,沒有證明固定 α=.2、跑 2000 回合在任意問題都會收斂。Watkins 與 Dayan 的表格型收斂結果有其條件,包括有界獎勵、持續充分造訪,以及每個 pair 的學習率序列需符合相應的和發散、平方和收斂條件。固定學習率的平方和不會收斂;有限次「六格都訪問過」也不是無限造訪條件。
訓練的 behavior 仍保留探索,所以平均每回合未折扣報酬為 .5371。訓練後另外凍結 Q、移除 ε 探索,greedy evaluation 才是 0R→1R→2R→goal,未折扣 return .8、discounted return .62。
不能把這條漂亮的 greedy 軌跡,當成訓練期間每一次都安全到達 goal。這個區分也提醒我們:學到某條策略的價值、實際蒐集資料時採什麼策略,以及上線後承擔什麼風險,是相關卻不同的問題。
用完整標準庫程式核對六格 Q 與終止更新
已實際執行的環境為 Python 3.10.12、CPU,只有標準庫,不需 pip 安裝第三方套件。requirements.txt 的內容為:
# Python 3.10.12; standard library only. No third-party packages required.
把完整程式存成 tabular_q_learning.py,在同目錄執行:
python3 tabular_q_learning.py > stdout.json
成功時 exit 0,JSON 可解析。除了最後 Q 表,請核對 goal+trap+truncated=2000、六個 pair 訪次合計 6318,以及第一回合 0L 的 target=−1、new Q=−.2。真正 terminal 的樣本不能帶有非零 bootstrap;controlled truncation 範例則應保留 .8 的下一狀態 continuation。
輸出也保存模型對照、greedy 完整軌跡、behavior 與 target 算術差異。它們是這個固定單 seed 合約的檢查材料,不是通用環境 API、function approximation、離線資料覆蓋或真實控制安全性的測試。
"""Original deterministic tabular MDP; standard-library mechanics, not a maze benchmark."""
import json
import math
import platform
import random
NONTERMINAL_STATES = (0, 1, 2)
ACTIONS = (0, 1) # L=0, R=1
GOAL, TRAP = 3, 4
GAMMA, ALPHA, EPSILON = 0.9, 0.2, 0.2
SEED, EPISODES, MAX_STEPS = 7, 2000, 20
def argmax_low_id(row):
return max(range(len(row)), key=lambda action: row[action])
def environment_step(state, action):
"""Only the environment/evaluator uses this complete transition model."""
transitions = {
(0, 0): (TRAP, -1.0, True),
(0, 1): (1, -0.1, False),
(1, 0): (0, -0.1, False),
(1, 1): (2, -0.1, False),
(2, 0): (1, -0.1, False),
(2, 1): (GOAL, 1.0, True),
}
if (state, action) not in transitions:
raise ValueError("Step accepts only nonterminal states0..2 and actions0..1")
return transitions[state, action]
class QLearner:
def __init__(self, seed):
self.q = [[0.0, 0.0] for _ in NONTERMINAL_STATES]
self.visits = [[0, 0] for _ in NONTERMINAL_STATES]
self.rng = random.Random(seed)
def choose(self, state):
if self.rng.random() < EPSILON:
# Random branch includes the greedy action as well.
return self.rng.randrange(len(ACTIONS))
return argmax_low_id(self.q[state])
def observe(self, state, action, reward, next_state, terminated):
# A true terminal has no continuation. Time-limit truncation is NOT terminal.
bootstrap = 0.0 if terminated else max(self.q[next_state])
target = reward + GAMMA * bootstrap
before = self.q[state][action]
td_error = target - before
after = before + ALPHA * td_error
self.q[state][action] = after
self.visits[state][action] += 1
return {"state": state, "action": action, "reward": reward,
"next_state": next_state, "terminated": terminated,
"old_q": before, "bootstrap_max_q": bootstrap,
"target": target, "td_error": td_error, "new_q": after}
def model_oracle():
"""Synchronous Bellman iteration using the known model, separate from the learner."""
q = [[0.0, 0.0] for _ in NONTERMINAL_STATES]
for sweep in range(1, 1001):
updated = []
for state in NONTERMINAL_STATES:
row = []
for action in ACTIONS:
next_state, reward, terminated = environment_step(state, action)
row.append(reward if terminated else reward + GAMMA * max(q[next_state]))
updated.append(row)
change = max(abs(updated[s][a] - q[s][a]) for s in NONTERMINAL_STATES for a in ACTIONS)
q = updated
if change < 1e-14:
return q, sweep
raise RuntimeError("Oracle iteration did not stabilize")
def evaluate_greedy(q):
state = 0
trajectory = []
for time_index in range(MAX_STEPS):
action = argmax_low_id(q[state])
next_state, reward, terminated = environment_step(state, action)
trajectory.append({"state": state, "action": action, "reward": reward,
"next_state": next_state, "terminated": terminated})
state = next_state
if terminated:
break
return {"trajectory": trajectory,
"undiscounted_return": math.fsum(x["reward"] for x in trajectory),
"discounted_return": math.fsum(GAMMA**t * x["reward"] for t, x in enumerate(trajectory)),
"terminated": trajectory[-1]["terminated"],
"truncated": not trajectory[-1]["terminated"] and len(trajectory) == MAX_STEPS}
def main():
learner = QLearner(SEED)
endings = {"goal": 0, "trap": 0, "truncated": 0}
terminal_samples = {"goal": [], "trap": []}
truncation_samples = []
first_episode_transitions = []
episode_lengths = []
episode_returns = []
for episode in range(EPISODES):
state = 0
rewards = []
for step in range(1, MAX_STEPS + 1):
action = learner.choose(state)
next_state, reward, terminated = environment_step(state, action)
# This flag controls the collector/reset only, not the Bellman target.
truncated = step == MAX_STEPS and not terminated
update = learner.observe(state, action, reward, next_state, terminated)
rewards.append(reward)
record = {"episode_0_based": episode, "step_1_based": step,
"truncated": truncated, **update}
if episode == 0:
first_episode_transitions.append(record)
if terminated:
kind = "goal" if next_state == GOAL else "trap"
endings[kind] += 1
if len(terminal_samples[kind]) < 3:
terminal_samples[kind].append(record)
break
if truncated:
endings["truncated"] += 1
if len(truncation_samples) < 3:
truncation_samples.append(record)
break
state = next_state
episode_lengths.append(len(rewards))
episode_returns.append(math.fsum(rewards))
oracle_q, sweeps = model_oracle()
max_error = max(abs(learner.q[s][a] - oracle_q[s][a])
for s in NONTERMINAL_STATES for a in ACTIONS)
greedy_evaluation = evaluate_greedy(learner.q)
# A controlled nonzero continuation example, NOT an extra training episode.
check = QLearner(0)
check.q = [row[:] for row in oracle_q]
truncation_check = check.observe(0, 1, -0.1, 1, False)
next_q = oracle_q[1]
greedy_action = argmax_low_id(next_q)
behavior_probabilities = [EPSILON / 2 + (1 - EPSILON if a == greedy_action else 0)
for a in ACTIONS]
comparison = {"transition": {"state": 0, "action": 1, "reward": -0.1, "next_state": 1},
"next_state_q_values": next_q,
"epsilon_behavior_probabilities_L_R": behavior_probabilities,
"q_learning_target_using_max": -0.1 + GAMMA * max(next_q),
"sarsa_target_if_next_behavior_action_is_L": -0.1 + GAMMA * next_q[0],
"expected_behavior_target_for_comparison_only": -0.1 + GAMMA * math.fsum(
p * q for p, q in zip(behavior_probabilities, next_q))}
assert sum(endings.values()) == EPISODES
assert sum(map(sum, learner.visits)) == sum(episode_lengths)
assert all(n > 0 for row in learner.visits for n in row)
assert max_error < 1e-10
assert [x["action"] for x in greedy_evaluation["trajectory"]] == [1, 1, 1]
assert math.isclose(greedy_evaluation["undiscounted_return"], .8)
assert math.isclose(greedy_evaluation["discounted_return"], .62)
print(json.dumps({
"scope": "Original small deterministic tabular MDP; actual2000trainingepisodes, "
"not a maze reproduction, policy benchmark, or finite-run convergence theorem.",
"versions": {"python": platform.python_version(), "dependencies": "standard library only"},
"settings": {"nonterminal_states": NONTERMINAL_STATES, "goal": GOAL, "trap": TRAP,
"actions": {"L": 0, "R": 1}, "gamma": GAMMA, "alpha": ALPHA, "epsilon": EPSILON,
"seed": SEED, "episodes": EPISODES, "collector_max_steps": MAX_STEPS,
"start_state_every_episode": 0, "initial_q": "all six entries zero",
"tie_break": "lowest action ID", "epsilon_branch": "uniform over both actions",
"update": "Q(s,a) += alpha*(r + gamma*maxQ(next) - Q(s,a)); no continuation for true terminals",
"truncation": "time limit resets collector only; bootstrap from observed next state retained"},
"model_for_reader_and_oracle_only": [
{"state": s, "action": a, "next_state": environment_step(s, a)[0],
"reward": environment_step(s, a)[1], "terminated": environment_step(s, a)[2]}
for s in NONTERMINAL_STATES for a in ACTIONS],
"training": {"episode_endings": endings, "total_observed_transitions": sum(episode_lengths),
"state_action_visit_counts_L_R": learner.visits,
"mean_episode_length": math.fsum(episode_lengths) / EPISODES,
"mean_undiscounted_episode_return": math.fsum(episode_returns) / EPISODES,
"first_episode_transitions": first_episode_transitions,
"first_terminal_updates": terminal_samples,
"first_observed_truncation_updates": truncation_samples},
"learned_q_L_R": learner.q,
"model_oracle": {"q_L_R": oracle_q, "synchronous_sweeps": sweeps,
"optimal_v": [max(row) for row in oracle_q], "max_learned_abs_error": max_error,
"role": "Known transition model only used AFTER training for evaluation, never learner update/choice"},
"greedy_evaluation_no_learning_no_exploration": greedy_evaluation,
"controlled_truncation_example_not_training": {
"description": "At time limit after 0R->1, next state1 is not terminal; continue bootstrapping",
"correct_update": truncation_check,
"wrong_target_if_truncation_mistaken_for_terminal": -0.1},
"behavior_vs_target_arithmetic_not_sarsa_training": comparison,
"limits": ["Learner receives only observed state/action/reward/nextstate/terminated tuples, not the model.",
"Fixed2000episodes and alpha.2 do not satisfy the decreasing-step-size convergence theorem in general.",
"All six pairs were visited in this run; finite positive visits are not infinite exploration.",
"Goal/trap terminal value is zero; terminal Q rows are not stored or read.",
"Collector truncation is exogenous, not a finite-horizon MDP terminal or a learned reset transition.",
"If time remaining changed the actual task objective, it would need to be included in the state.",
"Greedy evaluation freezes Q and removes epsilon exploration; it differs from training behavior.",
"An epsilon random branch may choose the greedy action; action probabilities are .9/.1 with unique best.",
"Oracle uses known deterministic transitions; it is a separate model-based reference, not model-free training.",
"Single seed, hand-designed rewards, no heldout tuning, stochastic environment, function approximation or real-world lift."]}, indent=2))
if __name__ == "__main__":
main()
模型沒有教你的事,要回到狀態、資料和目標檢查
這個例子之所以能逐格手算,是因為狀態完全可觀察、轉移確定、獎勵固定、每個狀態只有兩個行動。真實問題可能有觀察不足、隨機轉移、延遲回饋,或探索本身造成不可接受的代價。把 Q 表換成神經網路,也不會自動保留這裡的收斂性質。
Q-learning 最值得先掌握的,是如何把「這一步的 reward」與「下一狀態目前認為最好的 continuation」接起來,再用 TD error 修正一格估計。接著逐項檢查:狀態是否足夠、下一狀態有沒有真的觀察到、terminal 是否定義正確、哪些行動曾被覆蓋,以及你想要的是哪一種 return。
當這些定義不清楚,即使程式能跑、Q 值穩定,仍可能是在穩定回答另一個問題。從一個六格的小世界開始,把更新式的每個量都對到實際 transition,才更容易辨認後續方法增加了什麼,又犧牲了哪些可檢查的前提。
來源與延伸閱讀:
-
Watkins、Dayan(1992),Q-learning 作者頁與作者保存原 PDF,DOI 10.1007/BF00992698。§2 的表格更新與收斂條件是本篇方法依據;有限原型不重現其形式證明,也未重刊論文圖。
-
Sutton、Barto,Reinforcement Learning: An Introduction,第二版作者頁,相關 §3.1、§3.3–3.5、§6.5:Markov 狀態、return、terminal 的零 continuation、價值與 off-policy TD control。書中 maze/cliff 圖和結果不是本站環境,未重刊。
-
OpenAI,Spinning Up 的 RL 入門、固定來源圖檔及固定 MIT 授權:圖 1;本文只借用互動迴圈,不把其程式示例說成本站實測。
-
Waldoalvarez,Markov Decision Process:圖 2 與完整圖封面;Fschwarzentruber,Qlearning gridworld Q:圖 3,圖說依法文固定版本。兩作品均為自有圖,採 CC BY-SA 4.0,本次白底轉檔/等比封面改作同授權。
-
法文 Wikipedia 貢獻者,Q-learning,固定版本 239118544及頁面作者歷史:圖 4 的普通 Q 更新式,CC BY-SA 4.0。方法正負號、terminal 與收斂條件仍按 Watkins–Dayan/Sutton–Barto 原始方法核對,不沿用頁面的概括效能說法。
-
LearnDataSci,Q-Learning Matrix Initialized and After Training 作品頁及 Satwik Kansal、Brendan Martin 的完整 Taxi 教學:圖 5 僅引用 CC BY-SA 4.0 自有圖的初始化面板。本文未重跑其 Taxi-v2、使用其訓練成效或移植其超參數建議。
圖像授權與改作聲明:
DS67 selected illustrations: source attribution and changes
1. Agent–environment loop
OpenAI, Spinning Up, “Introduction to Reinforcement Learning,” https://spinningup.openai.com/en/latest/spinningup/rl_intro.html ; source file https://github.com/openai/spinningup/blob/038665d62d569055401d91856abb287263096178/docs/images/rl_diagram_transparent_bg.png . Copyright (c) 2018 OpenAI. The source PNG was alpha-composited on white; no crop, label or data was added. The full MIT license is reproduced below.
2. MDP transition graph and cover
Waldoalvarez, “Markov Decision Process.svg,” https://commons.wikimedia.org/wiki/File:Markov_Decision_Process.svg , CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/ . The whole vector was rendered on white as a PNG; the cover is the same complete graph fitted proportionally on a white canvas. Changes: SVG-to-PNG render, white background, and cover scaling only. The source’s +5 and −1 labels mark transition rewards, not terminal states. This derivative is released under CC BY-SA 4.0.
3. Q-grid action-value illustration
Fschwarzentruber, “Qlearning gridworld Q.png,” https://commons.wikimedia.org/wiki/File:Qlearning_gridworld_Q.png , CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/ . The whole source PNG was alpha-composited on white without changes to values, arrows or labels. The linked French Wikipedia caption explains darker arrows as larger Q(s,a) values and filled green arrows as maxima; this illustration is not a reported training trace. This derivative is released under CC BY-SA 4.0.
4. Q-learning update formula
Wikimedia contributors, “Q-learning,” French Wikipedia, revision 239118544, https://fr.wikipedia.org/w/index.php?title=Q-learning&oldid=239118544 ; page history https://fr.wikipedia.org/w/index.php?title=Q-learning&action=history ; CC BY-SA 4.0 page terms, https://creativecommons.org/licenses/by-sa/4.0/ . The displayed formula is the page’s ordinary Q-learning update (math element mwdA), rendered from the page math markup by Wikimedia’s math renderer, then rendered as a PNG at 804×99. No formula text was transcribed or altered. This math image is a faithful rendering of the page’s licensed mathematical text; the adapted PNG is provided under CC BY-SA 4.0. This does not extend the page-text license to unrelated external images. The formula is generic and does not itself show terminal masking.
5. Initialized Q table panel
LearnDataSci, “Q-Learning Matrix Initialized and After Training.png,” https://commons.wikimedia.org/wiki/File:Q-Learning_Matrix_Initialized_and_After_Training.png , CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/ . Only the complete top “Initialized” panel was excerpted from the 1000×1016 source image using source-pixel box [0,0,1000,480]; no table value was changed or added. The training arrow and entire post-training panel are excluded. This derivative is released under CC BY-SA 4.0. The tutorial linked on the Commons file page is by Satwik Kansal and Brendan Martin: https://www.learndatasci.com/tutorials/reinforcement-q-learning-scratch-python-openai-gym/ .
The CC BY-SA derivatives listed above are provided under CC BY-SA 4.0 with their respective attribution and changes retained.
Full MIT license for item 1
The MIT License
Copyright (c) 2018 OpenAI (http://openai.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
留言0
登入後就能留言。
登入