初探:
NOTE: 该文适合手端咖啡,在暖和的下午慢慢享用,语言较为通俗随性,更像是一篇故事。要了解更多的技术细节,可以移步文末的技术报告与代码链接(https://github.com/huangchaoxing/Vision-based-steering-angle-prediction)。【备好梯子,部分链接需要上墙】
最近这一年对端到端的自动驾驶比较感兴趣。所谓端到端自动驾驶,就是模型直接通过输入的图像或者视频信息得到汽车驾驶行为的指令(方向盘转角,油门大小,踩刹车的程度)。在 deep learning 时代之前,许多汽车自动驾驶行为的指令需要通过图像的预处理得到一些人工的特征信息进而计算得出。其实,神经网络直接开车早在1989年就已经实现了,当时的模型很浅而且输入也是作了简化的。2016年的时候,英伟达率先提出了利用CNN(卷积神经网络)直接将车载摄像头的图像映射到方向盘转角的方法,这让整个过程变得省时省力又舒心:)。 这种自动驾驶行为其实是一种模仿学习(或者叫行为克隆),需要事先收集人类开车时的图像以及这幅图所对应的方向盘转角,然后通过监督学习学习的方法让CNN去拟合一个从图像到方向盘转角的映射~ 这样我们就能随意逮虾户了。
我本人第一次接触到这个领域完全是出于对GTA V这款游戏的喜爱。一次偶然的机会我在Python 博主 sentdex的youtube频道上看到了一个用分类方法玩GTA 的视频(基于tensorflow)。后来我自己又如法炮制地用Pytorch制作了一个用CNN分类的方法在GTA V里开飞机的玩具project。这个开飞机的模型其实十分简陋,唯一能做到的就是让飞机在天上别掉下来(当然也可以避开高楼,高山和大海哈),当然还是有一定的娱乐性的,毕竟你要先亲自玩游戏开飞机呀。2019年春节的时候,我在参加澳大利亚机器人视觉中心的机器人视觉夏令营时,有一个workshop的环节需要训练一个CNN然后把它部署到一个小车上,从而让小车可以在车道上安全行驶。这个其实可以说是英伟达模型的玩具版本。我们要实现在车道上遥控开车,然后让CNN去拟合小车根据输入图像的行为。在这里放一个链接给大家过过眼瘾。我训练的模型比较菜(最终比赛成绩排名9/13,逃),这个效果是来自帝国理工的博士生和田健太郎先生的作品。
真实世界:
随着一个男人的成长,他的玩具也会一直变大。转眼到了做computer vision学期project的时候了,我也决定探索一下真实世界里的开车。2月底的一个下午,我和同学驱车到堪培拉Fyshwick入手了RTX2070+9代i5,折腾正式开始。在端到端驾驶领域,有几个benchamark的数据集:Udacity,Comma-ai,dbnet, DeepDrive 等。我尝试地在Comma-ai上训练了一下英伟达的结构,但发现这个数据集里低速情况和人为的规划性故意直角转弯实在有点多,模型非常难收敛。低速行驶下的行为以及直角转弯等往往会被视作是一种人类提前规划的行为,而非单一的被动反应。经过几番权衡后,我启用了一个叫SullyChen的数据集。这个数据集是由美国学生SullyChen收集的。驾驶的地方是洛杉矶的市郊,有着开阔的视野和众多弯曲的海岸山路(脑海里一片加州阳光的美景,这不就是现实版的GTA V 洛圣都吗)。这里总共是两个数据集共10万余张车载照相机以20 Hz收集到的图像以及对应的方向盘转角。然而,并不是所有的数据都适合拿来进行训练和测试的。在6万张的数据集中,因为当中有很长一段的山间停车场小路的兜兜转转(甚至有大角度掉头),我们不得不把这段予以剔除。然而,这就导致了整个视频的不完整,会给后期利用视频流的训练带来麻烦。于是乎我们干脆把这个数据集作为测试集的来源,在其中挑选了两段分别代表城市行驶和盘山公路行驶的视频片段作为测试集(共33000帧左右)。另外一个拥有四万多帧的数据集名正言顺地成为了训练集,其中最开始的在地下车库驶出路面的片段被剔除。至于数据增广,我们采用的是亮度抖动以模拟路面阳光和阴影的变化。我们还对图像实施了拉伸(压扁)以凸显路面的趋势。
在模型结构上,我们决定采用比较浅的模型,毕竟英伟达的模型也不是很深,几层足矣。总的来说是两块卷积块+两个全连接层。因为最后要输出一个方向盘的数值(回归问题),所以最后的输出个数设置为一。自然而然地,损失函数采用L2范数,即prediction和ground-truth的差之平方。首先,我们采取的是单帧输入得到方向盘输出的方法。实际的效果并不算太理想,方向盘转角误差可达20度。其实,人类在真实开车过程中往往不会一帧一帧地想我需要怎么去操作方向盘,而是会基于一种短期的变化趋势来决定自己的操作。我们抱着试试看看的态度把三帧的图像堆叠到了一起并送入神经网络,城市公路上的误差一下子去到了7点多度,而山路上的误差也去到了15度以下。这证明序列性的信息对开车是很有帮助的!
时光记忆
如何利用时间上的信息来提升模型性能成了我们要考虑的问题。RNN(循环神经网络)和LSTM(长短时记忆)的名字此时不时回荡在耳边,但梯度累计消失(爆炸),过拟合以及不稳定的问题同样是要考虑的问题。最终,还是简单主义占了上风。双流CNN的方法进入了我们的视野(如下图)。
所谓双流CNN,便是使用两组CNN,一组CNN提取的是RGB信息(普通照片)的特征,而另一组CNN负责提取时间信息(通常是光流,把两帧之间像素的移动速度投影到图像空间)中的特征。最后两组特征融合在一起并得到要输出的值。该方法一开始用于视频动作识别和动作预测。相应地,在这里我们的RGB流输入的是三诊堆叠的图像,时间流则是体现三帧之间变化的两帧光流图。
废话不多说,直接上演示结果:
https://www.bilibili.com/video/av53174716
好八,一个学期下来实在太累了,细节的东西就不写了。更多的就看项目链接里的内容吧。我要和朋友开车去新南威尔士州吃饭了(饿)。