本來轉(zhuǎn)自:DeepHub IMBA
本文系統(tǒng)講解從基本強(qiáng)化學(xué)習(xí)方法到高級(jí)技術(shù)(如PPO、A3C、PlaNet等)的實(shí)現(xiàn)原理與編碼過程,旨在通過理論結(jié)合代碼的方式,構(gòu)建對(duì)強(qiáng)化學(xué)習(xí)算法的全面理解。
為確保內(nèi)容易于理解和實(shí)踐,全部代碼均在Jupyter Notebook環(huán)境中實(shí)現(xiàn),僅依賴基礎(chǔ)庫進(jìn)行算法構(gòu)建。
代碼庫組織結(jié)構(gòu)如下:
├── 1_simple_rl.ipynb ├── 2_q_learning.ipynb ├── 3_sarsa.ipynb ... ├── 9_a3c.ipynb ├── 10_ddpg.ipynb ├── 11_sac.ipynb ├── 12_trpo.ipynb ... ├── 17_mcts.ipynb └── 18_planet.ipynb
說明:github地址見文章最后,文章很長所以可以根據(jù)需求查看感興趣的強(qiáng)化學(xué)習(xí)方法介紹和對(duì)應(yīng)notebook。
搭建環(huán)境
首先,需要克隆倉庫并安裝相關(guān)依賴項(xiàng):
# 克隆并導(dǎo)航到目錄
gitclone https://github.com/fareedkhan-dev/all-rl-algorithms.git
cdall-rl-algorithms
# 安裝所需的依賴項(xiàng)
pip install-rrequirements.txt
接下來,導(dǎo)入核心庫:
# --- 核心Python庫 ---
importrandom
importmath
fromcollectionsimportdefaultdict,deque,namedtuple
fromtypingimportList,Tuple,Dict,Optional,Any,DefaultDict# 用于代碼中的類型提示
# --- 數(shù)值計(jì)算 ---
importnumpyasnp
# --- 機(jī)器學(xué)習(xí)框架(PyTorch - 從REINFORCE開始廣泛使用) ---
importtorch
importtorch.nnasnn
importtorch.optimasoptim
importtorch.nn.functionalasF
fromtorch.distributionsimportCategorical,Normal# 用于策略梯度、SAC、PlaNet等
# --- 環(huán)境 ---
# 用于加載標(biāo)準(zhǔn)環(huán)境,如Pendulum
importgymnasiumasgym
# 注意:SimpleGridWorld類定義需要直接包含在代碼中
# 因?yàn)樗遣┛臀恼轮卸x的自定義環(huán)境。
# --- 可視化(由博客中顯示的圖表暗示) ---
importmatplotlib.pyplotasplt
importseabornassns# 經(jīng)常用于熱力圖
# --- 可能用于異步方法(A3C) ---
# 盡管在代碼片段中沒有明確展示,但A3C實(shí)現(xiàn)通常使用這些
# import torch.multiprocessing as mp # 或標(biāo)準(zhǔn)的'multiprocessing'/'threading'
# --- PyTorch設(shè)置(可選但是好習(xí)慣) ---
device=torch.device("cuda"iftorch.cuda.is_available()else"cpu")
print(f"Using device:{device}")
# --- 禁用警告(可選) ---
importwarnings
warnings.filterwarnings('ignore')# 抑制潛在的廢棄警告等
強(qiáng)化學(xué)習(xí)環(huán)境設(shè)置
雖然OpenAI Gym庫提供了常見的強(qiáng)化學(xué)習(xí)環(huán)境,但為了深入理解算法核心原理,我們將自行實(shí)現(xiàn)大部分環(huán)境。僅在少數(shù)需要特殊環(huán)境配置的算法中,才會(huì)使用Gym模塊。
本文主要關(guān)注兩個(gè)環(huán)境:
自定義網(wǎng)格世界(從頭實(shí)現(xiàn))
鐘擺問題(使用OpenAI Gymnasium)
# -------------------------------------
# 1. 簡單自定義網(wǎng)格世界
# -------------------------------------
classSimpleGridWorld:
""" 一個(gè)基本的網(wǎng)格世界環(huán)境。 """
def__init__(self,size=5):
self.size=size
self.start_state=(0,0)
self.goal_state=(size-1,size-1)
self.state=self.start_state
# 動(dòng)作: 0:上, 1:下, 2:左, 3:右
self.action_map={0: (-1,0),1: (1,0),2: (0,-1),3: (0,1)}
self.action_space_size=4
defreset(self)->Tuple[int,int]:
""" 重置到初始狀態(tài)。 """
self.state=self.start_state
returnself.state
defstep(self,action:int)->Tuple[Tuple[int,int],float,bool]:
""" 執(zhí)行一個(gè)動(dòng)作,返回next_state, reward, done。 """
ifself.state==self.goal_state:
returnself.state,0.0,True# 在目標(biāo)處停留
# 計(jì)算潛在的下一個(gè)狀態(tài)
dr,dc=self.action_map[action]
r,c=self.state
next_r,next_c=r+dr,c+dc
# 應(yīng)用邊界(如果碰到墻壁則原地不動(dòng))
ifnot(0<=next_r<self.sizeand0<=next_c<self.size):
next_r,next_c=r,c# 保持在當(dāng)前狀態(tài)
reward=-1.0 # 墻壁懲罰
else:
reward=-0.1 # 步驟成本
# 更新狀態(tài)
self.state=(next_r,next_c)
# 檢查是否達(dá)到目標(biāo)
done=(self.state==self.goal_state)
ifdone:
reward=10.0 # 目標(biāo)獎(jiǎng)勵(lì)
returnself.state,reward,done
SimpleGridWorld環(huán)境是一個(gè)基礎(chǔ)的二維網(wǎng)格強(qiáng)化學(xué)習(xí)環(huán)境,智能體需要從起始位置(0,0)導(dǎo)航至目標(biāo)位置(size-1, size-1)。智能體可以執(zhí)行四個(gè)基本方向的移動(dòng)動(dòng)作(上、下、左、右),在每一步會(huì)接收一個(gè)小的步驟懲罰(-0.1),碰撞墻壁則會(huì)獲得更大的懲罰(-1.0),而到達(dá)目標(biāo)則給予較大的獎(jiǎng)勵(lì)(10.0)。
# -------------------------------------
# 2. 加載Gymnasium鐘擺
# -------------------------------------
pendulum_env=gym.make('Pendulum-v1')
print("Pendulum-v1 environment loaded.")
# 重置環(huán)境
observation,info=pendulum_env.reset(seed=42)
print(f"Initial Observation:{observation}")
print(f"Observation Space:{pendulum_env.observation_space}")
print(f"Action Space:{pendulum_env.action_space}")
# 執(zhí)行隨機(jī)步驟
random_action=pendulum_env.action_space.sample()
observation,reward,terminated,truncated,info=pendulum_env.step(random_action)
done=terminatedortruncated
print(f"Step with action{random_action}:")
print(f" Next Obs:{observation}\n Reward:{reward}\n Done:{done}")
# 關(guān)閉環(huán)境(如果使用了渲染則很重要)
pendulum_env.close()
對(duì)于鐘擺問題,我們使用Gymnasium庫中的Pendulum-v1環(huán)境,這是一個(gè)基于物理的連續(xù)控制任務(wù)。上述代碼初始化環(huán)境并展示了基本交互過程,包括獲取初始觀察、顯示觀察空間和動(dòng)作空間的結(jié)構(gòu),以及執(zhí)行一個(gè)隨機(jī)動(dòng)作并處理反饋。
讓我們可視化這兩個(gè)環(huán)境:
網(wǎng)格世界和鐘擺
從上圖可以看出,在網(wǎng)格世界環(huán)境中,智能體的目標(biāo)是找到從起點(diǎn)到目標(biāo)的最短路徑;而在鐘擺環(huán)境中,目標(biāo)是將擺桿從任意初始位置控制到豎直向上的平衡點(diǎn)。
1、最簡單的強(qiáng)化學(xué)習(xí)算法
首先從強(qiáng)化學(xué)習(xí)的基礎(chǔ)概念出發(fā),即智能體與環(huán)境交互的循環(huán)過程。即使是最基本的方法也遵循這一交互模式。
以下圖示展示了強(qiáng)化學(xué)習(xí)智能體的基本工作原理:
在這個(gè)交互流程中,智能體首先觀察環(huán)境的當(dāng)前狀態(tài)s。基于該狀態(tài),智能體依據(jù)其當(dāng)前策略決定執(zhí)行一個(gè)動(dòng)作a。該動(dòng)作會(huì)影響環(huán)境,使環(huán)境轉(zhuǎn)移到一個(gè)新狀態(tài)s',并向智能體提供一個(gè)數(shù)值獎(jiǎng)勵(lì)r,指示動(dòng)作的即時(shí)效果。智能體利用這一反饋信息(s, a, r, s')學(xué)習(xí)或調(diào)整其策略,然后從新狀態(tài)s'繼續(xù)交互循環(huán)。
我們將實(shí)現(xiàn)的第一個(gè)智能體與后續(xù)算法不同,它不會(huì)進(jìn)行真正的"學(xué)習(xí)",而是通過記錄在特定狀態(tài)下執(zhí)行特定動(dòng)作所獲得的即時(shí)獎(jiǎng)勵(lì)來做決策。其目標(biāo)很簡單:在給定狀態(tài)時(shí),選擇過去在該狀態(tài)中平均即時(shí)獎(jiǎng)勵(lì)最高的動(dòng)作。該方法沒有考慮長期后果的概念。
首先,我們需要一個(gè)數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)智能體的記憶,采用一個(gè)將(狀態(tài),動(dòng)作)對(duì)映射到接收獎(jiǎng)勵(lì)列表的嵌套字典:
# 記憶結(jié)構(gòu):memory[(state_tuple)][action_index] -> [list_of_rewards]
agent_memory:DefaultDict[Tuple[int,int],DefaultDict[int,List[float]]]=\
defaultdict(lambda:defaultdict(list))
# 示例:存儲(chǔ)在狀態(tài)(0,0)中采取動(dòng)作1的獎(jiǎng)勵(lì)
# agent_memory[(0,0)][1].append(-0.1)
這個(gè)簡單的字典結(jié)構(gòu)能夠存儲(chǔ)每個(gè)狀態(tài)-動(dòng)作對(duì)的所有即時(shí)獎(jiǎng)勵(lì)記錄。
接下來,智能體需要一個(gè)策略來選擇其下一個(gè)動(dòng)作。我們將基于記憶中存儲(chǔ)的平均即時(shí)獎(jiǎng)勵(lì),實(shí)現(xiàn)一個(gè)ε-貪心方法:
defchoose_simple_action(state:Tuple[int,int],
memory:DefaultDict[Tuple[int,int],DefaultDict[int,List[float]]],
epsilon:float,
n_actions:int)->int:
""" 基于平均即時(shí)獎(jiǎng)勵(lì)使用epsilon-greedy選擇動(dòng)作。 """
ifrandom.random()<epsilon:
returnrandom.randrange(n_actions)# 探索
else:
# 利用:找到具有最佳平均即時(shí)獎(jiǎng)勵(lì)的動(dòng)作
state_action_memory=memory[state]
best_avg_reward=-float('inf')
best_actions=[]
foraction_idxinrange(n_actions):
rewards=state_action_memory[action_idx]
# 如果從這個(gè)狀態(tài)從未嘗試過這個(gè)動(dòng)作,將其平均獎(jiǎng)勵(lì)視為0或非常低
avg_reward=np.mean(rewards)ifrewardselse0.0
ifavg_reward>best_avg_reward:
best_avg_reward=avg_reward
best_actions=[action_idx]
elifavg_reward==best_avg_reward:
best_actions.append(action_idx)
# 如果沒有動(dòng)作有積極獎(jiǎng)勵(lì)或狀態(tài)未訪問,隨機(jī)選擇
ifnotbest_actions:
returnrandom.randrange(n_actions)
# 隨機(jī)打破平局
returnrandom.choice(best_actions)
該函數(shù)使智能體可以在隨機(jī)探索(以概率ε)和利用已知信息之間進(jìn)行平衡。當(dāng)選擇利用時(shí),智能體會(huì)選擇在歷史記錄中平均即時(shí)獎(jiǎng)勵(lì)最高的動(dòng)作。
最后,"學(xué)習(xí)"步驟僅僅是在執(zhí)行動(dòng)作后更新記憶:
defupdate_simple_memory(memory:DefaultDict[Tuple[int,int],DefaultDict[int,List[float]]],
state:Tuple[int,int],
action:int,
reward:float)->None:
""" 為狀態(tài)-動(dòng)作對(duì)添加接收到的獎(jiǎng)勵(lì)到記憶中。 """
memory[state][action].append(reward)
這個(gè)簡單的智能體僅記錄即時(shí)結(jié)果,沒有考慮長期回報(bào)或累積獎(jiǎng)勵(lì),這是我們將通過后續(xù)算法解決的主要局限性。
下面通過可視化來分析該智能體的學(xué)習(xí)過程及表現(xiàn):
從上圖可以觀察到幾個(gè)關(guān)鍵點(diǎn):
獎(jiǎng)勵(lì)趨勢:頂部圖表顯示了每個(gè)回合的總獎(jiǎng)勵(lì)。在早期階段,智能體表現(xiàn)不佳(獲得負(fù)獎(jiǎng)勵(lì)),但隨著時(shí)間推移,其性能逐漸改善,這從移動(dòng)平均線(橙色)的上升趨勢可以明確看出。
狀態(tài)訪問頻率:左下角熱力圖顯示了智能體訪問各個(gè)狀態(tài)的頻率??拷瘘c(diǎn)的區(qū)域顏色較亮,表明探索集中在這些區(qū)域,而目標(biāo)狀態(tài)(G)的訪問頻率相對(duì)較低。
最佳動(dòng)作獎(jiǎng)勵(lì)估計(jì):中間熱力圖表示智能體對(duì)每個(gè)狀態(tài)中最佳動(dòng)作的即時(shí)獎(jiǎng)勵(lì)估計(jì)。大部分值較低,除了給予高獎(jiǎng)勵(lì)的目標(biāo)狀態(tài)附近區(qū)域。
動(dòng)作選擇分布:右下角條形圖顯示了智能體從起始狀態(tài)(0,0)最常選擇的動(dòng)作。數(shù)據(jù)表明智能體傾向于向右和向下移動(dòng),這與通向目標(biāo)的最優(yōu)路徑方向一致。
通過增加訓(xùn)練回合數(shù),可以進(jìn)一步提高智能體的尋路能力和性能。接下來,我們將介紹更為先進(jìn)的Q學(xué)習(xí)算法。
2、Q學(xué)習(xí)
簡單的記憶型智能體受限于只考慮即時(shí)獎(jiǎng)勵(lì)。Q學(xué)習(xí)則向前邁進(jìn)了重要一步,它學(xué)習(xí)的是在一個(gè)狀態(tài)中執(zhí)行特定動(dòng)作的"質(zhì)量"或Q值,不僅考慮即時(shí)獎(jiǎng)勵(lì),還考慮期望獲得的總折扣未來獎(jiǎng)勵(lì)。
Q學(xué)習(xí)的目標(biāo)是學(xué)習(xí)最優(yōu)動(dòng)作值函數(shù) Q*(s,a)。
當(dāng)智能體在狀態(tài)s中執(zhí)行動(dòng)作a后,收到獎(jiǎng)勵(lì)r并轉(zhuǎn)換到狀態(tài)s'。為了更新原始(s,a)對(duì)的值,Q學(xué)習(xí)考慮了下一狀態(tài)s'中所有可能動(dòng)作a'的最佳Q值,表示為max Q(s', a')。
這個(gè)最大未來值經(jīng)過因子γ(gamma)折扣后,與即時(shí)獎(jiǎng)勵(lì)r相加構(gòu)成目標(biāo)值。然后,原始(s,a)對(duì)的Q值通過學(xué)習(xí)率α(alpha)向這個(gè)目標(biāo)值小幅調(diào)整。
學(xué)習(xí)通過以下更新規(guī)則進(jìn)行:
這意味著:
我們計(jì)算一個(gè)新的值估計(jì):當(dāng)前獎(jiǎng)勵(lì) + 折扣因子 * 最佳未來值
計(jì)算這個(gè)新估計(jì)與當(dāng)前Q值之間的差異(稱為時(shí)序差分誤差)
按照學(xué)習(xí)率確定的比例更新當(dāng)前Q值
首先,我們初始化Q表,使用defaultdict可以簡化實(shí)現(xiàn),將未知的Q值默認(rèn)初始化為0:
# Q表:q_table[(state_tuple)][action_index] -> q_value
q_table:DefaultDict[Tuple[int,int],Dict[int,float]]=\
defaultdict(lambda:defaultdict(float))
# 示例:訪問Q((0,0), 0=Up)將初始返回0.0
# print(q_table[(0,0)][0])
這個(gè)結(jié)構(gòu)存儲(chǔ)了每個(gè)狀態(tài)內(nèi)每個(gè)動(dòng)作的估計(jì)Q值。
動(dòng)作選擇仍然使用epsilon-greedy,但現(xiàn)在它基于學(xué)習(xí)到的Q值來利用,而不僅僅是即時(shí)獎(jiǎng)勵(lì)。
# 基于Q值的Epsilon-Greedy動(dòng)作選擇
defchoose_q_learning_action(state:Tuple[int,int],
q_table:DefaultDict[Tuple[int,int],Dict[int,float]],
epsilon:float,
n_actions:int)->int:
""" 基于Q表值使用epsilon-greedy選擇動(dòng)作。 """
ifrandom.random()<epsilon:
returnrandom.randrange(n_actions)# 探索
else:
# 利用:選擇該狀態(tài)下Q值最高的動(dòng)作
q_values_for_state=q_table[state]
ifnotq_values_for_state:# 如果狀態(tài)未被訪問/更新
returnrandom.randrange(n_actions)
max_q=-float('inf')
best_actions=[]
# 遍歷可用動(dòng)作(0到n_actions-1)
foraction_idxinrange(n_actions):
q_val=q_values_for_state[action_idx]# defaultdict如果鍵缺失則返回0
ifq_val>max_q:
max_q=q_val
best_actions=[action_idx]
elifq_val==max_q:
best_actions.append(action_idx)
returnrandom.choice(best_actions)# 隨機(jī)打破平局
智能體會(huì)以概率epsilon進(jìn)行隨機(jī)探索,否則選擇當(dāng)前狀態(tài)下估計(jì)長期回報(bào)最高的動(dòng)作。
Q學(xué)習(xí)的核心更新函數(shù)實(shí)現(xiàn)了貝爾曼方程更新:
# Q學(xué)習(xí)更新規(guī)則
defupdate_q_value(q_table:DefaultDict[Tuple[int,int],Dict[int,float]],
state:Tuple[int,int],
action:int,
reward:float,
next_state:Tuple[int,int],
alpha:float, # 學(xué)習(xí)率
gamma:float, # 折扣因子
n_actions:int,
is_done:bool)->None:
""" 執(zhí)行單個(gè)Q學(xué)習(xí)更新步驟。 """
# 獲取當(dāng)前Q值估計(jì)
current_q=q_table[state][action]
# 找到下一個(gè)狀態(tài)的最大Q值(Q學(xué)習(xí)特有)
# 這代表了從下一個(gè)狀態(tài)可達(dá)到的最佳可能值。
max_next_q=-float('inf')
ifnotis_doneandq_table[next_state]:# 檢查next_state是否有條目
max_next_q=max(q_table[next_state].values())
elifis_done:
max_next_q=0.0# 如果回合結(jié)束,則無未來獎(jiǎng)勵(lì)
else:
max_next_q=0.0# 如果next_state還沒有條目
# 計(jì)算TD目標(biāo):R + gamma * max(Q(s', a'))
td_target=reward+gamma*max_next_q
# 計(jì)算TD誤差:TD目標(biāo) - Q(s, a)
td_error=td_target-current_q
# 更新Q值:Q(s, a) <- Q(s, a) + alpha * TD_Error ?
q_table[state][action]=current_q+alpha*td_error
該函數(shù)根據(jù)即時(shí)獎(jiǎng)勵(lì)和下一狀態(tài)的最大Q值(這是Q學(xué)習(xí)的脫策略特性)計(jì)算目標(biāo)值,然后更新實(shí)際執(zhí)行的狀態(tài)-動(dòng)作對(duì)的Q值。
從上圖可以看出Q學(xué)習(xí)的效果:
獎(jiǎng)勵(lì)和回合長度:頂部圖表顯示了隨時(shí)間變化的累積獎(jiǎng)勵(lì)和回合長度。初始階段,回合較長,表明智能體在探索低效路徑。隨著學(xué)習(xí)進(jìn)行,回合長度明顯減少,表明學(xué)習(xí)進(jìn)程有效。
動(dòng)作Q值分布:四個(gè)熱力圖展示了向上、下、左、右四個(gè)動(dòng)作方向的Q值。黃色區(qū)域(高值)表示靠近目標(biāo)狀態(tài)的優(yōu)先動(dòng)作,而深色區(qū)域(低值)表示較不優(yōu)化的選擇。
學(xué)習(xí)策略可視化:最右側(cè)的圖表直觀展示了最終學(xué)習(xí)到的策略,箭頭指示各狀態(tài)的最優(yōu)動(dòng)作方向,清晰地顯示了通向目標(biāo)的路徑。
總體而言,通過Q學(xué)習(xí),智能體成功學(xué)習(xí)了一條通向目標(biāo)的最優(yōu)路徑。
3、Sarsa
SARSA(State-Action-Reward-State-Action,狀態(tài)-動(dòng)作-獎(jiǎng)勵(lì)-狀態(tài)-動(dòng)作)是另一種基于值的算法,與Q學(xué)習(xí)相似,但有一個(gè)關(guān)鍵區(qū)別:它是在策略的算法。
這意味著SARSA學(xué)習(xí)的是它當(dāng)前正在遵循的策略的價(jià)值,包括任何探索性動(dòng)作;而Q學(xué)習(xí)是脫策略的,它學(xué)習(xí)的是最優(yōu)策略,不論當(dāng)前采用何種探索策略。
智能體從狀態(tài)s開始,使用其策略選擇動(dòng)作a,獲得獎(jiǎng)勵(lì)r并轉(zhuǎn)換到狀態(tài)s'。關(guān)鍵在于,在更新原始(s,a)對(duì)的值之前,智能體確定它將使用相同策略在狀態(tài)s'中采取的下一個(gè)動(dòng)作a'。
這個(gè)特定下一狀態(tài)-動(dòng)作對(duì)的Q值Q(s', a')經(jīng)過因子γ折扣后與即時(shí)獎(jiǎng)勵(lì)r相加,構(gòu)成SARSA目標(biāo)。然后,原始的Q(s, a)按照學(xué)習(xí)率α的影響向這個(gè)目標(biāo)值更新。這個(gè)過程遵循完整的五元組(s, a, r, s', a'),這也是算法名稱的由來。
SARSA使用與Q學(xué)習(xí)相同的Q表結(jié)構(gòu)存儲(chǔ)狀態(tài)-動(dòng)作值,將狀態(tài)-動(dòng)作對(duì)映射到估計(jì)值。
動(dòng)作選擇通常也采用epsilon-greedy策略,與Q學(xué)習(xí)相同,以平衡探索和利用:
# Epsilon-Greedy動(dòng)作選擇(與Q學(xué)習(xí)相同的函數(shù))
defchoose_sarsa_action(state:Tuple[int,int],
q_table:DefaultDict[Tuple[int,int],Dict[int,float]],
epsilon:float,
n_actions:int)->int:
""" 基于Q表值使用epsilon-greedy選擇動(dòng)作。 """
ifrandom.random()<epsilon:
returnrandom.randrange(n_actions)# 探索
else:
# 利用:選擇Q值最高的動(dòng)作
q_values_for_state=q_table[state]
ifnotq_values_for_state:
returnrandom.randrange(n_actions)
max_q=-float('inf')
best_actions=[]
foraction_idxinrange(n_actions):
q_val=q_values_for_state[action_idx]# 默認(rèn)為0.0
ifq_val>max_q:
max_q=q_val
best_actions=[action_idx]
elifq_val==max_q:
best_actions.append(action_idx)
returnrandom.choice(best_actions)ifbest_actionselserandom.randrange(n_actions)
SARSA與Q學(xué)習(xí)的關(guān)鍵區(qū)別在于更新規(guī)則,它使用實(shí)際選擇的下一個(gè)動(dòng)作(a')的Q值,而非下一狀態(tài)中可能的最大Q值:
# SARSA更新規(guī)則
defupdate_sarsa_value(q_table:DefaultDict[Tuple[int,int],Dict[int,float]],
state:Tuple[int,int],
action:int,
reward:float,
next_state:Tuple[int,int],
next_action:int, # 為下一步實(shí)際選擇的動(dòng)作
alpha:float,
gamma:float,
is_done:bool)->None:
""" 執(zhí)行單個(gè)SARSA更新步驟。 """
# 獲取當(dāng)前Q值估計(jì)
current_q=q_table[state][action]
# 獲取*下一個(gè)狀態(tài)和策略選擇的下一個(gè)動(dòng)作*的Q值
# 這是與Q學(xué)習(xí)的核心區(qū)別
q_next_state_action=0.0
ifnotis_done:
q_next_state_action=q_table[next_state][next_action]# 使用Q(s', a')
# 計(jì)算TD目標(biāo):R + gamma * Q(s', a')
td_target=reward+gamma*q_next_state_action
# 計(jì)算TD誤差:TD目標(biāo) - Q(s, a)
td_error=td_target-current_q
# 更新Q值:Q(s, a) <- Q(s, a) + alpha * TD_Error ?
q_table[state][action]=current_q+alpha*td_error
由于SARSA在更新中使用Q(s',a')(下一個(gè)實(shí)際選擇的動(dòng)作的值,可能是探索性動(dòng)作),相比Q學(xué)習(xí),它傾向于學(xué)習(xí)更為保守的策略,特別是在存在潛在風(fēng)險(xiǎn)的環(huán)境中(如懸崖問題)。SARSA評(píng)估的是智能體當(dāng)前積極遵循的策略。
從SARSA的學(xué)習(xí)過程和結(jié)果可以觀察到:
學(xué)習(xí)進(jìn)展:回合長度顯著減少,表明智能體學(xué)會(huì)了更高效地到達(dá)目標(biāo)。
獎(jiǎng)勵(lì)表現(xiàn):獎(jiǎng)勵(lì)總體較高但存在波動(dòng),反映了一個(gè)有效但不完全穩(wěn)定的策略,這可能是由于持續(xù)的探索所致。
學(xué)習(xí)策略:Q值分布和最終策略圖表顯示智能體成功學(xué)習(xí)了指向目標(biāo)狀態(tài)('T')的動(dòng)作序列。
綜上所述,SARSA成功地學(xué)習(xí)了如何在環(huán)境中有效導(dǎo)航,提高了運(yùn)行效率并頻繁獲得高獎(jiǎng)勵(lì)。最終的策略能夠有效地引導(dǎo)智能體朝向目標(biāo),盡管性能上仍存在一定的變異性。
4、期望Sarsa
期望SARSA是在SARSA算法基礎(chǔ)上的直接擴(kuò)展,保持其在策略(on-policy)學(xué)習(xí)的核心特性,即基于當(dāng)前策略所采取的動(dòng)作進(jìn)行價(jià)值函數(shù)的更新。
與標(biāo)準(zhǔn)SARSA依賴單一下一個(gè)動(dòng)作(a')進(jìn)行更新不同,期望SARSA通過考慮后繼狀態(tài)中所有可能動(dòng)作并按照當(dāng)前策略π(a'∣s')的概率分布對(duì)其Q值進(jìn)行加權(quán)平均,從而計(jì)算下一個(gè)狀態(tài)的期望值。
這種期望計(jì)算機(jī)制有效降低了更新過程中的方差,相較于標(biāo)準(zhǔn)SARSA僅依賴可能包含探索噪聲的單一動(dòng)作樣本。降低方差通常帶來更平穩(wěn)的價(jià)值估計(jì)收斂過程,并可能加速學(xué)習(xí)效率。
期望SARSA的基本過程與SARSA相似:智能體在狀態(tài)'s'中執(zhí)行動(dòng)作'a',獲取獎(jiǎng)勵(lì)'r',并轉(zhuǎn)移至后繼狀態(tài)'s''。
然而在計(jì)算目標(biāo)值時(shí),期望SARSA考慮從's''可能執(zhí)行的所有動(dòng)作('a'?, 'a'?, ...)。算法從當(dāng)前策略中提取選擇每個(gè)動(dòng)作的概率(π(a'∣s'))以及相應(yīng)的Q值Q(s',a')。
隨后,算法通過將每個(gè)動(dòng)作的選擇概率與其對(duì)應(yīng)Q值的乘積求和,計(jì)算狀態(tài)'s''的期望Q值:
該期望值經(jīng)折扣因子(γ)調(diào)整后與獎(jiǎng)勵(lì)'r'相加構(gòu)成目標(biāo)值。最后,根據(jù)學(xué)習(xí)率(α)將當(dāng)前Q(s,a)向這個(gè)期望目標(biāo)值方向更新。
Q表初始化函數(shù)和動(dòng)作選擇機(jī)制沿用了與SARSA部分相同的基于epsilon-greedy策略的實(shí)現(xiàn)。
期望SARSA的主要區(qū)別在于其更新規(guī)則,現(xiàn)在基于epsilon-greedy策略概率分布計(jì)算后繼動(dòng)作的期望值。
# 期望SARSA更新規(guī)則
defupdate_expected_sarsa_value(
q_table:DefaultDict[Tuple[int,int],Dict[str,float]],
state:Tuple[int,int],
action:int,# 現(xiàn)在使用整數(shù)動(dòng)作索引
reward:float,
next_state:Tuple[int,int],
alpha:float,
gamma:float,
epsilon:float,# 計(jì)算期望值需要當(dāng)前epsilon
n_actions:int,
is_done:bool
)->None:
""" 執(zhí)行單個(gè)期望SARSA更新步驟。 """
# 獲取當(dāng)前Q值估計(jì)
current_q=q_table[state][action]
# 計(jì)算下一個(gè)狀態(tài)的期望Q值
expected_q_next=0.0
ifnotis_doneandq_table[next_state]:# 檢查next_state是否存在且有條目
q_values_next_state=q_table[next_state]
ifq_values_next_state:# 檢查字典是否非空
max_q_next=max(q_values_next_state.values())
# 找到所有最佳動(dòng)作(處理平局)
best_actions=[afora,qinq_values_next_state.items()ifq==max_q_next]
# 在epsilon-greedy下計(jì)算概率
prob_greedy=(1.0-epsilon)/len(best_actions)# 將貪婪概率分配給最佳動(dòng)作
prob_explore=epsilon/n_actions
# 計(jì)算期望值 E[Q(s', A')] = sum[ pi(a'|s') * Q(s', a') ]
fora_primeinrange(n_actions):
prob_a_prime=0.0
ifa_primeinbest_actions:
prob_a_prime+=prob_greedy# 添加貪婪概率
prob_a_prime+=prob_explore# 添加探索概率(適用于所有動(dòng)作)
expected_q_next+=prob_a_prime*q_values_next_state.get(a_prime,0.0)# 如果動(dòng)作未見則默認(rèn)為0
# TD目標(biāo): R + gamma * E[Q(s', A')]
td_target=reward+gamma*expected_q_next
# TD誤差: TD目標(biāo) - Q(s, a)
td_error=td_target-current_q
# 更新Q值
q_table[state][action]=current_q+alpha*td_error
此更新函數(shù)考慮了epsilon-greedy策略的概率分布特性,在計(jì)算未來狀態(tài)價(jià)值時(shí),使更新過程對(duì)下一步可能選擇的單一(可能隨機(jī))動(dòng)作的敏感度降低,從而相比標(biāo)準(zhǔn)SARSA提供更穩(wěn)定的學(xué)習(xí)過程。
期望Sarsa
學(xué)習(xí)進(jìn)展分析:回合長度迅速降低,表明智能體快速掌握了到達(dá)目標(biāo)的高效路徑。
獎(jiǎng)勵(lì)性能評(píng)估:初始學(xué)習(xí)階段后,智能體能夠頻繁且穩(wěn)定地獲得接近10的高獎(jiǎng)勵(lì)值,證明其策略有效性。
學(xué)習(xí)策略分析:Q值矩陣清晰地識(shí)別出了首選動(dòng)作,最終策略網(wǎng)格展示了智能體形成的合理路徑,能夠可靠地引導(dǎo)至終端狀態(tài)('T')。
期望SARSA展現(xiàn)了強(qiáng)大且高效的學(xué)習(xí)能力,能夠快速收斂至穩(wěn)定策略。智能體獲得持續(xù)高獎(jiǎng)勵(lì)的能力表明其學(xué)習(xí)到的策略具有穩(wěn)定性和有效性。
5、Dyna Q
之前介紹的算法均為無模型方法,即僅從與環(huán)境的直接交互中學(xué)習(xí)。
Dyna-Q引入了一種簡潔的基于模型強(qiáng)化學(xué)習(xí)框架,通過同時(shí)學(xué)習(xí)環(huán)境模型并利用該模型進(jìn)行額外的"規(guī)劃"步驟(模擬經(jīng)驗(yàn)),有效加速學(xué)習(xí)過程。
核心理念在于更高效地利用每次真實(shí)交互經(jīng)驗(yàn):將其用于直接Q學(xué)習(xí)更新、內(nèi)部模型更新,以及利用模型生成多次模擬未來場景并執(zhí)行額外Q學(xué)習(xí)更新。
這種方法通常能顯著提高樣本效率,即從更少的真實(shí)環(huán)境交互中獲取更快的學(xué)習(xí)速度。
當(dāng)智能體在狀態(tài)s執(zhí)行動(dòng)作a并觀測到獎(jiǎng)勵(lì)r與后繼狀態(tài)s'后,Dyna-Q算法并行執(zhí)行三項(xiàng)任務(wù):
直接強(qiáng)化學(xué)習(xí)(RL):利用真實(shí)經(jīng)驗(yàn)(s, a, r, s')更新Q值Q(s, a),與標(biāo)準(zhǔn)Q學(xué)習(xí)算法相同。
模型學(xué)習(xí):更新內(nèi)部環(huán)境模型,記錄狀態(tài)s執(zhí)行動(dòng)作a導(dǎo)致獎(jiǎng)勵(lì)r和后繼狀態(tài)s'的轉(zhuǎn)移關(guān)系。
規(guī)劃:執(zhí)行k次額外更新,每次隨機(jī)選擇先前經(jīng)歷過的狀態(tài)-動(dòng)作對(duì)(s_p, a_p),查詢學(xué)習(xí)到的模型獲取預(yù)測獎(jiǎng)勵(lì)r_p和預(yù)測后繼狀態(tài)s_p',然后使用這些模擬經(jīng)驗(yàn)(s_p, a_p, r_p, s_p')執(zhí)行Q學(xué)習(xí)更新。
Q表:維護(hù)Q(s,a)估計(jì)值。在最基本的表格形式中,這是一個(gè)字典結(jié)構(gòu),存儲(chǔ)先前訪問過的狀態(tài)-動(dòng)作對(duì)的觀察結(jié)果(獎(jiǎng)勵(lì)和后繼狀態(tài)):Model(s,a)→(r,s′)。
實(shí)現(xiàn)Dyna-Q需要定義Q表和模型的數(shù)據(jù)結(jié)構(gòu),以及一種追蹤已訪問狀態(tài)-動(dòng)作對(duì)用于規(guī)劃的機(jī)制:
# Q表:q_table[(state_tuple)][action_index] -> q_value(與之前相同)
q_table_dynaq:DefaultDict[Tuple[int,int],Dict[int,float]]=\
defaultdict(lambda:defaultdict(float))
# 模型:model[(state_tuple, action_index)] -> (reward, next_state_tuple)
model_dynaq:Dict[Tuple[Tuple[int,int],int],Tuple[float,Tuple[int,int]]]={}
# 跟蹤已觀察到的狀態(tài)-動(dòng)作對(duì),用于規(guī)劃期間的采樣
observed_state_actions:List[Tuple[Tuple[int,int],int]]=[]
動(dòng)作選擇仍然基于當(dāng)前Q表使用epsilon-greedy策略。直接RL更新采用標(biāo)準(zhǔn)Q學(xué)習(xí)更新規(guī)則(在Q學(xué)習(xí)部分中詳細(xì)介紹)。
算法的創(chuàng)新部分在于模型更新和規(guī)劃步驟的實(shí)現(xiàn)。
首先,我們需要一個(gè)基于真實(shí)經(jīng)驗(yàn)更新環(huán)境模型的函數(shù):
# 模型更新函數(shù)
defupdate_model(model:Dict[Tuple[Tuple[int,int],int],Tuple[float,Tuple[int,int]]],
observed_pairs:List[Tuple[Tuple[int,int],int]],
state:Tuple[int,int],
action:int,
reward:float,
next_state:Tuple[int,int])->None:
""" 更新確定性表格模型和已觀察對(duì)列表。 """
state_action=(state,action)
model[state_action]=(reward,next_state)# 存儲(chǔ)結(jié)果
# 如果這個(gè)對(duì)之前未見過,則添加到列表中
ifstate_actionnotinobserved_pairs:
observed_pairs.append(state_action)
此函數(shù)簡單記錄狀態(tài)-動(dòng)作對(duì)及其結(jié)果轉(zhuǎn)移信息。
規(guī)劃步驟函數(shù)實(shí)現(xiàn)了從模型采樣并應(yīng)用Q學(xué)習(xí)更新的核心機(jī)制:
# 規(guī)劃步驟函數(shù)
defplanning_steps(k:int,# 規(guī)劃步驟數(shù)
q_table:DefaultDict[Tuple[int,int],Dict[int,float]],
model:Dict[Tuple[Tuple[int,int],int],Tuple[float,Tuple[int,int]]],
observed_pairs:List[Tuple[Tuple[int,int],int]],
alpha:float,gamma:float,n_actions:int)->None:
""" 使用模型執(zhí)行'k'次模擬Q學(xué)習(xí)更新。 """
ifnotobserved_pairs:# 沒有觀察就無法規(guī)劃
return
for_inrange(k):
# 1. 采樣隨機(jī)先前觀察到的狀態(tài)-動(dòng)作對(duì)
state_p,action_p=random.choice(observed_pairs)
# 2. 查詢模型獲取模擬結(jié)果
reward_p,next_state_p=model[(state_p,action_p)]
# 3. 使用模擬經(jīng)驗(yàn)應(yīng)用Q學(xué)習(xí)更新
# (假設(shè)模擬步驟不會(huì)結(jié)束回合,除非模型表示如此)
# 這里需要Q學(xué)習(xí)部分的update_q_value函數(shù)。
update_q_value(q_table,state_p,action_p,reward_p,next_state_p,
alpha,gamma,n_actions,is_done=False)# 在模擬中假設(shè)未結(jié)束
# (更復(fù)雜的模型可以預(yù)測'done')
此規(guī)劃函數(shù)利用從智能體學(xué)習(xí)的環(huán)境模型中采樣的轉(zhuǎn)移數(shù)據(jù)執(zhí)行k次Q學(xué)習(xí)更新,實(shí)現(xiàn)了價(jià)值信息的更快傳播。
學(xué)習(xí)進(jìn)展分析:觀察到極為快速的收斂過程?;睾祥L度迅速下降,表明智能體能夠非常高效地學(xué)習(xí)到最優(yōu)路徑。
獎(jiǎng)勵(lì)性能分析:總獎(jiǎng)勵(lì)從初始負(fù)值陡峭上升至持續(xù)穩(wěn)定的高正值,展示了快速有效的策略學(xué)習(xí)過程。
效率評(píng)估(Dyna-Q特性):步數(shù)和獎(jiǎng)勵(lì)的快速改善明顯體現(xiàn)了Dyna-Q規(guī)劃機(jī)制(k=50)的優(yōu)勢,通過利用學(xué)習(xí)模型顯著加速學(xué)習(xí)過程。
Dyna-Q算法展現(xiàn)了卓越的樣本效率,使智能體能夠迅速學(xué)習(xí)網(wǎng)格環(huán)境中的有效策略。規(guī)劃組件促進(jìn)了快速收斂至高獎(jiǎng)勵(lì)和短回合長度的優(yōu)化目標(biāo)。
6、Reinforce
我們現(xiàn)在將討論從基于值的方法(Q學(xué)習(xí),SARSA)轉(zhuǎn)向基于策略的方法的重要轉(zhuǎn)變。
REINFORCE算法不是學(xué)習(xí)動(dòng)作值函數(shù),而是直接學(xué)習(xí)和優(yōu)化參數(shù)化策略π(a∣s;θ),該策略將狀態(tài)直接映射至動(dòng)作概率分布,由參數(shù)集θ決定。策略參數(shù)調(diào)整的目標(biāo)是使高質(zhì)量動(dòng)作(即導(dǎo)致高累積獎(jiǎng)勵(lì)的動(dòng)作)具有更高的發(fā)生概率。
REINFORCE采用蒙特卡洛方法框架,這意味著算法在更新策略參數(shù)前需要收集完整回合的獎(jiǎng)勵(lì)序列。
智能體使用當(dāng)前策略網(wǎng)絡(luò)(π_θ)生成一個(gè)完整回合的交互序列。在每個(gè)時(shí)間步驟,智能體:
基于當(dāng)前狀態(tài)s采樣一個(gè)動(dòng)作a。
存儲(chǔ)該動(dòng)作的對(duì)數(shù)概率(log π(a|s))。
記錄獲取的獎(jiǎng)勵(lì)r。
回合完成后,智能體回顧分析整個(gè)獎(jiǎng)勵(lì)序列。算法計(jì)算從每個(gè)時(shí)間步t開始的折扣累積回報(bào)(G_t)。
最終,策略參數(shù)(θ)通過梯度上升進(jìn)行更新:
對(duì)于后續(xù)獲得高回報(bào)(G_t)的動(dòng)作,更新過程增加其對(duì)數(shù)概率(log π(a|s))。
對(duì)于后續(xù)獲得低回報(bào)的動(dòng)作,更新過程降低其對(duì)數(shù)概率。
首先,我們定義策略網(wǎng)絡(luò)架構(gòu)。該網(wǎng)絡(luò)類似于Actor網(wǎng)絡(luò),通過Softmax層輸出動(dòng)作概率分布:
# 定義策略網(wǎng)絡(luò)架構(gòu)
classPolicyNetwork(nn.Module):
def__init__(self,n_observations:int,n_actions:int):
super(PolicyNetwork,self).__init__()
self.layer1=nn.Linear(n_observations,128)
self.layer2=nn.Linear(128,128)
self.layer3=nn.Linear(128,n_actions)# 輸出logits
defforward(self,x:torch.Tensor)->Categorical:
""" 前向傳播,返回動(dòng)作的Categorical分布。 """
ifnotisinstance(x,torch.Tensor):
x=torch.tensor(x,dtype=torch.float32,device=device)# 假設(shè)'device'已定義
elifx.dtype!=torch.float32:
x=x.to(dtype=torch.float32)
ifx.dim()==1:x=x.unsqueeze(0)
x=F.relu(self.layer1(x))
x=F.relu(self.layer2(x))
action_logits=self.layer3(x)
# 直接從logits創(chuàng)建Categorical分布
returnCategorical(logits=action_logits)
該網(wǎng)絡(luò)接收環(huán)境狀態(tài)作為輸入,并提供一種機(jī)制來采樣動(dòng)作并計(jì)算其對(duì)數(shù)概率。
接下來,動(dòng)作選擇函數(shù)利用策略網(wǎng)絡(luò)采樣動(dòng)作并記錄其對(duì)數(shù)概率:
# 通過采樣選擇動(dòng)作
def select_action_reinforce(state: torch.Tensor, policy_net: PolicyNetwork) -> Tuple[int, torch.Tensor]:
""" 通過從策略網(wǎng)絡(luò)的輸出分布采樣選擇動(dòng)作。 """
action_dist = policy_net(state)
action = action_dist.sample() # 采樣動(dòng)作
log_prob = action_dist.log_prob(action) # 獲取所選動(dòng)作的對(duì)數(shù)概率
return action.item(), log_prob
與epsilon-greedy策略不同,REINFORCE的探索機(jī)制是通過網(wǎng)絡(luò)輸出的概率分布采樣過程自然引入的。
在回合結(jié)束后,需要計(jì)算每個(gè)時(shí)間步的折扣累積回報(bào)Gt:
# 計(jì)算折扣回報(bào)
defcalculate_discounted_returns(rewards:List[float],gamma:float,standardize:bool=True)->torch.Tensor:
""" 計(jì)算每一步t的折扣回報(bào)G_t,可選擇標(biāo)準(zhǔn)化。 """
n_steps=len(rewards)
returns=torch.zeros(n_steps,dtype=torch.float32)# 保持在CPU上進(jìn)行計(jì)算
discounted_return=0.0
# 反向迭代
fortinreversed(range(n_steps)):
discounted_return=rewards[t]+gamma*discounted_return
returns[t]=discounted_return
ifstandardize:
mean_return=torch.mean(returns)
std_return=torch.std(returns)+1e-8# 添加epsilon以保持穩(wěn)定
returns=(returns-mean_return)/std_return
returnreturns.to(device)# 最后移動(dòng)到適當(dāng)?shù)脑O(shè)備
此函數(shù)計(jì)算回合中每個(gè)動(dòng)作后的實(shí)際累積回報(bào)(Gt)。標(biāo)準(zhǔn)化處理能夠提高訓(xùn)練穩(wěn)定性。
最后,策略更新函數(shù)利用收集的對(duì)數(shù)概率和回報(bào)調(diào)整網(wǎng)絡(luò)參數(shù):
# 策略更新步驟
defoptimize_policy(log_probs:List[torch.Tensor],
returns:torch.Tensor,
optimizer:optim.Optimizer)->float:
""" 執(zhí)行一次REINFORCE策略梯度更新。 """
# 堆疊對(duì)數(shù)概率并確?;貓?bào)具有正確的形狀
log_probs_tensor=torch.stack(log_probs)
returns=returns.detach()# 在此更新中將回報(bào)視為固定目標(biāo)
# 計(jì)算損失:- Sum(G_t * log_pi(a_t|s_t))
# 我們最小化負(fù)目標(biāo)
loss=-torch.sum(returns*log_probs_tensor)
# 執(zhí)行優(yōu)化
optimizer.zero_grad()
loss.backward()
optimizer.step()
returnloss.item()
此函數(shù)計(jì)算REINFORCE算法的策略梯度損失,并使用優(yōu)化器(如Adam)更新策略網(wǎng)絡(luò)參數(shù)θ,使有利的動(dòng)作序列在未來更可能出現(xiàn)。
學(xué)習(xí)進(jìn)展分析:智能體展現(xiàn)有效學(xué)習(xí)能力,從回合步驟(長度)的急劇減少并在低值穩(wěn)定可以明確觀察到。
獎(jiǎng)勵(lì)性能評(píng)估:總獎(jiǎng)勵(lì)從負(fù)值大幅提升并收斂到穩(wěn)定的高正值,表明智能體成功學(xué)習(xí)了高效策略。
損失和穩(wěn)定性分析:損失值在整個(gè)訓(xùn)練過程中表現(xiàn)出顯著波動(dòng),移動(dòng)平均線也未展示明確的收斂趨勢。這突顯了基本REINFORCE算法固有的高方差特性。
REINFORCE算法成功訓(xùn)練了智能體解決網(wǎng)格導(dǎo)航任務(wù),實(shí)現(xiàn)了高獎(jiǎng)勵(lì)和高效路徑規(guī)劃。然而,從損失曲線的波動(dòng)性可以看出,訓(xùn)練過程存在高方差現(xiàn)象,這是該算法的典型特征。
7、PPO(近端策略優(yōu)化)
像REINFORCE這樣的標(biāo)準(zhǔn)策略梯度方法可能存在訓(xùn)練不穩(wěn)定性,因?yàn)榛谠肼暬貓?bào)的單次更新可能導(dǎo)致策略發(fā)生劇烈變化,進(jìn)而導(dǎo)致性能嚴(yán)重下降。
信任區(qū)域策略優(yōu)化(TRPO)通過復(fù)雜的約束優(yōu)化機(jī)制解決了這一問題。而近端策略優(yōu)化(PPO)則提供了一種更為簡潔的替代方案,通過使用裁剪的替代目標(biāo)函數(shù)實(shí)現(xiàn)類似的穩(wěn)定性。
PPO是一種演員-評(píng)論家、在策略算法,設(shè)計(jì)理念是在更新過程中確保新策略與舊策略保持適當(dāng)?shù)南嗨菩裕乐蛊茐男缘拇蠓呗宰兓瑫r(shí)保持高效學(xué)習(xí)能力,通常在同一批數(shù)據(jù)上進(jìn)行多次迭代更新(epochs)。
與REINFORCE和A2C類似,PPO首先使用當(dāng)前的舊策略(π_old)收集一批經(jīng)驗(yàn)數(shù)據(jù)(s, a, r, s')。算法同時(shí)存儲(chǔ)每個(gè)動(dòng)作在該策略下的對(duì)數(shù)概率。評(píng)論家網(wǎng)絡(luò)(V_old)提供狀態(tài)值估計(jì)。
在收集足夠的經(jīng)驗(yàn)數(shù)據(jù)后,計(jì)算優(yōu)勢估計(jì)(?)—通常使用廣義優(yōu)勢估計(jì)(GAE)方法。
PPO核心更新在這批收集的數(shù)據(jù)上進(jìn)行多個(gè)epochs的迭代:
當(dāng)前的新策略(π_new)對(duì)批次狀態(tài)進(jìn)行評(píng)估以獲得新的動(dòng)作對(duì)數(shù)概率。
計(jì)算新舊策略之間的概率比率r。
PPO應(yīng)用裁剪目標(biāo)(L_CLIP),基于裁剪參數(shù)(?)限制r對(duì)更新的影響程度。
完整損失函數(shù)由以下組成部分構(gòu)成:
裁剪的策略損失(L_CLIP),確保策略更新穩(wěn)定性。
值函數(shù)損失(L_VF),優(yōu)化評(píng)論家網(wǎng)絡(luò)。
熵正則項(xiàng)(S),鼓勵(lì)足夠的探索行為。
演員(策略)和評(píng)論家(值函數(shù))網(wǎng)絡(luò)通過梯度下降基于此綜合損失函數(shù)進(jìn)行優(yōu)化。
PPO使用與A2C和TRPO相同的Actor(策略網(wǎng)絡(luò))和Critic(值網(wǎng)絡(luò))架構(gòu)。
算法通常采用相同的廣義優(yōu)勢估計(jì)(GAE)函數(shù)計(jì)算優(yōu)勢值。PPO的獨(dú)特之處在于其更新邏輯,特別是策略損失函數(shù)(L_CLIP)的計(jì)算方式。
更新邏輯方程
# PPO更新步驟(簡化視圖,假設(shè)數(shù)據(jù)已批處理)
defupdate_ppo(actor:PolicyNetwork,
critic:ValueNetwork,
actor_optimizer:optim.Optimizer,
critic_optimizer:optim.Optimizer,
states:torch.Tensor,
actions:torch.Tensor,
log_probs_old:torch.Tensor,# 來自用于rollout的策略的對(duì)數(shù)概率
advantages:torch.Tensor, # 計(jì)算的GAE優(yōu)勢
returns_to_go:torch.Tensor,# 值函數(shù)的目標(biāo)(Adv + V_old)
ppo_epochs:int, # 每批次的更新次數(shù)
ppo_clip_epsilon:float, # 裁剪參數(shù)ε
value_loss_coeff:float, # 評(píng)論家損失權(quán)重
entropy_coeff:float)->Tuple[float,float,float]:# 平均損失
total_policy_loss=0.0
total_value_loss=0.0
total_entropy=0.0
# 數(shù)據(jù)在進(jìn)入循環(huán)前應(yīng)該被分離
advantages=advantages.detach()
log_probs_old=log_probs_old.detach()
returns_to_go=returns_to_go.detach()
# 在同一批次上執(zhí)行多個(gè)epochs的更新
for_inrange(ppo_epochs):
# --- Actor(策略)更新 ---
policy_dist=actor(states) # 獲取當(dāng)前策略分布
log_probs_new=policy_dist.log_prob(actions)# 動(dòng)作在*新*策略下的對(duì)數(shù)概率
entropy=policy_dist.entropy().mean() # 平均熵
# 計(jì)算比率r(θ) = π_new / π_old
ratio=torch.exp(log_probs_new-log_probs_old)
# 計(jì)算裁剪的替代目標(biāo)部分
surr1=ratio*advantages
surr2=torch.clamp(ratio,1.0-ppo_clip_epsilon,1.0+ppo_clip_epsilon)*advantages
# 策略損失:-(min(surr1, surr2)) - entropy_bonus
policy_loss=-torch.min(surr1,surr2).mean()-entropy_coeff*entropy
# 優(yōu)化actor
actor_optimizer.zero_grad()
policy_loss.backward()
actor_optimizer.step()
# --- Critic(值)更新 ---
values_pred=critic(states).squeeze()# 使用當(dāng)前critic預(yù)測V(s)
value_loss=F.mse_loss(values_pred,returns_to_go)# 與計(jì)算的回報(bào)比較
# 優(yōu)化critic
critic_optimizer.zero_grad()
(value_loss_coeff*value_loss).backward()# 在backward前縮放損失
critic_optimizer.step()
# 累積統(tǒng)計(jì)
total_policy_loss+=policy_loss.item()
total_value_loss+=value_loss.item()
total_entropy+=entropy.item()
# 返回epochs上的平均損失
returntotal_policy_loss/ppo_epochs,total_value_loss/ppo_epochs,total_entropy/ppo_epochs
此更新函數(shù)在收集的數(shù)據(jù)批次上進(jìn)行多次迭代(epochs)。
在每次迭代中,函數(shù)計(jì)算策略比率,應(yīng)用裁剪機(jī)制限制策略變化幅度,計(jì)算值函數(shù)損失,并更新兩個(gè)網(wǎng)絡(luò)參數(shù)。這種組合機(jī)制實(shí)現(xiàn)了穩(wěn)定且高效的學(xué)習(xí)過程。
學(xué)習(xí)進(jìn)展分析:PPO展示極為快速的學(xué)習(xí)能力;平均回合長度急劇下降并迅速穩(wěn)定在較低水平。
獎(jiǎng)勵(lì)性能評(píng)估:平均獎(jiǎng)勵(lì)值呈陡峭上升趨勢并穩(wěn)定在接近最大可能值的水平,表明算法快速收斂到高效策略。
訓(xùn)練穩(wěn)定性分析:策略目標(biāo)(損失)和熵值均呈穩(wěn)步下降趨勢,表明策略持續(xù)改進(jìn)并逐步減少探索。值函數(shù)損失雖有波動(dòng)但整體保持在可控范圍內(nèi)。
學(xué)習(xí)策略評(píng)估:最終策略網(wǎng)格清晰展示了確定性且合理的導(dǎo)航路徑,指向網(wǎng)格右下方的目標(biāo)區(qū)域。
PPO算法表現(xiàn)卓越,特點(diǎn)是收斂速度快、學(xué)習(xí)過程穩(wěn)定且能持續(xù)獲得高獎(jiǎng)勵(lì)。智能體能夠迅速學(xué)習(xí)形成高效且有效的網(wǎng)格環(huán)境導(dǎo)航策略。
8、A2C(同步優(yōu)勢演員-評(píng)論家)
同步優(yōu)勢演員-評(píng)論家(A2C)是演員-評(píng)論家算法族中的一個(gè)同步、簡化變體。
與其他演員-評(píng)論家方法相似,A2C使用雙網(wǎng)絡(luò)架構(gòu):一個(gè)演員網(wǎng)絡(luò)負(fù)責(zé)動(dòng)作選擇,一個(gè)評(píng)論家網(wǎng)絡(luò)負(fù)責(zé)狀態(tài)評(píng)估。A2C特別采用優(yōu)勢函數(shù)估計(jì):
優(yōu)勢函數(shù)指導(dǎo)演員網(wǎng)絡(luò)的更新過程,相比REINFORCE算法能夠有效降低梯度估計(jì)的方差。
與其異步版本A3C不同,A2C執(zhí)行同步參數(shù)更新。
算法通常在收集一批經(jīng)驗(yàn)數(shù)據(jù)后(通常從并行環(huán)境收集,盡管本示例中按順序模擬)才同時(shí)計(jì)算并應(yīng)用梯度更新到演員和評(píng)論家網(wǎng)絡(luò)參數(shù)。
在交互采樣階段,演員網(wǎng)絡(luò)(π_θ)根據(jù)當(dāng)前狀態(tài)(s)選擇動(dòng)作(a),而評(píng)論家網(wǎng)絡(luò)(V_?)估計(jì)該狀態(tài)的價(jià)值(V(s))。
執(zhí)行動(dòng)作后獲得獎(jiǎng)勵(lì)(r)和后繼狀態(tài)(s')。此過程重復(fù)N步,收集一批交互數(shù)據(jù)。
在參數(shù)更新階段,收集的獎(jiǎng)勵(lì)序列和值估計(jì)用于計(jì)算目標(biāo)回報(bào)(R_t)和優(yōu)勢估計(jì)(?)。策略損失通過優(yōu)勢和動(dòng)作對(duì)數(shù)概率計(jì)算,目標(biāo)是增強(qiáng)具有正優(yōu)勢的動(dòng)作概率。
值函數(shù)損失計(jì)算為預(yù)測值(V(s_t))與目標(biāo)回報(bào)(R_t)之間的均方誤差。
最后,兩種損失函數(shù)的梯度被計(jì)算并用于同步更新演員(θ)和評(píng)論家(?)網(wǎng)絡(luò)參數(shù)。
演員網(wǎng)絡(luò):策略函數(shù)π(a∣s;θ),輸出動(dòng)作概率分布。
評(píng)論家網(wǎng)絡(luò):值函數(shù)V(s;?),估計(jì)狀態(tài)價(jià)值。
優(yōu)勢函數(shù):計(jì)算為?_t≈R_t?V(s_t),其中R_t通常是n步回報(bào)或通過GAE計(jì)算。它衡量動(dòng)作相對(duì)于狀態(tài)平均預(yù)期回報(bào)的相對(duì)優(yōu)勢。
同步更新機(jī)制:梯度在一批經(jīng)驗(yàn)數(shù)據(jù)上計(jì)算并同時(shí)應(yīng)用到演員和評(píng)論家網(wǎng)絡(luò)。
A2C使用與PPO和TRPO相同的Actor(策略網(wǎng)絡(luò))和Critic(值網(wǎng)絡(luò))架構(gòu)。
算法通常采用廣義優(yōu)勢估計(jì)(GAE)計(jì)算優(yōu)勢值和評(píng)論家網(wǎng)絡(luò)的目標(biāo)回報(bào)。
A2C更新函數(shù)計(jì)算組合損失并同步應(yīng)用梯度更新:
# A2C更新步驟
defupdate_a2c(actor:PolicyNetwork,
critic:ValueNetwork,
actor_optimizer:optim.Optimizer,
critic_optimizer:optim.Optimizer,
states:torch.Tensor,
actions:torch.Tensor,
advantages:torch.Tensor, # 計(jì)算的GAE優(yōu)勢
returns_to_go:torch.Tensor,# 值函數(shù)的目標(biāo)(Adv + V_old)
value_loss_coeff:float, # 評(píng)論家損失權(quán)重
entropy_coeff:float # 熵獎(jiǎng)勵(lì)權(quán)重
)->Tuple[float,float,float]:# 平均損失
# --- 評(píng)估當(dāng)前網(wǎng)絡(luò) ---
policy_dist=actor(states)
log_probs=policy_dist.log_prob(actions)# 所采取動(dòng)作的對(duì)數(shù)概率
entropy=policy_dist.entropy().mean() # 平均熵
values_pred=critic(states).squeeze() # 評(píng)論家的值預(yù)測
# --- 計(jì)算損失 ---
# 策略損失(演員):- E[log_pi * A_detached] - entropy_bonus
policy_loss=-(log_probs*advantages.detach()).mean()-entropy_coeff*entropy
# 值損失(評(píng)論家):MSE(V_pred, Returns_detached)
value_loss=F.mse_loss(values_pred,returns_to_go.detach())
# --- 優(yōu)化演員 ---
actor_optimizer.zero_grad()
policy_loss.backward() # 計(jì)算演員梯度
actor_optimizer.step() # 更新演員權(quán)重
# --- 優(yōu)化評(píng)論家 ---
critic_optimizer.zero_grad()
# 評(píng)論家損失的反向傳播(縮放后)
(value_loss_coeff*value_loss).backward()
critic_optimizer.step() # 更新評(píng)論家權(quán)重
# 返回用于記錄的損失(策略目標(biāo)部分,值損失,熵)
returnpolicy_loss.item()+entropy_coeff*entropy.item(),value_loss.item(),entropy.item()
此函數(shù)接收一批交互數(shù)據(jù),基于計(jì)算的優(yōu)勢估計(jì)和目標(biāo)回報(bào)計(jì)算策略和值函數(shù)損失,然后對(duì)演員和評(píng)論家網(wǎng)絡(luò)執(zhí)行獨(dú)立但同步的梯度更新。
學(xué)習(xí)進(jìn)展與效率分析:智能體展現(xiàn)出強(qiáng)勁的學(xué)習(xí)能力。平均回合獎(jiǎng)勵(lì)從顯著負(fù)值迅速上升,在約100-150次迭代后穩(wěn)定收斂在接近最大可能值水平。同時(shí),平均回合長度從最大步數(shù)限制急劇下降至低且穩(wěn)定的值,表明智能體迅速掌握了高效路徑規(guī)劃能力。
值函數(shù)學(xué)習(xí)過程:值損失(MSE)在初始階段呈上升趨勢,這是因?yàn)樵u(píng)論家網(wǎng)絡(luò)需要在快速變化的策略環(huán)境中學(xué)習(xí)準(zhǔn)確的狀態(tài)價(jià)值。損失在約75次迭代后達(dá)到峰值,隨后隨著策略穩(wěn)定而穩(wěn)步下降,表明評(píng)論家網(wǎng)絡(luò)對(duì)狀態(tài)價(jià)值的預(yù)測精度顯著提高。
策略優(yōu)化與穩(wěn)定性:策略損失曲線呈現(xiàn)一定噪聲,這是策略梯度方法的固有特性,反映了更新過程中的方差。然而,移動(dòng)平均趨勢顯示整體損失呈下降趨勢(盡管有波動(dòng)),表明策略持續(xù)改進(jìn)。
最終策略評(píng)估:策略網(wǎng)格展示了一個(gè)連貫且確定性的導(dǎo)航策略。方向箭頭一致地指引智能體,形成通向位于網(wǎng)格右下區(qū)域目標(biāo)位置的明確路徑,證明算法成功收斂到特定的導(dǎo)航方案。
A2C算法成功優(yōu)化了策略網(wǎng)絡(luò)(演員)和值函數(shù)網(wǎng)絡(luò)(評(píng)論家),實(shí)現(xiàn)了快速收斂到高平均獎(jiǎng)勵(lì)和高效導(dǎo)航路徑的目標(biāo),最終形成了清晰合理的策略決策模式。
9、A3C (異步優(yōu)勢演員-評(píng)論家算法)
異步優(yōu)勢演員-評(píng)論家算法(A3C)是一項(xiàng)突破性的強(qiáng)化學(xué)習(xí)方法,其創(chuàng)新之處在于通過并行化機(jī)制實(shí)現(xiàn)演員-評(píng)論家學(xué)習(xí)的穩(wěn)定性,而無需依賴DQN中使用的經(jīng)驗(yàn)回放緩沖區(qū)。
該算法部署多個(gè)并行執(zhí)行的"工作者"智能體,每個(gè)工作者與環(huán)境的獨(dú)立副本進(jìn)行交互。
A3C的核心原理是基于異步更新機(jī)制:各工作者根據(jù)其本地經(jīng)驗(yàn)獨(dú)立計(jì)算參數(shù)更新,并將這些更新異步應(yīng)用于共享的全局網(wǎng)絡(luò),無需相互協(xié)調(diào)或等待。
這種來自不同工作者的持續(xù)、多樣化的更新流有效降低了訓(xùn)練數(shù)據(jù)間的相關(guān)性,從而顯著提高了學(xué)習(xí)穩(wěn)定性。
該算法架構(gòu)中存在多個(gè)獨(dú)立工作者。每個(gè)工作者首先從共享的"全局網(wǎng)絡(luò)"復(fù)制參數(shù)。
隨后,工作者使用其本地網(wǎng)絡(luò)副本與專屬環(huán)境實(shí)例交互,執(zhí)行一系列步驟(即"n步展開")。
基于這段軌跡經(jīng)驗(yàn),工作者計(jì)算其本地網(wǎng)絡(luò)中演員和評(píng)論家組件的梯度。
最后,工作者異步地將這些梯度傳遞給共享優(yōu)化器,用于更新全局網(wǎng)絡(luò)參數(shù)。
由于各工作者獨(dú)立運(yùn)行且在不同時(shí)間點(diǎn)進(jìn)行更新,全局網(wǎng)絡(luò)接收到的是具有多樣性且相關(guān)性較低的更新流。
A3C的關(guān)鍵技術(shù)特點(diǎn)包括:
異步更新:工作者之間無需相互等待,減少了計(jì)算資源的閑置時(shí)間,同時(shí)降低了更新之間的數(shù)據(jù)相關(guān)性。
全局與本地網(wǎng)絡(luò)架構(gòu):工作者定期與中央全局網(wǎng)絡(luò)同步參數(shù),但在本地進(jìn)行梯度計(jì)算。
N步回報(bào)計(jì)算:更新通?;诙绦蛄?n步)內(nèi)收集的獎(jiǎng)勵(lì)總和,再加上由評(píng)論家網(wǎng)絡(luò)對(duì)n步后狀態(tài)的價(jià)值估計(jì)。這種方法平衡了單步時(shí)序差分學(xué)習(xí)的偏差與完整蒙特卡洛回報(bào)的方差。
優(yōu)勢估計(jì):優(yōu)勢函數(shù)計(jì)算采用?_t = R_t ? V(s_t)公式,其中R_t表示n步回報(bào)。
A3C典型實(shí)現(xiàn)采用共享初層特征提取的組合演員-評(píng)論家網(wǎng)絡(luò)架構(gòu):
# 共享的演員-評(píng)論家網(wǎng)絡(luò)(與A2C結(jié)構(gòu)相同)
classActorCriticNetwork(nn.Module):
def__init__(self,n_observations:int,n_actions:int):
super(ActorCriticNetwork,self).__init__()
self.layer1=nn.Linear(n_observations,128)
self.layer2=nn.Linear(128,128)
self.actor_head=nn.Linear(128,n_actions)# 動(dòng)作對(duì)數(shù)概率
self.critic_head=nn.Linear(128,1) # 狀態(tài)價(jià)值
defforward(self,x:torch.Tensor)->Tuple[Categorical,torch.Tensor]:
ifnotisinstance(x,torch.Tensor):
x=torch.tensor(x,dtype=torch.float32,device=x.device)
elifx.dtype!=torch.float32:
x=x.to(dtype=torch.float32)
ifx.dim()==1:x=x.unsqueeze(0)
x=F.relu(self.layer1(x))
shared_features=F.relu(self.layer2(x))
action_logits=self.actor_head(shared_features)
state_value=self.critic_head(shared_features)
# 確保在添加批次維度的情況下值被壓縮
ifx.shape[0]==1andstate_value.dim()>0:
state_value=state_value.squeeze(0)
returnCategorical(logits=action_logits.to(x.device)),state_value
每個(gè)工作者收集n步經(jīng)驗(yàn)并計(jì)算目標(biāo)回報(bào)和優(yōu)勢值:
# 計(jì)算N步回報(bào)和優(yōu)勢(在每個(gè)工作者內(nèi)使用)
defcompute_n_step_returns_advantages(rewards:List[float],
values:List[torch.Tensor],# 網(wǎng)絡(luò)預(yù)測的V(s_t)
bootstrap_value:torch.Tensor,# V(s_{t+n})預(yù)測,已分離
dones:List[float],# 完成標(biāo)志(0.0或1.0)
gamma:float
)->Tuple[torch.Tensor,torch.Tensor]:
""" 計(jì)算n步回報(bào)(評(píng)論家目標(biāo))和優(yōu)勢(演員指導(dǎo))。"""
n_steps=len(rewards)
returns=torch.zeros(n_steps,dtype=torch.float32)# 在CPU上存儲(chǔ)結(jié)果
advantages=torch.zeros(n_steps,dtype=torch.float32)
# 分離用于優(yōu)勢計(jì)算的值(作為基線的一部分)
values_detached=torch.cat([v.detach()forvinvalues]).squeeze().cpu()
R=bootstrap_value.detach().cpu()# 從自舉值開始
fortinreversed(range(n_steps)):
R=rewards[t]+gamma*R*(1.0-dones[t])# 計(jì)算n步回報(bào)
returns[t]=R
# 確保values_detached具有正確的形狀以進(jìn)行優(yōu)勢計(jì)算
value_t=values_detachedifvalues_detached.dim()==0elsevalues_detached[t]
advantages[t]=R-value_t# 優(yōu)勢 = N步回報(bào) - V(s_t)
# 可選:標(biāo)準(zhǔn)化優(yōu)勢
# advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8)
returnreturns,advantages
工作者基于n步經(jīng)驗(yàn)計(jì)算策略損失、價(jià)值損失和熵獎(jiǎng)勵(lì),在本地計(jì)算梯度,并通過共享優(yōu)化器異步更新全局網(wǎng)絡(luò)參數(shù):
# --- 工作者損失計(jì)算(概念性 - 由每個(gè)工作者執(zhí)行) ---
# 假設(shè)'log_probs_tensor'、'values_pred_tensor'、'entropies_tensor'包含
# n步展開的網(wǎng)絡(luò)輸出,
# 而'returns_tensor'、'advantages_tensor'包含計(jì)算出的目標(biāo)。
policy_loss=-(log_probs_tensor*advantages_tensor.detach()).mean()
value_loss=F.mse_loss(values_pred_tensor,returns_tensor.detach())
entropy_loss=-entropies_tensor.mean()
total_loss=policy_loss+value_loss_coeff*value_loss+entropy_coeff*entropy_loss
# --- 梯度應(yīng)用(概念性) ---
global_optimizer.zero_grad()
total_loss.backward()# 計(jì)算本地模型上的梯度
# 將梯度從local_model.parameters()傳輸?shù)絞lobal_model.parameters()
global_optimizer.step()# 將梯度應(yīng)用于全局模型
這種異步更新機(jī)制使多個(gè)工作者能夠并行貢獻(xiàn)梯度更新,顯著提高了多核系統(tǒng)上的訓(xùn)練時(shí)間效率。
獎(jiǎng)勵(lì)進(jìn)展:智能體從初始負(fù)分狀態(tài)顯著改善,移動(dòng)平均線表明在約300回合后收斂至穩(wěn)定的高正獎(jiǎng)勵(lì)水平。
效率提升:回合長度在250回合左右出現(xiàn)顯著下降,從最大步數(shù)減少至穩(wěn)定的較低平均值,表明任務(wù)完成效率大幅提高。
學(xué)習(xí)效果:圖表清晰展示了A3C的有效學(xué)習(xí)過程,從初始探索/低效階段轉(zhuǎn)變?yōu)榉€(wěn)定高效的策略,持續(xù)有效地解決任務(wù)。
A3C算法成功學(xué)習(xí)了目標(biāo)任務(wù),展現(xiàn)了從初始低效表現(xiàn)到穩(wěn)定高獎(jiǎng)勵(lì)水平的顯著進(jìn)步。
這一學(xué)習(xí)成效與效率的大幅提升緊密相關(guān),從回合長度的快速下降可以明確觀察到這一點(diǎn)。
智能體在大約300回合的訓(xùn)練后收斂到一個(gè)高質(zhì)量且高效的策略。
10、DDPG (用于連續(xù)動(dòng)作的演員-評(píng)論家算法)
深度確定性策略梯度(DDPG)是一種將演員-評(píng)論家方法擴(kuò)展到連續(xù)動(dòng)作空間環(huán)境的算法,適用于需要精確控制的任務(wù)(如施加特定扭矩、設(shè)定精確速度等)。
該算法巧妙地融合了DQN的核心技術(shù)(如經(jīng)驗(yàn)回放緩沖區(qū)和目標(biāo)網(wǎng)絡(luò))與確定性策略梯度方法。
DDPG的核心技術(shù)原理包括:
確定性演員網(wǎng)絡(luò):與REINFORCE/A2C/PPO等輸出動(dòng)作概率分布的算法不同,DDPG的演員網(wǎng)絡(luò)直接為給定狀態(tài)輸出一個(gè)確定性動(dòng)作向量。
Q值評(píng)論家網(wǎng)絡(luò):評(píng)論家網(wǎng)絡(luò)學(xué)習(xí)狀態(tài)-動(dòng)作值函數(shù)Q(s, a),類似于Q學(xué)習(xí),但針對(duì)連續(xù)動(dòng)作空間進(jìn)行了適配,評(píng)估在狀態(tài)(s)中執(zhí)行演員選擇的連續(xù)動(dòng)作(a)的價(jià)值。
離策略學(xué)習(xí):采用經(jīng)驗(yàn)回放緩沖區(qū)存儲(chǔ)交互經(jīng)驗(yàn)并隨機(jī)采樣小批量數(shù)據(jù)進(jìn)行學(xué)習(xí),實(shí)現(xiàn)從歷史數(shù)據(jù)中進(jìn)行穩(wěn)定學(xué)習(xí),類似于DQN的機(jī)制。
目標(biāo)網(wǎng)絡(luò)機(jī)制:為演員和評(píng)論家網(wǎng)絡(luò)均設(shè)置獨(dú)立的目標(biāo)網(wǎng)絡(luò),用于計(jì)算評(píng)論家的目標(biāo)值,顯著提高學(xué)習(xí)穩(wěn)定性。
探索策略:由于算法采用確定性策略,需要手動(dòng)添加探索機(jī)制,通常通過向演員網(wǎng)絡(luò)輸出動(dòng)作添加噪聲(如高斯噪聲或奧恩斯坦-烏倫貝克過程噪聲)實(shí)現(xiàn)。
在環(huán)境交互階段,演員網(wǎng)絡(luò)基于當(dāng)前狀態(tài)(s)生成確定性動(dòng)作。
為實(shí)現(xiàn)探索,在將動(dòng)作傳遞給環(huán)境執(zhí)行前,系統(tǒng)向該動(dòng)作添加噪聲。產(chǎn)生的轉(zhuǎn)移經(jīng)驗(yàn)(s, a, r, s', done)被存儲(chǔ)到經(jīng)驗(yàn)回放緩沖區(qū)中。
在訓(xùn)練階段,系統(tǒng)從回放緩沖區(qū)中隨機(jī)采樣批量數(shù)據(jù):
評(píng)論家網(wǎng)絡(luò)更新:目標(biāo)Q值(TD目標(biāo)y)通過結(jié)合即時(shí)獎(jiǎng)勵(lì)(r)、目標(biāo)演員和目標(biāo)評(píng)論家網(wǎng)絡(luò)對(duì)下一狀態(tài)(s')的評(píng)估計(jì)算得出。主評(píng)論家網(wǎng)絡(luò)計(jì)算當(dāng)前批次狀態(tài)和動(dòng)作的Q(s, a)值。系統(tǒng)使用目標(biāo)(y)與Q(s, a)之間的均方誤差(MSE損失)更新主評(píng)論家網(wǎng)絡(luò)參數(shù)(?)。
演員網(wǎng)絡(luò)更新:演員網(wǎng)絡(luò)為批次狀態(tài)(s)計(jì)算確定性動(dòng)作。這些動(dòng)作作為輸入傳遞給主評(píng)論家網(wǎng)絡(luò)以獲取對(duì)應(yīng)的Q值評(píng)估。演員網(wǎng)絡(luò)通過最大化這些Q值(即最小化負(fù)Q值,L_θ = ?Q)進(jìn)行參數(shù)更新。
目標(biāo)網(wǎng)絡(luò)更新:目標(biāo)演員和目標(biāo)評(píng)論家網(wǎng)絡(luò)(θ',?')通過軟更新機(jī)制逐步向主網(wǎng)絡(luò)參數(shù)靠近,以平滑學(xué)習(xí)過程并提高穩(wěn)定性。
DDPG實(shí)現(xiàn)需要設(shè)計(jì)獨(dú)立的演員和評(píng)論家網(wǎng)絡(luò)架構(gòu)。演員網(wǎng)絡(luò)輸出確定性連續(xù)動(dòng)作,通常使用tanh激活函數(shù)進(jìn)行歸一化和縮放:
# 簡化的DDPG演員網(wǎng)絡(luò)(輸出連續(xù)動(dòng)作)
classActorNetworkDDPG(nn.Module):
def__init__(self,state_dim:int,action_dim:int,max_action:float):
super(ActorNetworkDDPG,self).__init__()
self.layer1=nn.Linear(state_dim,256)
self.layer2=nn.Linear(256,256)
self.layer3=nn.Linear(256,action_dim)
self.max_action=max_action# 用于縮放輸出
defforward(self,state:torch.Tensor)->torch.Tensor:
x=F.relu(self.layer1(state))
x=F.relu(self.layer2(x))
# 使用tanh輸出-1到1之間的值,然后縮放
action=self.max_action*torch.tanh(self.layer3(x))
returnaction
# 簡化的DDPG評(píng)論家網(wǎng)絡(luò)(接收狀態(tài)和動(dòng)作)
classCriticNetworkDDPG(nn.Module):
def__init__(self,state_dim:int,action_dim:int):
super(CriticNetworkDDPG,self).__init__()
# 分別或一起處理狀態(tài)和動(dòng)作
self.layer1=nn.Linear(state_dim+action_dim,256)
self.layer2=nn.Linear(256,256)
self.layer3=nn.Linear(256,1)# 輸出單個(gè)Q值
defforward(self,state:torch.Tensor,action:torch.Tensor)->torch.Tensor:
# 連接狀態(tài)和動(dòng)作
x=torch.cat([state,action],dim=1)
x=F.relu(self.layer1(x))
x=F.relu(self.layer2(x))
q_value=self.layer3(x)
returnq_value
上述網(wǎng)絡(luò)定義了DDPG的核心組件。演員網(wǎng)絡(luò)學(xué)習(xí)"選擇什么動(dòng)作",評(píng)論家網(wǎng)絡(luò)學(xué)習(xí)"這些動(dòng)作的價(jià)值評(píng)估"。
完整實(shí)現(xiàn)還需要經(jīng)驗(yàn)回放緩沖區(qū)(類似DQN)和目標(biāo)網(wǎng)絡(luò)復(fù)制機(jī)制:
# 回放緩沖區(qū)(概念 - 使用deque或list)
# 目標(biāo)網(wǎng)絡(luò)(概念 - 創(chuàng)建演員/評(píng)論家的副本)
target_actor=ActorNetworkDDPG(...)
target_critic=CriticNetworkDDPG(...)
target_actor.load_state_dict(actor.state_dict())# 初始化
target_critic.load_state_dict(critic.state_dict())
DDPG的核心更新邏輯涉及計(jì)算演員和評(píng)論家網(wǎng)絡(luò)的損失函數(shù),并對(duì)目標(biāo)網(wǎng)絡(luò)實(shí)施軟更新:
# --- DDPG更新邏輯概述 ---
# (假設(shè)優(yōu)化器已定義: actor_optimizer, critic_optimizer)
# (假設(shè)tau: 軟更新率, gamma: 折扣因子已定義)
# 1. 從replay_buffer采樣批次: states, actions, rewards, next_states, dones
# --- 評(píng)論家更新 ---
# 從目標(biāo)演員獲取下一動(dòng)作: next_actions = target_actor(next_states)
# 從目標(biāo)評(píng)論家獲取目標(biāo)Q值: target_q = target_critic(next_states, next_actions)
# 計(jì)算TD目標(biāo): td_target = rewards + gamma * (1 - dones) * target_q
# 獲取當(dāng)前Q值估計(jì): current_q = critic(states, actions)
# 計(jì)算評(píng)論家損失(MSE): critic_loss = F.mse_loss(current_q, td_target.detach())
# 更新評(píng)論家:
critic_optimizer.zero_grad()
critic_loss.backward()
critic_optimizer.step()
# --- 演員更新 ---
# 從主演員獲取當(dāng)前狀態(tài)的動(dòng)作: actor_actions = actor(states)
# 計(jì)算演員損失(主評(píng)論家的負(fù)Q值): actor_loss = -critic(states, actor_actions).mean()
# 更新演員:
actor_optimizer.zero_grad()
actor_loss.backward()
actor_optimizer.step()
# --- 軟更新目標(biāo)網(wǎng)絡(luò) ---
soft_update(target_critic,critic,tau)
soft_update(target_actor,actor,tau)
這一實(shí)現(xiàn)框架展示了DDPG如何結(jié)合離策略學(xué)習(xí)、目標(biāo)網(wǎng)絡(luò)和雙網(wǎng)絡(luò)架構(gòu),實(shí)現(xiàn)連續(xù)動(dòng)作空間中的有效強(qiáng)化學(xué)習(xí)。
實(shí)際應(yīng)用中,智能體與環(huán)境交互時(shí)需要為演員網(wǎng)絡(luò)輸出動(dòng)作添加適當(dāng)噪聲以促進(jìn)探索。
獎(jiǎng)勵(lì)進(jìn)展:智能體展現(xiàn)出明確的學(xué)習(xí)過程。每回合總獎(jiǎng)勵(lì)(左圖)從極低水平(約-1500)開始穩(wěn)步提升,移動(dòng)平均線在約100回合處達(dá)到-250左右的水平。這表明在控制鐘擺以最小化成本函數(shù)方面取得了顯著進(jìn)步。盡管性能曲線存在波動(dòng),但整體呈現(xiàn)明顯的正向趨勢。
評(píng)論家學(xué)習(xí):平均評(píng)論家損失(中圖)在整個(gè)訓(xùn)練過程中呈現(xiàn)穩(wěn)步增長趨勢。這一現(xiàn)象在直覺上可能令人困惑,但在DDPG框架中,隨著演員性能提升并探索到更高價(jià)值狀態(tài),目標(biāo)Q值也相應(yīng)增加。評(píng)論家網(wǎng)絡(luò)不斷適應(yīng)這些演化的更高價(jià)值目標(biāo),因此損失增加實(shí)際上可能與學(xué)習(xí)成功同步發(fā)生,反映了價(jià)值函數(shù)適應(yīng)過程中規(guī)模/復(fù)雜度的增加。
演員學(xué)習(xí):平均演員"損失"(右圖,標(biāo)記為Avg -Q Value,實(shí)際表示演員實(shí)現(xiàn)的平均Q值)呈現(xiàn)明顯的上升趨勢,與獎(jiǎng)勵(lì)進(jìn)展高度相關(guān)。這表明演員成功學(xué)習(xí)選擇評(píng)論家評(píng)估為高價(jià)值(低成本)的動(dòng)作,推動(dòng)整體性能提升。圖表末端的平緩趨勢暗示學(xué)習(xí)可能正在趨于收斂。
DDPG算法成功地學(xué)習(xí)了鐘擺控制任務(wù),在約100回合的訓(xùn)練過程中顯著提高了累積獎(jiǎng)勵(lì)。演員網(wǎng)絡(luò)(負(fù)責(zé)選擇最優(yōu)動(dòng)作)和評(píng)論家網(wǎng)絡(luò)(負(fù)責(zé)評(píng)估狀態(tài)-動(dòng)作價(jià)值)均展現(xiàn)出有效的學(xué)習(xí)特征,盡管評(píng)論家損失增加是這類算法中常見的現(xiàn)象,反映了價(jià)值函數(shù)適應(yīng)過程的復(fù)雜性。
11、SAC (最大熵演員-評(píng)論家算法)
軟演員-評(píng)論家(SAC)是一種先進(jìn)的演員-評(píng)論家架構(gòu)算法,專為連續(xù)動(dòng)作空間任務(wù)設(shè)計(jì),在DDPG和TD3的基礎(chǔ)上引入了最大熵強(qiáng)化學(xué)習(xí)框架。
該算法的獨(dú)特之處在于智能體不僅被激勵(lì)最大化累積獎(jiǎng)勵(lì),還同時(shí)被鼓勵(lì)維持盡可能高的策略熵(最大化動(dòng)作隨機(jī)性)。
這種熵最大化機(jī)制促進(jìn)了更全面的環(huán)境探索,提高了算法的魯棒性,并與DDPG相比,通常能實(shí)現(xiàn)更快速、更穩(wěn)定的學(xué)習(xí)過程。與DDPG類似,SAC也采用離策略學(xué)習(xí)框架,利用經(jīng)驗(yàn)回放緩沖區(qū)。
在環(huán)境交互階段,與其他演員-評(píng)論家方法相似,但SAC的演員(π_θ)采用隨機(jī)策略– 輸出一個(gè)動(dòng)作概率分布,系統(tǒng)從中采樣具體動(dòng)作。交互產(chǎn)生的經(jīng)驗(yàn)(s, a, r, s', done)存儲(chǔ)于回放緩沖區(qū)中。
在訓(xùn)練階段(從緩沖區(qū)采樣批次數(shù)據(jù)):
評(píng)論家網(wǎng)絡(luò)更新:SAC采用特殊的Q值目標(biāo)計(jì)算方法。系統(tǒng)使用目標(biāo)網(wǎng)絡(luò)獲取對(duì)從當(dāng)前策略(在下一狀態(tài)s'評(píng)估)采樣的下一動(dòng)作(a')的最小Q值估計(jì)(Min Q')。
隨后從該最小Q值中減去**熵項(xiàng)(α * log π(a'|s'))以獲得"軟目標(biāo)值"。TD目標(biāo)(y)由即時(shí)獎(jiǎng)勵(lì)和此軟目標(biāo)組合而成。主評(píng)論家網(wǎng)絡(luò)(Q_?,通常是雙Q網(wǎng)絡(luò)Q1, Q2)通過最小化與y之間的MSE損失**進(jìn)行參數(shù)更新。
演員網(wǎng)絡(luò)更新:演員網(wǎng)絡(luò)**為批次狀態(tài)s采樣動(dòng)作(a_π)。損失函數(shù)設(shè)計(jì)鼓勵(lì)產(chǎn)生高Q值(由主評(píng)論家評(píng)估)且同時(shí)具有高熵(高log π)的動(dòng)作分布**。損失函數(shù)近似為:
(α * log π ? min(Q1, Q2)).mean()
Alpha自動(dòng)調(diào)節(jié)(可選):熵溫度參數(shù)(α)可通過自動(dòng)調(diào)節(jié)機(jī)制優(yōu)化,方法是設(shè)定目標(biāo)熵水平并調(diào)整α以促使**策略實(shí)際熵接近目標(biāo)值**。
目標(biāo)網(wǎng)絡(luò)更新:目標(biāo)評(píng)論家網(wǎng)絡(luò)通過軟更新機(jī)制逐步更新。SAC通常不使用目標(biāo)演員網(wǎng)絡(luò),而是使用當(dāng)前演員網(wǎng)絡(luò)進(jìn)行目標(biāo)動(dòng)作采樣。
SAC的核心技術(shù)特點(diǎn)包括:
最大熵框架:將策略熵H(π(?∣s))_H_(_π_(?∣ _s_))作為獎(jiǎng)勵(lì)的補(bǔ)充項(xiàng),在標(biāo)準(zhǔn)獎(jiǎng)勵(lì)基礎(chǔ)上添加熵獎(jiǎng)勵(lì)。
隨機(jī)演員設(shè)計(jì):輸出連續(xù)動(dòng)作概率分布(如高斯分布)參數(shù)(均值、標(biāo)準(zhǔn)差),并從中采樣具體動(dòng)作。
雙Q網(wǎng)絡(luò)機(jī)制:使用兩個(gè)獨(dú)立Q網(wǎng)絡(luò)并取其目標(biāo)值的最小值,以抑制Q值過估計(jì)問題(類似TD3)。
熵溫度系數(shù):控制獎(jiǎng)勵(lì)目標(biāo)與熵目標(biāo)間的平衡權(quán)重??稍O(shè)為固定值或通過自動(dòng)調(diào)整機(jī)制優(yōu)化。
LOG_STD_MAX=2
LOG_STD_MIN=-20
EPSILON=1e-6# 用于log_prob計(jì)算中的數(shù)值穩(wěn)定性
classActorNetworkSAC(nn.Module):
""" SAC的隨機(jī)高斯演員。"""
def__init__(self,state_dim:int,action_dim:int,max_action:float):
super(ActorNetworkSAC,self).__init__()
self.layer1=nn.Linear(state_dim,256)
self.layer2=nn.Linear(256,256)
self.mean_layer=nn.Linear(256,action_dim) # 輸出均值
self.log_std_layer=nn.Linear(256,action_dim)# 輸出對(duì)數(shù)標(biāo)準(zhǔn)差
self.max_action=max_action
defforward(self,state:torch.Tensor)->Tuple[torch.Tensor,torch.Tensor]:
""" 輸出壓縮后的動(dòng)作及其對(duì)數(shù)概率。"""
x=F.relu(self.layer1(state))
x=F.relu(self.layer2(x))
mean=self.mean_layer(x)
log_std=self.log_std_layer(x)
log_std=torch.clamp(log_std,LOG_STD_MIN,LOG_STD_MAX)# 為穩(wěn)定性而夾緊
std=torch.exp(log_std)
# 創(chuàng)建分布并使用重參數(shù)化技巧采樣
normal_dist=Normal(mean,std)
z=normal_dist.rsample()# 可微分樣本(壓縮前)
action_squashed=torch.tanh(z)# 應(yīng)用tanh壓縮
# 計(jì)算log_prob并修正tanh
# log_prob = log_normal(z) - log(1 - tanh(z)^2 + eps)
log_prob=normal_dist.log_prob(z)-torch.log(1-action_squashed.pow(2)+EPSILON)
# 在動(dòng)作維度上對(duì)log_prob求和(如果action_dim > 1)
log_prob=log_prob.sum(dim=-1,keepdim=True)
# 將動(dòng)作縮放至環(huán)境邊界
action_scaled=action_squashed*self.max_action
returnaction_scaled,log_prob
評(píng)論家網(wǎng)絡(luò)采用類似于TD3的雙Q網(wǎng)絡(luò)架構(gòu),將狀態(tài)和動(dòng)作作為輸入:
# SAC的評(píng)論家網(wǎng)絡(luò)(雙Q)
classCriticNetworkSAC(nn.Module):
def__init__(self,state_dim:int,action_dim:int):
super(CriticNetworkSAC,self).__init__()
# Q1架構(gòu)
self.l1_q1=nn.Linear(state_dim+action_dim,256)
self.l2_q1=nn.Linear(256,256)
self.l3_q1=nn.Linear(256,1)
# Q2架構(gòu)
self.l1_q2=nn.Linear(state_dim+action_dim,256)
self.l2_q2=nn.Linear(256,256)
self.l3_q2=nn.Linear(256,1)
defforward(self,state:torch.Tensor,action:torch.Tensor)->Tuple[torch.Tensor,torch.Tensor]:
sa=torch.cat([state,action],1)
q1=F.relu(self.l1_q1(sa))
q1=F.relu(self.l2_q1(q1))
q1=self.l3_q1(q1)
q2=F.relu(self.l1_q2(sa))
q2=F.relu(self.l2_q2(q2))
q2=self.l3_q2(q2)
returnq1,q2
SAC的更新邏輯結(jié)合了演員、評(píng)論家和可選的alpha參數(shù)優(yōu)化。這些核心計(jì)算反映了SAC算法的關(guān)鍵特性,包括目標(biāo)Q值計(jì)算中的熵項(xiàng)、演員損失中的熵正則化,以及雙Q網(wǎng)絡(luò)和可選的alpha自動(dòng)調(diào)整機(jī)制。
獎(jiǎng)勵(lì)曲線:SAC展示出優(yōu)異的學(xué)習(xí)效率,累積獎(jiǎng)勵(lì)從初始約-1500迅速提升,并在大約40-50回合后穩(wěn)定在約-200水平。收斂后的性能表現(xiàn)相對(duì)穩(wěn)定,波動(dòng)較小。
評(píng)論家學(xué)習(xí):平均評(píng)論家損失在初期顯著上升,隨后在一定波動(dòng)范圍內(nèi)趨于穩(wěn)定,類似于DDPG的模式,反映了隨著演員策略改進(jìn),評(píng)論家需要不斷適應(yīng)更高價(jià)值的狀態(tài)-動(dòng)作評(píng)估。
演員學(xué)習(xí):演員損失曲線呈現(xiàn)先增后減的趨勢,初期快速上升(表明策略成功更新朝向更高Q值方向),在約40回合達(dá)到峰值,之后逐漸下降,這可能反映了策略穩(wěn)定性提高和熵正則化效應(yīng)的平衡。
熵溫度調(diào)節(jié):熵溫度參數(shù)(Alpha)展示了動(dòng)態(tài)調(diào)整過程,初期減小,在主要學(xué)習(xí)階段(20-55回合)顯著增加,隨后再次降低,這與策略從初始探索逐漸轉(zhuǎn)向利用階段的預(yù)期行為一致。Alpha損失在零附近的波動(dòng)確認(rèn)了自動(dòng)調(diào)整機(jī)制的有效運(yùn)行,成功維持了目標(biāo)熵水平。
SAC算法成功解決了鐘擺控制任務(wù),展現(xiàn)出較快的收斂速度和穩(wěn)定的高獎(jiǎng)勵(lì)水平。熵溫度參數(shù)(alpha)的自動(dòng)調(diào)整機(jī)制在訓(xùn)練全過程中有效平衡了探索與利用的關(guān)系,促進(jìn)了高效且穩(wěn)健的學(xué)習(xí)過程。
12、TRPO (約束策略更新)
信任區(qū)域策略優(yōu)化(TRPO)是一種創(chuàng)新的策略梯度算法,其核心目標(biāo)是實(shí)現(xiàn)單調(diào)策略改進(jìn),通過約束機(jī)制確保(以高概率)每次策略更新不會(huì)導(dǎo)致性能下降。
該算法通過限制單次更新中策略變化幅度來實(shí)現(xiàn)學(xué)習(xí)穩(wěn)定性,具體使用新舊策略間的KL散度作為變化度量標(biāo)準(zhǔn)。
TRPO屬于在策略演員-評(píng)論家類算法(盡管評(píng)論家主要用于優(yōu)勢估計(jì),不在核心TRPO約束更新機(jī)制內(nèi))。
算法的主要技術(shù)挑戰(zhàn)在于如何高效求解其所涉及的約束優(yōu)化問題。
與其他在策略方法類似,TRPO使用當(dāng)前策略(πold)收集經(jīng)驗(yàn)批次并計(jì)算優(yōu)勢值(A)。隨后計(jì)算標(biāo)準(zhǔn)策略梯度向量('g')。
TRPO的核心創(chuàng)新在于其更新步驟的計(jì)算方法。它不是簡單地沿策略梯度'g'方向更新,而是求解一個(gè)約束優(yōu)化問題:在保持新舊策略間KL散度低于閾值(δ)的前提下,最大化策略性能改進(jìn)。
這一優(yōu)化問題通過尋找滿足Fs≈g的步驟方向's'來近似求解,其中F是Fisher信息矩陣(用于近似KL約束的曲率)。
TRPO采用共軛梯度(CG)算法高效計(jì)算's',無需顯式構(gòu)建或求逆Fisher矩陣F。CG算法只需計(jì)算Fisher-向量積(FVP)。
確定更新方向后,通過回溯線搜索確定最大可行步長(α),使得更新滿足實(shí)際KL約束和替代目標(biāo)改進(jìn)條件。
TRPO的關(guān)鍵技術(shù)要素包括:
信任區(qū)域約束:將策略更新限制在性能改進(jìn)近似有效的區(qū)域內(nèi),確保學(xué)習(xí)過程的穩(wěn)定性。
KL散度約束:使用平均Kullback-Leibler散度DKL(πold∣∣πnew)≤δ _DKL_ (_πold_ ∣∣ _πnew_ )≤ _δ_作為策略變化的度量標(biāo)準(zhǔn)。
Fisher信息矩陣(FIM):表征策略分布空間的局部曲率特性。TRPO通過涉及FIM的二次形式來近似KL約束。
Fisher-向量積(FVP):一種利用自動(dòng)微分高效計(jì)算FIM與任意向量乘積的技術(shù),避免了構(gòu)建和存儲(chǔ)完整FIM的計(jì)算開銷。
共軛梯度(CG)算法:一種迭代求解線性系統(tǒng)Fs≈g的方法,用于高效計(jì)算更新方向。
線搜索機(jī)制:確保最終采用的更新步長滿足KL約束,并根據(jù)替代目標(biāo)函數(shù)改進(jìn)性能。
TRPO需要定義演員(策略網(wǎng)絡(luò))和評(píng)論家(價(jià)值網(wǎng)絡(luò)),結(jié)構(gòu)與A2C/PPO等算法類似。
實(shí)現(xiàn)的復(fù)雜部分主要在于FVP計(jì)算、CG算法和線搜索機(jī)制。以下是概念性實(shí)現(xiàn)概述(詳細(xì)完整實(shí)現(xiàn)請(qǐng)參考12_trpo.ipynb或a3c_training.py):
# 使用Hessian-向量積近似計(jì)算Fisher向量積
# 這用于共軛梯度方法,計(jì)算TRPO更新步驟中的搜索方向
deffisher_vector_product(actor,states,vector,cg_damping):
log_probs=actor.get_log_probs(states).detach()
kl=(log_probs.exp()*(log_probs-log_probs.detach())).sum()
grads=torch.autograd.grad(kl,actor.parameters(),create_graph=True)
flat_grads=torch.cat([g.view(-1)forgingrads])
gv=torch.dot(flat_grads,vector)
hv=torch.autograd.grad(gv,actor.parameters())
flat_hv=torch.cat([h.view(-1)forhinhv])
# 添加阻尼項(xiàng)以提高數(shù)值穩(wěn)定性
returnflat_hv+cg_damping*vector
# 實(shí)現(xiàn)共軛梯度方法解Ax = b
# 這用于近似TRPO更新步驟中的自然梯度方向
defconjugate_gradient(fvp_func,b,cg_iters=10,tol=1e-10):
x=torch.zeros_like(b) # 初始化解向量
r=b.clone() # 殘差
p=b.clone() # 搜索方向
rs_old=torch.dot(r,r)
for_inrange(cg_iters):
Ap=fvp_func(p)
alpha=rs_old/torch.dot(p,Ap)
x+=alpha*p
r-=alpha*Ap
rs_new=torch.dot(r,r)
ifrs_new<tol:
break
p=r+(rs_new/rs_old)*p
rs_old=rs_new
returnx
# 執(zhí)行回溯線搜索以找到可接受的步長
# 確保滿足KL散度約束
# 且新策略改進(jìn)了替代損失
defbacktracking_line_search(actor,states,actions,advantages,old_log_probs,
step_direction,initial_step_size,max_kl,decay=0.8,max_iters=10):
theta_old={name:param.clone()forname,paraminactor.named_parameters()} # 存儲(chǔ)舊參數(shù)
foriinrange(max_iters):
step_size=initial_step_size*(decay**i) # 漸進(jìn)減小步長
# 將步驟應(yīng)用于演員參數(shù)
forparam,stepinzip(actor.parameters(),step_size*step_direction):
param.data.add_(step)
# 計(jì)算KL散度和替代損失
kl=actor.kl_divergence(states,old_log_probs)
surrogate=actor.surrogate_loss(states,actions,advantages,old_log_probs)
# 檢查KL是否在約束內(nèi)且替代損失是否有改善
ifkl<=max_klandsurrogate>=0:
returnstep_size*step_direction,True
# 如果步驟不成功,恢復(fù)舊參數(shù)
forname,paraminactor.named_parameters():
param.data.copy_(theta_old[name])
returnNone,False # 如果找不到有效步驟,返回失敗
# 使用TRPO算法更新演員(策略)和評(píng)論家(價(jià)值函數(shù))
defupdate_trpo(actor,critic,actor_optimizer,critic_optimizer,
states,actions,advantages,returns_to_go,log_probs_old,
max_kl=0.01,cg_iters=10,cg_damping=0.1,line_search_decay=0.8,
value_loss_coeff=0.5,entropy_coeff=0.01):
# 計(jì)算策略梯度
policy_loss=actor.surrogate_loss(states,actions,advantages,log_probs_old)
grads=torch.autograd.grad(policy_loss,actor.parameters())
g=torch.cat([grad.view(-1)forgradingrads])
# 使用共軛梯度計(jì)算自然梯度方向
fvp_func=lambdav:fisher_vector_product(actor,states,v,cg_damping)
step_direction=conjugate_gradient(fvp_func,g,cg_iters)
# 基于KL約束計(jì)算步長
sAs=torch.dot(step_direction,fvp_func(step_direction))
step_size=torch.sqrt(2*max_kl/(sAs+1e-8))
# 執(zhí)行回溯線搜索以確保滿足KL約束
step,success=backtracking_line_search(actor,states,actions,advantages,log_probs_old,
step_direction,step_size,max_kl,line_search_decay)
# 如果成功,應(yīng)用步驟
ifsuccess:
withtorch.no_grad():
forparam,step_valinzip(actor.parameters(),step):
param.data.add_(step_val)
# 計(jì)算并更新價(jià)值函數(shù),使用MSE損失
value_loss=nn.MSELoss()(critic(states),returns_to_go)
critic_optimizer.zero_grad()
value_loss.backward()
critic_optimizer.step()
returnpolicy_loss.item(),value_loss.item() # 返回?fù)p失值,用于監(jiān)控
TRPO通過利用Fisher信息矩陣(FIM)提供的二階優(yōu)化信息顯式約束策略更新幅度,采用共軛梯度和Fisher-向量積技術(shù)高效實(shí)現(xiàn)計(jì)算,并通過線搜索確保每次更新的有效性。
學(xué)習(xí)效率與性能:TRPO展示出極高的樣本效率;平均獎(jiǎng)勵(lì)在僅約20-30次迭代內(nèi)迅速攀升至接近最優(yōu)水平,并保持穩(wěn)定。平均回合長度同樣呈現(xiàn)快速下降趨勢,迅速穩(wěn)定在較低水平。
評(píng)論家學(xué)習(xí)穩(wěn)定性:評(píng)論家損失在初期波動(dòng)后相對(duì)迅速地趨于穩(wěn)定,表明價(jià)值函數(shù)學(xué)習(xí)過程高效且一致。
策略更新約束(KL散度):"實(shí)際KL散度"圖顯示每次迭代的策略變化量。TRPO設(shè)計(jì)目標(biāo)是將這一變化量維持在較小范圍內(nèi)(低于紅線所示Max KL閾值,通常約0.01)以確保更新穩(wěn)定性。圖中顯示的值呈現(xiàn)異常(部分為負(fù)值,理論上KL散度不應(yīng)為負(fù)),但算法的設(shè)計(jì)意圖是實(shí)現(xiàn)穩(wěn)定、約束的更新。
優(yōu)化目標(biāo)進(jìn)展:"替代目標(biāo)"圖顯示TRPO在采取更新步驟前計(jì)算的預(yù)期性能改進(jìn)。曲線在零附近的波動(dòng)表明逐步改進(jìn)保證并非總是完美滿足,但整體算法表現(xiàn)出色。
TRPO算法在網(wǎng)格任務(wù)上展示出卓越的樣本效率,迅速收斂至高性能且穩(wěn)定的策略。盡管內(nèi)部優(yōu)化指標(biāo)(KL散度,替代目標(biāo))數(shù)據(jù)存在一定噪聲或異常,但信任區(qū)域方法成功地引導(dǎo)學(xué)習(xí)過程快速達(dá)到有效解決方案。
13、DQN (深度Q學(xué)習(xí))
Q-Learning算法在狀態(tài)空間較小且結(jié)構(gòu)清晰的環(huán)境中表現(xiàn)出色。然而,當(dāng)面臨非常大或連續(xù)的狀態(tài)空間(例如處理游戲像素?cái)?shù)據(jù)或機(jī)器人傳感器輸入)時(shí),傳統(tǒng)Q-Learning方法的有效性會(huì)顯著降低。
深度Q網(wǎng)絡(luò)(DQN)通過引入深度神經(jīng)網(wǎng)絡(luò)替代傳統(tǒng)的Q表格,有效解決了這一問題。該網(wǎng)絡(luò)參數(shù)化為Q(s,a;θ),能夠?qū)值進(jìn)行高效近似。
DQN引入了兩項(xiàng)關(guān)鍵技術(shù)創(chuàng)新,用于穩(wěn)定神經(jīng)網(wǎng)絡(luò)環(huán)境下的Q學(xué)習(xí)過程:經(jīng)驗(yàn)回放(Experience Replay)和目標(biāo)網(wǎng)絡(luò)(Target Network)。
DQN的工作流程如下:
智能體基于主Q網(wǎng)絡(luò)(Q_θ)采用epsilon-greedy策略與環(huán)境進(jìn)行交互。每一個(gè)經(jīng)驗(yàn)轉(zhuǎn)換元組(s, a, r, s', done)被系統(tǒng)地存儲(chǔ)在回放緩沖區(qū)(Replay Buffer)中。
在訓(xùn)練階段,智能體從緩沖區(qū)中隨機(jī)采樣一個(gè)小批量(mini-batch)的歷史經(jīng)驗(yàn)。對(duì)于批次中的每個(gè)經(jīng)驗(yàn)樣本,系統(tǒng)計(jì)算目標(biāo)Q值(即TD目標(biāo)y),這一計(jì)算基于觀察到的即時(shí)獎(jiǎng)勵(lì)r以及從后續(xù)狀態(tài)s'可獲得的最大Q值。后者通過一個(gè)參數(shù)更新頻率較低的目標(biāo)網(wǎng)絡(luò)(Q_θ?)進(jìn)行估計(jì)。
主Q網(wǎng)絡(luò)負(fù)責(zé)預(yù)測在狀態(tài)s下執(zhí)行動(dòng)作a的Q值。系統(tǒng)計(jì)算目標(biāo)值y與預(yù)測Q值之間的誤差(使用均方誤差MSE或Huber損失函數(shù)),并通過梯度下降優(yōu)化算法更新主Q網(wǎng)絡(luò)的參數(shù)(θ)。
系統(tǒng)定期將主網(wǎng)絡(luò)的權(quán)重參數(shù)復(fù)制到目標(biāo)網(wǎng)絡(luò)中:θ? ← θ。
DQN的核心技術(shù)要素包括:
一個(gè)神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)(如多層感知機(jī)MLP或卷積神經(jīng)網(wǎng)絡(luò)CNN),用于近似Q(s, a)函數(shù)。該網(wǎng)絡(luò)通常接收狀態(tài)s作為輸入,輸出所有可能離散動(dòng)作的Q值。
一個(gè)用于存儲(chǔ)歷史交互數(shù)據(jù)(s, a, r, s', done)的經(jīng)驗(yàn)緩沖區(qū)。通過采樣隨機(jī)小批量數(shù)據(jù),有效打破了時(shí)序相關(guān)性,提高了學(xué)習(xí)過程的穩(wěn)定性和效率。
Q網(wǎng)絡(luò)的獨(dú)立副本,其參數(shù)(θ?)更新頻率較低(例如,每C步更新一次或通過慢速"軟"更新機(jī)制)。這為學(xué)習(xí)過程提供了穩(wěn)定的目標(biāo)值:
該方程為主Q網(wǎng)絡(luò)訓(xùn)練提供了穩(wěn)定的學(xué)習(xí)目標(biāo),有效防止了參數(shù)震蕩。
首先,定義Q網(wǎng)絡(luò)架構(gòu)。對(duì)于簡單的向量化狀態(tài)表示(例如網(wǎng)格世界中的歸一化坐標(biāo)),多層感知機(jī)(MLP)結(jié)構(gòu)通常已足夠:
# DQN網(wǎng)絡(luò)(MLP)
classDQN(nn.Module):
def__init__(self,n_observations:int,n_actions:int):
super(DQN,self).__init__()
self.layer1=nn.Linear(n_observations,128)
self.layer2=nn.Linear(128,128)
self.layer3=nn.Linear(128,n_actions)# 輸出每個(gè)動(dòng)作的Q值
defforward(self,x:torch.Tensor)->torch.Tensor:
""" 前向傳遞獲取Q值。"""
# 確保輸入是正確設(shè)備上的浮點(diǎn)張量
ifnotisinstance(x,torch.Tensor):
x=torch.tensor(x,dtype=torch.float32,device=x.device)
elifx.dtype!=torch.float32:
x=x.to(dtype=torch.float32)
x=F.relu(self.layer1(x))
x=F.relu(self.layer2(x))
returnself.layer3(x)# 原始Q值
該網(wǎng)絡(luò)結(jié)構(gòu)學(xué)習(xí)從環(huán)境狀態(tài)到動(dòng)作價(jià)值的映射關(guān)系。
接下來,實(shí)現(xiàn)經(jīng)驗(yàn)回放機(jī)制以存儲(chǔ)交互經(jīng)驗(yàn):
# 用于存儲(chǔ)轉(zhuǎn)換的結(jié)構(gòu)
Transition=namedtuple('Transition',
('state','action','next_state','reward','done'))
# 經(jīng)驗(yàn)回放緩沖區(qū)
classReplayMemory:
def__init__(self,capacity:int):
self.memory=deque([],maxlen=capacity)
defpush(self,*args:Any)->None:
""" 保存一個(gè)轉(zhuǎn)換元組(s, a, s', r, done)。"""
# 確保張量存儲(chǔ)在CPU上,避免GPU內(nèi)存問題
processed_args=[]
forarginargs:
ifisinstance(arg,torch.Tensor):
processed_args.append(arg.cpu())
elifisinstance(arg,bool):# 將done標(biāo)志作為張量存儲(chǔ)以保持一致性
processed_args.append(torch.tensor([arg],dtype=torch.bool))
else:
processed_args.append(arg)
self.memory.append(Transition(*processed_args))
?
? defsample(self,batch_size:int)->Optional[List[Transition]]:
? """ 采樣一個(gè)隨機(jī)轉(zhuǎn)換批次。"""
? iflen(self.memory)<batch_size:
? returnNone
? returnrandom.sample(self.memory,batch_size)
?
def__len__(self)->int:
returnlen(self.memory)
此緩沖區(qū)設(shè)計(jì)允許從歷史經(jīng)驗(yàn)中采樣不相關(guān)的批次數(shù)據(jù)進(jìn)行訓(xùn)練更新。動(dòng)作選擇基于主Q網(wǎng)絡(luò)的輸出,采用epsilon-greedy策略:
# 動(dòng)作選擇(使用DQN的Epsilon-Greedy)
defselect_action_dqn(state:torch.Tensor,
policy_net:nn.Module,
epsilon:float,
n_actions:int,
device:torch.device)->torch.Tensor:
""" 使用策略Q網(wǎng)絡(luò)以epsilon-greedy方式選擇動(dòng)作。"""
ifrandom.random()<epsilon:
# 探索:選擇一個(gè)隨機(jī)動(dòng)作
action=torch.tensor([[random.randrange(n_actions)]],device=device,dtype=torch.long)
else:
# 利用:根據(jù)Q網(wǎng)絡(luò)選擇最佳動(dòng)作
withtorch.no_grad():
# 如果需要,添加批次維度,確保張量在正確設(shè)備上
state=state.unsqueeze(0)ifstate.dim()==1elsestate
state=state.to(device)
# 獲取Q值并選擇具有最大Q的動(dòng)作
action=policy_net(state).max(1)[1].view(1,1)
returnaction
優(yōu)化過程使用目標(biāo)網(wǎng)絡(luò)計(jì)算TD目標(biāo),并更新主策略網(wǎng)絡(luò)參數(shù):
# DQN優(yōu)化步驟概述
defoptimize_model_dqn(memory:ReplayMemory,
policy_net:DQN,
target_net:DQN,
optimizer:optim.Optimizer,
batch_size:int,
gamma:float,
device:torch.device):
""" 對(duì)DQN策略網(wǎng)絡(luò)執(zhí)行一步優(yōu)化。"""
# 1. 從內(nèi)存中采樣批次
# 2. 準(zhǔn)備批次張量(states, actions, rewards, next_states, dones)在'device'上
# 3. 使用policy_net計(jì)算所采取動(dòng)作的Q(s_t, a_t)
state_action_values=policy_net(state_batch).gather(1,action_batch)
# 4. 使用target_net計(jì)算V(s_{t+1}) = max_{a'} Q(s_{t+1}, a'; θ?)
withtorch.no_grad():next_state_values=target_net(non_final_next_states).max(1)[0]
# 5. 計(jì)算TD目標(biāo)y = reward + gamma * V(s_{t+1}) (處理終止?fàn)顟B(tài))
expected_state_action_values=(next_state_values*gamma)+reward_batch
# 6. 計(jì)算Q(s_t, a_t)和TD目標(biāo)y之間的損失(例如,Huber損失)
loss=F.smooth_l1_loss(state_action_values,expected_state_action_values.unsqueeze(1))
# 7. 優(yōu)化policy_net
optimizer.zero_grad()
loss.backward()
torch.nn.utils.clip_grad_value_(policy_net.parameters(),100)# 可選梯度裁剪
optimizer.step()
# 完整實(shí)現(xiàn)見13_dqn.ipynb
這一核心訓(xùn)練循環(huán),結(jié)合目標(biāo)網(wǎng)絡(luò)的定期更新機(jī)制,使DQN能夠在使用復(fù)雜函數(shù)近似器(如神經(jīng)網(wǎng)絡(luò))的情況下實(shí)現(xiàn)有效學(xué)習(xí)。
DQN實(shí)驗(yàn)結(jié)果分析:
學(xué)習(xí)進(jìn)展:DQN展示了明顯的學(xué)習(xí)效果。平均獎(jiǎng)勵(lì)值從初始的負(fù)值顯著增長,在大約200-250回合后趨于穩(wěn)定,達(dá)到持續(xù)性的正向獎(jiǎng)勵(lì)水平。
訓(xùn)練效率:回合長度隨訓(xùn)練進(jìn)程顯著減少,與獎(jiǎng)勵(lì)增長趨勢相一致,表明智能體逐步掌握了更高效地到達(dá)目標(biāo)的能力。
探索機(jī)制:epsilon衰減曲線顯示了探索行為的逐步減少過程,使智能體能夠在后期訓(xùn)練階段更有效地利用已習(xí)得的知識(shí)。
策略學(xué)習(xí)效果:最終學(xué)習(xí)得到的策略網(wǎng)格展示了一個(gè)結(jié)構(gòu)合理的決策方案,動(dòng)作選擇通常引導(dǎo)智能體朝向目標(biāo)狀態(tài)'G'(位于網(wǎng)格右下角)。
DQN在自定義網(wǎng)格環(huán)境中成功學(xué)習(xí)了高效的導(dǎo)航策略,能夠找到通向目標(biāo)的最優(yōu)路徑。隨著探索概率的逐步降低,性能指標(biāo)(包括累積獎(jiǎng)勵(lì)和回合長度)顯著改善并趨于穩(wěn)定。
14、MADDPG (多智能體深度確定性策略梯度)
在多智能體學(xué)習(xí)環(huán)境中,當(dāng)多個(gè)智能體同時(shí)進(jìn)行學(xué)習(xí)時(shí),會(huì)出現(xiàn)一個(gè)獨(dú)特的技術(shù)挑戰(zhàn):環(huán)境非平穩(wěn)性(Non-stationarity)。
從任何單個(gè)智能體的視角來看,隨著其他智能體不斷更新各自的策略,環(huán)境本身也在持續(xù)變化。多智能體深度確定性策略梯度(MADDPG)算法通過集中式訓(xùn)練、分散式執(zhí)行(Centralized Training with Decentralized Execution)架構(gòu)擴(kuò)展了DDPG算法,有效解決了這一問題。
每個(gè)智能體基于其局部觀察學(xué)習(xí)獨(dú)立的Actor網(wǎng)絡(luò),但訓(xùn)練過程中每個(gè)智能體都擁有一個(gè)集中式Critic網(wǎng)絡(luò),該網(wǎng)絡(luò)接收來自所有智能體的信息(包括觀察和動(dòng)作)。
這種訓(xùn)練階段的信息共享機(jī)制有助于穩(wěn)定整個(gè)學(xué)習(xí)過程。
MADDPG工作流程:
每個(gè)智能體(1, 2, ...N)僅使用自身局部觀察(o1, o2)和對(duì)應(yīng)的Actor網(wǎng)絡(luò)(μ_θ1,μ_θ2)在環(huán)境中生成動(dòng)作(a1, a2),并添加噪聲以促進(jìn)探索。系統(tǒng)將聯(lián)合經(jīng)驗(yàn)(包含所有觀察、動(dòng)作、獎(jiǎng)勵(lì)、后續(xù)觀察)存儲(chǔ)在共享回放緩沖區(qū)中。
Critic更新(智能體i):智能體i的Critic網(wǎng)絡(luò)(Q_?i)基于目標(biāo)值進(jìn)行參數(shù)更新。該目標(biāo)值計(jì)算依賴于:智能體i的即時(shí)獎(jiǎng)勵(lì)(r_i);目標(biāo)集中式Critic(Q_?i′)的輸出,該Critic接收以下輸入:聯(lián)合后續(xù)觀察狀態(tài)以及所有目標(biāo)Actor網(wǎng)絡(luò)(μ_θj′(o_j′))預(yù)測的后續(xù)動(dòng)作
智能體i的Actor網(wǎng)絡(luò)(μ_θi)參數(shù)更新目標(biāo)是生成能夠最大化其主集中式Critic(Q_?i)估計(jì)的Q值的動(dòng)作,同時(shí)考慮所有Actor網(wǎng)絡(luò)當(dāng)前預(yù)測的動(dòng)作分布。
所有目標(biāo)網(wǎng)絡(luò)通過從對(duì)應(yīng)主網(wǎng)絡(luò)進(jìn)行緩慢的軟更新來更新參數(shù)。
MADDPG的核心技術(shù)概念包括:
分散式Actor架構(gòu):每個(gè)智能體i擁有獨(dú)立的策略網(wǎng)絡(luò)μ_i(o_i),該網(wǎng)絡(luò)僅使用智能體局部觀察o_i來選擇動(dòng)作a_i。
集中式Critic架構(gòu):每個(gè)智能體i配備對(duì)應(yīng)的Critic網(wǎng)絡(luò)Q_i(x, a_1, ..., a_N),該網(wǎng)絡(luò)以聯(lián)合狀態(tài)/觀察x和所有智能體的動(dòng)作(a_1, ..., a_N)作為輸入,用于估計(jì)智能體i的價(jià)值函數(shù)。
離策略學(xué)習(xí):算法使用存儲(chǔ)聯(lián)合交互數(shù)據(jù)的回放緩沖區(qū),支持從歷史經(jīng)驗(yàn)中進(jìn)行高效學(xué)習(xí)。
每個(gè)智能體的Actor網(wǎng)絡(luò)設(shè)計(jì)通常類似于DDPG中的actor結(jié)構(gòu),輸出確定性動(dòng)作(如需處理離散動(dòng)作空間,則可調(diào)整為輸出動(dòng)作概率分布):
# Actor網(wǎng)絡(luò)(類似于DDPG的,每個(gè)智能體一個(gè))
classActorNetworkMADDPG(nn.Module):
def__init__(self,obs_dim:int,action_dim:int,max_action:float):
super(ActorNetworkMADDPG,self).__init__()
self.layer1=nn.Linear(obs_dim,128)
self.layer2=nn.Linear(128,128)
self.layer3=nn.Linear(128,action_dim)
self.max_action=max_action
defforward(self,obs:torch.Tensor)->torch.Tensor:
x=F.relu(self.layer1(obs))
x=F.relu(self.layer2(x))
action=self.max_action*torch.tanh(self.layer3(x))# 縮放的連續(xù)動(dòng)作
returnaction
MADDPG與DDPG的關(guān)鍵區(qū)別在于集中式Critic設(shè)計(jì),該Critic將全局信息作為輸入:
# 集中式Critic網(wǎng)絡(luò)(每個(gè)智能體一個(gè))
classCentralizedCriticMADDPG(nn.Module):
def__init__(self,joint_obs_dim:int,joint_action_dim:int):
super(CentralizedCriticMADDPG,self).__init__()
# 輸入大小 = 所有觀察的組合維度 + 所有動(dòng)作
self.layer1=nn.Linear(joint_obs_dim+joint_action_dim,256)
self.layer2=nn.Linear(256,256)
self.layer3=nn.Linear(256,1)# 輸出該智能體的單一Q值
defforward(self,joint_obs:torch.Tensor,joint_actions:torch.Tensor)->torch.Tensor:
# 連接所有觀察和所有動(dòng)作
x=torch.cat([joint_obs,joint_actions],dim=1)
x=F.relu(self.layer1(x))
x=F.relu(self.layer2(x))
q_value=self.layer3(x)
returnq_value
該Critic網(wǎng)絡(luò)設(shè)計(jì)用于學(xué)習(xí)特定智能體的期望回報(bào),同時(shí)考慮環(huán)境中所有智能體的觀察和行為。
回放緩沖區(qū)需要存儲(chǔ)完整的聯(lián)合經(jīng)驗(yàn)數(shù)據(jù)(o_list, a_list, r_list, o_next_list, done_list):
# --- MADDPG更新邏輯概述(對(duì)于智能體i) ---
# 假設(shè)已處理優(yōu)化器、目標(biāo)網(wǎng)絡(luò)、批次采樣
# 1. 從緩沖區(qū)中采樣聯(lián)合轉(zhuǎn)換批次:
batch_obs, batch_actions, batch_rewards, batch_next_obs, batch_dones
# --- Critic_i更新 ---
with torch.no_grad():
target_next_actions = [target_actor_j(batch_next_obs_j) for j in range(num_agents)]
target_next_actions_cat = torch.cat(target_next_actions, dim=1)
joint_next_obs_cat = batch_next_obs.view(batch_size, -1)
q_target_next = target_critic_i(joint_next_obs_cat, target_next_actions_cat)
td_target_i = batch_rewards_i + gamma * (1 - batch_dones_i) * q_target_next
joint_obs_cat = batch_obs.view(batch_size, -1)
joint_actions_cat = batch_actions.view(batch_size, -1)
q_current_i = critic_i(joint_obs_cat, joint_actions_cat)
critic_loss_i = F.mse_loss(q_current_i, td_target_i.detach())
# 優(yōu)化critic_i
# --- Actor_i更新 ---
# 凍結(jié)critic梯度
current_actions = [actor_j(batch_obs_j) for j in range(num_agents)]
current_actions[i] = actor_i(batch_obs_i)
current_actions_cat = torch.cat(current_actions, dim=1)
actor_loss_i = -critic_i(joint_obs_cat, current_actions_cat).mean()
# 優(yōu)化actor_i
# 解凍critic梯度
# --- 軟更新目標(biāo)網(wǎng)絡(luò) ---
soft_update(target_critic_i, critic_i, tau)
soft_update(target_actor_i, actor_i, tau)
更新算法涉及上述組件的協(xié)同工作。通過在訓(xùn)練階段使用集中式Critic架構(gòu),MADDPG為每個(gè)Actor提供了一個(gè)能夠考慮其他智能體行為的穩(wěn)定學(xué)習(xí)信號(hào),有效緩解了非平穩(wěn)性問題,同時(shí)保持了分散式執(zhí)行的靈活性。
MADDPG實(shí)驗(yàn)結(jié)果分析:
獎(jiǎng)勵(lì)表現(xiàn)(共享):每回合總共享獎(jiǎng)勵(lì)呈現(xiàn)顯著波動(dòng),其移動(dòng)平均線僅顯示微弱的上升趨勢,最終在一個(gè)相對(duì)較低的水平(約-50)趨于平穩(wěn)。這表明智能體在學(xué)習(xí)過程中取得一定進(jìn)展,但在200回合的訓(xùn)練周期內(nèi)未能收斂至高效的合作策略。
Critic網(wǎng)絡(luò)表現(xiàn):平均Critic損失值快速下降并穩(wěn)定在較低水平,表明Critic網(wǎng)絡(luò)在預(yù)測當(dāng)前智能體策略組合下的價(jià)值函數(shù)方面逐漸變得準(zhǔn)確。
Actor網(wǎng)絡(luò)表現(xiàn):平均Actor損失(策略梯度)持續(xù)減小(朝負(fù)方向增大),表明Actor網(wǎng)絡(luò)從對(duì)應(yīng)Critic接收到一致的優(yōu)化信號(hào),策略更新方向符合預(yù)期。
MADDPG算法展示出明確的學(xué)習(xí)跡象,Critic和Actor損失均呈現(xiàn)一致的優(yōu)化趨勢。
然而,實(shí)際共享獎(jiǎng)勵(lì)的改善幅度有限且波動(dòng)較大,未能展示強(qiáng)烈的收斂特征。
這種表現(xiàn)差異可能反映了多智能體協(xié)調(diào)學(xué)習(xí)的固有挑戰(zhàn)、環(huán)境非平穩(wěn)性的影響,或者表明需要更長的訓(xùn)練周期才能形成有效的協(xié)作策略。
15、QMIX (協(xié)作型價(jià)值分解方法)
QMIX(Q值混合)算法專為具有共享團(tuán)隊(duì)獎(jiǎng)勵(lì)的協(xié)作型多智能體強(qiáng)化學(xué)習(xí)任務(wù)設(shè)計(jì)。與MADDPG類似,它采用集中訓(xùn)練、分散執(zhí)行的架構(gòu)范式。
然而,QMIX的核心差異在于:它不是為每個(gè)智能體學(xué)習(xí)獨(dú)立的集中式Critic,而是學(xué)習(xí)基于局部觀察的個(gè)體智能體Q函數(shù)(Q_i),并通過一個(gè)特殊設(shè)計(jì)的混合網(wǎng)絡(luò)(Mixing Network)將它們組合,以估計(jì)聯(lián)合行動(dòng)價(jià)值函數(shù)(Q_tot)。
算法的關(guān)鍵技術(shù)洞見是:對(duì)于許多協(xié)作任務(wù),如果一個(gè)智能體的行為增加了其局部效用(Q_i),那么這一行為也應(yīng)該增加(或至少不減少)整個(gè)團(tuán)隊(duì)的整體效用(Q_tot)。QMIX通過在混合網(wǎng)絡(luò)內(nèi)部結(jié)構(gòu)中強(qiáng)制執(zhí)行單調(diào)性約束(Monotonicity Constraint)來實(shí)現(xiàn)這一特性。
這一設(shè)計(jì)確保了基于個(gè)體Q_i值的分散貪婪動(dòng)作選擇與基于Q_tot選擇的貪婪聯(lián)合動(dòng)作保持一致。
混合網(wǎng)絡(luò)本身通過超網(wǎng)絡(luò)(Hypernetworks)技術(shù)接收全局狀態(tài)信息,使個(gè)體效用組合方式能夠根據(jù)整體環(huán)境上下文動(dòng)態(tài)調(diào)整。
QMIX工作流程:
在執(zhí)行階段,每個(gè)智能體i基于其局部觀察o_i和對(duì)應(yīng)的網(wǎng)絡(luò)Q_i(θ_i)選擇動(dòng)作a_i(通常采用epsilon-greedy策略)。系統(tǒng)存儲(chǔ)包含全局狀態(tài)x在內(nèi)的完整聯(lián)合交互經(jīng)驗(yàn)。
目標(biāo)Q_tot'計(jì)算過程:
對(duì)于每個(gè)智能體i,目標(biāo)網(wǎng)絡(luò)Q_i'(θ_i')用于確定從后續(xù)觀察o_i'出發(fā)的最優(yōu)動(dòng)作對(duì)應(yīng)的Q值。
這些個(gè)體最大Q值被輸入到目標(biāo)混合網(wǎng)絡(luò)``f_mix'(?_mix')中,該網(wǎng)絡(luò)同時(shí)接收后續(xù)全局狀態(tài)x'作為輸入,綜合生成目標(biāo)聯(lián)合價(jià)值Q_tot'。
系統(tǒng)計(jì)算標(biāo)準(zhǔn)TD目標(biāo)y:y = r + γQ_tot'。
當(dāng)前Q_tot計(jì)算與損失計(jì)算:
對(duì)于每個(gè)智能體i,主網(wǎng)絡(luò)Q_i(θ_i)計(jì)算在當(dāng)前批次數(shù)據(jù)中實(shí)際執(zhí)行的動(dòng)作a_i對(duì)應(yīng)的Q值。
這些Q值與當(dāng)前全局狀態(tài)x一起輸入到主混合網(wǎng)絡(luò)``f_mix(?_mix)中,生成當(dāng)前聯(lián)合價(jià)值估計(jì)Q_tot。
系統(tǒng)計(jì)算y與Q_tot之間的均方誤差損失。
參數(shù)優(yōu)化過程:
一個(gè)統(tǒng)一的優(yōu)化器根據(jù)計(jì)算得到的損失函數(shù)值同時(shí)更新所有智能體網(wǎng)絡(luò)(θ_i)和混合網(wǎng)絡(luò)(?_mix)的參數(shù)。各目標(biāo)網(wǎng)絡(luò)通過軟更新機(jī)制定期更新參數(shù)。
首先,定義個(gè)體智能體網(wǎng)絡(luò)結(jié)構(gòu)。這是一個(gè)標(biāo)準(zhǔn)的Q網(wǎng)絡(luò)設(shè)計(jì),接收局部觀察數(shù)據(jù)并輸出每個(gè)可能動(dòng)作的Q值:
# 智能體網(wǎng)絡(luò)(類似于DQN的Q網(wǎng)絡(luò))
classAgentQNetwork(nn.Module):
def__init__(self,obs_dim:int,action_dim:int):
super(AgentQNetwork,self).__init__()
# 可以是MLP或RNN(DRQN),取決于可觀察性需求
self.fc1=nn.Linear(obs_dim,64)
self.fc2=nn.Linear(64,64)
self.fc3=nn.Linear(64,action_dim)# 每個(gè)動(dòng)作的Q值
defforward(self,obs:torch.Tensor)->torch.Tensor:
x=F.relu(self.fc1(obs))
x=F.relu(self.fc2(x))
q_values=self.fc3(x)
returnq_values
混合網(wǎng)絡(luò)設(shè)計(jì)是QMIX的創(chuàng)新核心,它利用超網(wǎng)絡(luò)技術(shù)實(shí)現(xiàn)單調(diào)性約束:
# 簡化的QMIX混合網(wǎng)絡(luò)
classQMixer(nn.Module):
def__init__(self,num_agents:int,global_state_dim:int,mixing_embed_dim:int=32):
super(QMixer,self).__init__()
self.num_agents=num_agents
self.state_dim=global_state_dim
self.embed_dim=mixing_embed_dim
# W1的超網(wǎng)絡(luò)(生成正權(quán)重)
self.hyper_w1=nn.Sequential(
nn.Linear(self.state_dim,64),nn.ReLU(),
nn.Linear(64,self.num_agents*self.embed_dim)
)
# b1的超網(wǎng)絡(luò)
self.hyper_b1=nn.Linear(self.state_dim,self.embed_dim)
# W2的超網(wǎng)絡(luò)(生成正權(quán)重)
self.hyper_w2=nn.Sequential(
nn.Linear(self.state_dim,64),nn.ReLU(),
nn.Linear(64,self.embed_dim)# 輸出大小embed_dim -> 重塑為(embed_dim, 1)
)
# b2的超網(wǎng)絡(luò)(標(biāo)量偏置)
self.hyper_b2=nn.Sequential(
nn.Linear(self.state_dim,32),nn.ReLU(),nn.Linear(32,1)
)
defforward(self,agent_qs:torch.Tensor,global_state:torch.Tensor)->torch.Tensor:
# agent_qs形狀:(batch_size, num_agents)
# global_state形狀:(batch_size, global_state_dim)
batch_size=agent_qs.size(0)
agent_qs_reshaped=agent_qs.view(batch_size,1,self.num_agents)
# 從全局狀態(tài)生成權(quán)重/偏置
w1=torch.abs(self.hyper_w1(global_state)).view(batch_size,self.num_agents,self.embed_dim)
b1=self.hyper_b1(global_state).view(batch_size,1,self.embed_dim)
w2=torch.abs(self.hyper_w2(global_state)).view(batch_size,self.embed_dim,1)
b2=self.hyper_b2(global_state).view(batch_size,1,1)
# 混合層(確保第一層后有非線性如ELU/ReLU)
hidden=F.elu(torch.bmm(agent_qs_reshaped,w1)+b1)# (batch, 1, embed_dim)
q_tot=torch.bmm(hidden,w2)+b2# (batch, 1, 1)
returnq_tot.view(batch_size,1)# 返回形狀(batch, 1)
更新邏輯包括獲取相關(guān)動(dòng)作的Q_i值,將它們傳入混合器,使用目標(biāo)網(wǎng)絡(luò)計(jì)算TD目標(biāo)值,并通過混合網(wǎng)絡(luò)和所有智能體網(wǎng)絡(luò)反向傳播損失梯度。
QMIX提供了一種結(jié)構(gòu)化方法來學(xué)習(xí)協(xié)作策略,通過分解團(tuán)隊(duì)價(jià)值函數(shù),同時(shí)確保個(gè)體行為貢獻(xiàn)通過單調(diào)性約束與全局目標(biāo)保持一致性。
QMIX實(shí)驗(yàn)結(jié)果分析:
獎(jiǎng)勵(lì)表現(xiàn)(共享):智能體展示了顯著的學(xué)習(xí)進(jìn)步。共享獎(jiǎng)勵(lì)曲線呈現(xiàn)明顯的上升趨勢,特別是在移動(dòng)平均線中表現(xiàn)突出,從初始的顯著負(fù)值增長至最終約-10至-20的水平。盡管性能有了實(shí)質(zhì)性改善,但獎(jiǎng)勵(lì)仍然存在波動(dòng)且未能穩(wěn)定達(dá)到正值區(qū)間。
TD損失:平均TD損失(注意采用對(duì)數(shù)刻度)在前約150回合內(nèi)急劇下降,幅度接近兩個(gè)數(shù)量級(jí),表明Q網(wǎng)絡(luò)和混合器架構(gòu)迅速學(xué)會(huì)了對(duì)聯(lián)合動(dòng)作價(jià)值進(jìn)行有效近似。隨后損失值在一個(gè)較低水平趨于穩(wěn)定,表明系統(tǒng)成功學(xué)習(xí)到了相對(duì)于當(dāng)前策略的準(zhǔn)確值函數(shù)表示。
探索行為:Epsilon參數(shù)在整個(gè)訓(xùn)練過程中保持穩(wěn)定但緩慢的衰減趨勢。這種設(shè)計(jì)確保了持續(xù)的環(huán)境探索能力,可能導(dǎo)致獎(jiǎng)勵(lì)指標(biāo)的持續(xù)性波動(dòng),但同時(shí)允許智能體有效逃離局部最優(yōu)解。
QMIX算法成功促進(jìn)了協(xié)作學(xué)習(xí)過程,導(dǎo)致共享獎(jiǎng)勵(lì)指標(biāo)的顯著改善。值函數(shù)學(xué)習(xí)(通過TD損失反映)表現(xiàn)出高效性并迅速達(dá)到穩(wěn)定狀態(tài)。盡管在訓(xùn)練后期獎(jiǎng)勵(lì)趨于平穩(wěn)但仍有波動(dòng),總體趨勢清晰展示了多智能體協(xié)作策略學(xué)習(xí)的成功進(jìn)展。
16、HAC:層次化結(jié)構(gòu)解決長時(shí)域任務(wù)
在長序列動(dòng)作任務(wù)或獎(jiǎng)勵(lì)稀疏的環(huán)境中,傳統(tǒng)扁平結(jié)構(gòu)的強(qiáng)化學(xué)習(xí)智能體通常面臨顯著的性能挑戰(zhàn)。
層次化強(qiáng)化學(xué)習(xí)(Hierarchical Reinforcement Learning, HRL)通過在多個(gè)抽象層次上構(gòu)建策略體系來解決這一問題。該方法使高層策略能夠?yàn)榈蛯釉O(shè)定子目標(biāo),從而將復(fù)雜任務(wù)分解為更易處理的子任務(wù)序列。層次化演員-評(píng)論家(Hierarchical Actor-Critic, HAC)算法正是基于這一原理,結(jié)合了目標(biāo)條件策略和后見之明經(jīng)驗(yàn)回放技術(shù)。
HAC (層次化演員-評(píng)論家)采用多層次結(jié)構(gòu):
高層(第1層):接收當(dāng)前狀態(tài)s和最終目標(biāo)G作為輸入,其策略 (π_1) 為低層生成子目標(biāo)g?。
低層(第0層):接收當(dāng)前狀態(tài)s和來自高層的子目標(biāo)g?,其策略 (π_0) 選擇原始動(dòng)作a,旨在在固定時(shí)間范圍H內(nèi)實(shí)現(xiàn)子目標(biāo)。低層根據(jù)子目標(biāo)完成情況獲得內(nèi)在獎(jiǎng)勵(lì),用于更新其策略參數(shù)。
高層更新機(jī)制:高層獲取低層執(zhí)行過程中累積的環(huán)境獎(jiǎng)勵(lì)總和,并基于狀態(tài)轉(zhuǎn)換(從設(shè)置子目標(biāo)的初始狀態(tài)到低層執(zhí)行完畢的最終狀態(tài))來優(yōu)化其策略。
兩個(gè)層級(jí)均可利用評(píng)論家網(wǎng)絡(luò) (V_0, V_1) 來估計(jì)狀態(tài)或狀態(tài)-目標(biāo)組合的價(jià)值或優(yōu)勢函數(shù)。后見之明經(jīng)驗(yàn)回放技術(shù)(使用實(shí)際達(dá)到的狀態(tài)重新標(biāo)記轉(zhuǎn)換樣本)對(duì)于提高學(xué)習(xí)效率至關(guān)重要,尤其是對(duì)低層策略的訓(xùn)練。
在實(shí)現(xiàn)方面,目標(biāo)條件網(wǎng)絡(luò)是HAC算法的核心組件。對(duì)于離散網(wǎng)格世界環(huán)境,我們可以基于DQN的Q網(wǎng)絡(luò)架構(gòu)進(jìn)行調(diào)整,輸入維度需擴(kuò)展為state_dim + goal_dim以同時(shí)接收狀態(tài)和目標(biāo)信息。
# 目標(biāo)條件Q網(wǎng)絡(luò) (可用于HAC中的Actor/Critic代理)
# 假設(shè)狀態(tài)和目標(biāo)作為輸入連接在一起
classGoalConditionedQNetwork(nn.Module):
def__init__(self,input_dim:int,action_dim:int):
super(GoalConditionedQNetwork,self).__init__()
self.fc1=nn.Linear(input_dim,128)
self.fc2=nn.Linear(128,128)
# 輸出取決于層次:
# L0: 原始動(dòng)作的Q值
# L1: 選擇離散子目標(biāo)的Q值
self.fc3=nn.Linear(128,action_dim)
defforward(self,state_goal_concat:torch.Tensor)->torch.Tensor:
x=F.relu(self.fc1(state_goal_concat))
x=F.relu(self.fc2(x))
q_values=self.fc3(x)
returnq_values
# --- 網(wǎng)絡(luò)維度 ---
# state_dim = env.state_dim
# goal_dim = env.goal_dim # 如果目標(biāo)是狀態(tài),通常與state_dim相同
# primitive_action_dim = env.action_dim
# subgoal_action_dim = env.rows * env.cols # 如果子目標(biāo)是離散網(wǎng)格單元
# low_level_net = GoalConditionedQNetwork(state_dim + goal_dim, primitive_action_dim)
# high_level_net = GoalConditionedQNetwork(state_dim + goal_dim, subgoal_action_dim)
此網(wǎng)絡(luò)架構(gòu)同時(shí)處理當(dāng)前狀態(tài)和目標(biāo)作為輸入,輸出特定層次對(duì)應(yīng)的動(dòng)作Q值(L0層輸出原始動(dòng)作的Q值,L1層輸出子目標(biāo)選擇的Q值)。
后見之明回放緩沖區(qū)是另一個(gè)關(guān)鍵組件,用于存儲(chǔ)轉(zhuǎn)換樣本并根據(jù)實(shí)際達(dá)到的狀態(tài)進(jìn)行目標(biāo)重新標(biāo)記:
# 簡化的后見之明回放緩沖區(qū)概念
classHindsightReplayBuffer:
def__init__(self,capacity:int,hindsight_prob:float=0.8):
self.memory=deque([],maxlen=capacity)
self.hindsight_prob=hindsight_prob
defpush(self,state,action,reward,next_state,goal,done,level,achieved_goal):
# 存儲(chǔ)完整的轉(zhuǎn)換,包括預(yù)期目標(biāo)和實(shí)際達(dá)到的目標(biāo)
self.memory.append({
'state':state,'action':action,'reward':reward,
'next_state':next_state,'goal':goal,'done':done,
'level':level,'achieved_goal':achieved_goal
})
defsample(self,batch_size:int,level:int):
# 1. 篩選緩沖區(qū)中正確'level'的轉(zhuǎn)換
# 2. 從這些轉(zhuǎn)換中采樣一批
# 3. 對(duì)于批次中的每個(gè)轉(zhuǎn)換:
# - 保留原始轉(zhuǎn)換(state, action, reward, next_state, goal, done)
# - 以'hindsight_prob'的概率:
# - 創(chuàng)建一個(gè)*新的*后見之明轉(zhuǎn)換:
# - 使用相同的state, action, next_state。
# - 用'achieved_goal'替換'goal'。
# - 根據(jù)next_state是否匹配*新的*后見之明目標(biāo)重新計(jì)算'reward'
# (例如,如果匹配則為0,如果不匹配則為-1,用于L0內(nèi)在獎(jiǎng)勵(lì))。
# - 根據(jù)是否達(dá)到后見之明目標(biāo)重新計(jì)算'done'。
# - 將此后見之明轉(zhuǎn)換添加到正在準(zhǔn)備的批次中。
# 4. 將最終批次(原始+后見之明)轉(zhuǎn)換為張量。
HAC算法的核心理念是將這些組件以層次化方式整合:高層策略生成子目標(biāo),低層策略在指定時(shí)間窗口內(nèi)嘗試實(shí)現(xiàn)這些子目標(biāo),而兩個(gè)層次都通過離策略學(xué)習(xí)方法(包括后見之明重標(biāo)記)從經(jīng)驗(yàn)中進(jìn)行優(yōu)化。
實(shí)驗(yàn)結(jié)果分析:
獎(jiǎng)勵(lì)表現(xiàn):實(shí)驗(yàn)數(shù)據(jù)顯示智能體表現(xiàn)出負(fù)向?qū)W習(xí)趨勢,環(huán)境獎(jiǎng)勵(lì)在整個(gè)訓(xùn)練過程中持續(xù)下降。
執(zhí)行效率:未觀察到效率提升;回合長度持續(xù)維持在接近最大允許步數(shù)的水平。
層次化學(xué)習(xí)問題:高層損失函數(shù)呈現(xiàn)上升趨勢,表明目標(biāo)設(shè)定策略性能有所惡化。低層損失數(shù)據(jù)缺失或未顯示,這進(jìn)一步表明子目標(biāo)實(shí)現(xiàn)層次也存在學(xué)習(xí)障礙。
探索策略:盡管實(shí)施了標(biāo)準(zhǔn)線性epsilon衰減探索機(jī)制,但未能有效解決基礎(chǔ)學(xué)習(xí)問題。
基于以上分析,該HAC實(shí)現(xiàn)未能在網(wǎng)格世界任務(wù)環(huán)境中實(shí)現(xiàn)有效學(xué)習(xí)。關(guān)鍵性能指標(biāo)顯示,隨時(shí)間推移,性能呈現(xiàn)下降趨勢,表明在層次化學(xué)習(xí)框架實(shí)現(xiàn)中存在結(jié)構(gòu)性問題。
17、MCTS:基于模擬的探索規(guī)劃算法
蒙特卡洛樹搜索(Monte Carlo Tree Search, MCTS)將強(qiáng)化學(xué)習(xí)的重點(diǎn)從學(xué)習(xí)覆蓋整個(gè)狀態(tài)空間的值函數(shù)或策略函數(shù),轉(zhuǎn)變?yōu)獒槍?duì)當(dāng)前狀態(tài)的在線規(guī)劃方法。
給定特定狀態(tài),MCTS利用環(huán)境模型(或模擬器)生成大量可能的未來軌跡,構(gòu)建搜索樹以確定當(dāng)前最有前景的動(dòng)作選擇。
MCTS算法的每次迭代包含四個(gè)關(guān)鍵步驟,從當(dāng)前狀態(tài)對(duì)應(yīng)的根節(jié)點(diǎn)開始:
選擇(Selection):根據(jù)選擇策略(如UCB1)遞歸地選擇子節(jié)點(diǎn),從根節(jié)點(diǎn)遍歷現(xiàn)有樹結(jié)構(gòu)。該策略平衡了探索(訪問較少探索的節(jié)點(diǎn))與利用(訪問過去模擬中獲得高平均獎(jiǎng)勵(lì)的節(jié)點(diǎn))。此過程持續(xù)直到達(dá)到一個(gè)葉節(jié)點(diǎn)(尚未完全擴(kuò)展的節(jié)點(diǎn))。
擴(kuò)展(Expansion):若葉節(jié)點(diǎn)非終止節(jié)點(diǎn),通過選擇一個(gè)未嘗試的動(dòng)作并模擬執(zhí)行,生成新狀態(tài),并將表示該新狀態(tài)的節(jié)點(diǎn)添加到搜索樹中。
模擬(Simulation/Rollout):從新擴(kuò)展節(jié)點(diǎn)(若無法擴(kuò)展則為選擇的葉節(jié)點(diǎn))開始,使用簡單、高效的"rollout策略"(通常為隨機(jī)動(dòng)作選擇)進(jìn)行模擬,直到回合結(jié)束或達(dá)到預(yù)設(shè)深度限制。記錄此模擬過程獲得的累積獎(jiǎng)勵(lì)。
反向傳播(Backpropagation):使用模擬獲得的結(jié)果更新選擇和擴(kuò)展階段訪問過的所有節(jié)點(diǎn)的統(tǒng)計(jì)數(shù)據(jù),包括訪問計(jì)數(shù)和累積獎(jiǎng)勵(lì)值。
首先,我們需要定義樹節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu):
classMCTSNode:
""" 表示蒙特卡洛樹搜索中的節(jié)點(diǎn)。 """
def__init__(self,state:Tuple[int,int],parent:Optional['MCTSNode']=None,action:Optional[int]=None):
self.state=state
self.parent=parent
self.action_that_led_here=action# 父節(jié)點(diǎn)采取的動(dòng)作導(dǎo)致此節(jié)點(diǎn)
self.children:Dict[int,MCTSNode]={}# 映射動(dòng)作 -> 子節(jié)點(diǎn)
# 獲取可能動(dòng)作的函數(shù)(取決于環(huán)境)
self.untried_actions:List[int]=self._get_possible_actions(state)
self.visit_count:int=0
self.total_value:float=0.0# rollout獎(jiǎng)勵(lì)總和
def_get_possible_actions(self,state):
# 占位符:用實(shí)際環(huán)境調(diào)用替換
# 網(wǎng)格世界的示例(假設(shè)env可訪問或已傳遞):
ifenv.is_terminal(state):return[]
returnlist(range(env.get_action_space_size()))# 或env.get_valid_actions(state)
defis_fully_expanded(self)->bool:
returnnotself.untried_actions
defis_terminal(self)->bool:
# 占位符:用實(shí)際環(huán)境調(diào)用替換
returnenv.is_terminal(self.state)
defget_average_value(self)->float:
returnself.total_value/self.visit_countifself.visit_count>0else0.0
defselect_best_child_uct(self,exploration_constant:float)->'MCTSNode':
""" 選擇具有最高UCT評(píng)分的子節(jié)點(diǎn)。"""
best_score=-float('inf')
best_child=None
foraction,childinself.children.items():
ifchild.visit_count==0:
score=float('inf')# 優(yōu)先選擇未訪問節(jié)點(diǎn)
else:
exploit=child.get_average_value()
explore=exploration_constant*math.sqrt(math.log(self.visit_count)/child.visit_count)
score=exploit+explore
ifscore>best_score:
best_score=score
best_child=child
ifbest_childisNone:# 只應(yīng)在節(jié)點(diǎn)還沒有子節(jié)點(diǎn)時(shí)發(fā)生
returnself# 理想情況下不應(yīng)在沒有子節(jié)點(diǎn)的節(jié)點(diǎn)上調(diào)用
returnbest_child
該節(jié)點(diǎn)類存儲(chǔ)狀態(tài)信息、父子節(jié)點(diǎn)關(guān)系鏈接以及關(guān)鍵的統(tǒng)計(jì)數(shù)據(jù):訪問計(jì)數(shù)(N)和累積價(jià)值(W)。
MCTS主搜索函數(shù)協(xié)調(diào)四個(gè)核心步驟(選擇、擴(kuò)展、模擬、反向傳播),從當(dāng)前狀態(tài)開始執(zhí)行大量模擬,構(gòu)建搜索樹并利用積累的統(tǒng)計(jì)數(shù)據(jù)指導(dǎo)探索過程,最終確定最優(yōu)即時(shí)動(dòng)作。
實(shí)驗(yàn)結(jié)果分析:
性能表現(xiàn):MCTS算法持續(xù)實(shí)現(xiàn)正向總獎(jiǎng)勵(lì),移動(dòng)平均值穩(wěn)定維持在+6至+7區(qū)間。這表明在給定的模擬預(yù)算(100次模擬)條件下,規(guī)劃過程能有效找到高獎(jiǎng)勵(lì)路徑。
執(zhí)行效率:回合長度普遍較低且相對(duì)穩(wěn)定,平均約為30-40步。數(shù)據(jù)未顯示明顯的下降趨勢,這表明MCTS從早期階段就能夠發(fā)現(xiàn)高效路徑,而非通過多回合學(xué)習(xí)逐步提升效率。
規(guī)劃特性:作為規(guī)劃算法,MCTS的性能主要取決于每個(gè)回合內(nèi)的搜索質(zhì)量。結(jié)果顯示搜索過程持續(xù)有效,但不呈現(xiàn)傳統(tǒng)強(qiáng)化學(xué)習(xí)算法中參數(shù)更新帶來的典型"學(xué)習(xí)曲線"特征。
路徑可視化:最后一個(gè)回合的智能體軌跡展示了從起點(diǎn)('S')到目標(biāo)('G')的清晰、有向路徑,直觀驗(yàn)證了規(guī)劃成功。
綜合評(píng)估,MCTS算法有效利用其規(guī)劃能力(基于100次模擬的預(yù)算),在網(wǎng)格世界環(huán)境中穩(wěn)定地發(fā)現(xiàn)通往目標(biāo)的高質(zhì)量、相對(duì)高效的路徑,從訓(xùn)練初期就能實(shí)現(xiàn)穩(wěn)定的正向獎(jiǎng)勵(lì)。
18、PlaNet:潛在空間規(guī)劃網(wǎng)絡(luò)
PlaNet(Deep Planning Network)代表一種先進(jìn)的基于模型的強(qiáng)化學(xué)習(xí)方法,特別適用于處理高維觀察數(shù)據(jù)(如圖像)的學(xué)習(xí)任務(wù)。
其核心創(chuàng)新在于不直接在復(fù)雜的觀察空間中學(xué)習(xí)世界模型(動(dòng)力學(xué)模型),而是在學(xué)習(xí)得到的緊湊潛在空間中構(gòu)建模型并執(zhí)行規(guī)劃,大幅提高了計(jì)算效率。

