# RL_basic_study **Repository Path**: xiao_peipei/rl_basic_study ## Basic Information - **Project Name**: RL_basic_study - **Description**: 基础贝尔曼方程学习(环境:grid world) - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-29 - **Last Updated**: 2026-08-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 学习TD ## 回顾 state value 的贝尔曼方程: 期望形式: $$v_{\pi}=\mathbb{E}_{\pi}\big[R+\gamma P_{\pi}v_{\pi}\big]$$ 其元素形式下: $$v_{\pi}(s)=\sum_{a}\pi(a|s)\sum_{s'}p(s'|s,a)\big[r(s,a,s')+\gamma v_{\pi}(s')\big]$$ 矩阵形式为: $$v_{\pi}=(I-\gamma P_{\pi})^{-1}R_{\pi}$$ 求解方法有: 1. 迭代方法求解:$$v_{k+1}=R_{\pi}+\gamma P_{\pi}v_k$$ 2. 矩阵求逆方法求解:$$v_k=(I-\gamma P_{\pi})^{-1}R_{\pi}$$ 如果没有模型的Ppi 的转移概率,则可以用数据驱动学习,TD 估计 Vt 的公式 :$$v_t=v_{t}-\alpha_{t}[v_t(s_{t}) - (r_{t+1}+\gamma v_{t+1}(s_{t+1}))]$$ 其中 TD target:$$r_{t+1}+\gamma v_{t+1}(s_{t+1})$$ TD error:$$\delta_t=v_t(s_{t}) - \big(r_{t+1}+\gamma v_{t+1}(s_{t+1})\big)$$ ## 引入 Q value 的贝尔曼方程: 从V值中引入Q:$$v_{\pi}(s)=\sum_{a\in\mathcal{A}}\pi(a|s)\,q_{\pi}(s,a)$$ 因此 Q值定义为 :$$Q_{\pi}(s,a)=r(s,a)+\gamma\sum_{s'}P(s'|s,a)\,v_{\pi}(s')$$ 由此得到 Q值的贝尔曼方程: 元素形式: $$Q_{\pi}(s,a)=R(s,a)+\gamma\sum_{s'}P(s'|s,a)\sum_{a'}\pi(a'|s')Q_{\pi}(s',a')$$ 矩阵形式: $$\mathbf{q}_{\pi}=\mathbf{r}+\gamma\mathbf{P}_{\pi}\mathbf{q}_{\pi}$$ 其中各变量维度如下(设状态数为 $|\mathcal{S}|$,动作数为 $|\mathcal{A}|$,令 $N=|\mathcal{S}|\times|\mathcal{A}|$): - $\mathbf{q}_{\pi}\in\mathbb{R}^{N\times 1}$:所有状态-动作对的 Q 值向量,第 $i$ 个元素为 $Q_{\pi}(s_i,a_i)$ - $\mathbf{r}\in\mathbb{R}^{N\times 1}$:奖励向量,第 $i$ 个元素为 $R(s_i,a_i)$ - $\mathbf{P}_{\pi}\in\mathbb{R}^{N\times N}$:状态-动作对之间的转移概率矩阵,元素 $[\mathbf{P}_{\pi}]_{ij}=\sum_{s'}P(s'|s_i,a_i)\pi(a_j|s')$,表示从 $(s_i,a_i)$ 转移到 $(s',a_j)$ 的概率 - $\gamma\in[0,1)$:折扣因子 已知模型信息下,求解方法有: 1. 迭代方法求解:$$Q_{k+1}=\mathbf{r}+\gamma\mathbf{P}_{\pi}Q_{k}$$ 2. 矩阵求逆方法求解:$$Q_{\pi}=(I-\gamma\mathbf{P}_{\pi})^{-1}\mathbf{r}$$ ```python from grid_world import GridWorld import numpy as np import matplotlib.pyplot as plt # ---------- 元素形式下: 迭代求解 action value:策略评估(给定 π)---------- def iterative_action_value(env, policy, gamma=0.9, theta=1e-6, max_iter=1000,TD_max=False): Q = np.zeros((env.num_states, env.num_actions)) for _ in range(max_iter): Q_new = np.zeros_like(Q) for s in range(env.num_states): for a in range(env.num_actions): s1 = env.get_next_state_index(s, a) if TD_max: # TD target 取 max Q(s',a'),求解最优贝尔曼的Q值 next_Q = np.max(Q[s1]) # ← 用策略 π 的期望 (这个值就是state value) else: next_Q = np.sum(policy[s1] * Q[s1]) # ← 用策略 π 的期望 (这个值就是state value) Q_new[s, a] = env.get_reward(s, a) + gamma * next_Q if np.max(np.abs(Q_new - Q)) < theta: break Q = Q_new return Q # ---------- 矩阵形式下: 迭代求解 和 直接求解 action value:策略评估(给定 π)---------- def iterative_action_value_matrix(env, policy, gamma=0.9, theta=1e-6, max_iter=1000,TD_max=False): S, A = env.num_states, env.num_actions # ---- 构造 P^π (125×125) 和 P (125×25) ---- P_pi = np.zeros((S*A, S*A)) P = np.zeros((S*A, S)) for s in range(S): for a in range(A): s1 = env.Nstate[s, a] # 获取 s, a 对应的下一个状态 s1 P[s*A+a, s1] = 1.0 # 确定性环境,s,a 到 s1 概率是 1 for a1 in range(A): P_pi[s*A+a, s1*A+a1] = policy[s1, a1] # A 的联合转移 r_vec = env.r.reshape(-1, 1) # (125,1) # ---- A 矩阵法(一次性闭式解)---- :max 操作下是非线性方程,只能迭代求解 Q_pi_matrix = np.linalg.solve(np.eye(S*A) - gamma*P_pi, r_vec).reshape(S, A) # ---- B 矩阵算子迭代法 ---- Q = np.zeros((S, A)) for _ in range(max_iter): if TD_max: v_next = Q.max(axis=1).reshape(-1, 1) # (25,1) else: v_next = (policy * Q).sum(axis=1).reshape(-1, 1) # (25,1) 按策略 pi 加权得到 v(s') Q_new = (r_vec + gamma * P @ v_next).reshape(S, A) # Q = r + γ*P*v 的迭代形式,等价于 Q = r + γ*P^π*Q if np.max(np.abs(Q_new - Q)) < theta: break Q = Q_new return Q_pi_matrix, Q # Q 值是可以取max操作求解的,Q_pi_matrix 不能,返回的就是正常Q值 ``` ### 迭代求解 Q 值 ```python env = GridWorld() policy_matrix=[1,1,1,1,0,2,2,1,1,0,2,3,0,1,0,2,1,4,3,0,2,1,2,3,3] policy_softgreedy = env.index_list_to_softonehot_matrix(policy_matrix,num_actions=5,epsilon=0.4) Q_iter =iterative_action_value(env, policy_softgreedy,gamma=0.9, theta=1e-6, max_iter=1000,TD_max=False) Q_matrix, Q_iter_matrix = iterative_action_value_matrix(env, policy_softgreedy,gamma=0.9, theta=1e-6, max_iter=1000,TD_max=False) err1 = np.max(np.abs(Q_iter_matrix - Q_matrix)) err2 = np.max(np.abs(Q_iter - Q_iter_matrix)) print('err1: {}, err2: {}'.format(err1,err2)) # 0.0, 0.0,结果表明,不管是元素方法迭代还是矩阵方法迭代或者求逆,结果都一样 env.plot_action_values(Q_iter) ``` ``` err1: 9.74128044717304e-06, err2: 0.0 ``` ![png](main_files/main_3_1.png) ### 无模型下,用TD方法估计 Q value ```python env = GridWorld() # policy_matrix=[1,1,1,0,0,2,2,1,0,0,2,3,0,1,0,2,1,4,3,0,2,1,2,3,3] policy_matrix=[1,1,1,1,0,2,2,1,1,0,2,3,0,1,0,2,1,4,3,0,2,1,2,3,3] policy_softgreedy = env.index_list_to_softonehot_matrix(policy_matrix,num_actions=5,epsilon=0.4) # env.plot_policy(policy_softgreedy) est_actionValue,errors= env.TD7_1_estimate_action_value(policy_softgreedy,start_state=0,len_episodes=200000, gamma=0.9,Alpha=50) env.plot_action_values(est_actionValue) err3 = np.max(np.abs(Q_iter - est_actionValue)) print('err3: {}'.format(err3)) # ``` ![png](main_files/main_5_2.png) ``` err3: 2.9300646507970285 ``` ```python plt.subplot() # 绘制收敛误差曲线 log 对数坐标 # plt.plot(np.log(errors), label='Truncate Num=1') plt.plot(errors, label='len=100000') plt.legend() plt.xlabel('Iteration') plt.ylabel('Convergence Error') plt.title('Convergence Error vs Iteration') plt.grid(True) plt.tight_layout() plt.show() ``` ![png](main_files/main_6_3.png) ## 引入最优 Q value 的贝尔曼方程: 最优 Q 值贝尔曼方程(最优策略 $\pi_*$ 下,与行为策略无关),元素形式: $$Q_*(s,a)=R(s,a)+\gamma\sum_{s'}P(s'|s,a)\max_{a'}Q_*(s',a')$$ 简写:$$Q_* = r + \gamma \max Q_*$$(确定性环境下 $\sum_{s'}P(s'|s,a)$ 只剩一个 $s'$,max 作用于下一状态的各动作 Q 值) 最优 state value 为 $V_*(s)=\max_a Q_*(s,a)$,对上式两边关于 $a$ 取最大值,即退化为最优 state value 的贝尔曼方程: $$V_*(s)=\max_a\Big[R(s,a)+\gamma\sum_{s'}P(s'|s,a)V_*(s')\Big]$$ 注意:$\max$ 操作是非线性的,最优贝尔曼方程**没有矩阵求逆闭式解**,只能迭代求解(如价值迭代 Value Iteration): $$Q_{k+1}(s,a)=R(s,a)+\gamma\sum_{s'}P(s'|s,a)\max_{a'}Q_k(s',a')$$ ### 迭代求解最优 Q 值 ```python # 迭代求解 最优的 Q value , 与前面代码一致,除了修改 TD_max=False 改成 True env = GridWorld() policy_matrix=[1,1,1,1,0,2,2,1,1,0,2,3,0,1,0,2,1,4,3,0,2,1,2,3,3] policy_softgreedy = env.index_list_to_softonehot_matrix(policy_matrix,num_actions=5,epsilon=0.4) Q_iter_max =iterative_action_value(env, policy_softgreedy,gamma=0.9, theta=1e-6, max_iter=1000,TD_max=True) Q_matrix, Q_iter_matrix_max = iterative_action_value_matrix(env, policy_softgreedy,gamma=0.9, theta=1e-6, max_iter=1000,TD_max=True) err4 = np.max(np.abs(Q_iter_max - Q_iter_matrix_max)) print('err4: {}'.format(err4)) # 0.0, 0.0,结果表明,不能直接用矩阵求逆得到,因为 max 操作是非线性的,必须迭代求解 env.plot_action_values(Q_iter_max) ``` ``` err4: 0.0 ``` ![png](main_files/main_9_4.png) ### 验证迭代求解最优Q值得到最优策略 对 最优 Q 值取max操作,就得到了最优 state value , 取最大值动作方向即为最优策略。 (注意:Q learning 算法中,理论上不需要更新目标策略,用数据更新完最优Q值后,取最大动作方向就是最优策略) ```python maxAction = np.max(Q_iter_max, axis=1) # 取最大Q值 maxAction_Index = np.argmax(Q_iter_max, axis=1) # 取最优策略 env.grid_plot() optimal_policy_iter = env.index_list_to_softonehot_matrix(policy_matrix,num_actions=5,epsilon=0) env.plot_policy(optimal_policy_iter) env.add_values(maxAction) ``` ![png](main_files/main_11_5.png) ```python # 用 truncated_iteration_policy 求解真实的 optimal policy, 验证 optimal state value 的误差 optimal_policy, Vnew, errors2 = env.truncated_iteration_policy(gamma=0.9,theta=1e-3,truncate_num=10,max_iterations=1000) err5 = np.max(np.abs(Vnew.squeeze() - maxAction)) print('err5: {}'.format(err5)) # 0.0, 0.0,结果表明,用 truncated_iteration_policy 验证 optimal state value 的误差 ``` ``` err5: 5.55332867264724e-05 ``` ### 无模型下用 TD 方法估计 最优 Q 值 ```python # policy_matrix=[1,1,1,0,0,2,2,1,0,0,2,3,0,1,0,2,1,4,3,0,2,1,2,3,3] policy_matrix=[1,1,1,1,0,2,2,1,1,0,2,3,0,1,0,2,1,4,3,0,2,1,2,3,3] policy_softgreedy = env.index_list_to_softonehot_matrix(policy_matrix,num_actions=5,epsilon=0.4) est_actionValueMax,errors1= env.TD7_1_estimate_action_value_qLearning(policy_softgreedy,start_state=0,len_episodes=1000000, gamma=0.9,Alpha=10) env.plot_action_values(est_actionValueMax) ``` ![png](main_files/main_14_6.png) TD 方法估计最优Q值,比较难收敛,容易发散 ```python plt.subplot() # 绘制收敛误差曲线 log 对数坐标 # plt.plot(np.log(errors), label='Truncate Num=1') plt.plot(errors1, label='TD error') plt.legend() plt.xlabel('Iteration') plt.ylabel('Convergence Error') plt.title('Convergence Error vs Iteration') plt.grid(True) plt.tight_layout() plt.show() ``` ![png](main_files/main_16_7.png) 可视化 TD 估计最优Q值和真实最优Q值误差,大部分地方完全收敛,部分地方有较大误差。 ```python env.plot_action_values(est_actionValueMax - Q_iter_max) # 误差可视化 err6 = np.max(np.abs(est_actionValueMax - Q_iter_max)) print('err6: {}'.format(err6)) # 0.0, 0.0,结果表明,用 TD 方法估计最优Q值,误差很大,不能收敛 ``` ![png](main_files/main_18_8.png) ``` err6: 3.0059064020590958 ```