文章目录
- 前言
- 1. 先搞清楚这玩意儿是个啥
- 2. 环境准备——劝退重灾区
- 3. 安装包这一步,全是套路
- 4. 小试牛刀:让小球别掉下来
- 5. 自己写智能体脚本
- 6. 训练配置文件怎么改
- 7. TensorBoard 看曲线
- 8. 想跑快点?把游戏打包成 exe
- 9. 唠到这儿
P.S. 推荐一个大神的教程给想要了解或者学习人工智能知识的读者,这个教程里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏教程,请点击下方链接查看, 传送门https://blog.csdn.net/qq_74013365
前言
说出来你可能不信,我一个写了二十年代码的老炮,前段时间被一个游戏插件按在地上摩擦了三天。
事情是这样的。Unity 这玩意儿大家都知道,做游戏的,业内顶流。但它最近几年不务正业,搞了个叫 ML-Agents 的东西——简单说就是,让你在 Unity 里养一个 AI,你教它做事,它学会了给你表演。
我一开始想:这不就是强化学习嘛,OpenAI Gym 我都玩腻了。结果真上手才发现,Gym 那是健身房撸铁,ML-Agents 这是搬砖——量大体沉,还得自己搭台子。
今天就把我踩过的坑、跑通的路,一次性给你们唠明白。看完你至少能把第一个小球平衡的 Demo 跑起来,不至于像我那样对着一屏幕报错发呆到凌晨三点。
1. 先搞清楚这玩意儿是个啥
ML-Agents 严格来说不是一个软件,是一套工具包。你可以把它理解成一个外卖平台:Unity 负责做菜(游戏环境),Python 负责派单(训练算法),中间靠一根网线把两边串起来。
它里面拆成了这么几块:
1.1 Unity 侧的两个包
一个叫com.unity.ml-agents,这是主菜,必装。另一个叫ml-agents.extensions,是实验性配菜,装不装随你,就像点外卖加不加辣——加了可能真香,也可能胃疼。
1.2 Python 侧的三个包
mlagents是训练算法本体,你直接装这个就行;mlagents_envs是它的小弟,负责跟 Unity 通信;gym_unity是给 OpenAI Gym 用户准备的适配层,意思是"你以前怎么玩 Gym,现在还怎么玩"。
1.3 Project 文件夹
官方给的示例场景合集,相当于新东方厨师学校的练习菜谱。你别一上来就自己炒回锅肉,先跟着菜谱煎个蛋。
2. 环境准备——劝退重灾区
我先说句大实话:强化学习这行,80% 的时间不是在调算法,是在配环境。剩下 20% 的时间,在怀疑人生。
2.1 版本要求
Unity 得是 2019.4 以上,Python 得是 3.6.1 以上。别问为什么,问就是官方说的。你要是还在用 Python 3.5,那你该考虑的不是 ML-Agents,是给项目办个追悼会。
2.2 路径里千万别出现中文
这一条我用血的教训换回来的。我当时把仓库 clone 到了D:\AI学习\强化学习\ML插件,训练的时候死活连不上 Unity,报错报得跟天书一样。后来把文件夹改成全英文路径,一秒钟就连上了。
我当时的心情怎么形容呢——就像你修了一下午电视,最后发现插头没插。
2.3 用 Anaconda 建虚拟环境
别往系统 Python 里乱塞包,不然过三个月你都不知道自己装了些啥。老老实实用 conda:
# 查看所有环境 conda env list # 建一个专门的环境 conda create -n ml-agents python=3.6 # 激活它 activate ml-agents看到没,conda env list,不是conda-env list。我第一次敲命令的时候手滑多打了个横杠,conda 表示你在教我做事?
3. 安装包这一步,全是套路
3.1 本地装两个 Python 包
把 GitHub 下来的仓库解压开,分别进到ml-agents和ml-agents-envs两个目录,执行:
pip install .注意最后那个点,别漏了。那个点代表"当前目录",就像你跟外卖小哥说"就我楼下",他才找得到你。
3.2 验证安装
mlagents-learn --help如果哗啦啦打印一堆参数说明,恭喜,装好了。如果报错,大概率是你忘了装 PyTorch。
3.3 PyTorch 下载慢怎么办
这是一个世界性难题。你去 PyTorch 官网复制那条 pip 命令,速度大概跟蜗牛搬家差不多,还搬着个壳。动不动就卡在 99% 然后给你断了,比老板画饼还不靠谱。
解决方案是上清华源:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ conda config --set show_channel_urls yes然后用官方命令装 PyTorch 的时候,把结尾那个-c pytorch删掉。那个参数的意思是"强制从官网下",你都配了清华源了还强制官网,那不是脱裤子放屁嘛。
改完之后速度起飞,我第一次用的时候都怀疑自己是不是连错网了。
3.4 Unity 侧装包
打开 Unity,新建一个 3D 工程,顶部菜单Window → Package Manager,左上角点加号,选Add package from disk,然后找到你解压目录里com.unity.ml-agents文件夹下的package.json,双击。
extensions 那个包同理。装完之后左边 Packages 列表里能看到两个 ML-Agents,齐活。
4. 小试牛刀:让小球别掉下来
环境配好了,咱得来个开门红。打开官方 Project,进到Assets/ML-Agents/Examples/3DBall/Scenes,把第一个场景点开。
你会看到一屏幕蓝色小方块,每个方块上顶着一个小球。任务很简单:训练这些方块倾斜自己,别让球滚下去。
这游戏我小时候玩过——就是那种平衡木玩具,球一歪就掉。区别是人家是你用手晃,现在是 AI 自己晃。
4.1 启动训练
打开 Anaconda Prompt,激活你的环境,cd 到仓库根目录,执行:
mlagents-learn config/ppo/3DBall.yaml --run-id=3DBallTest --force这条命令拆开看:用3DBall.yaml这个配置,给这次训练起名叫3DBallTest,数据存到results目录下同名文件夹。
--force这个参数很重要——它的意思是"别废话,覆盖旧数据,给我跑"。你要是不加这个,上次跑过同名的文件夹在那儿杵着,它就停下来问你:“覆盖不?” 你以为它在等你回答,其实它在那儿装死,能装十分钟。
命令跑起来之后,终端会蹦出来一个巨大的 ASCII 艺术字 Unity Logo,然后提示你:“去 Unity 里点 Play 吧。”
这时候你切回 Unity,点一下那个三角形播放按钮。你会发现游戏画面以八倍速狂奔,小球跟不要钱一样往下掉,但掉着掉着——它就不掉了。
控制台会持续输出:
[INFO] Connected to Unity environment with package version 2.1.0-exp.1 [INFO] Connected new brain: 3DBall?team=0 [INFO] 3DBall. Step: 12000. Mean Reward: 1.182. Training. [INFO] 3DBall. Step: 24000. Mean Reward: 1.430. Training.看着那个 Mean Reward 一点点往上涨,比看股票涨还爽。股票绿的时候你只能关灯吃面,这个 Reward 涨的时候你是真的在养一个 AI。
训练够了就停掉 Unity,去results/3DBallTest文件夹里找那个.onnx文件——这就是训练好的神经网络模型。把它拖到场景里 Agent 的Behavior Parameters → Model槽位上,再点 Play,你会发现这堆小方块跟开了挂一样,球怎么晃都不掉。
那种感觉怎么说呢,就像你养了条狗,教了它三个月握手,它突然有一天自己学会了接飞盘。
5. 自己写智能体脚本
Demo 跑爽了,接下来咱得自己上手写代码,不然永远是调包侠。
5.1 三个必挂组件
一个智能体身上必须挂三个东西:
第一个是Behavior Parameters,大脑。里面Behavior Name是名字,Space Size是输入向量维度,Continuous Actions是连续动作数量,Discrete Branch是离散动作数量。
维度怎么算?位置是 3 维,旋转是四元数 4 维,速度 3 维,角速度 3 维。你要观察啥就加啥,别瞎填——填多了 AI 看不过来,填少了 AI 跟瞎了一样。
第二个是Decision Requester,触发器。决定 AI 每隔几步做一次决策。你可以理解成闹钟,闹钟一响 AI 就动一下。
第三个,就是你自己写的 Agent 脚本,必须继承Agent类。
5.2 必须重写的四个方法
继承了 Agent 之后,有四个方法你最好都重写一遍,它们分别管一件事:
Initialize()——出生的时候干啥。拿组件、取参数,在这儿搞。
CollectObservations()——告诉 AI 它看到了啥。位置、速度、角度,全往sensor里塞。这就是神经网络的输入层。
OnActionReceived()——AI 给出动作了,你让游戏物体照着做。同时发奖励、判断游戏结束没。
OnEpisodeBegin()——一局结束了,重置。球放哪、角度清零,都在这儿。
还有一个可选的Heuristic(),这个有意思——你自己用键盘玩,AI 在旁边抄作业。相当于你学车的时候副驾坐了个教练,他不光看你开,还偷偷记你打方向盘的角度。
5.3 看一下核心代码长啥样
头文件先引好:
using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Actuators; using Unity.MLAgents.Sensors; using Random = UnityEngine.Random;成员变量:
[Header("Specific to Ball3D")] public GameObject ball; public bool useVecObs; Rigidbody m_BallRb; EnvironmentParameters m_ResetParams;初始化:
public override void Initialize() { m_BallRb = ball.GetComponent<Rigidbody>(); m_ResetParams = Academy.Instance.EnvironmentParameters; SetResetParameters(); }收集观察:
public override void CollectObservations(VectorSensor sensor) { if (useVecObs) { sensor.AddObservation(transform.rotation.z); sensor.AddObservation(transform.rotation.x); sensor.AddObservation(ball.transform.position - transform.position); sensor.AddObservation(m_BallRb.velocity); } }最关键的OnActionReceived,动作和奖励全在这儿:
public override void OnActionReceived(ActionBuffers actionBuffers) { var actionZ = 2f * Mathf.Clamp(actionBuffers.ContinuousActions[0], -1f, 1f); var actionX = 2f * Mathf.Clamp(actionBuffers.ContinuousActions[1], -1f, 1f); if ((transform.rotation.z < 0.25f && actionZ > 0f) || (transform.rotation.z > -0.25f && actionZ < 0f)) { transform.Rotate(new Vector3(0, 0, 1), actionZ); } if ((transform.rotation.x < 0.25f && actionX > 0f) || (transform.rotation.x > -0.25f && actionX < 0f)) { transform.Rotate(new Vector3(1, 0, 0), actionX); } if ((ball.transform.position.y - transform.position.y) < -2f || Mathf.Abs(ball.transform.position.x - transform.position.x) > 3f || Mathf.Abs(ball.transform.position.z - transform.position.z) > 3f) { SetReward(-1f); EndEpisode(); } else { SetReward(0.1f); } }看到没,球没掉就给 +0.1,掉了直接 -1 然后结束。这就是奖励函数——AI 是个贱皮子,你奖它它就来劲,你罚它它就躲。比养小孩简单多了,小孩你奖他他还得寸进尺。
重置一局:
public override void OnEpisodeBegin() { transform.rotation = new Quaternion(0f, 0f, 0f, 0f); transform.Rotate(new Vector3(1, 0, 0), Random.Range(-10f, 10f)); transform.Rotate(new Vector3(0, 0, 1), Random.Range(-10f, 10f)); m_BallRb.velocity = Vector3.zero; ball.transform.position = new Vector3( Random.Range(-1.5f, 1.5f), 4f, Random.Range(-1.5f, 1.5f)) + transform.position; SetResetParameters(); }手动操控模式:
public override void Heuristic(in ActionBuffers actionsOut) { var continuous = actionsOut.ContinuousActions; continuous[0] = -Input.GetAxis("Horizontal"); continuous[1] = Input.GetAxis("Vertical"); }代码这东西,你逐行看觉得每一行都认识,合起来就不知道在干啥。正常,我第一次看的时候也是这个感觉。但你把它跑起来,看着小方块真的开始平衡小球,那种"哦原来如此"的顿悟感,比喝了三杯咖啡还精神。
6. 训练配置文件怎么改
脚本写完,算法参数在config/ppo/3DBall.yaml里。Unity 官方给了两种算法:PPO 和 SAC。咱新手先用 PPO,稳。
behaviors: 3DBall: trainer_type: ppo hyperparameters: batch_size: 64 buffer_size: 12000 learning_rate: 0.0003 beta: 0.001 epsilon: 0.2 lambd: 0.99 num_epoch: 3 learning_rate_schedule: linear network_settings: normalize: true hidden_units: 128 num_layers: 2 vis_encode_type: simple reward_signals: extrinsic: gamma: 0.99 strength: 1.0 keep_checkpoints: 5 max_steps: 500000 time_horizon: 1000 summary_freq: 12000这里有个大坑:behaviors下面那个3DBall,必须跟你场景里Behavior Parameters 组件上的 Behavior Name 一模一样。
大小写敏感,下划线敏感,多一个空格都不行。我第一次写错成3dball,训练了十分钟发现 AI 根本没在学,Reward 跟心电图一样平。后来对照了五分钟才发现是名字没对上。
这种错误最坑的地方在于——它不报错。它不告诉你名字不对,它就默默地用默认配置跑,让你以为是算法不行,开始怀疑人生。
想接着上次的训练继续跑,把--force换成--resume:
mlagents-learn config/ppo/3DBall.yaml --run-id=3DBallTest --resume7. TensorBoard 看曲线
训练的时候光看命令行刷字,跟看老式电传打字机似的,没感觉。你得把数据可视化出来。
另开一个 Anaconda Prompt,同样激活环境,cd 到仓库目录,执行:
tensorboard --logdir .\results\ --port 6006然后浏览器打开localhost:6006,你就能看到奖励曲线、Loss 曲线一条条蹦出来。
看着 Cumulative Reward 从 0 一路爬到 100 并趋于平稳,那种满足感——我跟你讲,比你追的剧大结局还让人踏实。剧烂尾你会骂街,Reward 涨上去它可不会下来。
8. 想跑快点?把游戏打包成 exe
在 Unity 编辑器里训练,那是真慢。编辑器光一个场景视图就吃掉你一半性能,还得渲染 Gizmo、渲染 Inspector,跟你一边写代码一边开着三个浏览器标签页看短视频一样,能快才怪。
正确做法:File → Build Settings → Build,把游戏打包成 exe。打完之后,把 yaml 配置文件也丢进那个文件夹,然后:
mlagents-learn 配置文件名.yaml --run-id=试一下 --env=执行文件名.exe --num-envs=9 --force看到没,--num-envs=9,一口气开 9 个窗口同时训练。九个小方块同时学平衡小球,那种场面,像一个班的小朋友同时练平衡木。
要是连图形窗口都不想看(窗户口在那儿晃确实分心),后面再加个--no-graphics,性能还能再涨一截。我一般是挂着机器去喝咖啡,回来就训完了。
9. 唠到这儿
整个 ML-Agents 的路子其实就三步:搭场景 → 写 Agent 脚本告诉 AI 看啥做啥 → 敲命令开训。
听着简单是吧?但我跟你讲,配环境那一步就能把 80% 的人劝退。剩下的 20%,会在"名字没对上 yaml"和"路径有中文"这两个坑里反复横跳。
等你真把第一个 onnx 模型跑起来,看着方块稳稳托住小球那一刻,前面熬的夜、掉的头发,都值了。
后面还有更复杂的东西——多智能体对战、视觉输入模仿人类、自己改算法。咱慢慢玩,不急。
P.S. 推荐一个大神的教程给想要了解或者学习人工智能知识的读者,这个教程里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏教程,请点击下方链接查看,传送门https://blog.csdn.net/qq_74013365