手機(jī)上怎么建網(wǎng)站怎么推廣軟件
目錄
- 一、引言
- 二、PPO 算法原理
- 2.1 策略梯度
- 2.2 PPO 核心思想
- 三、PPO 算法公式推導(dǎo)
- 3.1 重要性采樣
- 3.2 優(yōu)勢函數(shù)估計
- 四、PPO 算法代碼實現(xiàn)(以 Python 和 PyTorch 為例)
- 五、PPO 算法案例應(yīng)用
- 5.1 機(jī)器人控制
- 5.2 自動駕駛
- 六、總結(jié)
一、引言
強(qiáng)化學(xué)習(xí)作為機(jī)器學(xué)習(xí)中的一個重要領(lǐng)域,旨在讓智能體通過與環(huán)境交互,學(xué)習(xí)到最優(yōu)的行為策略以最大化長期累積獎勵。近端策略優(yōu)化(Proximal Policy Optimization,PPO)算法是強(qiáng)化學(xué)習(xí)中的明星算法,它在諸多領(lǐng)域都取得了令人矚目的成果。本文將深入探討 PPO 算法,從原理到代碼實現(xiàn),再到實際案例應(yīng)用,力求讓讀者全面掌握這一強(qiáng)大的算法。
二、PPO 算法原理
2.1 策略梯度
在強(qiáng)化學(xué)習(xí)里,策略梯度是一類關(guān)鍵的優(yōu)化方法,你可以把它想象成是智能體在學(xué)習(xí)如何行動時的 “指南針”。假設(shè)策略由參數(shù) θ \theta θ 表示,這就好比是智能體的 “行動指南” 參數(shù),智能體在狀態(tài) s s s 下采取行動 a a a 的概率為 π θ ( a ∣ s ) \pi_{\theta}(a|s) πθ?(a∣s) ,即根據(jù)當(dāng)前的 “行動指南”,在這個狀態(tài)下選擇這個行動的可能性。
策略梯度的目標(biāo)是最大化累計獎勵的期望,用公式表示就是: J ( θ ) = E s 0 , a 0 , ? [ ∑ t = 0 T γ t r ( s t , a t ) ] J(\theta)=\mathbb{E}_{s_0,a_0,\cdots}\left[\sum_{t = 0}^{T}\gamma^{t}r(s_t,a_t)\right] J(θ)=Es0?,a0?,??[t=0∑T?γtr(st?,at?)]
這里的 γ \gamma γ 是折扣因子,它的作用是讓智能體更關(guān)注近期的獎勵,因為越往后的獎勵可能越不確定,就像我們在做決策時,往往會更看重眼前比較確定的好處。 r ( s t , a t ) r(s_t,a_t) r(st?,at?) 是在狀態(tài) s t s_t st? 下采取行動 a t a_t at? 獲得的獎勵,比如玩游戲時,在某個游戲場景下做出某個操作得到的分?jǐn)?shù)。
根據(jù)策略梯度定理,策略梯度可以表示為: ? θ J ( θ ) = E s , a [ ? θ log ? π θ ( a ∣ s ) A ( s , a ) ] \nabla_{\theta}J(\theta)=\mathbb{E}_{s,a}\left[\nabla_{\theta}\log\pi_{\theta}(a|s)A(s,a)\right] ?θ?J(θ)=Es,a?[?θ?logπθ?(a∣s)A(s,a)]
這里的 A ( s , a ) A(s,a) A(s,a) 是優(yōu)勢函數(shù),它表示采取行動 a a a 相對于平均策略的優(yōu)勢。簡單來說,就是判斷這個行動比一般的行動好在哪里,好多少,幫助智能體決定是否要多采取這個行動。
2.2 PPO 核心思想
PPO 算法的核心是在策略更新時,限制策略的變化幅度,避免更新過大導(dǎo)致策略性能急劇下降。這就好像我們在調(diào)整自行車的變速器,如果一下子調(diào)得太猛,可能車子就沒法正常騎了。
它通過引入一個截斷的目標(biāo)函數(shù)來實現(xiàn)這一點: L C L I P ( θ ) = E t [ min ? ( r t ( θ ) A ^ t , clip ( r t ( θ ) , 1 ? ? , 1 + ? ) A ^ t ) ] L^{CLIP}(\theta)=\mathbb{E}_{t}\left[\min\left(r_t(\theta)\hat{A}_t, \text{clip}(r_t(\theta), 1 - \epsilon, 1+\epsilon)\hat{A}_t\right)\right] LCLIP(θ)=Et?[min(rt?(θ)A^t?,clip(rt?(θ),1??,1+?)A^t?)]
其中 r t ( θ ) = π θ ( a t ∣ s t ) π θ o l d ( a t ∣ s t ) r_t(\theta)=\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)} rt?(θ)=πθold??(at?∣st?)πθ?(at?∣st?)? 是重要性采樣比,它反映了新策略和舊策略對于同一個狀態(tài) - 行動對的概率差異。 A ^ t \hat{A}_t A^t? 是估計的優(yōu)勢函數(shù), ? \epsilon ? 是截斷參數(shù),通常設(shè)置為一個較小的值,如 0.2 。這個截斷參數(shù)就像是給策略更新幅度設(shè)定了一個 “安全范圍”,在這個范圍內(nèi)更新策略,能保證策略既有所改進(jìn),又不會變得太糟糕。
三、PPO 算法公式推導(dǎo)
3.1 重要性采樣
重要性采樣是 PPO 算法中的關(guān)鍵技術(shù)之一。由于直接從當(dāng)前策略采樣數(shù)據(jù)效率較低,我們可以從舊策略 π θ o l d \pi_{\theta_{old}} πθold?? 采樣數(shù)據(jù),然后通過重要性采樣比 r t ( θ ) r_t(\theta) rt?(θ) 來校正數(shù)據(jù)的分布。 E s ~ π θ [ f ( s ) ] ≈ 1 N ∑ i = 1 N π θ ( s i ) π θ o l d ( s i ) f ( s i ) \mathbb{E}_{s\sim\pi_{\theta}}[f(s)]\approx\frac{1}{N}\sum_{i = 1}^{N}\frac{\pi_{\theta}(s_i)}{\pi_{\theta_{old}}(s_i)}f(s_i) Es~πθ??[f(s)]≈N1?i=1∑N?πθold??(si?)πθ?(si?)?f(si?)
比如我們要了解一群鳥的飛行習(xí)慣,直接去觀察所有鳥的飛行軌跡很困難,那我們可以先觀察一部分容易觀察到的鳥(舊策略采樣),然后根據(jù)這些鳥和所有鳥的一些特征差異(重要性采樣比),來推測整個鳥群的飛行習(xí)慣。
3.2 優(yōu)勢函數(shù)估計
優(yōu)勢函數(shù) A ( s , a ) A(s,a) A(s,a) 可以通過多種方法估計,常用的是廣義優(yōu)勢估計(Generalized Advantage Estimation,GAE): A ^ t = ∑ k = 0 ∞ ( γ λ ) k δ t + k \hat{A}_t=\sum_{k = 0}^{\infty}(\gamma\lambda)^k\delta_{t + k} A^t?=k=0∑∞?(γλ)kδt+k?
其中 δ t = r t + γ V ( s t + 1 ) ? V ( s t ) \delta_{t}=r_t+\gamma V(s_{t + 1})-V(s_t) δt?=rt?+γV(st+1?)?V(st?) 是 TD 誤差, λ \lambda λ 是 GAE 參數(shù),通常在 0 到 1 之間。優(yōu)勢函數(shù)的估計就像是給智能體的行動打分,告訴它每個行動到底有多好,以便它做出更好的決策。
四、PPO 算法代碼實現(xiàn)(以 Python 和 PyTorch 為例)
import torchimport torch.nn as nnimport torch.optim as optimimport gymclass Policy(nn.Module):def __init__(self, state_dim, action_dim):super(Policy, self).__init__()self.fc1 = nn.Linear(state_dim, 64)self.fc2 = nn.Linear(64, 64)self.mu_head = nn.Linear(64, action_dim)self.log_std_head = nn.Linear(64, action_dim)def forward(self, x):x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))mu = torch.tanh(self.mu_head(x))log_std = self.log_std_head(x)std = torch.exp(log_std)dist = torch.distributions.Normal(mu, std)return distclass Value(nn.Module):def __init__(self, state_dim):super(Value, self).__init__()self.fc1 = nn.Linear(state_dim, 64)self.fc2 = nn.Linear(64, 64)self.v_head = nn.Linear(64, 1)def forward(self, x):x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))v = self.v_head(x)return vdef ppo_update(policy, value, optimizer_policy, optimizer_value, states, actions, rewards, dones, gamma=0.99,clip_epsilon=0.2, lambda_gae=0.95):states = torch.FloatTensor(states)actions = torch.FloatTensor(actions)rewards = torch.FloatTensor(rewards)dones = torch.FloatTensor(dones)values = value(states).squeeze(1)returns = []gae = 0for i in reversed(range(len(rewards))):if i == len(rewards) - 1:next_value = 0else:next_value = values[i + 1]delta = rewards[i] + gamma * next_value * (1 - dones[i]) - values[i]gae = delta + gamma * lambda_gae * (1 - dones[i]) * gaereturns.insert(0, gae + values[i])returns = torch.FloatTensor(returns)old_dist = policy(states)old_log_probs = old_dist.log_prob(actions).sum(-1)for _ in range(3):dist = policy(states)log_probs = dist.log_prob(actions).sum(-1)ratios = torch.exp(log_probs - old_log_probs)advantages = returns - values.detach()surr1 = ratios * advantagessurr2 = torch.clamp(ratios, 1 - clip_epsilon, 1 + clip_epsilon) * advantagespolicy_loss = -torch.min(surr1, surr2).mean()optimizer_policy.zero_grad()policy_loss.backward()optimizer_policy.step()value_loss = nn.MSELoss()(value(states).squeeze(1), returns)optimizer_value.zero_grad()value_loss.backward()optimizer_value.step()def train_ppo(env_name, num_episodes=1000):env = gym.make(env_name)state_dim = env.observation_space.shape[0]action_dim = env.action_space.shape[0]policy = Policy(state_dim, action_dim)value = Value(state_dim)optimizer_policy = optim.Adam(policy.parameters(), lr=3e-4)optimizer_value = optim.Adam(value.parameters(), lr=3e-4)for episode in range(num_episodes):states, actions, rewards, dones = [], [], [], []state = env.reset()done = Falsewhile not done:state = torch.FloatTensor(state)dist = policy(state)action = dist.sample()next_state, reward, done, _ = env.step(action.detach().numpy())states.append(state)actions.append(action)rewards.append(reward)dones.append(done)state = next_stateppo_update(policy, value, optimizer_policy, optimizer_value, states, actions, rewards, dones)if episode % 100 == 0:total_reward = 0state = env.reset()done = Falsewhile not done:state = torch.FloatTensor(state)dist = policy(state)action = dist.meannext_state, reward, done, _ = env.step(action.detach().numpy())total_reward += rewardstate = next_stateprint(f"Episode {episode}, Average Reward: {total_reward}")if __name__ == "__main__":train_ppo('Pendulum-v1')
五、PPO 算法案例應(yīng)用
5.1 機(jī)器人控制
在機(jī)器人控制領(lǐng)域,PPO 算法可以用于訓(xùn)練機(jī)器人的運(yùn)動策略。例如,訓(xùn)練一個雙足機(jī)器人行走,機(jī)器人的狀態(tài)可以包括關(guān)節(jié)角度、速度等信息,行動則是關(guān)節(jié)的控制指令。通過 PPO 算法,機(jī)器人可以學(xué)習(xí)到如何根據(jù)當(dāng)前狀態(tài)調(diào)整關(guān)節(jié)控制,以實現(xiàn)穩(wěn)定高效的行走。
5.2 自動駕駛
在自動駕駛場景中,車輛的狀態(tài)包括位置、速度、周圍環(huán)境感知信息等,行動可以是加速、減速、轉(zhuǎn)向等操作。PPO 算法可以讓自動駕駛系統(tǒng)學(xué)習(xí)到在不同路況和環(huán)境下的最優(yōu)駕駛策略,提高行駛的安全性和效率。
六、總結(jié)
PPO 算法作為強(qiáng)化學(xué)習(xí)中的優(yōu)秀算法,以其高效的學(xué)習(xí)能力和良好的穩(wěn)定性在多個領(lǐng)域得到了廣泛應(yīng)用。通過深入理解其原理、公式推導(dǎo),結(jié)合代碼實現(xiàn)和實際案例分析,我們能夠更好地掌握和運(yùn)用這一算法,為解決各種復(fù)雜的實際問題提供有力的工具。