您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
   
 
 订阅
基于深度学习的自动驾驶小车
 
作者:清华计算机学堂
  78  次浏览      7 次
 2025-2-27
 
编辑推荐:
本文主要介绍了基于深度学习的自动驾驶小车开发相关内容。 希望对您的学习有所帮助。
本文来自于微信公众号清华计算机学堂,由火龙果软件Linda编辑、推荐。

01卷积神经网络基础

卷积神经网络(Convolution Neural Network,CNN)是一类特殊的人工神经网络,是深度学习中最重要的一个分支。卷积神经网络在很多领域都表现优异,精度比传统学习算法高很多。特别是在图像处理领域,卷积神经网络是解决图像分类、目标检测和语义分割的主流模型。本节内容会进行更多工程上的讲解,不会涉及太多理论公式,读者如果对于理论部分不熟悉也没关系,可以在学会工程技巧之后再去反哺数学理论,从工程实践去引领理论知识的学习能够起到事半功倍的效果。

PaddlePaddle将深度神经网络模型按照层(Layer)的概念呈现。在本书接下来的内容中,会见到各种不同类型的层。那么怎么理解神经网络中层这个概念呢?

在参考书2.4节投资预测案例中使用了直线方程y=ax+b来拟合数据,这个模型非常简单,拟合精度有限。如果希望强化这个模型,让它能够与观测数据更契合,这时候可以在直线方程基础上继续提高x的阶数,如下所示:

很明显,提高阶数后的y2模型要比y1模型更复杂,属于二次非线性函数,具备更强的数据拟合能力。这里的y2是在y1的基础上乘上x再加上常数c完成的。因此,可以将y1和y2看作两层,且y2是在y1的基础上做了某些特定操作完成的,这就是最简单的层的概念。如果继续按照上述层操作,依次得到y3、y4等,那么越往后阶数越高,模型越复杂。

神经网络与高阶函数一样,理论上随着层数的增加函数的表达能力越强。卷积神经网络是通过一层层具备不同功能的操作堆叠出来的,一般由卷积层、激活函数层、池化层、线性变换层组成。下面将介绍各层的基本原理和计算规则。

1. 卷积层

卷积层的作用就是提取图像卷积特征。典型二维卷积操作如图2.31所示。

■ 图2.31典型二维卷积操作示意图

在图2.31所示中,输入图像形状是32×32×3,其中宽和高均为32像素,通道数为3,卷积层是一个5×5×3的滤波器,通过这样一个滤波器与输入图像进行卷积(卷积操作时假设padding=0),可以得到一个28×28×1大小的特征图。

一般情况会使用多层卷积来提取更深层次的特征。随着卷积层的加深,提取到的特征越来越抽象,对图像的理解能力也越来越强,如图2.32所示。在高层特征之后一般可以级联分类器对最终提取的高层特征进行分类,得到物体的最终类别。

■ 图2.32基于多层卷积的特征提取

那么卷积层是怎么计算的呢?

其实卷积层计算原理与参考书1.3节中介绍的图像卷积类似,只不过图像卷积操作一般1次只使用1个卷积,而深度学习中的卷积层可以1次使用多个卷积进行操作。例如对于形状为32×32×3的图像,如果使用1个卷积滤波器(形状为5×5×3)对其进行卷积可以得到28×28×1的特征图像; 如果使用n个同样大小的卷积滤波器,那么就会产生n个28×28×1的特征图,这些特征图合并就组成了28×28×n大小的特征图。可以看到,通过这样的卷积层操作,将原本只有32×32×3大小的输入图像变成了28×28×n大小。

PaddlePaddle提供了封装好的二维卷积层函数: Conv2D(),完整定义如下:

各参数说明如下:

上述参数比较多,读者第一次接触这些参数如果不能完全掌握也没有关系,后面在案例部分遇到具体的问题时会再深入讲解。这里需要重点掌握的就是如何根据输入特征形状计算卷积的输出特征形状。

下面是使用Conv2D()的一个简单示例(demo/demo9.py):

