多智能体连续行为空间问题求解——MADDPG
目錄
- 1. 問題出現:連續行為空間出現
- 2. DDPG 算法
- 2.1 DDPG 算法原理
- 2.2 DDPG 算法實現代碼
- 2.2.1 Actor & Critic
- 2.2.2 Target Network
- 2.2.3 Memory Pool
- 2.2.4 Update Parameters(evaluate network)
- 2.2.5 Update Parameters(target network)
- 3. MADDPG 算法
- 3.1 Actor 網絡定義
- 3.2 Critic 網絡定義
- 3.3 Update Parameters 過程
MADDPG 是一種針對多智能體、連續行為空間設計的算法。MADDPG 的前身是DDPG,DDPG 算法旨在解決連續性行為空間的強化學習問題,而 MADDPG 是在 DDPG 的基礎上做了改進,使其能夠適用于多智能體之間的合作任務學習。本文先從 DDPG 引入,接著再介紹如何在 DDPG 算法上進行修改使其變成 MADDPG 算法。
1. 問題出現:連續行為空間出現
Q-Learning 算法是強化學習中一種常用的方法,但傳統的 Q-Learning 需要枚舉所有的狀態空間并建立 Q-Table,為了解決龐大不可枚舉的狀態空間問題,DQN 被人們設計出來,利用神經網絡近似擬合的方法來避免了窮舉所有可能的狀態空間。但 DQN 算法有一個問題,那就是在計算當前 Q 值的時候需要求出下一個狀態中每一個動作的值函數,選擇最大的動作值函數值來進行計算。
Qπ(st,at)=R(st,at)+γmaxaQπ(st+1,at+1)Q^{\pi}(s_t, a_t) = R(s_t, a_t) + \gamma max_aQ^{\pi}(s_{t+1}, a_{t+1}) Qπ(st?,at?)=R(st?,at?)+γmaxa?Qπ(st+1?,at+1?)
在 Actor-Critic 算法中同樣會面臨這個問題,更新 critic 網絡時候需要計算下一個狀態下所有行為的Q值并取其平均值,計算公式如下:
Qπ(st,at)=R(st,at)+γEπ[Qπ(st+1,at+1)]Q^{\pi}(s_t, a_t) = R(s_t, a_t) + \gamma E_{\pi}[Q^{\pi}(s_{t+1}, a_{t+1})] Qπ(st?,at?)=R(st?,at?)+γEπ?[Qπ(st+1?,at+1?)]
其中 Eπ[Qπ(st+1,at+1)]E_{\pi}[Q^{\pi}(s_{t+1}, a_{t+1})]Eπ?[Qπ(st+1?,at+1?)] 是枚舉所有動作的得分效用并乘上對應動作的選取概率(當然在 AC 中可以直接通過擬合一個 V(s)V(s)V(s) 來近似替代枚舉結果)。那么不管是 DQN 還是 AC 算法,都涉及到需要計算整個行為空間中所有行為的效用值,一旦行為空間演變為連續型的就無法使用以上算法,因為無法窮舉所有的行為并計算所有行為的值之和了。為此,在解決連續行為空間問題的時候,我們需要一種新的算法,能夠不用窮舉所有行為的值就能完成算法更新,DDPG 的出現很好的解決了這個問題。
2. DDPG 算法
2.1 DDPG 算法原理
DPG(Deterministic Policy Gradient)算法是一種 “確定性行為策略” 算法,我們之前問題的難點在于對于連續的龐大行為空間,我們無法一一枚舉所有可能的行為。因此,DPG 認為,在求取下一個狀態的狀態值時,我們沒有必要去計算所有可能的行為值并跟據每個行為被采取的概率做加權平均,我們只需要認為在一個狀態下只有可能采取某一個確定的行為 aaa,即該行為 aaa 被采取的概率為百分之百,這樣就行了,于是整個 Q 值計算函數就變成了:
Qμ(st,at)=R(st,at)+γQμ(st+1,μ(st+1))]Q^{\mu}(s_t, a_t) = R(s_t, a_t) + \gamma Q^{\mu}(s_{t+1}, \mu{(s_{t+1})})] Qμ(st?,at?)=R(st?,at?)+γQμ(st+1?,μ(st+1?))]
即,原本的行為 aaa 是由隨機策略 π\piπ 進行概率選擇,而現在這個行為由一個確定性策略 μ\muμ 來選擇,確定性策略是指只要輸入一個狀態就一定能得到唯一一個確定的輸出行為,而隨機性策略指的是輸入一個狀態,輸出的是整個行為空間的所有行為概率分布。DDPG 是 DPG 算法上融合進神經網絡技術,變成了 Deep Deterministic Policy Gradient,其整體思路和 DPG 是一致的。
2.2 DDPG 算法實現代碼
DDPG 沿用了 Actor-Critic 算法結構,在代碼中也存在一個 Actor 和一個 Critic,Actor 負責做行為決策,而 Critic 負責做行為效用評估,這里使用 DDPG 學習玩 gym 中一個倒立擺的游戲,游戲中的 action 為順時針或逆時針的旋轉力度,旋轉力度是一個連續行為,力的大小是一個連續的隨機變量,最終期望能夠通過不斷學習后算法能夠學會如何讓桿子倒立在上面靜止不動,如下圖所示:
2.2.1 Actor & Critic
我們先來看看在 DDPG 中 Actor 和 Critic 分別是怎么實現的的,Actor 和 Critic 的定義如下(代碼參考自這里):
class Actor(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(Actor, self).__init__()self.linear1 = nn.Linear(input_size, hidden_size)self.linear2 = nn.Linear(hidden_size, hidden_size)self.linear3 = nn.Linear(hidden_size, output_size)def forward(self, s):x = F.relu(self.linear1(s))x = F.relu(self.linear2(x))x = torch.tanh(self.linear3(x))return xclass Critic(nn.Module):def __init__(self, input_size, hidden_size, output_size):super().__init__()self.linear1 = nn.Linear(input_size, hidden_size)self.linear2 = nn.Linear(hidden_size, hidden_size)self.linear3 = nn.Linear(hidden_size, output_size)def forward(self, s, a):x = torch.cat([s, a], 1) # DDPG與普通AC算法的不同之處x = F.relu(self.linear1(x))x = F.relu(self.linear2(x))x = self.linear3(x)return xActor 的設計和以往相同,沒什么太大變化。
Critic 的實現有了一些改變,在 forward 函數中,原始的 critic 只用傳入狀態sss,輸出所有動作的效用值,但由于這是連續動作空間,無法輸出每一個行為的值,因此 critic 網絡改為接收一個狀態 sss 和一個具體行為 aaa 作為輸入,輸出的是具體行為 aaa 在當前狀態 sss 下的效用值,即 critic 網絡輸出維度為1。
2.2.2 Target Network
除了在 critic 網絡上有了改變之外,DDPG 在整個算法層面上也做了修改。DDPG 參照了 DQN 的方式,為了算法添加了 target network,即固定住一個 target 網絡產生樣本,另一個 evaluate 網絡不斷更新迭代的思想,因此整個算法包含 4 個網絡:
actor = Actor(s_dim, 256, a_dim) actor_target = Actor(s_dim, 256, a_dim) critic = Critic(s_dim+a_dim, 256, a_dim) # 輸入維度是 狀態空間 + 行為空間 critic_target = Critic(s_dim+a_dim, 256, a_dim)值得注意的是,在上述 critic 網絡中輸入的是 s_dim + a_dim,為什么是加 a_dim 呢?因為在 DDPG 算法中,critic 網絡評判的是一組行為的效用值,即如果有(油門、方向盤)這兩個行為的話,那么傳入的應該是(油門大小、方向盤轉動度數)這一組行為,critic 網絡對這一組動作行為做一個效用評判。
2.2.3 Memory Pool
之前提到 DDPG 算法借用了 DQN 思想,除了加入了 Target 網絡之外還引入了 Memory Pool 機制,將收集到的歷史經驗存放到記憶庫中,在更新的時候取一個 batch 的數據來計算均值,memory pool 代碼如下:
# 經驗池 buffer = []# 往經驗池存放經驗數據 def put(self, *transition): if len(self.buffer)== self.capacity:self.buffer.pop(0)self.buffer.append(transition)2.2.4 Update Parameters(evaluate network)
在定義好了這些結構之后,我們就開始看看如何進行梯度更新吧。所需要更新參數的網絡一共有 4 個,2 個 target network 和 2 個 evaluate network,target network 的更新是在訓練迭代了若干輪后將 evaluate network 當前的參數值復制過去即可,只不過這里并不是直接復制,會做一些處理,這里我們先來看 evaluate network 是如何進行參數更新的,actor 和 critic 的更新代碼如下 :
def critic_learn():a1 = self.actor_target(s1).detach()y_true = r1 + self.gamma * self.critic_target(s1, a1).detach() # 下一個狀態的目標狀態值y_pred = self.critic(s0, a0) # 下一個狀態的預測狀態值loss_fn = nn.MSELoss()loss = loss_fn(y_pred, y_true)self.critic_optim.zero_grad()loss.backward()self.critic_optim.step()def actor_learn():loss = -torch.mean( self.critic(s0, self.actor(s0)) )self.actor_optim.zero_grad()loss.backward()self.actor_optim.step()我們先來看 critic 的 learn 函數,loss 函數比較的是 用當前網絡預測當前狀態的Q值 和 利用回報R與下一狀態的狀態值之和 之間的 error 值,現在問題在于下一個狀態的狀態值如何計算,在 DDPG 算法中由于確定了在一種狀態下只會以100%的概率去選擇一個確定的動作,因此在計算下一個狀態的狀態值的時候,直接根據 actor 網絡輸出一個在下一個狀態會采取的行為,把這個行為當作100%概率的確定行為,并根據這個行為和下一刻的狀態輸入 critic 網絡得到下一個狀態的狀態值,最后通過計算這兩個值的差來進行反向梯度更新(TD-ERROR)。
再來看看 actor 的 learn 函數,actor 還是普通的更新思路 —— actor 選擇一個可能的行為,通過 reward 來決定增加選取這個 action 的概率還是降低選擇這個 action 的概率。而增加/減少概率的多少由 critic 網絡來決定,若 critic 網絡評判出來當前狀態下采取當前行為會得到一個非常高的正效用值,那么梯度更新后 actor 下次采取這個行為的概率就會大幅度增加。而傳統的 actor 在進行行為選擇時神經網絡會輸出每一個行為的被采取概率,按照這些概率來隨機選擇一個行為,但在 DDPG 算法中,所有行為都是被確定性選擇的,不會存在隨機性,因此在代碼中傳入的是經過 actor 后得到的輸出行為,認為該行為就是100%被確定性選擇的,沒有之前的按概率選擇行為這一個環節了。 選好行為后和當前狀態一起傳給 critic 網絡做效用值評估。
2.2.5 Update Parameters(target network)
Target Network 在 DDPG 算法中沿用了 DQN 的思路,在迭代一定的輪數后,會從 evaluate network 中 copy 參數到自身網絡中去。但是不同的是,DDPG 在進行參數復制的時候選擇的是 soft update 的方式,即,在進行參數復制的時候不是進行直接復制值,而是將 target net 和 evaluate net 的參數值以一定的權重值加起來,融合成新的網絡參數,代碼如下:
def soft_update(net_target, net, tau):for target_param, param in zip(net_target.parameters(), net.parameters()):target_param.data.copy_(target_param.data * (1.0 - tau) + param.data * tau)參數 tau 是保留程度參數,tau 值越大則保留的原網絡的參數的程度越大。
3. MADDPG 算法
在理解了 DDPG 算法后,理解 MADDPG 就比較容易了。MADDPG 是 Multi-Agent 下的 DDPG 算法,主要針對于多智能體之間連續行為進行求解。MADDPG 同樣沿用了 AC 算法的架構,和 DDPG 相比只是在 Critic 網絡上的輸入做了一些額外信息的添加,下面結合實際代碼來分析:
3.1 Actor 網絡定義
class Actor(nn.Module):def __init__(self, args, agent_id):""" 網絡層定義部分 """super(Actor, self).__init__()self.fc1 = nn.Linear(args.obs_shape[agent_id], 64) # 定義輸入維度self.fc2 = nn.Linear(64, 64)self.fc3 = nn.Linear(64, 64)self.action_out = nn.Linear(64, args.action_shape[agent_id]) # 定義輸出維度def forward(self, x):""" 網絡前向傳播過程定義 """x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = F.relu(self.fc3(x))actions = torch.tanh(self.action_out(x))return actions上面是 MADDPG 中 actor 網絡的定義代碼,由于一個場景中可能存在多種不同的智能體,其觀測空間維度與行為空間維度都不盡相同,因此在進行 actor 定義時需傳入每個智能體自身所符合的維度信息,如上述代碼一樣,通過 agent_id 來獲取具體的智能體信息,前向傳播過程與 DDPG 相同,沒有什么特殊之處。
3.2 Critic 網絡定義
class Critic(nn.Module):def __init__(self, args):super(Critic, self).__init__()self.max_action = args.high_actionself.fc1 = nn.Linear(sum(args.obs_shape) + sum(args.action_shape), 64) # 定義輸入層維度(聯合觀測+聯合行為)self.fc2 = nn.Linear(64, 64)self.fc3 = nn.Linear(64, 64)self.q_out = nn.Linear(64, 1)def forward(self, state, action):state = torch.cat(state, dim=1) # 聯合觀測action = torch.cat(action, dim=1) # 聯合行為x = torch.cat([state, action], dim=1) # 聯合觀測 + 聯合行為x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = F.relu(self.fc3(x))q_value = self.q_out(x)return q_valueCritic 的代碼如上,可見 MADDPG 中的 Critic 是一個中心化網絡,即傳入的不只是當前 Agent 的(s,a)信息,還加入了其他 Agent 的(s,a)信息。這種做法在多智能體算法中不算新奇了,在訓練學習階段利用中心化的評價網絡來指導 Actor 的更新在許多多智能體算法當中都用到了這個技巧。值得一提的是,由于 Critic 需要指導 Actor 的更新,所以理論上需要讓 Critic 比 Actor 更快的收斂,因此通常 Critic 的 learning rate 需要設置的比 Actor 要稍大些。
3.3 Update Parameters 過程
下面我們來看看 Actor 和 Critic 的更新過程:
- Critic 更新
上面是 Critic 的更新過程,Critic 的更新很好理解,利用聯合觀測來確定聯合行為(DPG中一個觀測就對應一個具體的行為),輸入到 Critic 網絡中進行計算,最后利用 TD-Error 進行梯度更新。
- Actor 更新
Actor 在進行更新的時候,首先把當前 Agent 的當前行為替換成了另外一個行為,再用新的聯合行為去預估 Critic 的值,新的聯合行為中其他 Agent 的行為是保持不變的。那么這里為什么要單獨改變自身 Agent 的行為呢?這是因為 MADDPG 是一種 off-policy 的算法,我們所取的更新樣本是來自 Memory Pool 中的,是以往的歷史經驗,但我們現在自身的 Policy 已經和之前的不一樣了(已經進化過了),因此需要按照現在的 Policy 重新選擇一個行為進行計算。這和 PPO 算法中的 Importance Sampling 的思想一樣,PPO 是采用概率修正的方式來解決行為不一致問題,而 MADDPG 中干脆直接就舍棄歷史舊行為,按照當前策略重采樣一次行為來進行計算。
- Target 網絡更新
和 DDPG 一樣,MADDPG 中針對 Actor 和 Critic 的 target 網絡也是采用 soft update 的,具體內容參見 2.2.5 小節。
以上就是 MADDPG 的全部內容。
總結
以上是生活随笔為你收集整理的多智能体连续行为空间问题求解——MADDPG的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Sigmoid函数与逻辑回归
- 下一篇: MultiProcessing中主进程与