人工智能课预习 : 7.3 动态规划算法
动态规划算法
动态规划算法(Dynamic Programming) 是一种求解多阶段决策过程最优化问题的方法。在动态规划中,通过把原问题分解为相对简单的子问题,先求解子问题,再由子问题的解而得到原问题的解。
- 要求:具有最优子结构和子问题重叠
- 最优子结构(Optimal substructure):适用最优原理,最优解可分解为子问题的解
- 重叠子问题(Overlapping subproblems):子问题会多次出现,其解可缓存复用
马尔可夫决策过程满足上述特性:贝尔曼方程提供了递归分解方式,价值函数存储并复用求解结果。
MDP :
-
预测(Prediction)
-
输入:MDP 模型 \(\langle \mathcal{S}, \mathcal{A}, \mathcal{P}, \mathcal{R}, \gamma \rangle\) 和给定策略 \(\pi\)
-
输出:该策略的价值函数 \(v_\pi(s)\)
-
-
控制(Control)
-
输入:MDP 模型 \(\langle \mathcal{S}, \mathcal{A}, \mathcal{P}, \mathcal{R}, \gamma \rangle\)
-
输出:最优价值函数 \(v_*\) 或最优策略 \(\pi_*\)
-
迭代策略评估(Iterative Policy Evaluation)
给定 MDP 模型,评估策略 \(\pi\),即,计算其价值函数 \(v_\pi\)
迭代策略评估:反复应用 贝尔曼期望方程 进行迭代
同步(synchronous)迭代:\(k+1\) 步的价值函数 \(v_{k+1}(s)\) 由 \(k\) 步的价值函数 \(v_k(s)\) 针对所有状态 \(s \in \mathcal{S}\) 统一进行更新
扩展阅读:收缩映射定理(Contraction Mapping Theorem) 保证上述迭代过程一定会收敛到唯一的不动点 \(v_\pi\)
刚刚手推了一下,这个让我感觉好像高中做的那种被称为 “马尔科夫链” 的题,也是找出递推式,然后左右取极限,(其实是转移矩阵的很多次迭代),得到稳定值。当然,这个的求法也可以矩阵特征值分解,然后令 n 趋于无穷。我觉得这个就有点像迭代,然后稳定到一个值,这就是在这个策略下的价值。
\(e.g.1\) \(\langle \mathcal{S}, \mathcal{P} \rangle\) 小明家楼下有两家早餐铺,其中A主营小笼包,B主营煎饼果子。当某日小明早餐选择 \(A\) ,那么下一天就有可能 \(\begin{cases} 40\%选择A \\ 60\%选择B \end{cases}\) ;若某日选择 \(B\) ,那么下一天就有 \(\begin{cases} 50\%选择A \\ 50\%选择B \end{cases}\) 。若第一天选择A,那么第 n 天选择A的概率是多少?
- $\mathcal{S} = { A , B } $
- \(\mathcal{P} : P (A | A) = 0.4, P( B | A ) = 0.6, P(A|B) = 0.5, P(B|B) = 0.5\)
\(e.g.2\) 甲乙丙丁4人传接球训练,球从甲脚下开始,等可能地随机传向3人中的一人,接球者接到球后,再等可能地随机传向另外3人中的1人,依此类推。假设所有传出的球都能接住。
记第\(n\)次传球之前,球在甲脚下的概率为\(P_n\ (n \in \mathbb{N}^*)\),易知\(P_1 = 1, P_2 = 0\) \(\\\)
(1) 推导\(P_n\)相关的递推式及通项 \(\\\)
(2) 设第\(n\)次传球之前,球在乙脚下的概率为\(Q_n\),比较\(P_n\)与\(Q_n\ (n \geq 2)\)的大小
策略迭代算法
策略评估(Policy Evaluation) :给定当前策略 \(\pi\) ,计算其价值函数 \(v_\pi\) 。如,迭代策略评估,线性代数直接求解等。
策略改进(Policy Improvement) :在每个状态 \(s\) 上,基于 \(v_\pi\) 采取 贪心行动 \(\pi' = \text{greedy}(v_\pi)\)
收缩映射定理(Contraction Mapping Theorem) :保证上述迭代过程一定会收敛到唯一的不动点,最优策略 \(\pi^*\)
价值迭代算法
若已知子问题的最优值函数解 \(v_*(s')\)
则状态 \(s\) 的最优值函数解 \(v_*(s)\) 可通过一步迭代得到:
价值迭代:按上述公式迭代更新
与策略迭代不同,值迭代中没有显式的策略表示,中间过程的值函数可能不对应任何实际策略
代码示例
import numpy as np
import pandas as pd
# 环境参数
grid_size = (3, 3)
# 状态
states = [(i, j) for i in range(grid_size[0]) for j in range(grid_size[1])]
terminal = (2, 1) # 终止状态
# 动作 A
actions = {
'↑': (-1, 0),
'↓': (1, 0),
'←': (0, -1),
'→': (0, 1),
}
# 折扣因子
gamma = 1.0
# 初始策略:均匀随机
policy = {s: {a: 1/4 for a in actions} for s in states if s != terminal}
# 转移与奖励
def step(s, a):
# 状态转移
if s == terminal:
return s, 0
di, dj = actions[a]
ni, nj = s[0] + di, s[1] + dj
if 0 <= ni < grid_size[0] and 0 <= nj < grid_size[1]:
next_s = (ni, nj)
else:
next_s = s
# 即时奖励
reward = 0 if next_s == terminal else -1
# 转移后的状态、这一步的奖励
return next_s, reward
# 迭代式策略评估
def policy_evaluation(policy, theta=1e-4):
# 初始化价值函数:都为0
V = {s: 0.0 for s in states}
# 迭代过程
while True:
delta = 0
for s in states:
if s == terminal:
continue
# 新的价值状态
v_new = 0.0
# 把原价值状态存储起来
v = V[s]
# 对每个动作按策略加权
for a, pa in policy[s].items():
# TODO:
next_s, reward = step(s, a)
v_new += pa * (reward + gamma * V[next_s])
# 更新
V[s] = v_new
# 收敛时停止更新
delta = max(delta, abs(V[s] - v))
if delta < theta:
break
return V
# 策略改进
def policy_improvement(V):
new_policy = {}
# 对于所有状态,每项动作都试一遍
for s in states:
if s == terminal:
continue
# 计算所有动作的Q值
q_vals = {}
for a in actions:
next_s, reward = step(s, a)
q_vals[a] = reward + gamma * V[next_s]
# 找到最大Q值对应的动作集
max_q = max(q_vals.values())
best_as = [a for a, q in q_vals.items() if np.isclose(q, max_q)]
prob = 1 / len(best_as)
# 更新策略
new_policy[s] = {a: (prob if a in best_as else 0.0) for a in actions}
return new_policy
# 策略迭代
def policy_iteration():
current_policy = policy.copy()
while True:
# 1. 按当前策略评估价值函数
V = policy_evaluation(current_policy)
# 2. 改进策略
new_policy = policy_improvement(V)
# 3. 检查策略是否稳定
if all(new_policy[s] == current_policy[s] for s in new_policy):
return V, new_policy
current_policy = new_policy
# 运行
V_opt, policy_opt = policy_iteration()
# 输出结果
v_matrix = np.array([[V_opt[(i, j)] for j in range(3)] for i in range(3)])
p_matrix = np.array([[ ''.join([a for a in actions if policy_opt.get((i,j), {}).get(a,0)>0])
for j in range(3)] for i in range(3)])
df_values = pd.DataFrame(v_matrix, index=[f"Row {i}" for i in range(3)],
columns=[f"Col {j}" for j in range(3)])
df_policy = pd.DataFrame(p_matrix, index=[f"Row {i}" for i in range(3)],
columns=[f"Col {j}" for j in range(3)])
print("Optimal Value Function V*:")
print(df_values)
print("\nOptimal Policy π*:")
print(df_policy)
运行结果:
Optimal Value Function V*:
Col 0 Col 1 Col 2
Row 0 -2.0 -1.0 -2.0
Row 1 -1.0 0.0 -1.0
Row 2 0.0 0.0 0.0
Optimal Policy π*:
Col 0 Col 1 Col 2
Row 0 ↓→ ↓ ↓←
Row 1 ↓→ ↓ ↓←
Row 2 → ←

浙公网安备 33010602011771号