共计 9548 个字符,预计需要花费 24 分钟才能阅读完成。
本文首发于:行者 AI
Unity 是寰球最受欢迎的游戏开发引擎之一,有大量的游戏开发者在应用 Unity 开发他们的游戏。在这个 AI、大数据等风行词遍布各行各业的时代,Unity 也没有被潮流抛下,推出了他们本人的基于深度强化学习来训练游戏 AI 的工具包 Unity ML-agents。这个工具包功能丰富,非常弱小。能够帮忙你在你的游戏内实现一个新的 AI 算法,并且疾速的用到你的游戏当中。这么弱小的工具包难以在一篇文章外面概括其所有性能。本文就先抛砖引玉,略微讨论一下 Unity ML-agents 训练的时候须要用到的各种参数的意义,其罕用的取值又是如何。
本文所有内容参考 Unity ML-agents 的官网文档(地址:https://github.com/Unity-Tech…)
1. 训练参数设置
在你开始你的训练之前,你须要针对你的训练任务设定一个训练参数文件(个别是一个.yaml 文件)。
接下来就简略介绍一下 ml-agents 环境里的参数设置概要。本文次要参考 ml-agents 最新版本对于参数设置的官网文档,做了一些概括性的翻译并退出肯定集体了解。
具体文档地址:https://github.com/Unity-Tech…
训练参数次要分为罕用训练参数(Common Trainer Configurations), 训练形式专用参数(Trainer-specific Configurations),超参数(hyper-parameters),处分信号参数(Reward Signals),行为克隆(Behavioral Cloning),应用 RNN 加强智能体记忆能力的参数(Memory-enhanced Agents using Recurrent Neural Networks),以及自我反抗训练参数(Self-Play)这几个大的模块。这几个模块上面又有一些小的模块,在后文会进一步阐明,而且这些模块并不需要总是全都去设定。事实上,除了前三个模块是简直每个环境训练必须的参数之外,其余的模块仅用在须要应用到对应性能的训练任务。接下来具体阐明每个参数的含意。
2. 罕用训练参数模块(Common Trainer Configurations)
- trainer_type: (default =
ppo
) 这个参数决定了应用什么智能体训练算法,当初临时只反对 Proximal Policy Gradient(PPO,具体应为 OpenAI 版本的 PPO2),Soft Actor-Critic(SAC),以及 MA-POCA。前两种都只是单智能体训练算法。留神:在你改变了训练算法后,记得去调整一下前面的相应参数。对于不同的算法,上面的参数也往往有不同的适用范围,并非无缝连接的。上面会具体阐明。 - summary_freq: (default =
50000
) 这个参数决定了多少步数(step)之后,开始记录咱们的训练统计数据。 - time_horizon: (default =
64
) 这个参数决定了在多少步数之后,开始把收集到的教训数据放入到教训池(experience buffer)。这个量同样也决定了应用多少步后的采样来对以后动作的预期处分进行训练。简略来说,这个值如果越大,就相当于你更靠近于一局(episode)游戏的实在回报,从而偏差更小。然而因为要进行一局游戏能力更新一个动作的处分预期,这个过程相当的长,并且每局游戏可能状况变化很大。不同局之间,做同样的动作可能最终收益天壤之别(因为这个动作可能其实对这个游戏的影响基本没有那么大),从而导致方差较大。反过来,当你采样的步数太小,可能对最终的处分预估会偏差很大,然而可能带来较小的方差。其实这也跟机器学习外面经典的简略模型简单模型(过拟合欠拟合)问题一样,须要在方差和偏差当中取一个均衡。官网倡议当你的环境太大(跑一步耗时太长)或者你设置的处分比拟密集的时候,能够把这个值设的低一点,反之则须要增大。比方在足球比赛这样处分十分稠密的工作当中,范例文档设置的该参数值为 1000。留神,这个参数决定了采样的步数,和 batch_size、buffer_size、epoch 等参数亦有分割。前面提到这些参数的时候会再对其中关系加以阐明。常见范畴:32 – 2048 - max_steps: (default =
500000
) 这个参数决定了本次训练任务总共会进行多少步数。如果你有多个同样动作的智能体,他们每个的步数都会计入到这个总步数当中;同样的,如果你有多个环境并行的在多台服务器上运行,所有环境里的智能体的总步数都会计入思考。所以,当你并行训练多 agent 算法的时候,务必将这个值设的更大一些。常见范畴:5e5 – 1e7 - keep_checkpoints: (default =
5
) 这个参数决定了保留多少个训练时候产生的 checkpoint,其中每一个 checkpoint 都是在 checkpoint_interval 步数后产生的。 - checkpoint_interval:(default =
500000
) 如前文所说,这个参数决定了每多少步数当前,你的模型会存储一个节点。 - init_path: (default=None) 这个参数决定了你的模型是否从某个之前训练好的模型存储点持续训练。须要提供模型的确切地位,比如说,
./models/{run-id}/{behavior_name}
。其实在训练的时候,应用 –initialize-from 这个 CLI 参数就足以让所有的训练任务从同一个存储模型持续训练,提供这个参数是为了不便让不同的训练从不同的模型持续训练(须要一一设定)。很少用到 - threaded:(default =
false
) 开启 python 的多线程性能来实现一边训练一边存储模型,防止 I / O 耗费太多工夫。官网倡议在开启 self-play 性能的时候尽量避免应用该性能。
3. 接下来是一些常见超参数(hyper-parameters)的具体设定
- hyperparameters → learning_rate: (default =
3e-4
),这个参数决定了梯度降落的学习率。当该值过大时训练会变的不稳固(reward 不能稳步回升,时常大幅震荡)。常见范畴:1e-5 – 1e-3 - hyperparameters → batch size:这个参数决定了每次更新参数的时候,会有多少步的(state,action,reward…) 状态元组被用来进行学习。留神:这个参数应该永远是 buffer_size 的几分之一(因为实际上程序会先将 buffersize 拿来切分成 batchsize 大小的几个 batches。所以 buffer_size 永远要能被 batch_size 整除 )。对于一个间断动作空间的训练任务,这个参数应该设定在 1000 以上这个级别(因为动作空间须要尽可能多的采样来失去不同的数据),如果是离散空间,这个值往往设定在几十到几百就好了(依据你动作空间的大小来定)。 常见范畴:(间断 -PPO)512 – 5120;(间断 -SAC)128 – 1024;(离散,PPO&SAC):32 – 512.
- hyperparameters → buffer size: (default =
10240
for PPO and50000
for SAC)。PPO:对于 PPO 算法来说,程序先要集满 buffer_size 那么多步数之后才会开启一轮训练。而后如前文所说,每次收集够了 buffer_size 个状态元组之后,咱们把 buffer 外面的状态分成 buffer/batch_size 个 batch,而后每个 batch 进行一次训练更新参数, 这个过程反复 epoch(epoch 也是一个超参数)次。所以实际上每过一个 buffer_size 的采样之后,参数都会进行 num_epoch * buffer/batch 次数的更新 。通常一个较大的 buffer_size 会带来一个更加稳固的训练后果。SAC:对于 SAC 算法来说, 通常来说教训池要是其设 episode 长度的几千倍,从而能让它训练的时候同时利用到较旧和最近的采样。常见范畴:(PPO)2048 – 409600;(SAC) 50000 – 1000000 - hyperparameters → learning_rate_schedule: (default =
linear
for PPO andconstant
for SAC) 这个参数决定了是否应用学习率衰减的方法来稳固训练。两个可选的模式别离是 linear 和 constant,前者会对你的学习率进行线性递加,后者则不会扭转 。通常来说,学习率越大,往往容易呈现训练不稳固,学习率越小则容易呈现长时间训练不收敛的状况。所以应用学习率衰减先用较大的学习率疾速的找到一个极值点方向,而后再逐渐膨胀学习率使得训练稳固在极值左近,而不会来回摆动。 官网倡议,对 PPO 开启 linear 模式,进行线性递加,以达到更快的收敛速度。对 SAC 来说,则倡议维持学习率不变。
4. 接下来介绍一些罕用的网络模型的超参数
- twork_settings → hidden_units:(default = 1
28
) 这个参数决定了你的训练网络暗藏层的神经元数量,或者说它的维度。这个数值的大小决定了神经网络对游戏状态的表达能力。简略来说,较大的暗藏层往往对更大的察看空间有着较好的表达能力。所以这个值应该随着察看空间的维度变大而变大。常见范畴:32 – 512 - network_settings → num_layers: (default =
2
) 这个参数决定了你的训练网络的层数。这个数字越大,你的模型越深。尽管多层叠加可能进步模型对环境的表达能力。然而模型并不是越深越好,过深的层数往往会带来梯度隐没的问题,并且会使得训练速度变缓。倡议优先加大 hiddent_unitys 再加大本参数。常见范畴:1 – 3 - network_settings → normalize: (default =
false
) 这个参数决定了模型是否对输出的察看向量进行归一化(normalization)。具体公式大略为 (obs – mean) / std,其中 mean 和 std 别离是 observation 的平均值和标准差。官网倡议,对于简单的间断动作空间工作,应用 normalization 可能有帮忙,然而对于简略的离散工作应用 normalization 则可能带来负作用。 - network_settings → vis_encode_type: (default = simple) 这个参数决定了你的编码器的构造。留神,ppo 也好,sac 也好,只是一个训练架构,不同的工作你应用 ppo 也须要不同的编码器。比如说一个卡牌类游戏,你能够把所有的察看向量用一般的全连贯层解决,然而如果是一个动作游戏,你的察看可能是一张图片,那么这个时候你最好应用 CNN 作为你的特征提取编码器。这个参数就是在让你抉择应用何种编码器。simple是一个两层的卷积网络;Nature CNN则是应用 Human Level Reinforcement Learning 这篇文章的实现 ;resent 则是应用 IMPALA RESNET 这种架构,这个网络的特点在于提取 pattern 能力强,不易梯度隐没。match3 则是更适宜于卡牌游戏的一种 CNN 构造,特点是更小的构造然而能够捕获空洞空间的示意信息。fully_connected则是一个单层全连贯层。因为卷积核大小的匹配要求,每种编码方式有一个最小输出维度的上限。比方 simple 最小 20 20;nature_cnn 最小反对 36 36;resent 最小反对 15 *
15,match3 最小反对 5 * 5,留神:应用 match3 来解决超大的输出维度可能会拖慢训练速度。 - network_settings → contioning_type: (default = hyper) 这个参数决定了是否应用 hypernetwork 来解决工作指标的信息。hyper 网络的参数比拟多,当应用 hyper 网络的时候请缩小暗藏网络的层数。
5. Trainer-specific Configurations
接下来咱们介绍一下针对不同训练算法的专门参数。
5.1 PPO-specific Configurations(PPO 专门参数)
- beta: (default = 5.0e-3) 这个参数决定了激励摸索多样化策略的熵正则项的强度(entropy regularization)。简略来说,熵正则化通常是为了丰盛咱们的策略函数摸索不同策略和动作,咱们应用一个 KL 散度去掂量新的策略和老策略的相似性,并通过减少 entropy 来让动作策略更加随机。换句话说,当 beta 越大,越激励摸索。调节这个参数要联合 TensorBoard 外面的 entropy 和 reward 来看。当你的 entropy 降落的时候,reward 依然没有起色,那就把这个 beta 增大使得 entropy 可能再继续一段时间。常见范畴:1e-4 – 1e-2
- epsilon: (default = 0.2) 这个参数决定了策略更新的速度。这个参数就是 ppo2 论文外面的 clip 范畴,这个范畴限度了每一次参数更新偏离范畴,以保障 ppo 可能依附 importance sampling 作为一个 on policy 的办法持续训练。能够发现当 epsilon 越大,咱们的旧策略参数 theta’变动较小。这能够使得训练更加稳固,然而随之而来的就是更慢的收敛速度。常见范畴:0.1 – 0.3
- lambd:(default = 0.95) 这个参数依据官网文档阐明是决定了咱们的算法多大程度上依赖预估的处分值,又多大程度上依赖理论的处分值。实际上这个 laambda 指的是 GAE 办法中的一个超参数 lambda。GAE 办法是在策略梯度降落中罕用的一种 Advantage,用于更新管制 policy 在 gradient 方向上的更新幅度。GAE 办法简略来说就是求 TD(0), TD(1) 始终到 TD 无穷(即蒙特卡洛采样)的一个加权平均值。lambda 这个值介于 0 到 1 之间,当 lambda 等于 0 时就是 TD(0)预计,当 lambda 等于 1 时就是蒙特卡洛采样。常见范畴:0.9 – 0.95
- num_epoch:(default = 3) 这个参数决定了每次进行梯度降落更新的次数。详见前文 buffersize 的局部。常见范畴:3 – 10
6. Reward Signals
处分信号可分为两种,一种是外在的(extrinsic)来自于环境的处分,一种是外在的(intrinsic)来自于外部的处分(比方好奇心处分等)。不论是外部还是内部处分信号,都至多要设定两个参数,一个是信号强度(strength),一个是信号衰减率(gamma)。并且,你须要至多设定一种处分,不然没方法训练。
6.1 Extrinsic Rewards
- extrinsic → strength: (default = 1.0) 这个参数决定了模型收到的外部环境处分信号的强度。常见范畴:1.00
- extrinsic → gamma:(default = 0.99) 这个参数决定了远期处分的衰减率。简略来说,退出咱们的模型在某一步收到了 100 的处分,那么咱们前一步的处分应该是多少呢?如果上一步没有失去其余的处分,那么上一步咱们的收益就应该是 gamma 100 = 99,同理,再上一步的收益就是 gamma^2 100,以此类推。直观的了解,gamma 约靠近一,那么较前期的收益也能反馈到后期的动作。反之就是动作策略进行学习的时候会更加倚重于短期内的回报。对于那种处分较为稠密,必须通过一系列动作之后能力取得一次处分的工作,务必将这个值设定得更靠近于一,反之则能够略微小一些。常见范畴:0.8 – 0.995
6.2 Intrinsic Reward
- curiosity → strength: (default = 1.0) 这个参数决定了好奇心处分的强度。这个比例须要调整到一个刚好的水平,使得好奇心处分既不会吞没了内部处分的信号,又不会和内部处分比起来过于不值一提。常见范畴:0.001 – 0.1
- curiosity → gamma: (default = 0.99)如前所述,这个参数决定了远期处分的衰减率。详见上文。
- curiosity → network_settings: 这个参数次要是用来决定 ICM 模型的暗藏层维度的。即不能太大也不能太小。(64 – 256)
- curiosity → learning_rate: (default = 0.99)这个参数决定了你的 ICM 模型的学习率。过大的学习率会导致训练不稳固,过小的学习率会导致收敛迟缓。常见范畴:1e-5 – 1e-3
7. Memory-enhanced Agents Using Recurrent Neural Networks
7.1 能够通过减少记忆模块的方法来减少模型的表达能力。留神,memory section 要加在 network 上面
- network_settings → memory → memory_size: (default=128) 这个参数决定了你的 LSTM 网络的暗藏层的维度。这个值必须是偶数。大小视你的状态的复杂程度而定。最好要可能足够大,能力学习到如何记忆之前的状况。常见范畴:32 – 256
- network_settings → memory → sequence_length: (default = 64) 这个参数决定了你的记忆网络 RNN 循环的次数或者说是序列长度。为了可能训练这么长的序列,咱们的采集到的教训也须要有这么长。所以依据我的猜想,只管文档没有明说,然而这个参数肯定要小于 time_horizon 的值。另外,这个数如果设定的太小,那么可能他无奈记住太多的货色,反过来,如果太大,训练会很慢。
7.2 应用记忆网络须要留神以下几点
- LSTM 网络在间断动作空间工作上体现不佳,官网倡议更多的用在离散动作空间的工作下面。
- 增加了一个 RNN 层会减少神经网络的复杂度,务必适度升高神经网络的层数。
- 肯定要记住把 memory_size 设定为偶数。
8. Self Play 参数设置
self play 这个 section 只有在对抗性训练的时候须要应用,如果仅仅只有一个 agent,或者多个 agent 中没有任何意义上的交互,则不须要设定这一个参数。Unity ml-agent 也是利用 self play 参数的退出来启动它自带的对抗性训练模块。
参考(https://github.com/Unity-Tech…)
- trainer_steps 和 ghost steps : 在了解 self play 参数之前咱们须要先了解两个概念,trainer_steps 和 ghost_steps。在一个反抗训练当中,咱们往往须要固定住一些 agent 的参数,在肯定的步骤外面让他们作为对手去训练咱们的 agents。那么咱们的 learning agents 进行的步数就是 trainer_steps,而与之绝对的,那些固定参数的对手所走的步数就是 ghost_steps,为什么这两个值要别离计数呢?因为有些游戏并不是对称反抗训练 (asymmetrical game),比方咱们训练一个 2v1 的场景,这时候在学习的队伍是 2 个 agent,对手可能就是 1 个 agent。在这种状况下,trainer_steps 的增长就会两倍快于 ghost_steps, 因为咱们计步的时候都是计算总和。了解了这两个概念之后,再来看上面的参数设定就会分明很多,不然会一头雾水。
- save_steps: 这个值决定了咱们的 learning agents,每 save_steps 个 trainer steps 会去存储一个以后策略的参数。另外,如果 save_steps 足够大,比方咱们把方才例子里的 save_steps 改成 20480,那么在存储一次快照之前,参数就要进行至多 80 次更新,这样每个快照之间的难度曲线就会更平缓,使得每次训练的不稳定性增大,然而带来的可能是更好的最终后果,以及在简单工作上更好的体现。
- team_change 和 swap_steps:方才咱们曾经探讨过了什么是 trainer steps,什么是 ghost steps。当初来看一下这两个值怎么在反抗训练中决定咱们更换对手的频率。team_change 参数是决定咱们要用同一个 learning agent 训练多少次的参数。比方咱们当初有红蓝两队球队,如果咱们设定 team_change=10000,那红队就会先训练 10000 个 trainer steps 才会轮到蓝队。而 swap_steps 则决定了咱们在一次 team change 之中,要更换几次对手。用下面的例子来看,就是红队在这 10000 个 trainer steps 外面要面对几个不同的蓝队的过来的快照。这里有一个简略的公式能够计算这种关系,假如咱们当初有设定 team change 为 t,而后想要切换对手的次数为 x,而咱们的队伍有 a1 个 agents,对手的队伍有 a2 个 agents,则咱们的 swap_steps =(a2/a1) * (t / x),如果这是一个对称反抗游戏,则上式能够简化为 t/x。能够看见,team_changes 和 swap_steps,独特决定了一个更换对手的频率,这个频率越大,如同咱们后面剖析过的那样,咱们可能会遇到更多不同等级和策略的对手,从而会学到更多货色,但也造成了训练不稳固,参数难以收敛的问题。然而每个 learning agent 学到的策略可能更加不局限于某种对手,更加通用,不会过拟合。
- play_against_latest_model_ratio: (default =
0.5
) 这个参数决定了你和本人以后的模型对决的概率。这个值越大概容易和以后的本人的策略对决,也就更少的和本人以往的 snapshot 交战。
behaviors:
SoccerTwos: #游戏的名字
trainer_type: ppo #选定应用何种训练算法
hyperparameters: #PPO 算法的超参数设置
batch_size: 2048
buffer_size: 20480 # buffer 大小必须是 batch 大小的整数倍,这里是十倍
learning_rate: 0.0003
beta: 0.005 #熵正则的超参数
epsilon: 0.2 #PPO 算法的 clip 范畴
lambd: 0.95 #GAE 算法的 lambda
num_epoch: 8 #每次更新训练多少次
learning_rate_schedule: linear #学习率衰减形式,这里是线性衰减
network_settings: #解决 observation 信息的网络结构设置
normalize: false
hidden_units: 256
num_layers: 2
vis_encode_type: simple
reward_signals: #处分超参数设置
extrinsic:
gamma: 0.99
strength: 1.0
keep_checkpoints: 5 #一共保留最近的五个 checkpoint
checkpoint_interval: 100000 #每 100000 个 timestep 保留一个 checkpoint
max_steps: 50000000 #最多训练这么多不(留神,这是多个 agent 加起来的值)time_horizon: 1000
summary_freq: 5000
threaded: false # 是否应用线程,在应用 self-play 性能时最好关掉
self_play: #self-play 相干参数设定
save_steps: 50000
team_change: 250000
swap_steps: 2000
window: 10 #一共保留十个过来过来的 snapshot
play_against_latest_model_ratio: 0.5
initial_elo: 1200.0