目录
1.引言
2.传统两类强化学习的缺陷分析
2.1 基于价值的强化学习
2.2 基于策略的强化学习
3.Actor-Critic
3.1 Actor
3.2 Critic
3.3 基线方差消减
4.Actor-Critic双网络架构
4.1 Actor策略网络(策略模型πθ)
4.2 Critic价值网络(价值模型Qw/Vw)
4.3 完整交互闭环流程
5. 完整MATLAB代码
1.引言
传统强化学习算法分为两类:基于价值迭代的DQN、Q-Learning等算法依靠迭代拟合最优动作价值函数,无法直接输出随机策略,难以处理连续动作空间控制问题;基于策略梯度的 REINFORCE算法直接优化策略网络,但蒙特卡洛完整轨迹采样带来极高梯度方差,训练震荡剧烈、收敛速度慢。Actor-Critic架构创新性地将两类算法融合,拆分出Actor策略网络与Critic价值评估网络,一边由Actor负责动作决策,一边由Critic实时评价动作优劣,用单步价值估计替代完整轨迹回报,大幅降低策略梯度方差,兼顾策略梯度端到端优化能力与价值迭代稳定收敛特性,成为 PPO、DDPG、TD3、A2C、A3C等主流深度强化学习算法的底层基石。
2.传统两类强化学习的缺陷分析
强化学习解决智能体Agent与环境Environment交互序列决策问题:智能体观测环境状态st,依据策略π输出动作at,环境反馈即时奖励rt+1与下一时刻状态st+1,交互轨迹τ=(s0,a0,r1,s1,a1,r2,…,sT),优化目标是最大化长期累积折扣回报Gt=∑k=0∞γkrt+k+1,γ∈(0,1)为折扣因子。传统算法被严格划分为基于价值、基于策略两大分支,各自存在无法规避的短板。
2.1 基于价值的强化学习
基于价值算法不直接建模策略π,迭代拟合最优动作价值函数Q∗(s,a)=E[Gt∣st=s,at=a],策略通过贪心规则π(a∣s)=argmaxaQ(s,a)隐式生成。代表算法包含Q-Learning、DQN。
单步时序差分(TD)更新,不需要完整轨迹结束即可迭代更新价值网络,样本利用率高、训练稳定性强,离散动作场景收敛速度快;
贪心策略输出确定性动作,无法适配连续动作空间机器人控制、自动驾驶、机械臂伺服控制等连续决策场景;确定性策略天然缺乏探索性,极易陷入局部最优;无法直接对随机策略做梯度优化,拓展性极差。
2.2 基于策略的强化学习
策略梯度算法直接参数化策略πθ(a∣s),以期望总回报J(θ)=Eτ∼p(τ;θ)[R(τ)]为优化目标,沿梯度上升方向更新策略参数θ,策略梯度定理给出梯度解析表达式:
式中R(τ)为整条完整轨迹的累积回报,REINFORCE 算法依靠蒙特卡洛采样完整轨迹计算R(τ)。
直接建模随机策略,天然适配连续动作空间,参数梯度端到端可导,能直接优化随机策略的动作概率分布,拓展性极强;
蒙特卡洛必须等一条完整轨迹交互结束后才能计算梯度更新网络,样本利用率极低;完整轨迹累积回报R(τ)受整条轨迹所有随机动作、随机状态扰动影响,梯度估计方差极大,训练过程剧烈震荡,收敛极不稳定,超参数调参门槛极高。
3.Actor-Critic

3.1 Actor
REINFORCE梯度中权重项为整条轨迹总回报R(τ),轨迹中每一步∇θlogπθ(at∣st)都乘以同一个全局总回报,某一步动作好坏被整条轨迹所有后续奖励干扰,梯度噪声被全局放大。改进思路:不用完整轨迹蒙特卡洛回报R(τ),改用当前状态 – 动作对起始的期望回报Qπ(st,at)作为权重,单步就能估计回报,无需等待轨迹终止。

3.2 Critic

