PyTorch自动驾驶视觉感知算法实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

前言
PREFACE

2012年,多伦多大学Geoffrey Hinton教授指导的学生Alex Krizhevsky发表了AlexNet深度卷积神经网络模型,在ImageNet图像识别任务上大幅超越第二名,开启了深度学习的新纪元。同年,笔者于慕尼黑工业大学毕业,彼时,笔者选修了Daniel Cremers教授开设的多门课程,醉心于学习凸优化、微分几何等经典计算机视觉的理论知识,对卷积神经网络一无所知,丝毫感觉不到一个人工智能的伟大时代就此揭开帷幕。25年前,也是在慕尼黑工业大学计算机系,Jürgen Schmidhuber教授指导的学生Sepp Hochreiter发表了论文LSTM(Long Short-Term Memory),他们也决然无法预料,被SVM等机器学习方法打败的仿生人工智能,居然会在几十年后忽然起死回生,迎来爆发式发展。

从2012年AlexNet的发表到今天,不过10年有余,卷积神经网络和相关硬件的发展可谓一日千里。笔者在自动驾驶视觉感知领域从业五年,深感这个领域教育资源的发展远远跟不上学术界和工业界的发展。该领域涉及的知识庞杂,既广又深:知识广度方面,从最优化理论,常用模型的特点,到使用C++编写高性能、高可靠性的程序和对各种神经网络加速芯片的了解,都属于自动驾驶感知算法工程师技术栈的覆盖范围;知识深度方面,工程师要对卷积神经网络的数学理论有足够深入的理解,而不应止步于调参的范围。

也就是说,一个自动驾驶算法工程师,不但要有深厚的数学基础,掌握凸优化和统计学,还要熟悉高性能嵌入式软件的编写,这是一个横跨学术界和工业界的多面手职业。尤其是自动驾驶行业一日千里,很多工程师只能在工作中边干边学,一路走来可谓磕磕绊绊,如果能有一本书全面覆盖自动驾驶感知算法工程师的能力圈,那职业之路走起来就会顺畅很多。笔者就是出于这个目的,根据自己的职业经验和理论知识,编写了本书。

本书特点

考虑到上文提及的自动驾驶感知算法工程师的种种职业特点,本书的内容将会兼顾计算机视觉学术界的最新研究成果和自动驾驶的工程实践。

兼顾细节与理论

深度学习的很多算法用公式或语言来描述会困难重重,用示意图来表现则是一目了然。对算法和模型的细节,笔者绘制了大量的三维示意图进行讲解,争取让读者一看就懂。

但光有细节是不够的,深度学习算法工程师常被取笑为“调参侠”“炼丹师”。这是因为卷积神经网络被认为是一个巨大的黑盒(Black Box),其运作规律难以为人类所理解。诚然,深度学习的理论仍在构建之中,尚不完善,但学术界从未停止过对深度学习的理解。已经有大量学术成果能加深人们对卷积神经网络各种现象的理解,本书将吸收这些成果对神经网络的运作进行解释。例如,ResNet的有效性,除了原论文中的解释,还有其他学者也对其进行了研究,产生了新的理解,这些研究也被纳入到本书中来。

总之,笔者争取让读者知其然,也知其所以然,超越“调参侠”的职业定位。

注重动手实践

本书除了对理论进行深入浅出的讲解,也注重将理论落到实处。深度学习一个很大的特点是“一看就懂,一做就懵”。理论很熟悉了,但实际操作起来会遇到各种各样的小问题。这是因为算法工程师应能将数学符号和代码中的数据结构连接起来,这是这个职业所需要的独特能力。本书对重要的模型细节都展示了代码示例,对代码中各个张量的维度,各维度的含义都有详细的注释和讲解。对于复杂的模型,笔者直接在公式下方展示代码,尽量做到让读者从公式中的符号轻松地落实到代码中的变量中。

提供迷你数据集

自动驾驶视觉感知任务的另一个特点是任务多而杂,每个任务往往都有一些通用的数据集。例如,深度估计有KITTI数据集,语义分割有Cityscape,目标检测有nuScenes等。学习的时候往往会遇到的一个问题是每一个任务都要下载一个巨大无比的数据集,并专门写接口。如果要进行多任务训练,往往需要nuScenes等巨型数据集,而且标注还不全面。如果只用于学习的目的,杂乱而庞大的数据集无疑大大增加了学习的时间和经济成本。

为此笔者特意自制了一个方便学习的迷你数据集。数据集采集于德国慕尼黑一片安静的城区,场景类似于KITTI,仅包含7000多帧图像。笔者使用当时精度最高的目标检测和语义分割网络对这个迷你数据集进行标注,并逐帧对标注的伪真值进行后期处理,尽量获得高质量的标注数据。数据集是一个连续的视频,笔者还对相机进行了标定,故可以用于无监督深度估计任务。

强调模型部署落地