在实际的图像处理应用中,为了能够方便运算,一般将多张图像按照通道方向拼在一起进行训练和推理。例如有两幅图像,其形状均为[3,8,8],其中3表示图像是3通道的,第1个8表示图像高度为8像素,第2个8表示图像宽度为8像素。将两幅图像按照通道拼接在一起后形成了一个4维的数组,其形状为[2,3,8,8](顺序为NCHW),这里的2就是指一次拼接的图像样本数。上述代码中,直接使用paddle.uniform()函数构建了一个均匀分布的形状为[2,3,8,8]的Tensor,紧接着构建了一个二维卷积层conv,并使用这个卷积层对输入的 进行1次特征提取,这个卷积层的输入特征通道数为3,输出特征通道数为6,卷积核大小为5×5,最终输出结果为

这里需要关注3点。

(1) 由于输入特征x的通道数为3,因此Conv2D的第一个参数输入通道数必须也为3,否则执行运算会报错。

(2) Conv2D的输出特征通道数是6,所以最终的y的输出通道数也为6。

(3) 输入特征x的高、宽为[8,8],最终输出特征y的高、宽变为[4,4],这个是怎么计算的呢?这里可以套用简单的公式:

out=(in-kernel+2×padding)/stride+1

式中,out表示输出形状大小; in表示输入特征形状大小; kernel表示核大小; padding表示边缘扩增尺寸(默认为0); stride表示步长(默认为1)。

对于这个示例,参考上述公式计算如下:

2. 激活函数层

显然,单纯的线性模型的特征提取能力有限,不足以对复杂的实际问题进行建模。例如对于图像卷积,其操作就是对每个像素点赋予一个权值然后与滤波器核对应位置元素相乘再累加,这个操作显然就是线性的。对于真实图像来说,仅依赖卷积不能很好地进行区分。为了解决这个问题,可以进行非线性变换,解决线性模型所不能解决的问题。激活函数层就是深度学习中用来引入非线性能力的模块。

深度神经网络需要保证可以计算每个节点的梯度,从而可以使用反向传播更新梯度信息,因此选取的激活函数也需要能保证其输入输出都是可微的。

下面介绍三种在深度学习模型构建过程中常见的激活函数。

(1) Sigmoid函数。函数形式如下:

该激活函数可以将任意输入映射到0~1,在一定程度上对数据进行了归一化,如图2.33所示。但是该激活函数有个明显的缺点,就是饱和时梯度非常小。由于神经网络算法反向传播时后面的梯度是以乘性方式传递到前层的,因此当层数比较深

的时候,传到前面的梯度就会非常小,网络权值得不到有效的更新,产生所谓的“梯度消失”现象。

■ 图2.33Sigmoid激活函数曲线图

(2)ReLU 函数。函数形式如下:

图片该激活函数由Alex在2012年提出,在很大程度上解决了优化深度神经网络时梯度消失的问题,曲线图如图2.34所示。ReLU是目前构建深度学习网络使用最频繁的激活函数,比较简单且运算量小。当x>0时,ReLU的梯度恒等于1,无梯度消失问题,收敛快。

■ 图2.34ReLU激活函数曲线图

PaddlePaddle中提供了ReLU()激活函数层,示例代码如下(demo/demo11.py):

(3) ELU函数

函数形式如下:

ELU训练速度快,相比Sigmoid和ReLU等激活函数,它实现了更高的准确性,其函数曲线如图2.35所示。

■ 图2.35ELU激活函数曲线图

PaddlePaddle中提供了ELU()激活函数层,示例代码如下(demo/demo12.py):

3. 池化层

池化层的作用主要是对输入的特征图进行压缩。图2.36所示是一种典型的池化操作——最大池化。该池化层的滤波器参数为2×2,步长为2。其具体含义是指在2×2局部滑动窗口内找到当前最大元素值作为输出特征值,并以步长为2进行滑动,遍历整个输入特征图像得到最后的输出。除了最大池化操作以外还有平均池化操作。与最大池化操作不同的是,平均池化操作在局部滑动窗口内使用的是局部特征的平均值作为输出。

