強化學習(Reinforcement Learning, RL)是一種機器學習方法,旨在通過與環境交互,使智能體(Agent)學習如何采取最優行動,以最大化某種累積獎勵。它與監督學習和無監督學習不同,強調試錯探索(Exploration-Exploitation)以及基于獎勵信號的學習。
強化學習任務通常用馬爾可夫決策過程來描述:機器處于環境 E E E中,狀態空間 X X X,其中每個狀態 x ∈ X x \in X x∈X是機器感知到的環境的描述,機器能采取的動作構成了動作空間 A A A,若某個動作 a ∈ A a \in A a∈A作用在當前狀態 x x x上,則潛在的轉移函數 P P P將使得環境從當前狀態按照某種概率轉移到另一個狀態,在轉移到另一個狀態的同時,環境會根據潛在的“獎賞”函數 R R R反饋給機器一個獎賞。
在環境中狀態的轉移、獎賞的返回是不受機器控制的,機器只能通過選擇要執行的動作來影響環境,也只能通過觀察轉移后的狀態和返回的獎賞來感知環境。
機器要做的是通過在環境中不斷地嘗試而學得一個“策略”,根據這個“策略”在狀態 x x x下就能知道要執行得動作。
在強化學習任務中,學習的目的就是要找到能使長期累積獎賞最大化的策略。
強化學習與監督學習來說,強化學習是沒有人直接告訴機器在什么狀態下應該做什么動作,只有等到最終結果揭曉,才能通過“反思”之前的動作是否正確來進行學習,因此,強化學習在某種意義上可看作具有“延遲標記信息”的監督學習問題。
強化學習任務的最終獎賞是在多步動作之后才能觀察到,這里考慮簡單情形:最大化單步獎賞,即僅考慮一步操作。單步強化學習任務對應了一個理論模型:k-搖臂賭博機。
k- 搖臂賭博機:有k個搖臂,賭徒在投入一個硬幣后可選擇按下其中一個搖臂,每個搖臂以一定的概率吐出硬幣,但這個概率賭徒并不知道。賭徒的目標是通過一定的策略最大化自己的獎賞,即獲得最多的硬幣。
若僅為獲知每個搖臂的期望獎賞,則可采用“僅探索”法:將所有的嘗試機會平均分配給每個搖臂,最后以每個搖臂各自的平均吐幣概率作為其獎賞的近似評估。若僅為執行獎賞最大的動作,則可采用“僅利用”法:按下目前最優的搖臂。“僅探索”法會失去很多選擇最優搖臂的機會;“僅利用”法可能經常選不到最優搖臂。
? \epsilon ?貪心法是基于一個概率來對探索和利用進行折中:每次嘗試時,以 ? \epsilon ?的概率進行探索,以 1 ? ? 1 - \epsilon 1??的概率進行利用。
則平均獎賞為:
Q ( k ) = 1 n ∑ i = 1 n v i Q(k) = \frac{1}{n} \sum_{i=1}^nv_i Q(k)=n1?i=1∑n?vi?
可以改成增量計算:
Q n ( k ) = 1 n ( ( n ? 1 ) × Q n ? 1 ( k ) + v n ) = Q n ? 1 ( k ) + 1 n ( v n ? Q n ? 1 ( k ) ) Q_n(k) = \frac {1}{n} ( (n - 1) \times Q_{n-1}(k) + v_n) \\ = Q_{n-1}(k) + \frac{1}{n}(v_n - Q_{n-1}(k)) Qn?(k)=n1?((n?1)×Qn?1?(k)+vn?)=Qn?1?(k)+n1?(vn??Qn?1?(k))
代碼
k-搖臂賭博機實現:
import numpy as npclass KArmedBandit:def __init__(self, k=10, true_reward_mean=0, true_reward_std=1):"""k: 搖臂數量true_reward_mean: 獎勵均值的均值true_reward_std: 獎勵均值的標準差"""self.k = kself.q_true = np.random.normal(true_reward_mean, true_reward_std, k) # 每個搖臂的真實均值def step(self, action):"""執行動作(拉某個搖臂),返回獎勵"""reward = np.random.normal(self.q_true[action], 1) # 以 q*(a) 為均值的正態分布return reward
? \epsilon ?貪心實現:
from data_processing import KArmedBandit
import numpy as np
import matplotlib.pyplot as pltdef select_action(epsilon:float, q_estimates:np.ndarray):"""根據 epsilon-greedy 策略選擇動作"""if np.random.rand() < epsilon: # 隨機選擇return np.random.choice(len(q_estimates)) # else:return np.argmax(q_estimates) # 選擇估計獎勵最高的動作
def update_estimates(q_estimates:np.ndarray, action:int, reward:float, action_counts:np.ndarray):"""更新動作的估計獎勵"""action_counts[action] += 1q_estimates[action] += (reward - q_estimates[action]) / action_counts[action]return q_estimates, action_countsdef start(k:int, epsilon:float, epochs:int, stps:int):"""開始運行 epsilon-greedy 算法"""q_estimates = np.zeros(k) # 每個搖臂的估計獎勵action_counts = np.zeros(k) # 每個搖臂被選擇的次數avg_rewards = np.zeros(stps) # 記錄每次拉搖臂的獎勵for epoch in range(epochs):bandit = KArmedBandit(k)rewards = []for step in range(stps):action = select_action(epsilon, q_estimates)reward = bandit.step(action)q_estimates, action_counts = update_estimates(q_estimates, action, reward, action_counts)rewards.append(reward) # 記錄獎勵avg_rewards += np.array(rewards) # 記錄每次拉搖臂的獎勵avg_rewards /= epochsreturn avg_rewardsif __name__ == '__main__':k = 10epsilon = 0.1epochs = 2000stps = 1000avg_rewards = start(k, epsilon, epochs, stps)plt.plot(avg_rewards)plt.xlabel('Steps')plt.ylabel('Average reward')plt.title('RL: epsilon-greedy Performance')plt.show()
深入理解強化學習(一)- 概念和術語 - 知乎 (zhihu.com)