強(qiáng)化學(xué)習(xí)強(qiáng)在哪里?基礎(chǔ)探索
強(qiáng)化學(xué)習(xí)代表了我們對人工智能思考方式的深刻轉(zhuǎn)變——從僅僅識別模式的系統(tǒng),轉(zhuǎn)變?yōu)橥ㄟ^交互學(xué)習(xí)并通過經(jīng)驗改進(jìn)的智能體。正如我們將在本系列中看到的,這種范式正在推動當(dāng)今一些最令人印象深刻的人工智能成就,并開辟機(jī)器學(xué)習(xí)研究的新前沿。
強(qiáng)化學(xué)習(xí)的基礎(chǔ)
擊敗圍棋世界冠軍的算法可不只是按程序設(shè)定運(yùn)行,它還會學(xué)習(xí)。在復(fù)雜城市環(huán)境中自動駕駛的汽車,并非遵循著明確指令,而是在不斷適應(yīng)。重塑我們數(shù)字體驗的突破性語言模型,也不只是在靜態(tài)數(shù)據(jù)上進(jìn)行訓(xùn)練,還通過交互不斷優(yōu)化。
超越傳統(tǒng)學(xué)習(xí):強(qiáng)化學(xué)習(xí)范式
機(jī)器學(xué)習(xí)傳統(tǒng)上分為兩個常見類別:監(jiān)督學(xué)習(xí)(從有標(biāo)記的示例中學(xué)習(xí))和無監(jiān)督學(xué)習(xí)(在無標(biāo)記的數(shù)據(jù)中尋找模式)。強(qiáng)化學(xué)習(xí)則代表了一種根本不同的方法。
在強(qiáng)化學(xué)習(xí)中,智能體通過與環(huán)境互動來學(xué)習(xí),根據(jù)其采取的行動獲得獎勵或懲罰。這里沒有預(yù)先標(biāo)記的示例,也沒有靜態(tài)數(shù)據(jù)集,只有動態(tài)反饋引導(dǎo)智能體趨向最優(yōu)行為。
這種范式轉(zhuǎn)變反映了人類學(xué)習(xí)復(fù)雜行為的實際方式:通過試錯、在反饋的引導(dǎo)下并受目標(biāo)驅(qū)動。
強(qiáng)化學(xué)習(xí)的核心組件
要理解強(qiáng)化學(xué)習(xí),我們需要拆解其基本組件:
- 智能體:學(xué)習(xí)者或決策者。
- 環(huán)境:智能體與之互動的系統(tǒng)。
- 狀態(tài):當(dāng)前的情況或配置。
- 行動:智能體可以采取的行為。
- 獎勵:評估行動的反饋信號。
- 策略:智能體選擇行動的策略。
這些元素之間的相互作用形成了一個持續(xù)的循環(huán):智能體觀察當(dāng)前狀態(tài),根據(jù)其策略采取行動,獲得獎勵,并轉(zhuǎn)移到新的狀態(tài)。這個循環(huán)不斷重復(fù),智能體不斷優(yōu)化其策略以最大化累積獎勵。
強(qiáng)化學(xué)習(xí)與其他范式的區(qū)別在于探索(嘗試新行動以發(fā)現(xiàn)其結(jié)果)和利用(利用已知的獎勵)之間的關(guān)鍵相互作用。這種基本的矛盾——探索 - 利用困境,是強(qiáng)化學(xué)習(xí)獨特挑戰(zhàn)的核心。
神奇背后的數(shù)學(xué):馬爾可夫決策過程
探索 - 利用困境:深入探究
也許強(qiáng)化學(xué)習(xí)中最引人入勝的挑戰(zhàn)是平衡探索和利用。這不僅僅是一個技術(shù)問題,而是一個在各個領(lǐng)域都存在的基本困境:
- 利用:選擇已知能產(chǎn)生高獎勵的行動。
- 探索:嘗試新行動,有可能發(fā)現(xiàn)更好的策略。
考慮一個選擇餐廳的類比:你是回到一家你知道自己喜歡的餐廳(利用),還是嘗試一家可能更好的新餐廳(探索)?無論選擇哪一個方向出錯,你要么錯過發(fā)現(xiàn)更好餐廳的機(jī)會,要么浪費(fèi)一次保證有良好體驗的機(jī)會。
在強(qiáng)化學(xué)習(xí)中,這種困境體現(xiàn)在各種方法中:
簡單的老虎機(jī)問題:你的第一個強(qiáng)化學(xué)習(xí)實現(xiàn)
強(qiáng)化學(xué)習(xí)(RL)乍一看可能很復(fù)雜,但我們可以通過一個經(jīng)典問題來開始理解它:多臂老虎機(jī)問題。讓我們以一種更容易可視化和理解的方式來拆解它。
什么是多臂老虎機(jī)問題?
想象你在一家賭場,里面有多個老虎機(jī)(也叫 “臂”)。每臺老虎機(jī)都有自己隱藏的給予獎勵的概率。你的目標(biāo)很簡單:盡可能多贏錢。但有個難題——你不知道哪臺機(jī)器的 payouts 比其他的更好。你需要通過試錯來弄清楚。
這就產(chǎn)生了我們所說的 “探索與利用困境”:
- 探索:嘗試不同的老虎機(jī),了解哪臺更好。
- 利用:堅持使用你目前認(rèn)為最好的老虎機(jī)。
逐步理解我們的實現(xiàn)
讓我們逐步構(gòu)建解決方案:
import numpy as np
import matplotlib.pyplot as plt
class MultiArmedBandit:
def __init__(self, n_arms=10):
self.true_rewards = np.random.normal(0, 1, n_arms)
self.n_arms = n_arms
print("每臺老虎機(jī)的真實獎勵值(智能體未知):", self.true_rewards)
print("最優(yōu)的老虎機(jī)是 #", np.argmax(self.true_rewards), ",預(yù)期獎勵為",
np.max(self.true_rewards))
def pull(self, arm):
return np.random.normal(self.true_rewards[arm], 1)
class EpsilonGreedyAgent:
def __init__(self, n_arms=10, epsilon=0.1, learning_rate=0.1):
self.n_arms = n_arms
self.epsilon = epsilon
self.learning_rate = learning_rate
self.q_values = np.zeros(n_arms)
self.arm_counts = np.zeros(n_arms)
def select_action(self):
if np.random.random() < self.epsilon:
return np.random.randint(self.n_arms)
else:
return np.argmax(self.q_values)
def update(self, arm, reward):
self.arm_counts[arm] += 1
self.q_values[arm] += self.learning_rate * (reward - self.q_values[arm])
def run_bandit_experiment(n_arms=10, n_steps=1000, epsilon=0.1, learning_rate=0.1, random_seed=42):
np.random.seed(random_seed)
bandit = MultiArmedBandit(n_arms)
agent = EpsilonGreedyAgent(n_arms, epsilon=epsilon, learning_rate=learning_rate)
rewards = np.zeros(n_steps)
optimal_actions = np.zeros(n_steps)
optimal_arm = np.argmax(bandit.true_rewards)
for step in range(n_steps):
arm = agent.select_action()
optimal_actions[step] = 1 if arm == optimal_arm else 0
reward = bandit.pull(arm)
rewards[step] = reward
agent.update(arm, reward)
cumulative_average_reward = np.cumsum(rewards) / (np.arange(n_steps) + 1)
optimal_action_percentage = np.cumsum(optimal_actions) / (np.arange(n_steps) + 1)
return {
'rewards': rewards,
'cumulative_average_reward': cumulative_average_reward,
'optimal_action_percentage': optimal_action_percentage,
'agent': agent,
'bandit': bandit,
'optimal_arm': optimal_arm
}
def visualize_results(results):
plt.figure(figsize=(12, 10))
plt.subplot(2, 1, 1)
plt.plot(results['cumulative_average_reward'])
plt.xlabel('步驟')
plt.ylabel('平均獎勵')
plt.title('隨時間的平均獎勵')
plt.grid(True, alpha=0.3)
plt.subplot(2, 1, 2)
plt.plot(results['optimal_action_percentage'])
plt.xlabel('步驟')
plt.ylabel('最優(yōu)行動百分比')
plt.title('選擇最優(yōu)行動的頻率')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("\n最終結(jié)果:")
print(f"智能體對每臺老虎機(jī)的最終價值估計: {results['agent'].q_values.round(3)}")
print(f"真實獎勵值: {results['bandit'].true_rewards.round(3)}")
print(f"最優(yōu)老虎機(jī): {results['optimal_arm']}")
print(f"每臺老虎機(jī)被拉動的次數(shù): {results['agent'].arm_counts.astype(int)}")
plt.figure(figsize=(10, 5))
plt.bar(range(len(results['agent'].arm_counts)), results['agent'].arm_counts)
plt.xlabel('老虎機(jī)')
plt.ylabel('拉動次數(shù)')
plt.title('老虎機(jī)選擇分布')
plt.show()
results = run_bandit_experiment(n_arms=10, n_steps=1000, epsilon=0.1)
visualize_results(results)
def compare_epsilons():
epsilons = [0.01, 0.1, 0.5]
plt.figure(figsize=(15, 6))
for i, epsilon in enumerate(epsilons):
results = run_bandit_experiment(epsilon=epsilon, random_seed=42)
plt.subplot(1, 2, 1)
plt.plot(results['cumulative_average_reward'], label=f'ε={epsilon}')
plt.subplot(1, 2, 2)
plt.plot(results['optimal_action_percentage'], label=f'ε={epsilon}')
plt.subplot(1, 2, 1)
plt.xlabel('步驟')
plt.ylabel('平均獎勵')
plt.title('隨時間的平均獎勵')
plt.legend()
plt.grid(True, alpha=0.3)
plt.subplot(1, 2, 2)
plt.xlabel('步驟')
plt.ylabel('最優(yōu)行動百分比')
plt.title('最優(yōu)行動頻率')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
智能體通過經(jīng)驗逐漸改進(jìn)其獎勵估計,這通過兩個關(guān)鍵可視化得以展示:隨時間的平均獎勵和最優(yōu)行動頻率。這優(yōu)雅地展示了強(qiáng)化學(xué)習(xí)智能體如何通過與不確定環(huán)境的直接互動發(fā)現(xiàn)最優(yōu)策略。
拆解代碼和概念
- 環(huán)境:我們的一排老虎機(jī)
在代碼中,我們首先創(chuàng)建了??MultiArmedBandit?
? 類,它代表我們的一排老虎機(jī)。每臺老虎機(jī)都有一個智能體不知道的隱藏 “真實獎勵” 值。
class MultiArmedBandit:
def __init__(self, n_arms=10):
self.true_rewards = np.random.normal(0, 1, n_arms)
self.n_arms = n_arms
想象每臺老虎機(jī)都有自己的 “個性”:有些很慷慨(正獎勵值),有些很吝嗇(負(fù)獎勵值)。我們使用正態(tài)分布,所以大多數(shù)老虎機(jī)是中等水平,有少數(shù)非常好或非常差的。當(dāng)我們拉動拉桿(臂)時,我們根據(jù)那臺機(jī)器的真實值加上一些隨機(jī)噪聲獲得獎勵:
def pull(self, arm):
return np.random.normal(self.true_rewards[arm], 1)
噪聲使學(xué)習(xí)變得更困難——僅僅因為一臺機(jī)器一次支付豐厚并不意味著它實際上是整體最好的機(jī)器!
2. 智能體:我們的賭場玩家
??EpsilonGreedyAgent?
? 類代表試圖最大化獎勵的玩家:
class EpsilonGreedyAgent:
def __init__(self, n_arms=10, epsilnotallow=0.1, learning_rate=0.1):
self.epsilon = epsilon
self.q_values = np.zeros(n_arms)
智能體一開始一無所知(所有估計值為零),必須通過試錯學(xué)習(xí)。關(guān)鍵參數(shù)是 ,它控制智能體探索與利用的頻率:
def select_action(self):
if np.random.random() < self.epsilon:
return np.random.randint(self.n_arms)
else:
return np.argmax(self.q_values)
每次拉動后,智能體更新其對該臂價值的估計:
def update(self, arm, reward):
self.arm_counts[arm] += 1
self.q_values[arm] += self.learning_rate * (reward - self.q_values[arm])
這個更新規(guī)則是許多強(qiáng)化學(xué)習(xí)算法使用的簡化版本。它的意思是:“根據(jù)新信息的方向稍微調(diào)整你的估計。”
3. 實驗:隨時間學(xué)習(xí)
主要實驗運(yùn)行許多步驟,智能體選擇臂、接收獎勵并更新其知識:
for step in range(n_steps):
arm = agent.select_action()
reward = bandit.pull(arm)
agent.update(arm, reward)
我們跟蹤:
- 每一步收到的獎勵。
- 智能體是否選擇了最優(yōu)臂(真實獎勵最高的臂)。
4.結(jié)果:我們學(xué)到了什么?
智能體通過試錯逐漸了解哪些臂更好。我們用兩個關(guān)鍵圖可視化這個學(xué)習(xí)過程:
- 隨時間的平均獎勵:顯示智能體在學(xué)習(xí)過程中是否獲得了更好的獎勵。
- 最優(yōu)行動百分比:顯示智能體選擇真正最佳臂的頻率。
核心強(qiáng)化學(xué)習(xí)循環(huán)
這個簡單的例子展示了強(qiáng)化學(xué)習(xí)的基本循環(huán):
- 觀察:智能體觀察當(dāng)前狀態(tài)(在這種情況下,只知道有哪些臂可用)。
- 行動:智能體選擇一個行動(拉哪條臂)。
- 接收獎勵:環(huán)境給出反饋(拉臂獲得的獎勵)。
- 學(xué)習(xí):智能體更新其對世界的理解。
超越老虎機(jī):構(gòu)建實際應(yīng)用
雖然多臂老虎機(jī)提供了一個易于理解的切入點,但現(xiàn)實世界的強(qiáng)化學(xué)習(xí)應(yīng)用要處理復(fù)雜得多的場景:龐大的狀態(tài)空間、延遲的獎勵和部分可觀測的環(huán)境。
想想DeepMind的AlphaGo:狀態(tài)空間包括所有可能的圍棋棋盤配置(比可觀測宇宙中的原子數(shù)量還多)。獎勵嚴(yán)重延遲(只有在游戲結(jié)束時才收到)。早期行動與最終結(jié)果之間的聯(lián)系極其復(fù)雜。
然而基本原理仍然相同:智能體與環(huán)境互動,接收獎勵,并學(xué)習(xí)一種策略以最大化累積獎勵。
挑戰(zhàn)與局限
盡管強(qiáng)化學(xué)習(xí)在概念上很優(yōu)雅,但它面臨著重大挑戰(zhàn):
- 樣本效率:強(qiáng)化學(xué)習(xí)算法通常需要與環(huán)境進(jìn)行大量交互才能有效學(xué)習(xí)。
- 穩(wěn)定性:學(xué)習(xí)過程可能不穩(wěn)定,超參數(shù)的微小變化可能導(dǎo)致截然不同的結(jié)果。
- 獎勵設(shè)計:設(shè)計真正捕捉所需行為的獎勵函數(shù)出奇地困難。
- 泛化能力:智能體通常難以將在一個環(huán)境中學(xué)到的知識轉(zhuǎn)移到另一個環(huán)境中。
這些挑戰(zhàn)代表了活躍的研究前沿,最近基于模型的方法、離策略學(xué)習(xí)和分層強(qiáng)化學(xué)習(xí)的進(jìn)展解決了許多這些局限性。
本文轉(zhuǎn)載自??柏企閱文??,作者:柏企
