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