算法流程:智能體首先觀察環(huán)境狀態(tài)(o_t),編碼器將其(可能結(jié)合歷史上下文)映射到潛在狀態(tài)表示(s_t)。
規(guī)劃器組件(通常采用交叉熵方法,CEM)利用當(dāng)前潛在狀態(tài)和習(xí)得的世界模型,在未來時(shí)域內(nèi)搜索最優(yōu)動(dòng)作序列。
算法僅執(zhí)行搜索得到的最優(yōu)序列中的第一個(gè)動(dòng)作(a_t*),并將由此產(chǎn)生的觀察(o_{t+1})、執(zhí)行的動(dòng)作(a_t*)、獲得的獎(jiǎng)勵(lì)(r_t)及完成標(biāo)志存儲(chǔ)到回放緩沖區(qū)中。
同時(shí),系統(tǒng)會(huì)從緩沖區(qū)中采樣序列批次,用于訓(xùn)練和優(yōu)化世界模型(包括編碼器、轉(zhuǎn)換預(yù)測器、獎(jiǎng)勵(lì)預(yù)測器等組件)。
實(shí)現(xiàn)一個(gè)完整的、支持圖像處理和遞歸狀態(tài)空間模型(RSSM)的PlaNet系統(tǒng)較為復(fù)雜。為簡化說明,我們可以使用向量狀態(tài)(如鐘擺系統(tǒng))的簡化版本:
"潛在狀態(tài)"可由環(huán)境的狀態(tài)向量(或其簡單MLP編碼)近似表示
世界模型簡化為預(yù)測下一狀態(tài)向量和獎(jiǎng)勵(lì)的多層感知器(MLP)網(wǎng)絡(luò)
# 簡化的動(dòng)力學(xué)模型(預(yù)測下一個(gè)狀態(tài)向量和獎(jiǎng)勵(lì))
classDynamicsModel(nn.Module):
def__init__(self,state_dim:int,action_dim:int,hidden_dim:int=200):
super(DynamicsModel,self).__init__()
self.fc1=nn.Linear(state_dim+action_dim,hidden_dim)
self.fc2=nn.Linear(hidden_dim,hidden_dim)
self.fc_next_state=nn.Linear(hidden_dim,state_dim)
self.fc_reward=nn.Linear(hidden_dim,1)
defforward(self,state:torch.Tensor,action:torch.Tensor)->Tuple[torch.Tensor,torch.Tensor]:
# 連接狀態(tài)和動(dòng)作
x=torch.cat([state,action],dim=-1)
x=F.relu(self.fc1(x))
x=F.relu(self.fc2(x))
pred_next_state=self.fc_next_state(x)
pred_reward=self.fc_reward(x)
returnpred_next_state,pred_reward
該網(wǎng)絡(luò)學(xué)習(xí)基于當(dāng)前狀態(tài)和動(dòng)作預(yù)測即時(shí)的狀態(tài)轉(zhuǎn)移和獎(jiǎng)勵(lì)。
規(guī)劃器組件使用這個(gè)預(yù)測模型搜索最優(yōu)動(dòng)作序列。交叉熵方法(CEM)是PlaNet中常用的規(guī)劃算法:
# CEM規(guī)劃器概述
defcem_planner(model:DynamicsModel,initial_state:torch.Tensor,horizon:int,
num_candidates:int,num_elites:int,num_iterations:int,
gamma:float,action_low,action_high,action_dim,device)->torch.Tensor:
# 初始化動(dòng)作分布(例如,高斯mean=0, std=high)
action_mean=torch.zeros(horizon,action_dim,device=device)
action_std=torch.ones(horizon,action_dim,device=device)# 開始時(shí)方差高
for_inrange(num_iterations):
# 1. 采樣候選動(dòng)作序列(batch, horizon, action_dim)
action_dist=Normal(action_mean,action_std)
candidate_actions=action_dist.sample((num_candidates,))
candidate_actions=torch.clamp(candidate_actions,torch.tensor(action_low,device=device),torch.tensor(action_high,device=device))
# 2. 使用模型評(píng)估序列
total_rewards=torch.zeros(num_candidates,device=device)
current_states=initial_state.repeat(num_candidates,1)
withtorch.no_grad():
fortinrange(horizon):
actions_t=candidate_actions[:,t, :]
next_states,rewards=model(current_states,actions_t)
total_rewards+=(gamma**t)*rewards.squeeze(-1)# 確保reward被擠壓
current_states=next_states
# 3. 選擇精英動(dòng)作序列
_,elite_indices=torch.topk(total_rewards,num_elites)
elite_actions=candidate_actions[elite_indices]
# 4. 重新擬合動(dòng)作分布
action_mean=elite_actions.mean(dim=0)
action_std=elite_actions.std(dim=0)+1e-6# 添加epsilon保持穩(wěn)定性
# 返回最終平均序列的第一個(gè)動(dòng)作
returnaction_mean[0]
CEM規(guī)劃器通過迭代優(yōu)化過程,使用學(xué)習(xí)的模型模擬多條軌跡,并將分布集中在高性能序列上,從而細(xì)化動(dòng)作序列分布。
訓(xùn)練過程包括收集交互序列,將其存儲(chǔ)在經(jīng)驗(yàn)回放緩沖區(qū)中,并訓(xùn)練動(dòng)力學(xué)模型以最小化預(yù)測誤差(通常使用下一狀態(tài)和獎(jiǎng)勵(lì)的均方誤差損失):
# --- 模型訓(xùn)練概述 ---
# (假設(shè)已定義model, optimizer, sequence_buffer)
for_inrange(num_train_steps):
1.從sequence_buffer中采樣序列批次
2.對(duì)于序列中的每一步(或其子集):
-從批次獲取state_t,action_t,reward_t,next_state_t
-預(yù)測next_state_pred,reward_pred=model(state_t,action_t)
-計(jì)算損失=MSE(next_state_pred,next_state_t)+MSE(reward_pred,reward_t)
3.平均批次/步驟的損失
4.optimizer.zero_grad()
5.loss.backward()
6.optimizer.step()
PlaNet算法展示了如何通過學(xué)習(xí)精確的世界模型,即使在壓縮的潛在表示空間中,也能實(shí)現(xiàn)高效的規(guī)劃,從而在復(fù)雜環(huán)境中實(shí)現(xiàn)高樣本效率的學(xué)習(xí)。
實(shí)驗(yàn)結(jié)果分析:
獎(jiǎng)勵(lì)表現(xiàn):PlaNet展現(xiàn)出顯著的學(xué)習(xí)進(jìn)展。每回合平均獎(jiǎng)勵(lì)從極低的初始值(約-800)快速提升至較高水平(移動(dòng)平均值達(dá)到約-100至-200)。然而,即使在初始快速改善后,迭代間的表現(xiàn)仍存在明顯波動(dòng)。
模型學(xué)習(xí)效果:平均模型損失(對(duì)數(shù)刻度)在初期階段(前~25次迭代)大幅下降,降低了約兩個(gè)數(shù)量級(jí)。隨后損失在較低值處趨于穩(wěn)定,表明PlaNet能夠迅速學(xué)習(xí)鐘擺系統(tǒng)動(dòng)力學(xué)和獎(jiǎng)勵(lì)預(yù)測的準(zhǔn)確模型。
基于模型的學(xué)習(xí)有效性:獎(jiǎng)勵(lì)的顯著改善與模型損失的快速下降呈現(xiàn)強(qiáng)相關(guān)性。這凸顯了PlaNet的核心優(yōu)勢:通過快速構(gòu)建準(zhǔn)確的世界模型,使其規(guī)劃組件能夠發(fā)現(xiàn)高獎(jiǎng)勵(lì)的動(dòng)作策略。
綜合評(píng)估,PlaNet在鐘擺任務(wù)上展示了基于模型學(xué)習(xí)的顯著效果。它能夠迅速建立準(zhǔn)確的世界動(dòng)力學(xué)模型,從而使其規(guī)劃機(jī)制能夠?qū)崿F(xiàn)顯著的性能提升,盡管性能仍有一定波動(dòng)性。
算法選擇指南
針對(duì)不同任務(wù)場景的強(qiáng)化學(xué)習(xí)算法選擇:
對(duì)于簡單的離散動(dòng)作任務(wù),Q-Learning或SARSA算法是理想的起點(diǎn)。當(dāng)任務(wù)要求更高的穩(wěn)定性和樣本效率時(shí),尤其是在復(fù)雜環(huán)境中,近端策略優(yōu)化(PPO)算法通常表現(xiàn)出較好的魯棒性和學(xué)習(xí)效率。
對(duì)于機(jī)器人控制等連續(xù)動(dòng)作空間問題,軟演員-評(píng)論家(SAC)和深度確定性策略梯度(DDPG)算法是有力的選擇,其中SAC通常在穩(wěn)定性和探索效率方面表現(xiàn)更為出色。若環(huán)境模擬成本較低,基于模型的方法(如PlaNet)或基于規(guī)劃的算法(如MCTS)可能會(huì)帶來顯著的性能優(yōu)勢。
盡管沒有放之四海而皆準(zhǔn)的算法選擇,但PPO和SAC因其在多種現(xiàn)代強(qiáng)化學(xué)習(xí)任務(wù)中的良好表現(xiàn)而被廣泛采用。建議從這些算法入手,并根據(jù)具體環(huán)境特性和任務(wù)目標(biāo)進(jìn)行適當(dāng)調(diào)整。最優(yōu)算法的選擇最終取決于特定應(yīng)用場景的具體需求和約束條件。
本文代碼:
https://github.com/FareedKhan-dev/all-rl-algorithms
作者:Fareed Khan
-
學(xué)習(xí)算法
+關(guān)注
關(guān)注
0文章
16瀏覽量
7523 -
GitHub
+關(guān)注
關(guān)注
3文章
481瀏覽量
17454
發(fā)布評(píng)論請(qǐng)先 登錄
基于強(qiáng)化學(xué)習(xí)的自動(dòng)碼率調(diào)節(jié)算法的技術(shù)架構(gòu)與實(shí)現(xiàn)要點(diǎn)