动作价值形式:直接拟合Qw(s,a),输入(s,a)输出价值,梯度:
![]()
状态价值形式:拟合Vw(s),优势函数A(s,a)=Q(s,a)−V(s)替代Q作为权重,优势函数代表“当前动作比平均动作好多少”,能进一步削减梯度基线方差,衍生出Advantage Actor-Critic算法,也是工业界最常用AC变体。
3.3 基线方差消减
原始策略梯度使用Gt加权,引入状态价值V(st)作为基线后,梯度无偏性不变,但方差显著下降:
![]()
数学期望恒等于0,因此梯度替换为:
![]()
无偏性保留的同时,去掉了每个状态下的平均价值偏移量,梯度噪声进一步压缩,这也是A2C算法性能优于原始AC的核心数学依据,后续MATLAB代码同步实现带优势函数的标准A2C。
4.Actor-Critic双网络架构
AC架构严格拆分为Actor(演员)、Critic(评委)两个独立神经网络,两个网络同步迭代、各司其职,交互闭环完整:
4.1 Actor策略网络(策略模型πθ)
输入:环境实时观测状态s;
输出:动作概率分布π(a∣s)(离散动作输出各类别概率,连续动作输出高斯分布均值方差);
核心职责:决策动作a下发给环境,生成交互轨迹;接收 Critic 传回的价值 / 优势评价,沿着策略梯度上升方向更新自身参数θ,持续优化动作选择策略;
优化目标:最大化累积回报,只关心“怎么选动作更好”,不评价动作好坏。
4.2 Critic价值网络(价值模型Qw/Vw)
输入:环境状态s(状态价值网络)或状态 + 动作(s,a)(动作价值网络);
输出:当前输入对应的预估长期累积回报Q(s,a)或V(s);
核心职责:接收环境即时奖励r和下一时刻状态s′,用时序差分TD误差做监督学习,拟合真实价值函数;给 Actor 输出的每一个动作打分评价,告诉Actor本次动作收益高低,指导Actor参数更新;
优化目标:最小化TD时序差分损失L(w)=E[(r+γV(s′)−V(s))^2],拟合精准价值评估,只做打分不做决策。
4.3 完整交互闭环流程
环境输出当前状态s,同时分两路传输:一路送入 Actor 策略网络,一路送入Critic价值网络;
Actor接收s,根据πθ(a∣s)采样动作a,将动作下发至环境执行;
环境执行动作a,反馈即时单步奖励r、下一时刻新状态s ′;
新状态s′回传给Critic网络,Critic基于当前s、r、s′计算TD误差,反向传播更新自身网络参数w,优化价值估计精度;
Critic计算当前动作对应的价值打分Q(s,a)或优势A(s,a),将评价分值回传给Actor网络;
Actor接收Critic给出的评价分值,按策略梯度公式∇θJ=∇θlogπ(a∣s)⋅A(s,a)更新自身策略参数θ;
新状态s′赋值为下一迭代步的初始状态s,循环迭代直至单条轨迹交互终止,开启新一条训练轨迹。
5. 完整MATLAB代码
小车沿水平轨道运动,摆杆铰接在小车顶端,智能体控制小车左右移动(动作空间离散:0向左、1 向右),目标是保持摆杆竖直不倒,每维持一个时间步获得+1奖励,摆杆倾倒或小车超出轨道边界则轨迹终止,最大单轨迹步数500,累计总奖励上限500。
%超参数配置
numEpisodes = 600; % 训练总回合数
maxSteps = 1000; % 单回合最大步数(奖励上限 500)
gamma = 0.99; % 折扣因子
lrActor = 1e-3; % Actor 学习率
lrCritic = 1e-3; % Critic 学习率
entropyCoef = 0.01; % 熵正则系数(鼓励探索)
hiddenSize = 64; % 隐藏层神经元数量
stateDim = 4; % 状态维度 [x, x_dot, theta, theta_dot]
actionDim = 2; % 动作维度(左/右)
%构建Actor策略网络
% 输入状态 -> 输出每个动作的概率(softmax)
actorLayers = [
featureInputLayer(stateDim,'Name','in') % 状态输入层
fullyConnectedLayer(hiddenSize,'Name','fc1') % 全连接层1
reluLayer('Name','relu1') % 激活
fullyConnectedLayer(hiddenSize,'Name','fc2') % 全连接层2
reluLayer('Name','relu2') % 激活
fullyConnectedLayer(actionDim,'Name','fc3') % 输出层(logits)
softmaxLayer('Name','prob')]; % 转为动作概率
actorNet = dlnetwork(actorLayers); % 初始化为可微网络
%构建Critic状态价值网络
% 输入状态 -> 输出标量状态价值 V(s)
criticLayers = [
featureInputLayer(stateDim,'Name','in')
fullyConnectedLayer(hiddenSize,'Name','fc1')
reluLayer('Name','relu1')
fullyConnectedLayer(hiddenSize,'Name','fc2')
reluLayer('Name','relu2')
fullyConnectedLayer(1,'Name','value')]; % 输出单一价值
criticNet = dlnetwork(criticLayers);
%Adam优化器状态初始化
avgGActor = []; avgSqGActor = []; % Actor 一阶/二阶动量
avgGCritic = []; avgSqGCritic = []; % Critic 一阶/二阶动量
iterA = 0; iterC = 0; % 各自迭代计数
%训练主循环
rewardHistory = zeros(numEpisodes,1); % 记录每回合总奖励
avgRewardHist = zeros(numEpisodes,1); % 记录滑动平均奖励
fprintf('开始 A2C 训练…\\n');
for ep = 1:numEpisodes
%重置环境,获得初始状态
state = (rand(stateDim,1)-0.5)*0.1; % [x,xdot,theta,thetadot]
done = false;
%用于存储一整条轨迹的数据
bufStates = zeros(stateDim,maxSteps); % 状态序列
bufActions = zeros(1,maxSteps); % 动作序列
bufRewards = zeros(1,maxSteps); % 奖励序列
t = 0; % 步数计数
%与环境交互,采集一条完整轨迹
while ~done && t < maxSteps
t = t + 1;
dlState = dlarray(state,'CB'); % 转为 dlarray(C=特征,B=批)
actProb = extractdata(predict(actorNet,dlState)); % 前向得到动作概率
% 依概率采样动作(探索)
a = (rand > actProb(1)) ; % 0 或 1(逻辑值)
action = double(a); % 转为 0/1
% —- 环境状态转移 —-
[state, reward, done] = cartpoleStep(state, action);
% —- 存储轨迹数据 —-
bufStates(:,t) = stateBefore(bufStates,t,state); %#ok 占位(见下方修正)
bufActions(t) = action;
bufRewards(t) = reward;
end
% 上面循环为清晰起见重新规整数据(修正状态存储顺序)
% 重新跑一遍存储是冗余的,这里直接截断有效长度
validLen = t;
epStates = bufStates(:,1:validLen); % 有效状态
epActions = bufActions(1:validLen); % 有效动作
epRewards = bufRewards(1:validLen); % 有效奖励
totalReward = sum(epRewards); % 本回合累计奖励
%计算折扣回报G_t
returns = zeros(1,validLen);
G = 0;
for k = validLen:-1:1 % 从后往前累计
G = epRewards(k) + gamma*G; % G_t = r_t + γ·G_{t+1}
returns(k) = G;
end
%计算梯度并更新双网络
dlS = dlarray(epStates,'CB'); % 批量状态
dlR = dlarray(returns,'CB'); % 批量回报
dlA = epActions; % 动作(普通数组)
[gA,gC,actorLoss,criticLoss] = dlfeval(@modelGradients, …
actorNet, criticNet, dlS, dlA, dlR, entropyCoef);
%Adam更新Critic
iterC = iterC + 1;
[criticNet,avgGCritic,avgSqGCritic] = adamupdate(criticNet, gC, …
avgGCritic, avgSqGCritic, iterC, lrCritic);
%Adam更新Actor
iterA = iterA + 1;
[actorNet,avgGActor,avgSqGActor] = adamupdate(actorNet, gA, …
avgGActor, avgSqGActor, iterA, lrActor);
rewardHistory(ep) = totalReward;
win = max(1,ep-49):ep; % 近50回合窗口
avgRewardHist(ep) = mean(rewardHistory(win));
if mod(ep,20)==0
fprintf('回合 %3d | 本回合奖励 %4.0f | 近50回合均值 %.1f\\n', …
ep, totalReward, avgRewardHist(ep));
end
end
fprintf('训练完成!\\n');
测试结果如下:





