Actor-Critic强化学习算法原理与Matlab工程实现详解 📅 发布时间:2026/9/3 17:23:00 👁 浏览次数: 简介本资源是面向强化学习初学者与Matlab实践者的Actor-Critic算法完整实现包聚焦于连续/离散控制任务中的策略优化与价值评估协同训练问题适用于高校课程设计、科研原型验证及RL算法原理理解。压缩包共10个文件含7个核心MATLAB源码.m与3个备份脚本.asv涵盖环境仿真simulator.m、策略网络更新computpi.m、价值函数逼近evaluate.m、优势计算computpsi.m、主训练流程AC.m等关键模块结构清晰、注释充分便于分步调试与原理对照。资源仅5KB轻量易读无冗余依赖可直接在MATLAB R2020a及以上版本运行。目前已有460人学习下载读者可快速掌握Actor-Critic双网络架构设计、策略梯度更新机制、Critic均方误差损失构建以及rl Toolbox兼容的环境交互范式是深入理解深度强化学习中“决策评估”解耦思想的优质入门材料。1. 项目概述Actor-Critic网络与Matlab实现最近在整理硬盘时翻出了一个老项目文件名字就叫“actor-critic网络 Matlab.zip”。这让我想起了几年前为了搞明白强化学习里这个经典算法在Matlab里吭哧吭哧敲代码、调参数的日子。Actor-Critic翻译过来就是“演员-评论家”听起来挺文艺但在强化学习领域它可是一个非常核心且实用的算法框架。简单来说它把智能体Agent做决策的过程分成了两部分Actor演员负责根据当前环境状态选择要执行的动作Critic评论家则负责评价这个状态或者状态-动作对的好坏给Actor的“表演”打分。两者相互配合共同学习最终目标是让智能体学会一套能获得最高长期回报的策略。这个用Matlab实现的压缩包本质上就是一个完整的、可运行的Actor-Critic算法工具箱。它特别适合那些对强化学习理论有一定了解但希望有一个清晰、可修改的代码实现来加深理解或者想快速搭建一个原型进行算法验证的研究者、工程师和学生。Matlab环境以其强大的矩阵运算、丰富的可视化工具和相对友好的语法成为了很多算法初学者的首选实验平台。通过这个项目你不仅能看懂Actor-Critic是怎么工作的更能亲手运行它、修改它甚至用它来解决你自己的问题比如让一个小车学会平衡、让一个机械臂学会抓取或者在一个简单的游戏里找到最优策略。2. Actor-Critic核心原理深度拆解要真正用好这个Matlab工具包不能只停留在“跑通代码”的层面必须深入理解其背后的设计思想。这能帮助你在调试时知道该动哪里在扩展时知道如何下手。2.1 算法框架与核心思想Actor-Critic属于策略梯度Policy Gradient算法家族但它巧妙地引入了价值函数作为基线Baseline以降低训练方差从而比单纯的REINFORCE算法更稳定、收敛更快。它的核心运作机制是一个紧密耦合的闭环交互与采样智能体由Actor和Critic组成与环境交互。在时刻t智能体观察到环境状态s_t。Actor决策Actor网络通常是一个神经网络接收s_t输出一个动作的概率分布π(a|s_t)然后依此分布采样得到实际执行的动作a_t。环境反馈执行a_t后环境转移到新状态s_{t1}并给出即时奖励r_t。Critic评价Critic网络另一个神经网络负责评估状态的价值。它接收s_t或(s_t, a_t)输出一个标量值V(s_t)代表处于状态s_t的长期期望回报。计算优势函数这是关键一步。我们计算时序差分误差Temporal-Difference Error, TD-Errorδ_t r_t γ * V(s_{t1}) - V(s_t)。其中γ是折扣因子。这个δ_t可以理解为实际获得的回报r_t γV(s_{t1})与Critic之前预测的回报V(s_t)之间的差异也就是优势Advantage的一个无偏估计。它量化了在状态s_t下执行动作a_t比“平均表现”好多少如果δ_t 0或差多少如果δ_t 0。网络更新Critic更新目标是让Critic的预测更准确。使用δ_t作为损失信号通过梯度下降最小化δ_t^2均方误差更新Critic网络的参数。这相当于让Critic学会更精准地评价每个状态。Actor更新目标是让Actor的策略变得更好。利用计算出的优势δ_t来更新Actor网络。如果δ_t为正说明当前(s_t, a_t)是好的那么就通过梯度上升微调Actor网络参数使得未来在类似状态s_t下选择动作a_t的概率增加反之如果δ_t为负则降低选择该动作的概率。这个“Actor行动Critic打分根据分数调整行动”的过程非常像学徒Actor在导师Critic的指导下学习。导师不直接告诉学徒该怎么做而是对他的每次尝试给出“好”或“不好”的评价学徒根据这些评价逐渐调整自己的行为模式。2.2 与其他强化学习算法的对比理解Actor-Critic的定位有助于你在不同场景下做出选择。与值函数方法如Q-Learning、DQN对比值函数方法如Deep Q-Network, DQN直接学习一个动作价值函数Q(s, a)然后通过选择Q值最大的动作来决策。这类方法通常用于离散动作空间。而Actor-Critic是直接学习策略本身一个从状态到动作概率分布的映射因此天然支持连续动作空间。你不需要在连续空间中寻找最大Q值这是一个优化问题而是由Actor网络直接输出连续的动作值如速度、力。与纯策略梯度方法如REINFORCE对比REINFORCE算法也直接优化策略但它使用从一幕episode开始到结束的完整回报来更新策略方差很大导致训练不稳定且缓慢。Actor-Critic引入Critic提供的价值函数作为基线用TD-Error单步或几步的回报替代完整回报极大地降低了方差实现了更稳定、更快的在线学习无需等待一幕结束。与先进算法如PPO、SAC的关系现代深度强化学习的许多明星算法如近端策略优化PPO、软演员-评论家SAC都是在Actor-Critic框架基础上发展而来的。它们通过引入重要性采样、熵正则化、裁剪等技巧进一步提升了样本效率、稳定性和性能。因此掌握经典的Actor-Critic是理解这些更高级算法的基石。3. Matlab实现的关键模块解析打开“actor-critic网络 Matlab.zip”你通常会看到几个核心的.m文件。我们来逐一拆解每个模块的功能和实现要点。3.1 环境接口模块 (Environment.m或类似)任何强化学习实验都始于环境。这个模块定义了智能体与之交互的世界。classdef CartPoleEnv properties gravity 9.8 masscart 1.0 masspole 0.1 total_mass 1.1 length 0.5 polemass_length 0.05 force_mag 10.0 tau 0.02 % 仿真时间步长 theta_threshold_radians 12 * pi / 180 x_threshold 2.4 end methods function [obs, reward, done, info] step(obj, action) % 输入action (力的大小连续值或离散索引) % 输出obs (新状态) reward (即时奖励) done (是否结束) info (调试信息) % 这里实现小车和杆的物理仿真逻辑欧拉积分 % ... % 计算奖励通常杆子越直立、小车越居中奖励越高 % 判断结束条件杆子倒下或小车出界 end function obs reset(obj) % 重置环境到初始状态如小车居中杆子轻微随机角度 obs [0; 0.05*randn(); 0; 0]; % [位置 角度 速度 角速度] end end end实操要点状态归一化环境的原始状态如位置、角度可能数值范围差异很大。在输入神经网络前务必进行归一化例如缩放到[-1, 1]或均值0方差1。这能显著提高训练的稳定性和速度。可以在reset和step函数返回前处理也可以单独写一个归一化函数。奖励函数设计奖励函数是指引智能体学习的“指挥棒”。设计不当会导致学习失败或学到奇怪策略。对于倒立摆CartPole常见的奖励是每一步杆子直立就给1倒下则结束。也可以设计为reward 1.0 - abs(theta/theta_threshold)让奖励与角度偏差成反比提供更平滑的梯度。离散 vs 连续动作Matlab实现可能处理离散动作如向左/向右施力或连续动作输出一个[-10, 10]的力。代码中的action参数需要与环境期望的格式匹配。3.2 神经网络模型定义 (createNetworks.m)这是Actor和Critic的核心通常使用Matlab的deepLearningToolbox来构建。function [actorNetwork, criticNetwork] createNetworks(stateDim, actionDim, actionMax) % Actor网络输入状态输出动作均值连续或动作概率离散 actorLayers [ featureInputLayer(stateDim, Name, stateInput) fullyConnectedLayer(128, Name, actorFC1) reluLayer(Name, actorRelu1) fullyConnectedLayer(64, Name, actorFC2) reluLayer(Name, actorRelu2) fullyConnectedLayer(actionDim, Name, actorOutput) % 对于连续动作通常加一个tanh层将输出限制在[-1,1]再乘以actionMax tanhLayer(Name, actorTanh) scalingLayer(Name, actorScale, Scale, actionMax) ]; actorNetwork dlnetwork(actorLayers); % Critic网络输入状态输出状态价值V(s) criticLayers [ featureInputLayer(stateDim, Name, stateInput) fullyConnectedLayer(128, Name, criticFC1) reluLayer(Name, criticRelu1) fullyConnectedLayer(64, Name, criticFC2) reluLayer(Name, criticRelu2) fullyConnectedLayer(1, Name, criticOutput) % 输出单个标量值 ]; criticNetwork dlnetwork(criticLayers); end注意事项与心得网络结构不宜过深对于大多数经典控制任务如倒立摆、月球着陆器2-3个隐藏层每层64-256个神经元通常足够。过深的网络容易过拟合且训练更慢。激活函数选择隐藏层常用ReLU或其变种Leaky ReLU因为它们能缓解梯度消失问题计算也快。Actor的输出层对于连续动作使用tanh将输出约束在有限范围内是关键对于离散动作则使用softmax层输出概率分布。参数初始化使用deepLearningToolbox的默认初始化如Glorot通常可以。但对于Actor的输出层有时将其初始权重设小一点如乘以0.01可以让初始策略接近随机有利于探索。使用dlnetwork对象Matlab推荐使用dlnetwork来定义自定义训练循环的网络它比layerGraph更灵活便于计算自定义损失函数的梯度。3.3 经验回放缓冲区 (ReplayBuffer.m)为了打破数据间的时序相关性提高数据利用率几乎所有的现代深度强化学习算法都会使用经验回放缓冲区Replay Buffer。classdef ReplayBuffer handle properties capacity % 缓冲区容量 buffer % 存储经验的单元数组或结构体数组 ptr % 当前写入指针 size % 当前缓冲区大小 batch_size % 采样批次大小 end methods function obj ReplayBuffer(capacity, stateDim, actionDim) obj.capacity capacity; obj.buffer.state zeros(stateDim, capacity); obj.buffer.action zeros(actionDim, capacity); obj.buffer.reward zeros(1, capacity); obj.buffer.next_state zeros(stateDim, capacity); obj.buffer.done false(1, capacity); obj.ptr 1; obj.size 0; end function store(obj, state, action, reward, next_state, done) % 存储一条经验 (s, a, r, s, done) idx obj.ptr; obj.buffer.state(:, idx) state; obj.buffer.action(:, idx) action; obj.buffer.reward(idx) reward; obj.buffer.next_state(:, idx) next_state; obj.buffer.done(idx) done; obj.ptr mod(idx, obj.capacity) 1; obj.size min(obj.size 1, obj.capacity); end function [states, actions, rewards, next_states, dones] sample(obj, batch_size) % 随机采样一批经验 if obj.size batch_size error(Buffer does not have enough samples.); end indices randi(obj.size, [1, batch_size]); states obj.buffer.state(:, indices); actions obj.buffer.action(:, indices); rewards obj.buffer.reward(indices); next_states obj.buffer.next_state(:, indices); dones obj.buffer.done(indices); end end end核心技巧缓冲区容量容量太小数据快速被覆盖学不到长期依赖容量太大占用内存多且旧数据可能来自性能很差的策略对当前学习无益。对于中等复杂度的任务1e5到1e6是个不错的起点。批次采样更新网络时从缓冲区随机采样一个批次如128、256的数据而不是使用最近的一条经验。这种随机化能有效减少梯度更新间的相关性使训练更稳定。优先经验回放PER这是一个高级技巧。基本的均匀采样假设所有经验同等重要。但事实上那些TD-Error大的经验即Critic预测误差大或Actor做出了令人“意外”的好/坏决策可能包含更多信息。PER会根据TD-Error的大小给每条经验赋予不同的采样优先级。在Matlab中实现PER稍复杂需要维护一个求和树SumTree数据结构来高效采样。在初始版本中可以先使用均匀采样。3.4 核心训练循环 (trainAC.m)这是所有模块组装起来的地方是算法的心脏。function [actor, critic, episode_rewards] trainAC(env, actor, critic, params) % 参数解包 num_episodes params.num_episodes; max_steps params.max_steps; gamma params.gamma; actor_lr params.actor_lr; critic_lr params.critic_lr; batch_size params.batch_size; % 初始化回放缓冲区 buffer ReplayBuffer(params.buffer_capacity, env.obs_dim, env.act_dim); % 优化器 actor_optimizer adamOptimizer(actor_lr); critic_optimizer adamOptimizer(critic_lr); episode_rewards zeros(1, num_episodes); for ep 1:num_episodes state env.reset(); ep_reward 0; done false; step 0; while ~done step max_steps % 1. 选择动作 (带探索) action selectAction(actor, state, params.exploration_noise); % 2. 与环境交互 [next_state, reward, done, ~] env.step(action); % 3. 存储经验 buffer.store(state, action, reward, next_state, done); state next_state; ep_reward ep_reward reward; step step 1; % 4. 如果缓冲区有足够样本则更新网络 if buffer.size batch_size [states, actions, rewards, next_states, dones] buffer.sample(batch_size); % 转换为 dlarray 以支持自动微分 states dlarray(states, CB); % Channel x Batch actions dlarray(actions, CB); next_states dlarray(next_states, CB); % 5. 更新 Critic [critic_loss, critic_grad] dlfeval(criticLoss, critic, states, rewards, next_states, dones, gamma); critic updateNetwork(critic, critic_optimizer, critic_grad); % 6. 更新 Actor [actor_loss, actor_grad] dlfeval(actorLoss, actor, critic, states, actions, gamma); actor updateNetwork(actor, actor_optimizer, actor_grad); end end episode_rewards(ep) ep_reward; % 每隔一段时间打印日志或绘图 if mod(ep, 100) 0 fprintf(Episode %d, Reward: %.2f, Steps: %d\n, ep, ep_reward, step); plot(episode_rewards(1:ep)); drawnow; end end end关键函数解析selectAction: 此函数基于Actor网络输出选择动作。对于连续动作通常在网络输出的均值上添加探索噪声最常见的是奥恩斯坦-乌伦贝克OU噪声或简单的高斯噪声。OU噪声具有惯性适合惯性系统如机械控制而高斯噪声更简单。对于离散动作通常采用ε-greedy策略或直接按概率采样。criticLoss: Critic的损失函数是TD-Error的均方值。function loss criticLoss(criticNet, states, rewards, next_states, dones, gamma) V forward(criticNet, states); % 当前状态价值 V_next forward(criticNet, next_states); % 下一状态价值 % 对于终止状态下一状态价值为0 V_next(dones) 0; % TD目标 target rewards gamma * extractdata(V_next); % 均方误差损失 loss mse(V, target); endactorLoss: Actor的损失函数是策略梯度。对于离散动作常用交叉熵损失加权优势对于连续动作假设输出是高斯分布的均值损失是负的对数概率加权优势。function loss actorLoss(actorNet, criticNet, states, actions, gamma) % 假设连续动作Actor输出动作均值mu mu forward(actorNet, states); % 计算动作的对数概率假设固定方差或由另一个网络头输出 log_probs -0.5 * sum((actions - mu).^2, 1); % 忽略常数项 % 计算优势A(s,a) ≈ δ V forward(criticNet, states); % 注意这里简化了实际需要next_states来计算TD error。 % 更严谨的做法是在存储经验时也存储TD-error或在这里重新计算。 % 这里用负的Critic值作为简单的优势估计鼓励去到价值高的状态。 advantages -extractdata(V); % 这是一个简化示例实际应用TD-error % 策略梯度损失 -log_prob * advantage loss -mean(log_probs .* advantages); end注意上面的actorLoss函数是一个高度简化的示例用于说明概念。在实际的Actor-Critic中优势函数advantages应该用TD-Errorδ来计算这需要rewards和next_states。通常我们在trainAC主循环中先计算好TD-Error然后将其作为额外参数传入actorLoss或者直接使用dlfeval计算包含Critic前向传播的完整损失。4. 实战调参与训练技巧有了代码框架成功与否很大程度上取决于超参数设置和训练技巧。这里分享一些从无数次失败中总结出的经验。4.1 超参数设置指南没有一套放之四海而皆准的超参数但以下范围可以作为你调试的起点超参数推荐范围/值作用与影响学习率 (Actor/Critic)1e-4到1e-3控制参数更新步长。Critic的学习率通常可以比Actor稍大如3e-4vs1e-4因为价值函数通常比策略更容易学习。太大导致震荡太小收敛慢。折扣因子 (γ)0.95到0.99衡量未来奖励的重要性。越接近1智能体越有远见。对于回合制任务如游戏通关可以设高一些0.99对于连续控制且每一步都重要的任务可以设低一些0.95。回放缓冲区容量1e5到1e6存储经验的数量。应远大于一个回合的步数。批次大小 (Batch Size)64,128,256每次更新时从缓冲区采样的经验数量。太小噪声大太大计算慢且容易过拟合。GPU内存允许下可以尝试256。探索噪声高斯噪声:sigma0.1~0.3OU噪声:theta0.15, sigma0.2控制探索程度。开始时可以大一些随着训练进行可以线性衰减sigma max(0.01, sigma * 0.995)。OU噪声的theta控制回归均值速度sigma控制噪声强度。网络结构[128, 64]或[256, 128]隐藏层神经元数量。任务越复杂网络可以适当加深加宽但也要防止过拟合。优化器Adam(默认参数)最常用的自适应学习率优化器。对于RL通常不需要调整Adam的beta1和beta2。调试顺序建议如果训练不收敛首先检查学习率这是最常见的问题源。可以先尝试调低一个数量级。其次检查奖励函数设计是否合理智能体是否能轻易获得正向奖励。然后调整探索噪声的大小和衰减策略。最后再考虑修改网络结构。4.2 训练过程监控与可视化“黑箱”训练是RL调试的噩梦。必须建立有效的监控手段。回合奖励曲线这是最核心的指标。绘制每个训练回合获得的总奖励。你期望看到曲线总体呈上升趋势并最终稳定在一个较高的水平。如果曲线剧烈震荡或持续下降说明训练不稳定。% 在训练循环内 if mod(ep, 10) 0 moving_avg movmean(episode_rewards(max(1, ep-100):ep), 100); plot(1:ep, episode_rewards(1:ep), b., 1:ep, moving_avg, r-, LineWidth, 2); xlabel(Episode); ylabel(Total Reward); legend(Raw, Moving Avg (100)); drawnow; endCritic损失曲线Critic的损失TD-Error的均方应该随着训练逐渐下降并趋于平稳。如果损失爆炸变成NaN几乎肯定是学习率太高或网络结构有问题。动作与状态分布定期输出Actor网络在某个测试状态下的动作分布或者记录智能体执行动作的均值和方差。这有助于观察探索是否充分策略是否收敛到某个确定模式。实时渲染对于有图形界面的环境如CartPole的Matlab动画可以每隔N个回合渲染一次直观地看智能体的表现。但注意渲染会大幅降低训练速度。4.3 探索与利用的平衡这是强化学习的根本挑战。在Actor-Critic中主要通过在Actor的输出上添加噪声来实现探索。高斯噪声简单直接action mu sigma * randn(size(mu))。sigma标准差的大小直接控制探索强度。可以设置一个衰减计划让sigma随着训练回合数增加而线性或指数衰减从而实现从“广泛探索”到“精细利用”的过渡。奥恩斯坦-乌伦贝克OU噪声更适合连续控制任务特别是具有惯性的物理系统。它的噪声具有相关性不会像高斯噪声那样频繁地正负跳跃动作更平滑。其更新公式为dx theta * (mu - x) sigma * dW其中x是噪声状态theta是回归速度sigma是噪声强度dW是维纳过程可近似为高斯随机数。在Matlab中需要维护一个噪声状态变量。个人心得对于初学者从高斯噪声线性衰减开始是最稳妥的。先设置一个较大的初始sigma如0.5每回合衰减一点点如乘以0.995并设置一个下限如0.01。观察训练曲线如果奖励很早就停滞不前可能是探索不够初始sigma太小或衰减太快如果奖励曲线一直像“心电图”一样乱跳可能是探索太强sigma太大策略无法稳定。5. 常见问题排查与解决方案在实际运行Matlab Actor-Critic代码时你几乎一定会遇到下面这些问题。这里我把踩过的坑和解决方法整理出来。5.1 训练不收敛奖励曲线毫无起色这是最令人沮丧的情况。请按以下清单逐一排查检查环境与奖励首先写一个简单的随机策略action rand()*2-1在环境中运行几十个回合看看平均奖励是多少。如果随机策略的奖励都比你训练后的高那肯定是算法或代码出了问题。其次确认你的奖励函数是否正确。智能体是否有可能获得正向奖励奖励是否过于稀疏检查学习率这是头号嫌疑犯立刻将Actor和Critic的学习率同时降低一个数量级例如从1e-3降到1e-4再试。RL对学习率非常敏感过高会导致梯度更新步伐太大在优化地形里“跳来跳去”甚至发散。检查梯度在更新网络前打印出梯度actor_gradcritic_grad的范数norm。如果梯度是NaN或无限大说明出现了数值不稳定可能是除零、指数爆炸等。如果梯度范数非常小如1e-8说明学习信号太弱可能网络结构或损失函数有误。检查探索初始阶段智能体是否在进行有效的探索可以打印出前几个回合的动作值看看它们是否在合理范围内随机变化。如果动作几乎不变可能是探索噪声sigma设得太小或者Actor网络输出被激活函数如tanh饱和了。检查网络输出确保Actor网络的最终输出层有正确的激活函数。对于连续动作空间tanh层是必须的它将输出限制在[-1,1]然后你需要乘以一个缩放系数actionMax来匹配环境的动作范围。如果忘记加tanh网络可能输出非常大的值导致环境产生异常状态。5.2 训练初期表现尚可随后突然崩溃“遗忘”现象智能体先学到一点东西然后奖励突然断崖式下跌之后再也回不来。回放缓冲区污染这是主要原因。当智能体策略改进后它会产生高质量的经验存入缓冲区。但如果缓冲区容量有限这些好经验很快会被后期策略探索阶段产生的、质量较低的经验覆盖。当网络从混合了新旧好坏经验的缓冲区中学习时可能会被“带偏”。解决方案增大缓冲区容量或者实现优先经验回放PER让算法更关注TD-error大的经验通常是那些“ surprising ”的好经验或坏经验。学习率未衰减在训练后期策略接近最优需要更精细的调整。如果学习率保持不变一次大的梯度更新可能会让策略“跳”出最优区域。可以考虑设置一个学习率衰减计划如每N个回合乘以0.9。探索噪声衰减过快如果探索噪声衰减得太快智能体过早地停止探索可能会陷入一个局部最优解一旦环境有微小扰动或由于参数更新偶然跳出该区域就可能无法找回原来的好策略。可以放缓噪声衰减速度或者保留一个很小的基础噪声。5.3 收敛速度慢训练耗时过长批次大小与更新频率尝试增大批次大小如从64到256这可以使梯度估计更稳定但也会增加每次更新的计算量。另外可以尝试每收集K步如4步或5步经验就更新一次网络而不是每一步都更新这能提高数据效率。网络结构过于复杂对于简单任务如CartPole过大的网络如好几层每层几百个神经元不仅不会提升性能反而会因为参数过多、需要调整的维度大增而拖慢收敛速度。尝试简化网络如两层每层64个神经元。使用GPU加速确保你的Matlab版本支持GPU计算并且正确地将数据和网络转移到GPU上。使用dlarray和dlnetwork会自动利用GPU如果可用。在代码开始处使用gpuDevice(1)可以检查和选择GPU。向量化操作确保你的经验回放缓冲区的存储和采样操作是向量化的避免在循环中进行单个元素的赋值这能在Matlab中带来巨大的速度提升。5.4 Matlab特有的数值与性能问题数据类型转换dlarray和普通Matlab数值数组double,single之间的转换需要注意。使用extractdata(gather(...))来从dlarray中提取数值进行计算如记录奖励。自动微分要求前向传播的输入是dlarray。内存管理经验回放缓冲区会占用大量内存。如果任务步数很长如数万步注意不要将整个训练过程中的所有状态/动作都存储在内存中。使用固定容量的循环缓冲区。对于图像输入的状态考虑存储压缩后的数据或使用专门的存储方式。并行化Matlab的parfor可以用于并行运行多个环境实例来收集数据这能显著加快数据采集速度。但需要注意线程安全每个worker最好有自己独立的环境实例和随机数种子。网络更新仍需在客户端进行。最后保持耐心。强化学习训练本身具有随机性即使超参数完全正确两次运行的结果也可能有差异。通常需要多次运行如5-10次并取平均性能来评估一个算法或一组参数的好坏。这个Matlab实现的Actor-Critic项目是一个绝佳的学习和实验平台通过亲手调试这些“旋钮”你会对强化学习如何工作有更深刻、更直观的理解。本文还有配套的精品资源点击获取