AI强化学习游戏开发历程

前段时间自己手搓了一个简单的赛车小游戏,用来做深度学习实验。

算法选的是DDPG,这个在连续动作上的效果比较好。要是不知道DDPG是啥,可以去看看莫凡的教学。

游戏设计

游戏的控制很简单,aswd四个键前后左右,后面简化了一下,前进和刹车共用一个w键,

按下加速,到最大速度为止,松开减速,就像特斯拉的那种操纵一样。

参数设计

围绕车子一周设定了10个距离探测器,尤其是斜角的位置,放了两个。

然后再上传速度和角速度就行了。

场地

手工拼接了一个包含了所有地图原件种类的图作为训练场地。一旦这个图跑通了,后面就算随机拼接也是可以一直跑的。

训练

一开始就这样拿去训练,结果车子原地打转,因为没有前进方向,后面不得不又在道路中央加了个导航用的箭头

就是画圈的那个白色的长条,用它的方向来指示道路方向,运行时隐藏。

同时传入速度的向量改成相对于前进方向的垂直和水平分量(Vz, Vx),注意这里z是前后,x是水平

一开始我的奖励公式是:

<math xmlns="http://www.w3.org/1998/Math/MathML"> R e w a r d = − ( ( 1 − V z ′ ) 2 + V x ′ 2 ) × a 2 × d 2 Reward = - ( (1-V_z')^2+V_x'^2) \times a^2 \times d^2 </math>Reward=−((1−Vz′)2+Vx′2)×a2×d2

这里面 <math xmlns="http://www.w3.org/1998/Math/MathML"> V x ′ V_x' </math>Vx′和 <math xmlns="http://www.w3.org/1998/Math/MathML"> V z ′ V_z' </math>Vz′分别是相对于道路方向水平和垂直方向的速度,并且相对于最大速度做了归一化,a是车子与前进方向的夹角除以180度后的归一化值,d是车子与道路中心的归一化距离。因为奖励是负的,所以只要各个评分项越小,奖励越大。设计初衷就是想让车子尽量在道路中间开, 并且沿着道路方向前进。

一开始这个奖励公式收敛极快,才十几回合就学会直走了。然而在开始学习过弯的时候问题出现了。这个公式下,AI学过弯很慢,一个120度弯学了172回合才学会,换个角度大点的弯又得从头学。

而且随着训练次数的增加,AI开始越来越倾向贴着道路右侧开,到500回合的时候连直道都开不好了,遇到弯也不拐,到最后干脆直接一开始就右转加速撞墙,直到慢慢的停原地不动开始摆烂。

也就是说,出现了很多人提到的,随着训练次数增多,不但没收敛反而越学越差,开始劣化。

我不得不换个奖励公式

参考了一下网上其他人的公式,换成了

<math xmlns="http://www.w3.org/1998/Math/MathML"> R e w a r d = − ( ( 1 − V z ′ ) C o s θ + V x ′ S i n θ ) 2 − a 2 − d 2 Reward = - ( (1-V_z') Cos\theta + V_x' Sin\theta)^2 - a^2 - d^2 </math>Reward=−((1−Vz′)Cosθ+Vx′Sinθ)2− a2− d2

依旧是 <math xmlns="http://www.w3.org/1998/Math/MathML"> V x ′ V_x' </math>Vx′和 <math xmlns="http://www.w3.org/1998/Math/MathML"> V z ′ V_z' </math>Vz′分别是相对于道路方向水平和垂直方向的速度,并且相对于最大速度做了归一化,a是车子与前进方向的夹角除以180度后的归一化值,d是车子与道路中心的归一化距离。

这里引入了 <math xmlns="http://www.w3.org/1998/Math/MathML"> θ \theta </math>θ,就是车子前进方向与道路方向的夹角。

这个式子是对前面那个的优化,用相加代替相乘,这样就不会因为一个因素变成0而导致整个结果为0。在这种情况下,贴边前进是要扣分的。

这次学习直行没有之前那么快了,平均50-60回合才学会,然而就是学不会转弯,同时依旧存在训练一两百回合之后开始出现擦边、越学越差的问题。跑了一晚上,弯道没学会,反而连一开始学会的直走都不会了。只会开局右转撞墙,然后停在原地摆烂。

无奈,我只好把其他人的公式照抄过来试试,同时增加神经元的数量,又把Actor网络多加了一层

<math xmlns="http://www.w3.org/1998/Math/MathML"> R e w a r d = V z C o s θ − V x S i n θ − ∣ d ∣ × ∣ V x ∣ Reward = V_z Cos\theta - V_x Sin\theta - |d|\times|V_x| </math>Reward=VzCosθ−VxSinθ−∣d∣×∣Vx∣

这是个正向奖励的公式,速度没有做归一化, <math xmlns="http://www.w3.org/1998/Math/MathML"> V x V_x </math>Vx和 <math xmlns="http://www.w3.org/1998/Math/MathML"> V z V_z </math>Vz就是相对于道路方向水平和垂直方向的原始速度,θ是前进方向与道路方向的夹角,d是归一化了的车与道路中央的距离。公式最后一项就是对于车子远离道路中央的行为施加惩罚。

这个式子的目的就是使车子沿道路方向的速度尽量大,同时避免横向远离道路中央.

不得不说神经元多了AI也变得聪明许多。开始训练后,学习直线前进的速度跟之前那个差不多,也是平均50-60回合才会,但是不会再剧烈的左右晃动了,但同时依旧个弯道困难户,一开始运气好一下子开过了好几个弯,之后就一直撞墙,开始越学越差,最后退化成开局右转擦边撞墙。

这时我打算把整个过程的奖励和神经网络的loss画出来看看。

结果这一看才发现,loss在一开始的一百回合内慢慢变小之后,又开始渐渐变大,critic网络的loss在一开始几个回合之后便不再有大的波动。

然后是奖励曲线,由于撞墙会直接给0分奖励,所以整个奖励图就像个心电图,每一回合从零分开始再到撞墙零分结束为一个周期,一直重复。

(这里之前的曲线图删了,所以没有了)

不过也不是没有发现,就是每次撞墙前的reward居然是正的,而且整个回合属于是从起步开始reward就在逐渐变大,直到撞墙那一刻突然归零。

这就表示对于AI来说,起步右转恰恰是获得更高奖励方式,目前给的奖励公式居然在鼓励起步右转撞墙。这显然是不对的。

罪魁祸首就是因为从零加速的过程中因为速度增加而追加的奖励,大于了因为偏离道路中央而施加的惩罚。所以整体的奖励是在增加的。

针对这个问题我又把公式改了又改,依旧不理想,要么最后又变成开局撞墙,要么学不会转弯。
经过一段时间的思考,我突然想起,可以用车上的距离传感器的数据算奖励

具体是这样的,取所有传感器中距离最小那个值。距离越小说明越容易撞墙,得扣分,越大表明越靠近路中央,得给与奖励。然后为了不让AI停在原地,再加上之前的垂直方向速度奖励:

<math xmlns="http://www.w3.org/1998/Math/MathML"> R e w a r d = V z C o s θ + ∣ d ∣ Reward = V_z Cos\theta+ |d| </math>Reward=VzCosθ+∣d∣

这里 <math xmlns="http://www.w3.org/1998/Math/MathML"> V z V_z </math>Vz是车子相对于道路方向垂直方向上的速度, <math xmlns="http://www.w3.org/1998/Math/MathML"> θ \theta </math>θ角度是车子前进方向与道路方向的夹角,d是所有传感器中最小的那个距离。

之前查资料的时候有看到大佬的说法是,奖励规则越简单越好,所以其他限定条件就不加了。只要保证靠越近道路边缘分数越低就行,防止AI又变成之前只会开局右转的样子。

这次训练明显学习直线的回合变多了,直到第80次左右才学会开直线,然而,AI却怎么也学不会转弯,虽然有时运气好,突然能转过去一次,但AI好像并不会去吸取这次的经验。

本着奖励规则越简单越好的原则,这次我干脆把其他条件都删了

这次的公式非常简单:

<math xmlns="http://www.w3.org/1998/Math/MathML"> R e w a r d = f × d Reward = f \times d </math>Reward= f×d

d就是距离传感器中最小的那个值,为了防止车屁股贴路边也扣分,只取车前方的那几个传感器的数据。f的值只有1和0,车停下来就是0,只要有速度就是1,防止AI停路中间摆烂。

这次终于训练成功了!

附上训练视频

www.bilibili.com/video/BV1QA...

Git源码: github.com/DarkAngelZT...

以及最后炼丹成功的统计图

(横轴episode,纵轴value)

AI终于开完全部赛道的那一刻,我只想起一个词:大道至简,Less is more。有些时候规则制定太多反而什么都学不会。

相关推荐
盼小辉丶9 小时前
PyTorch强化学习实战(7)——表格学习与贝尔曼方程
pytorch·深度学习·强化学习
盼小辉丶3 天前
PyTorch强化学习实战——使用交叉熵方法解决 FrozenLake 环境
人工智能·pytorch·python·强化学习
Luca_kill4 天前
深度解构 Hermes Agent:从“中央调度”到“自我进化”的架构哲学
大模型·强化学习·agent框架·ai架构·hermes agent
盼小辉丶5 天前
PyTorch强化学习实战(6)——交叉熵方法详解与实现
人工智能·pytorch·python·强化学习
盼小辉丶5 天前
PyTorch强化学习实战(5)——PyTorch Ignite 事件驱动机制与实践
人工智能·pytorch·python·强化学习
joshchen2156 天前
强化学习基础(赵世钰)第一章
人工智能·深度学习·算法·机器学习·强化学习
joshchen2156 天前
强化学习基础(赵世钰)第二章 贝尔曼方程
人工智能·python·机器学习·强化学习
星马梦缘9 天前
强化学习实战8.3——用PPO打赢星际争霸【编写自定义环境GYM】
人工智能·强化学习·gymnasium·星际争霸·sc2·starcraft2·sb3
盼小辉丶10 天前
PyTorch强化学习实战(4)——PyTorch基础
人工智能·pytorch·python·强化学习
星马梦缘10 天前
强化学习实战8——用PPO打赢星际争霸【整合版】
强化学习·ppo·星际争霸·sc2·starcraft2·sb3