神经网络参数(权重) = 大脑里学会的知识,刷题(训练)的时候自己慢慢更新超参数 = 你提前定好的整套学习计划,刷题本身不会自动改变计划,需要我们自己设置
我们把训练倒立摆想象成:让一个学生反复练习 "保持一根杆子不倒" 这个杂技。下面所有配置,就是你给这个学生定的学习计划,对照代码一条一条讲:
num_steps_per_env = 16
max_iterations = 150
save_interval = 50
experiment_name = "cartpole"
policy = RslRlPpoActorCriticCfg(
init_noise_std=1.0,
actor_obs_normalization=False,
critic_obs_normalization=False,
actor_hidden_dims=[32, 32],
critic_hidden_dims=[32, 32],
activation="elu",
)
algorithm = RslRlPpoAlgorithmCfg(
value_loss_coef=1.0,
use_clipped_value_loss=True,
clip_param=0.2,
entropy_coef=0.005,
num_learning_epochs=5,
num_mini_batches=4,
learning_rate=1.0e-3,
schedule="adaptive",
gamma=0.99,
lam=0.95,
desired_kl=0.01,
max_grad_norm=1.0,
)
一、最顶层:整个学习周期的大计划
num_steps_per_env = 16
每个学生(每个仿真倒立摆)一轮练习先试 16 次动作,收集这 16 次的成败记录,再坐下来复盘总结。不是练一次改一次想法,是攒一小批经验再一起复盘。
max_iterations = 150
整套大复习循环最多做 150 轮。一轮 = 先实操收集经验 + 坐下来复盘改进想法。做完 150 轮就停止学习,不再练了。
save_interval = 50
每做完 50 轮大复习,就把学生当前的本事存档保存(生成 model_xx.pt)。万一后面越学越差,可以回退到 50 轮、100 轮时候的版本。
experiment_name = "cartpole"
给这次学习起个名字叫 cartpole,日志、存档文件都会放到这个名字的文件夹,方便你后面用 play.py 调取。
二、policy 部分:学生的脑子长什么样(Actor+Critic)
Actor = 负责做动作 的脑子(看到杆子状态,决定小车往左还是右推)Critic = 负责估好坏的脑子(预判:现在这个状态,后续能不能稳住杆子,大概能拿多少分)
init_noise_std=1.0
刚开始学的时候,允许动作有比较大的随机试探。一开始学生啥也不会,要多瞎试试不同推法,看看哪种能稳住杆子;学熟练后,试探会慢慢变小,不再乱晃。
actor_obs_normalization=False/critic_obs_normalization=False
要不要把看到的信息(杆子角度、速度)做标准化缩放。倒立摆的观测数值范围很简单,不用额外换算;复杂四足机器狗一般要开这个,相当于统一 "看东西的标尺"。
actor_hidden_dims=[32, 32]
做动作的脑子有两层思考区,每层有 32 个脑细胞。脑细胞越多,能学会的规律越复杂;倒立摆任务简单,不需要很大的脑子。
critic_hidden_dims=[32, 32]
评估好坏的脑子,同样两层,每层 32 个脑细胞。
activation="elu"
脑细胞的思考方式。类比:脑细胞不会非黑即白,就算情况不好也还能继续思考,不容易直接 "宕机学废"。
三、algorithm 部分:复盘的时候怎么调整想法(PPO 核心规则)
一轮实操收集完经验后,坐下来复盘,下面就是复盘的规矩:
value_loss_coef=1.0
评估好坏(Critic)的对错,在本次复盘里占多大比重。1.0 代表:预判能不能拿分这件事,和动作策略的重要程度一样。
use_clipped_value_loss=True
复盘时,限制 "估分脑子" 一次改动的幅度。防止这次看了几条经验之后,直接推翻之前全部的好坏判断,估分逻辑一下子崩掉。
clip_param=0.2
PPO 最重要的一条规矩:不要一次改想法改太猛。新想法和旧想法差别不能超过 20%。比如以前觉得 "往左推",复盘后不能直接一下变成拼命往右推,避免刚学会的本事直接忘掉。
entropy_coef=0.005
鼓励保留一点点随机试探的意愿。就算学得差不多了,也不要变成死板固定动作,留一点点探索空间;这个数值很小,倒立摆不需要太多试探。
num_learning_epochs=5
拿到这一批 16 步的实操记录,可以反复翻看复盘 5 遍。同样一份错题经验,多看几遍,加深理解。看多了也容易过拟合,记住这一批特例而不是通用规律。
num_mini_batches=4
把这批练习记录分成 4 小份,分批看、分批改想法。一次性看全部数据压力太大(显存不够),拆成小份慢慢复盘。
learning_rate=1.0e-3也就是 0.001
每次复盘,调整想法的步子大小。步子太大容易学飘,步子太小学的很慢。
schedule="adaptive"
自适应调整学习步子。会自动对比:新想法和老想法差别大不大。
- 改动太大 → 步子收小一点,谨慎学习
- 改动很小 → 步子放大一点,加快学习
gamma=0.99
打分的时候,有多看重长远收益。杆子现在稳住不算,还要看接下来能不能持续稳住。0.99 代表:未来的分数会稍微打一点折扣,优先兼顾当下,也不忽略后面的结果。如果 gamma 接近 1,就是非常看重长久稳定。
lam=0.95
复盘算 "这次动作到底好不好" 的一套折中方案。用来平衡两种判断:只看即时得分,和预估未来得分。简单理解:让对动作好坏的评价更稳,不要忽高忽低。
desired_kl=0.01
自适应学习率的目标:希望每轮复盘之后,新想法和旧想法的差距维持在很小的水平(0.01)。不要一轮学完直接换一套思路。
max_grad_norm=1.0
保护机制:万一某一批经验非常极端,最多只能改这么多想法。防止一次翻车,直接把之前学会的全部冲垮(梯度爆炸)。
整体串一遍这个学生的学习流程
- 一共最多进行 150 轮大练习,每一轮:
- 每个倒立摆学生先实操试 16 次动作,记录杆子倒没倒、得分多少
- 把收集到的记录拆成 4 小份,反复翻看复盘 5 轮
- 复盘的时候,严格控制:新想法不能和旧想法差太多(clip_param),自适应调整学习快慢
- 每做完 50 轮完整练习,存档一份当前的学习成果 model.pt
- 全部结束,你用 play.py 调出存档,把 "做动作的脑子(Actor)" 单独打包成 policy.pt(JIT),单独用来实操
一句话区分重点
- Actor 脑子:遇到情况,决定怎么做动作
- Critic 脑子:预判这么做后续能拿多少分
- 所有这些配置,全部是你定的学习规则;学生在训练里自己变化的,只有脑子里记住的判断逻辑(网络权重参数)。