欢迎来到图解强化学习的世界博客主页卿云阁欢迎关注点赞收藏⭐️留言首发时间2026年5月23日✉️希望可以和大家一起完成进阶之路目录Actor-Critic算法的基础认识Actor-Critic算法的网络结构Actor策略网络Critic价值网络Actor-Critic算法的网络更新手算AC算法网络的输入输出选择动作模型更新核心点Actor-Critic算法的基础认识Actor-Critic演员 - 评论家算法价值算法只估价值不能直接优化动作策略连续动作不好处理纯策略梯度更新方差大、收敛慢要等回合结束才能更新AC 算法Actor 直接优化行动策略适配各类动作空间。Critic 实时评估动作好坏降低更新波动、加速收敛。边交互边更新不用等待回合完结学习效率更高Actor-Critic算法的网络结构Actor策略网络目标在状态 s 下输出动作 a让未来总奖励最大化。输入状态 s输出离散动作动作概率分布连续动作确定性动作或动作分布参数学习方式根据 Critic 的评价调整策略参数让 “高分动作” 出现的概率越来越高。Critic价值网络目标学会给 Actor 的动作打分判断 “这个动作在当前状态下好不好”。输入状态 s或状态 动作 (s,a)输出状态价值 (V(s))在状态 s 下未来能拿到多少平均奖励动作价值 (Q(s,a))在状态 s 做动作 a未来能拿到多少平均奖励。学习方式用 TD 误差时序差分误差更新价值估计让打分越来越准。Actor-Critic算法的网络更新Actor的更新目的让 Actor 根据 Critic 的评价TD 误差调整动作策略让好动作被更多选择坏动作被更少选择持续优化决策。1获取当前交互得到的状态 s、动作 a、奖励 r、下一状态 s、是否结束 done。2将状态 s 输入 Critic 网络得到当前状态价值 V (s)将下一状态 s 输入 Critic 网络得到下一状态价值 V (s)。3Critic 计算 TD 误差δ r γ * V (s) - V (s)δ 代表动作的好坏正 好负 差4将状态 s 输入 Actor 网络得到策略对动作 a 的输出概率 / 得分。5依据策略梯度定理更新在线 Actor 网络参数Actor 根据 Critic 算出的 TD 误差来更新动作好就加强动作差就减弱。TD Target时序差分目标优势函数AdvantageActor 损失策略梯度Critic的更新目的精准预估状态价值缩小评估偏差为 Actor 优化提供可靠评判依据1获取单步交互数据当前状态s、即时奖励r、下一状态s、终止标记done2把s、s分别输入 Critic 网络得到估值(V(s))与(V(s))3计算时序差分误差4以误差为损失依据反向传播更新 Critic 网络参数不断修正估值结果Critic 损失价值回归手算AC算法网络的输入输出input_dim 6 Acrobot 的 6 维观测空间两个角余弦、两个角正弦、两个角速度output_dim 3 Acrobot 的 3 个离散动作-1扭矩, 0扭矩, 1扭矩假设输入X是X [1.0, 0.0, 1.0, 0.0, 0.0, 0.0]actor_output:[0.07, 0.93, 0.00] 给环境采样用的动作概率动作 0向左猛踢-1扭矩0.07 (7%)动作 1腰部放松0扭矩0.93 (93%)动作 2向右猛踢1扭矩0.00 (0%)critic_output:-98.5 状态价值选择动作假设此时 Acrobot 的状态 state 如下对应 [cos1, sin1, cos2, sin2, v1, v2]state [0.0, 1.0, 1.0, 0.0, 0.5, -0.2]action_probtensor([[0.02, 0.85, 0.13]])action 1大概率会返回 1但有极小可能返回 0 或 2是一个采样过程所以这段代码的作用是根据当前动作输入到Actor网络中选择出一个动作。模型更新假设我们的 buffer 如下经验1(s1, a12, r1-1.0, ns1, d10) 经验2(s2, a20, r2-1.0, ns2, d20) states [ [1,0,1,0,0,0], # s1 [0,1,0,1,0.1,0.1] # s2 ] actions [2, 0] rewards [-1.0, -1.0] dones [0, 0] gamma 0.99 默认AC常用网络前向输出Actor 输出动作概率action_prob [ [0.07, 0.93, 0.00], # s1 对应动作概率 [0.02, 0.85, 0.13] # s2 对应动作概率 ]Critic 输出当前状态价值state_value [ [-98.5], # V(s1) [-95.0] # V(s2) ]Critic 输出下一状态价值next_state_value [ [-97.0], # V(s1) [-93.0] # V(s2) ]手工计算经验 1td_target1 -1.0 0.99 * 1.0 * (-97.0) -1.0 - 96.03 -97.03经验 2td_target2 -1.0 0.99 * 1.0 * (-93.0) -1.0 - 92.07 -93.07最终td_target [-97.03, -93.07]计算 TD Delta误差经验 1td_delta1 -97.03 - (-98.5) 1.47经验 2td_delta2 -93.07 - (-95.0) 1.93最终td_delta [1.47, 1.93]正数 → 动作比预期好 → Actor 要加强这个动作计算 log_prob动作对数概率log_prob2 log(0.02) ≈ -3.91log_prob log( 选中动作的概率 )经验 1动作 a2概率 0.00log_prob1 log(0.00) → 负无穷这里我们换成 0.01 方便计算 log(0.01) ≈ -4.6经验 2动作 a0概率 0.02log_prob2 log(0.02) ≈ -3.91最终log_prob [-4.6, -3.91]计算 Actor Loss经验 1 -4.6 * 1.47 -6.76 经验 2 -3.91 * 1.93 -7.55 平均 mean (-6.76 -7.55) / 2 -7.155 加负号 actor_loss -(-7.155) 7.155计算 Critic Loss经验 1 (-98.5 97.03)² (-1.47)² 2.16 经验 2 (-95.0 93.07)² (-1.93)² 3.72 平均 critic_loss (2.16 3.72) / 2 2.94 第六步总 Loss loss actor_loss 0.5 * critic_loss 7.155 0.5*2.94 7.155 1.47 8.625td_target [-97.03, -93.07] td_delta [1.47, 1.93] log_prob [-4.6, -3.91] actor_loss 7.155 critic_loss 2.94 total_loss 8.625Critic 让自己的估值更准Actor 因为 td_delta 为正加强了刚才选择的动作AC 只需要一步数据就能更新不需要等回合结束AC算法是单步更新在线更新AC算法核心更新仅依赖单步交互数据s,a,r,s满足即时计算TD误差、完成参数更新的数学条件天生支持单步更新传统策略梯度需整回合累计回报才能计算无法单步更新。代码采用回合批量更新只是为提升训练稳定性与运算效率。核心点Actor 损失为什么是actor_loss - (log_prob * td_delta).mean()Actor 的任务让 “好动作” 概率变高让 “坏动作” 概率变低。对数转换后乘积求导转为加减求导梯度计算大幅简化。最大化动作概率等价于最大化对数概率配合负号就能转为深度学习通用的最小损失优化范式。log_prob torch.log( 策略网络输出的动作概率 )你选了这个动作就取这个动作的概率再取对数例子概率 0.07 → log (0.07) ≈ -2.66作用用来告诉网络 “我刚才选了哪个动作”。td_delta 实际收益 - 网络预估收益td_delta 0这个动作比想象中好td_delta 0这个动作比想象中差作用评价刚才动作的好坏为什么要把 log_prob 和 td_delta 乘起来loss_part log_prob * td_delta本质含义✅ 如果动作好td_delta 正log (prob) 是负数正数 × 负数 负数❌ 如果动作差td_delta 负log (prob) 是负数负数 × 负数 正数为什么前面要加一个 负号actor_loss - loss_part好动作 → 算出来是负数 → 加负号 → 变成正数 → 网络会减小它 → 让概率上升坏动作 → 算出来是正数 → 加负号 → 变成负数 → 网络会增大它 → 让概率下降神经网络永远做一件事想尽办法 让 损失loss 变 小不管你怎么设计公式网络只会loss 越小越好 → 拼命减小 loss好动作的损失是正数actor_loss - ( -0.2 ) 0.2现在网络要做什么网络想让 loss 变小loss 现在是 0.2网络想把它变成 0.1、0.05、0…怎么才能让 loss 变小必须让 log_prob 变大从 -0.1 → -0.05 → -0.01log_prob 变大 → 概率变大