■ 图2.36最大池化操作

针对图像处理任务,PaddlePaddle提供了最大池化层函数MaxPool2D(),其完整定义如下:

各参数含义如下:

通过池化操作,可以有效缩小原特征图尺寸,实现空间上的特征融合。在深度卷积神经网络模型中,经常会使用池化操作,而池化层往往跟在卷积层后面。

示例代码如下(demo/demo13.py):

上述代码中构建了一个形状为[1,3,32,32]的输入特征,然后使用了最大池化操作paddle.nn.MaxPool2D()对其进行特征聚合,最终输出的特征形状如下:

这里依然可以套用二维卷积层 Conv2D ()的简单公式进行特征尺寸计算:

式中,out 表示输出形状大小;in 表示输入特征形状大小;kernel 表示池化核大小;padding 表示边缘扩增尺寸(默认为 0 );stride 表示步长(默认为 1 )。对于这个示例,参考上述公式计算如下:

4.线性变换层

线性变换层中的每一层是由许多神经元组成的平铺结构,一般会放在网络的最后,用来融合所有特征并进行降维,其数学形式如下:

式中,X 表示输入的 Tensor ;W 表示权重;b 表示偏置。图 2.37 所示展示了常见的线性变换层接入形式。

■ 图2.37接入线性变换层

在图2.37中,原始输入图像大小为[3,28,28],经过卷积层、非线性激活层和池化层以后变为[20,12,12],后面接着线性变换层,这个线性变换层的作用就是把尺寸为[20,12,12]大小的特征图展平成[20×12×12,1]的特征图,然后再降维成大小为[2,1]的低维序列,用于最后的分类输出。

PaddlePaddle提供了线性变换层Linear(),其定义如下:

各参数说明如下:

示例代码如下(demo/demo14.py):

上述代码首先使用paddle.ParamAttr()函数对线性变换层的weight_attr和bias_attr参数进行了初始化,然后以此构建了一个线性变换层。接下来通过paddle.randn()函数随机构建一个[3,2]大小的特征x,然后使用线性变换层对x进行运算得到大小为[3,4]的y。

输出结果如下:

除了上述基本操作以外,还可以通过PaddlePaddle提供的Sequential()函数将两个线性变换层级联,组合成一个新的层再对特征Tensor进行操作,如下所示(demo/demo15.py):

输出结果如下:

可以看到两个输出结果是一样的。有了类似这样的级联功能,就可以更加简洁快速地编写模型代码,高效实现模型组网。

02算法原理

第1章通过OpenCV图像处理算法实现了一个简单的自动驾驶小车,该算法需要大量人工定义的参数,如车道线颜色、分割阈值等。一旦道路环境有所改变,所有这些参数都需要重新调整。由于参数之间存在强耦合性,参数调优工作量大且对经验要求高。

那么能不能模仿前面的投资预测案例,丢给机器一大堆图片数据,让机器自己去学习如何从当前图像中分析出小车下一步合适的转向角度呢?答案是可以的。深度学习能够从大量图像数据中自行学习特征,完成媲美人类甚至超越人类的推理水平。整个学习过程不用人为干预,所要做的就是“喂”一堆图片并且设定好需要优化的目标函数即可。“喂”的图片越多,覆盖场景越丰富,最终机器学习到的驾驶水平越高。

本章算法实现思路来源于2016年英伟达发表的论文End to End Learning for SelfDriving Cars。这篇论文的核心思想就是使用卷积神经网络自动提取图像特征,实现端到端的控制。该论文使用了深度网络结构,大大增强了图像特征表达能力,最终取得了不错的效果。所训练出来的模型无论是普通道路还是高速道路、无论是有道路标线还是没有道路标线都非常有效,解决了传统算法泛化性能不足的问题。在2016年自动驾驶研究火热时,该论文是一篇影响力很大的文章,即使放到现在,也可以作为自动驾驶入门的学习材料。

