贝尔曼方程(Bellman Equation)是动态规划和强化学习中的一个核心概念,用于描述一个状态的价值函数(Value Function)与其后续状态的价值函数之间的关系。它能够帮助我们递归地定义并求解每个状态的价值,从而找到最优策略。
贝尔曼方程的基本形式
在一个马尔可夫决策过程(MDP)中,贝尔曼方程的基本形式如下:
V s π = E [ R t + γ V π ( S t + 1 ) ∣ S t = s ] V^\pi_s=E[R_t+\gamma V^{\pi} (S_{t+1})|S_t=s] Vsπ=E[Rt+γVπ(St+1)∣St=s]
其中:
- V s π V^\pi_s Vsπ:在状态 s s s下按照策略 π \pi π行动的价值函数.
- E:期望值运算符.
- R t R_t Rt:在时间步t获得的即时奖励.
- γ \gamma γ:折扣因子,介于 0 和 1 之间,表示未来奖励的折扣率.
- S t + 1 S_{t+1} St+1:在时间步t+1的状态.
最优贝尔曼方程
最优贝尔曼方程描述了在最优策略
π
∗
\pi^*
π∗下,每个状态的最优价值函数
V
∗
(
s
)
V^*(s)
V∗(s):
v ∗ ( s ) = m a x π E [ R t + γ V ∗ ( S t + 1 ) ∣ S t = s ] v^*(s)=max_{\pi} E[R_t+\gamma V^* (S_{t+1})|S_t=s] v∗(s)=maxπE[Rt+γV∗(St+1)∣St=s]
这个方程表明,一个状态的最优价值等于从该状态出发所能获得的即时奖励加上折扣后的下一个状态的最优价值的期望值
矩阵形式的贝尔曼方程
在一些情况下,我们可以将贝尔曼方程用矩阵形式表示
v = R + γ P v v=R+\gamma Pv v=R+γPv
其中:
- v:是一个包含所有状态价值的列向量.
- R:是包含所有状态即时奖励的列向量.
- γ \gamma γ:是状态转移概率矩阵.
通过矩阵形式的贝尔曼方程,我们可以用线性代数的方法直接求解状态价值:
( I − γ P ) v = R v = ( I − γ P ) − 1 ) R (I-\gamma P)v=R\\ v=(I-\gamma P)^{-1})R (I−γP)v=Rv=(I−γP)−1)R
介绍完贝尔曼方程的一系列形式过后,我们具体来理解一下贝尔曼方程的核心思想,贝尔曼方程通过递归定义状态的价值函数,我们通过提前确定好各种策略,包括即时奖励和目标点与出发点的初始价值,就可以帮助我们求解最优策略和最优价值,
V
s
π
=
E
[
R
t
+
γ
V
π
(
S
t
+
1
)
∣
S
t
=
s
]
V^\pi_s=E[R_t+\gamma V^{\pi} (S_{t+1})|S_t=s]
Vsπ=E[Rt+γVπ(St+1)∣St=s]
这个式子中,计算了当前s状态下的价值,这个价值是由它所包含的未来行动带来的报酬所计算的,我们以gridworld为例:
对于如下一个3x3的列表,我们假定(0,0)和(2,2)分别是出发点和目标点,这9个格子分别表示9个状态,这些状态下我们可以进行的操作包括上下左右四个方向的移动,同时执行这些操作的概率一样,我们假定每次移动都一定会得到-1的即时奖励,同时如果移动方向无法前进,下一状态价值量就是现状态本身价值量,假设折扣因子 γ \gamma γ=0.9,假定初始时目标价值为2,其余为0:
0 0 0 0 0 0 0 0 2
那么第一次迭代:
V ( 0 , 0 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 1 V(0,0)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]=-1 V(0,0)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]=−1
V ( 1 , 0 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 1 V(1,0)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]=-1 V(1,0)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]=−1
V ( 2 , 0 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 1 V(2,0)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]=-1 V(2,0)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]=−1
V ( 0 , 1 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 1 V(0,1)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]=-1 V(0,1)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]=−1
V ( 1 , 1 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 1 V(1,1)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]=-1 V(1,1)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]=−1
V ( 2 , 1 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 2 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 0.55 V(2,1)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 2]+0.25\cdot [-1+0.9\times 0]=-0.55 V(2,1)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×2]+0.25⋅[−1+0.9×0]=−0.55
V ( 0 , 2 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] = − 1 V(0,2)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]=-1 V(0,2)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]=−1
V ( 1 , 2 ) = 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 0 ] + 0.25 ⋅ [ − 1 + 0.9 × 2 ] = − 0.55 V(1,2)=0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 0]+0.25\cdot [-1+0.9\times 2]=-0.55 V(1,2)=0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×0]+0.25⋅[−1+0.9×2]=−0.55
得到第一次迭代的grid:
-1 -1 -1 -1 -1 -0.55 -1 -0.55 2
以此类推可以继续迭代直至每一个位置的价值收敛
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
# 定义网格大小
grid_size = 3
V = np.zeros((grid_size, grid_size))
V[2, 2] = 2
# 定义折扣因子和阈值
gamma = 0.9
theta = 1e-4
# 定义奖励结构
reward = -1
def plot_grid(V, iteration):
fig, ax = plt.subplots()
cmap = colors.ListedColormap(['white', 'lightblue', 'blue'])
bounds = [0, 0.5, 1, 1.5]
norm = colors.BoundaryNorm(bounds, cmap.N)
ax.imshow(V, cmap='coolwarm', interpolation='nearest')
for i in range(grid_size):
for j in range(grid_size):
ax.text(j, i, f'{V[i, j]:.2f}', va='center', ha='center')
plt.title(f'Iteration: {iteration}')
plt.colorbar(ax.imshow(V, cmap='coolwarm', interpolation='nearest'))
plt.show()
# 价值迭代算法
def value_iteration(V, grid_size, gamma, theta, reward):
delta = float('inf')
iteration = 0
while delta > theta:
delta = 0
new_V = V.copy()
for i in range(grid_size):
for j in range(grid_size):
if (i, j) == (2, 2):
continue
v = V[i, j]
values = []
if i > 0:
values.append(reward + gamma * V[i-1, j])
if i < grid_size - 1:
values.append(reward + gamma * V[i+1, j])
if j > 0:
values.append(reward + gamma * V[i, j-1])
if j < grid_size - 1:
values.append(reward + gamma * V[i, j+1])
if i == 0:
values.append(reward + gamma * V[i, j])
if j == 0:
values.append(reward + gamma * V[i, j])
if i == grid_size - 1:
values.append(reward + gamma * V[i, j])
if j == grid_size - 1:
values.append(reward + gamma * V[i, j])
new_V[i, j] = np.array([0.25,0.25,0.25,0.25]).dot(np.array(values).T)
delta = max(delta, abs(v - new_V[i, j]))
V = new_V
iteration += 1
plot_grid(V, iteration) # 可视化每次迭代
return V
这个方程式中的一些概念可以这样理解,如果说我们把贝尔曼方程看成探险,目标点就是我们寻求的宝藏,但是在探险途中,我们每走一步或者说我们开车每过一段距离就要耗油,这个就可以看成即时奖励,表示我们做这个行动的固有收获,而下一状态的价值就是我们在探险走了一步后能得到的宝物价值,虽然可能没到目标点,但是因为离目标点近,我们也可以视作已经得到了一部分宝藏,而为了评估一个状态的价值,我们就是把我们可能的每一个动作得到的价值(固有收获+下一状态价值)乘以执行该动作的概率求和(也就是公式中的求期望),这里我有一个概念没有提到,那就是公式中的 γ \gamma γ:折扣因子.
在上面我提到的gridworld例子中,我们设定折扣因子为0.9,但是在我们理解中,不带折扣的贝尔曼方程理解起来确实看上去没毛病,那么这个折扣因子有什么用呢?
- 数学上的便利性:
折扣因子使得累积回报在数学上更加稳定和可处理。在无折扣的情况下,累积回报可能会变得非常大,特别是在无穷远期的问题中。而折扣因子将未来的回报按指数方式缩减,从而确保累积回报是有限的,便于分析和计算
无关原本无折扣定义的合理与否,我们知道随着迭代次数增加,各状态计算出的价值是以指数形式增大,这会导致数值变得非常大甚至无穷,而如果我们在每一次迭代中都进行折扣,在不影响各状态价值比较的情况下,使得数值发生缩减可以合理计算
- 避免无限回报
在某些循环马尔可夫过程中,如果没有折扣因子,回报可能会无限累积
比如一个智能体在一个循环路径中不断获取正回报,在没有折扣因子的情况下,其累积回报将趋向于无穷大。折扣因子通过将未来回报递减,使得回报值收敛
- 考虑未来的不确定性
未来的不确定性是现实世界中的一个重要因素。折扣因子 γ \gamma γ表示智能体对未来回报的重视程度。较小的 γ \gamma γ值表示智能体对未来的回报不太重视(可能是因为未来不确定性较高),较大的 γ \gamma γ 值表示智能体对未来的回报更为重视
一个折扣因子只在多次迭代中可以体现出其作用,可以看成你给予不同迭代时间下不同的权重,体现了你对未来回报的重视度,这点很合理
- 时间偏好
在许多情况下,立即获得的回报比未来获得的回报更有价值。这种时间偏好可以通过折扣因子来表示
我们的定义中,即时奖励和下一状态的汇报是之间相加的,但是为了展示我们对于即时回报和下一状态回报不同的重视程度,可以通过设计折扣因子调整二者的决定当前状态价值时的权重
- 动态规划中的应用
在动态规划中,折扣因子帮助我们递归地定义和求解价值函数
价值函数表示从状态初始点出发到达终点所能获得的累积回报,通过引入折扣因子,我们可以确保未来的回报被适当地缩减,使得迭代更新过程稳定且收敛
到此为止我们可以大致了解清楚了贝尔曼方程的构造原理以及他的应用方式了.