什么是深度強(qiáng)化學(xué)習(xí)?深度強(qiáng)化學(xué)習(xí)算法應(yīng)用分析

經(jīng)典算法大全(51個(gè)C語言算法+單片機(jī)常用算法+機(jī)器學(xué)十大算法)
深度強(qiáng)化學(xué)習(xí)實(shí)戰(zhàn)
深度學(xué)習(xí)技術(shù)的開發(fā)與應(yīng)用
將深度學(xué)習(xí)和強(qiáng)化學(xué)習(xí)相結(jié)合的深度強(qiáng)化學(xué)習(xí)DRL
基于強(qiáng)化學(xué)習(xí)的MADDPG算法原理及實(shí)現(xiàn)
如何構(gòu)建強(qiáng)化學(xué)習(xí)模型來訓(xùn)練無人車算法
機(jī)器學(xué)習(xí)中的無模型強(qiáng)化學(xué)習(xí)算法及研究綜述

模型化深度強(qiáng)化學(xué)習(xí)應(yīng)用研究綜述

7個(gè)流行的強(qiáng)化學(xué)習(xí)算法及代碼實(shí)現(xiàn)
徹底改變算法交易:強(qiáng)化學(xué)習(xí)的力量
7個(gè)流行的強(qiáng)化學(xué)習(xí)算法及代碼實(shí)現(xiàn)

評(píng)論