整个算法原理很简单,是对真实人类操作的一个模拟。对于人类驾驶员来说,假设要驾驶车辆,首先用眼睛查看前方路面情况,然后大脑根据当前眼睛看到的画面进行分析,最后将分析结果反馈到手部转动方向盘,从而控制车辆始终行驶在规定区域内。这篇论文算法实现原理也是一样的,具体流程如图2.38所示。

■ 图2.38算法原理流程

在图2.38所示中,由摄像头采集图像,然后将图像输入预先训练好的CNN网络,这个网络的输出是方向盘的转向角度,从而可以控制小车按照这个角度打方向盘。接下来需要解决的就是如何构建这个CNN模型。

针对每帧图像,都可以认为有一个最佳的转向角度,即网络的输入是图像,输出是一个代表方向盘转向角的回归值。具体模型结构如图2.39所示。

■ 图2.39算法模型结构

在图2.39所示中,算法输入在底部,输出在顶部。整个模型结构并不复杂,就是一堆的卷积神经网络模块按照顺序堆叠。这个模型一共包含30层,由于其输入图像的精度比较低(高66像素、宽200像素),因此推理速度比较快。借助GPU,该算法可以实现实时推理。具体的,输入图像首先进行归一化,然后经过5组卷积层处理,最后拉平以后通过多个线性变换层计算得到一个回归值,这个回归值就是所需要的转向角。

这里会遇到一个问题,训练上述深度神经网络需要大量的数据,即每帧图像以及对应的最佳转向值,这些数据从哪里获取呢?这篇论文里提出了一个方法,既然是模拟人类行为,那么只要让驾驶员在相关赛道上进行驾驶,驾驶时一边记录每帧图像的同时也记录当前帧对应的操控的转向角,这样一组组数据记录下来就是“最佳”训练数据。

获得训练数据以后,在模型训练阶段,每次迭代时计算模型预测角度与当前图像期望角度的误差,这个误差通过神经网络反向传播来更新模型参数。整个过程一直循环重复,直到误差足够低,这意味着模型已经学会了如何合理地转向,最终模型的输出结果是非常符合人类驾驶经验的。

上述学习过程省去了传统算法中的颜色区域提取、感兴趣区域选择、霍夫变换等一系列复杂的图像处理步骤。该论文研究团队通过收集不到100h的训练数据进行训练,最后得到的模型足以支持在各种条件下稳定操控车辆,比如高速公路、普通公路和居民区道路,以及可以面对多种不同的天气状况,如晴天、多云和雨天等。这里需要额外说明的是,这个模型的输出仅有一个转向角度,模型相对简单。如果输出变量再多一些,如考虑油门值、摄像头角度、行人避障等,那么这个模型还需要再进一步优化。

 

   
78 次浏览       7
 
相关文章

CMM之后对CMMI的思考
对软件研发项目管理的深入探讨
软件过程改进
软件过程改进的实现
 
相关文档

软件过程改进框架
软件过程改进的CMM-TSP-PSP模型
过程塑造(小型软件团队过程改进)
软件过程改进:经验和教训
 
相关课程

以"我"为中心的过程改进(iProcess )
iProcess过程改进实践
CMMI体系与实践
基于CMMI标准的软件质量保证

最新活动计划
DeepSeek大模型应用开发实践 3-15[在线]
DeepSeek助力职场效率提升 3-22[在线]
流程设计与建模 3-8[北京]
OpenGauss数据库调优实践 3-11[北京]
基于 UML 和EA进行分析设计 3-20[北京]
业务建模&领域驱动设计 3-27[北京]
 
 
最新文章
iPerson的过程观:要 过程 or 结果
基于模型的需求管理方法与工具
敏捷产品管理之 Story
敏捷开发需求管理(产品backlog)
Kanban看板管理实践精要
最新课程
基于iProcess的敏捷过程
软件开发过程中的项目管理
持续集成与敏捷开发
敏捷过程实践
敏捷测试-简单而可行
更多...   
成功案例
英特尔 SCRUM-敏捷开发实战
某著名汽车 敏捷开发过程与管理实践
北京 敏捷开发过程与项目管理
东方证券 基于看板的敏捷方法实践
亚信 工作量估算
更多...