正如上文所说,要成为一个优秀的算法工程师,其工作内容不仅是调参那么简单,另一块重要的工作内容就是将模型部署到生产环境。对于互联网行业的算法工程师来说,模型部署可能相对简单,有成熟的工具链支持,但自动驾驶的模型部署就复杂得多了。首先自动驾驶系统运行的硬件平台往往不是常见的x86平台,自动驾驶系统的模型部署,其实已经属于嵌入式软件开发了。其次,自动驾驶系统实时性高,吞吐率需要达到10FPS(Frame-Per-Second)或更高,同时需要运行的神经网络模型很多,而硬件平台上的神经网络加速器往往算力有限。因此,为了将神经网络模型部署到算力有限的硬件平台,并达到实时性要求,需要结合硬件的特点对模型进行设计和压缩。

模型的部署涉及模型压缩、模型导出、Nvidia芯片的模型量化和模型推理、C++的开发等知识,都是深度学习课堂上不会涉及的工程实践内容。这些工程实践知识是非常重要的,但超出了很多长期在Ubuntu和Python开发环境下的读者的“舒适区”。本书将全面覆盖相关知识,帮助读者更轻松地扩大自己的“舒适区”,为将来的工作做好准备。

本书内容

第1章讲解卷积神经网络的理论基础,用简洁的篇幅介绍了神经网络和卷积神经网络的基础知识。包括反向传播的推导、神经网络的各种网络层、常用的损失函数、正则化、优化器和学习率调整方法等。

第2章介绍深度学习开发的常用工具,从显卡和操作系统的概念,到Python开发中用到的常用工具。例如,pip包管理器、Anaconda虚拟环境以及NumPy和OpenCV两个常用的库。最后配合示例代码着重讲解PyTorch的使用,示例代码将实现一个简单的卷积神经网络并进行训练。

第3章讲解卷积神经网络中主干网络的概念。本章首先介绍主干网络在卷积神经网络中的位置和作用,以及对比学习等主干网络预训练技术。之后会对最常用的几种主干网络的特点和使用场景进行讲解。最后通过示例代码展示如何加载TorchVision中的主干网络模型。

第4章介绍自动驾驶系统中最经典的一个任务——目标检测。本章首先讲解目标检测算法中的几个基本概念,如锚框、极大值抑制、一阶段和两阶段算法等。随后以FasterRCNN为例介绍两阶段网络,以Yolo为例讲解一阶段网络,以CenterNet为例讲解无锚框网络。最后讲解Yolo的PyTorch示例代码。

第5章聚焦于自动驾驶系统中和图像分割有关的两个任务:语义分割和实例分割。本章讲解语义分割的网络结构、损失函数、常用精度指标等基础知识。也会涉及实际工作中需要解决的问题,尤其会介绍语义分割模型的几种信息融合方法和设计思路。本章5.3节介绍三个实例分割算法,特别是会介绍一种半监督的实例分割算法。最后介绍计算机视觉领域最常用的框架OpenMMLab的系统结构和使用方法。

第6章的内容是近几年来新出现的自动驾驶感知任务——单目深度估计。本章首先介绍多视图三维几何理论,然后讲解单目深度估计的无监督训练方法,最后结合实际工作中会遇到的若干难点提出一些解决方案。

第7章分为两部分,第一部分介绍多任务网络的结构和设计思路,着重介绍多任务网络训练时的损失平衡问题及其基于不确定度的损失平衡方案;第二部分介绍神经网络的压缩,以通道剪枝为例介绍L1正则化增加网络稀疏度和可微通道剪枝的网络压缩方法。最后通过示例代码讲解如何用PyTorch实现网络压缩。

第8章讲解神经网络模型的部署,包括C++开发环境的搭建,LibTorch和TensorRT这两个神经网络推理库。最后介绍模型量化的相关理论知识和工程实践,并对FP32精度模型和INT8精度模型进行精度与推理速度对比。

本书代码资源

本书强调动手实践,笔者为本书的出版制作了一个迷你数据集,并为大部分内容编写了代码。代码均以MIT许可证开源,既可用于学习,也可直接应用于日常工作中。开源代码托管于代码库https://github.com/vision-adas/code。

开源代码的具体内容详见代码库的README页面,迷你数据集的下载链接也公布于此。代码库中代码包括:

1)目标检测和语义分割多任务网络模型的全套训练代码。

2)无监督单目深度估计的全套训练代码。

3)多任务模型的网络压缩代码。

4)将模型导出为onnx、pt和TensorRT格式的模型导出代码。

5)在目标硬件上使用LibTorch和TensorRT部署模型的C++示例代码。

6)配置代码环境所需的Dockerfile。

致谢

笔者长年在知乎论坛的深度学习社区参与讨论,很多对深度学习的理解都来自于社区讨论。网友的批评指正和提问都是对笔者的鞭策,而关注者的认可也在激励笔者不断进步,特此对网友们表示感谢。本书成书于疫情期间,父母对笔者长年不回国探亲报以极大的宽容和理解,长时间的专注让本书得以完成。笔者的小伙伴杨丹青对本书的第1章进行了审阅,对行文提出了很多有价值的建议,更要感谢她对笔者疏于陪伴的谅解。

笔者