使用深度学习在Unity环境中训练Donkey Car —— 训练模型

前言:

        上一篇里说到部署开源环境并制造训练数据,接下来我们需要使用这些数据来训练一个模型。

        本篇训练模型使用了英伟达在16年发布的论文中的网络结构,这是这篇论文的地址:End to End Learning for Self-Driving Cars

        在训练模型之前我们需要装好 python,tensorflow >= 1.12, pillow, matplotlib 。

       如果你还没有制造数据或是没有部署完环境,请转到我的上一篇博客,有疑问可以直接留言:使用深度学习在Unity环境中训练Donkey Car —— 环境搭建和数据制造 – 简书

运行流程:

        在我们训练模型之前,我们应该先来理解Donkey Car是如何运行的!

        首先摄像头拍到路面图片,然后将图片送入模型中,模型最后会传出两个值,一个是转向值,一个是油门值(一般油门恒定在某个速度),得到两个值之后再传到Donkey Car中,用来控制车辆行驶。Donkey Car就在这样一个运作机制中行驶。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 Donkey Car 运行原理图

             我们看完运行流程之后会发现模型在这当中有很大的作用,所以我们需要了解模型结构。

模型结构:

        模型使用了五层CNN(卷积神经网络)和三层全连接层,首先对输入的图片进行归一化,接着连续三层使用步长为2×2的5×5卷积核,再是两层非跨卷积,卷积核大小为3×3,五层卷积都使用relu激活函数,这前五层主要作用是提取特征。卷积层结束之后把数据拉平经行最后三层全连接层,使用relu激活函数。算上归一化那一层一共是九层网络,图片经过这九层网络会输出一个值(转向值)或两个值(转向值和油门值)。

        输出值的数量根据你的需求,通常都是通过网络输出一个转向值,油门值设为恒定,当然你也可以使输出两个值,但是两个值会有诸多因素考虑,如当超过某个速度时摄像头拍摄得到的图片会模糊引发网络无法提取特征,这样一来则会让小车失控,其次就是在Unity环境中制造的数据都是匀速的那我们训练出来的网络也是匀速的。在考虑这些因素之后我们通常让小车匀速形式,其实在实际开车中大部分时间不也是匀速行驶吗?所以对于Donkey Car 无需太执着于控制实时速度。

        既然我们决定让网络只输出一个转向值,那么我们该如何让网络学会通过图片判断出正确的转向值?这正是通过使用训练数据对模型训练来达到此效果。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 网络结构

训练模型:

        训练数据中的图像被输入神经网络,然后计算出一个建议的转向值。将建议的转向值与图片的真实转向值进行比较,对该图像的转向值和神经网络的权重进行调整,使神经网络输出更接近图片真实的转向值。权重调整使用反向传播(bp)实现。优化器使用adam,损失函数使用均方误差(mse)。同时我们在真正训练时使用早停法。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 训练网络

代码:

        当我们理解其原理之后我们再看src文件夹下的代码。首先在PyCharm中打开上一篇博客我们的开源环境文件,我们会看到如下图的文件。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 文件目录

        在src文件夹下有6个py文件:

conf.py : 用来保存网络参数,其中有图片的输入维度,神经网络输出几个值,训练轮数,批次数量和早停法的patience参数设置

models.py:  用来保存网络结构,这里使用keras写神经网络

train.py : 使用训练数据来训练神经网络

prepare:_data.py  用来将一次生成的数据移动到dataset文件夹下(在上一篇博客制造训练数据中用到了)

tcp_server.py:  写了一个tcp服务器用来和unity环境交互

predict_server.py:  与unity环境交互,使用训练好的模型操纵小车在unity中行驶

        我们打开models.py文件(如下图),我们可以看见在models.py中不仅使用keras手写了九层网络,还在每层后面加上了0.2的Dropout进行了随机施活,在最前面还对图片进行了一个切割操作,使160×120的图片变成120×120。 在之后我也尝试过去掉dropout,发现效果比之前更差了,所以这样的一个网络结构应该是比较不错的,我也尝试了一些改进虽然有一些提升但不明显,我也就不在这里详说如何改进了,因为效果提升不是太明显了。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 网络结构

        接下来我们打开train.py文件,我们会发现在训练文件中有大部分在写如何使用训练数据(如下图),因为我们在造训练数据时,我们只得到了图片,那转向值从何而来?其实转向值就在图片的名称里,所以这几个函数可以将图片和转向值分离出来。由于图片太多同时引用会占用太多内存,而这几个方法则是通过文件保存路径来进行操作,这样可以节省很多内存。比如批次为60张时,生成器则会选取60张图片的路径,通过路径找到图片并且从名字中提取出转向值,这样一来内存占用就不会很大,节省空间。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》

        在train.py中我们还需要理解一个地方(如下图),这里在训练模型时使用了早停法,当你的模型性能不再提升时或是将要过拟合时停止训练保存模型,其中我们需要知道的是patience参数,它的作用是当你的模型损失值在连续多少次都没降低的情况下就会停止网络训练,比如patience设置为5,那么当损失值连续5次一样时模型将会停止训练,保存上一次的模型。

        在保存模型时,我们需要知道的是save_best_only参数,当它为True时,保存的模型则是在验证集上效果最好的模型,当它为False时则保存所有模型。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 早停法

        看完这些细节我们就对整个网络的训练有了大致了解,剩余的代码大家可以自己浏览一下,在训练数据处理那部分写的比较巧妙,建议大家可以仔细阅读。

开始训练网络:

        理解整个原理以及拥有训练数据之后,我们需要开始训练了。我们首先打开src文件夹的上一级文件夹,在sdsandbox-master文件夹下打开cmd或者PowerShell,输入“ python src/train.py outputs/mymodel.h5 ”指令,其中mymodel.h5中的mymodel是你保存模型的名字,可以随意修改。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 上一级文件夹
《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 输入指令

        在模型开始训练之前会输出神经网络每层参数以及维度,训练数据量等等。

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 开始训练(1)

        开始正式训练网络,我这里一个epoch有1618张图片,每次输入64张图片进行训练。我在我的环境中配置了tensorflow GPU版本,如果使用cpu进行训练会慢五倍。如何配置tensorflow GPU版本,我在这里找到一篇不错的博客,是我一个大佬朋友写的:深度学习环境搭建-CUDA9.0、cudnn7.3、tensorflow_gpu1.10的安装 – 简书

《使用深度学习在Unity环境中训练Donkey Car —— 训练模型》 开始训练(2)

        在训练结束的最后会跳出一张折线图,用来显示每一轮epoch中模型在训练集和验证集上的损失值。

总结:

        使用五层CNN和三层DNN并用上Dropout带来的效果是不错,我们需要注意的是我们训练数据时应尽可能包含不同地图的数据,不能只有直行数据或只有转向数据,否则训练出来的模型不会转向或直行。

        大家可以在详细看完代码了解每一步作用之后,对神经网络进行一些改动,或是对训练数据做一个预处理使其提取特征更容易。这样做的目的都是为了在使用模型驾驶Donkey Car时能有更好的效果。

        在下一篇博客中将讲述如何使用训练好的模型驾驶Donkey Car!

        博客链接:使用深度学习在Unity环境中训练Donkey Car —— 驾驶Donkey Car – 简书

    原文作者:MGK_Tracy
    原文地址: https://www.jianshu.com/p/7b52a6fc110a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