网络搭建训练步骤:
- 数据收集
- 网络搭建
- 网络训练
- 模型测试
一、 总体思路
1.1 模型体系结构
我的网络模型中的卷积层,前三层卷积神经网络的stride
为 \({2}\times{2}\),kernel
为\({5}\times{5}\),而后两层卷积神经网络的stride
为 \({1}\times{1}\),kernel
为 \({3}\times{3}\)。我跟随五个卷积层和三个完全连接的层,得到一个输出控制值,即反向转弯半径。这参考了NVIDIA在16年发表的论文“End to End Learning for Self-Driving Cars”,本文提出了一种将单个前置摄像头的原始像素直接映射到转向指令的网络。所以这篇论文与这个项目的目的是一致的。
NVIDIA的工作是基于卷积的设计。根据作者的观点,他们设计了卷积层作为特征提取器,而全连接层负责控制转向角。但是,正如他们所指出的,由于系统端到端的特性,使得在网络中分离出特性提取器和控制器的位置是极为困难的。
1.2 防止模型过度拟合
该模型包含池化层,以减少过度拟合,在不同的数据集上对模型进行训练和验证,以保证模型不过度拟合。
最后对模型进行了测试,通过在模拟器上运行该模型,并确保车辆能够保持在轨道上。
1.3 优化器
该模型使用adam优化器,因此学习速度不是手动调优的
model.compile(loss='mse', optimizer='adam')
1.4 训练数据
选择训练数据以保持车辆在道路上行驶。我使用了中心车道驾驶的组合,从道路左右两侧的转向角由于校正恢复,校正就是将原本不是处在中心的相机通过对角度进行 \(\pm {correction}\),最后等效于中心相机的效果,这算是数据增强的一种方式。
correction = 0.2 # this is a parameter to tune
二、模型架构和培训策略
2.1 方案设计
推导模型体系结构的总体策略是通过摄像机图像来控制汽车的转向角。
我的第一步是使用卷积神经网络模型类似于LeNet。我认为这个模型可能是合适的,因为它是一个成熟的分类网络。
之后为了衡量模型运行得有好坏,我将图像和转向角数据分割成一个训练和验证集。我发现我的第一个模型在训练集上有一个低的均方误差,但在验证集上有一个高的均方误差。这意味着模型过度拟合。为了克服过拟合,我对模型进行了修改,使网络能够减少过拟合。然后我添加了dropout图层,但是效果不是很理想。之后,我参考了NVIDIA的工作。
最后在模拟器上测试,看看小车在轨道上的行驶情况。当小车经过一些特定的地方时,会脱离轨道,为了改善这些情况下的驾驶行为,我打乱了数据集的训练顺序,增加了批次的数量。在经过这个步骤后,车辆能够在不离开道路的情况下自动绕轨道行驶。
2.2 网络结构
最终的模型结构由一个卷积神经网络组成,该网络信息如下,
Layer | Description |
---|---|
Input | 90x320x3 RGB image |
Convolution 5x5(RELU) | 2x2 stride, same padding, outputs 45x160x24 |
Max pooling | 1x1 stride, outputs 44x159x24 |
Convolution 5x5(RELU) | 2x2 stride, same padding, outputs 22x80x36 |
Max pooling | 1x1 stride, outputs 21x79x36 |
Convolution 5x5(RELU) | 2x2 stride, same padding, outputs 11x40x48 |
Max pooling | 1x1 stride, outputs 10x39x48 |
Convolution 3x3(RELU) | 1x1 stride, same padding, outputs 10x39x64 |
Max pooling | 1x1 stride, outputs 9x38x48 |
Convolution 3x3(RELU) | 1x1 stride, same padding, outputs 9x38x64 |
Max pooling | 1x1 stride, outputs 8x37x48 |
Fully connected(RELU) | inputs 18944, outputs 1164 |
Fully connected(RELU) | inputs 1164, outputs 100 |
Fully connected(RELU) | inputs 100, outputs 50 |
Fully connected(RELU) | inputs 50, outputs 10 |
Fully connected | inputs 10, outputs 1 |
起初,我采用了dropout策略,发现容易欠拟合,模型不容易收敛,所以我选择了step
为 \({1}\times{1}\) 的pooling层。同时,利用步幅为 \({1}\times{1}\) 的卷积,尽可能多地保留预测信息。
下面是该网络结构的可视化。
Figure 1 网络
2.3 网络训练与测试
为了捕捉良好的驾驶行为,我从互联网上下载了相关的 数据集。下面是一个中心车道驾驶的例子:
Figure 2 训练图片
由于模拟器会同时会为左右摄像头保存图像,于是我将左右摄像头采集的数据,经过转向角由于校正,等效于中心相机的数据。
为了扩充数据,我还翻转了图像和角度,认为这样可以提高网络预测的稳定性。例如,下面是一个已经翻转的图像。
不过,并不是所有这些像素都包含有用的信息。在上面的图像中,图像的顶部部分捕捉树木、山丘和天空,底部部分捕捉汽车的引擎盖。我使用Cropping2D
裁剪图像。例如,下面是一个经过裁剪的图像。
最后,我随机打乱数据集,将20%的数据放入验证集。
我使用这些训练数据来训练模型。验证集帮助确定模型是否超过或低于拟合。理想的迭代数是10,可以通过可视化的损失来说明。
Figure 6 损失曲线
我使用了adam优化器,因此不需要手动训练学习率。
三、总结
车辆行为克隆网络中需要调整的参数是
- batch_size=32,
- correction = 0.2,
- cropping=((50,20), (0,0))
- train_test_split(samples, test_size=0.2)
此外,数据集的在训练时需要做随机处理,而且训练数据越多,训练效果越好。