SECOND模型
参考链接【3D目标检测】SECOND算法解析 - 知乎 (zhihu.com)
论文地址:Sensors | Free Full-Text | SECOND: Sparsely Embedded Convolutional Detection (mdpi.com)
代码链接:traveller59/second.pytorch: SECOND for KITTI/NuScenes object detection (github.com)
模型解决问题
模型来自于VoexlNet。
论文提出的主要动机为:
(1)考虑到VoxelNet论文在运算过程中运算量较大,且速度不佳。作者引入了稀疏3D卷积去代替VoxelNet中的3D卷积层,提高了检测速度和内存使用;
(2)VoxelNet论文有个比较大的缺点就是在训练过程中,与真实的3D检测框相反方向的预测检测框会有**较大的损失函数,**从而造成训练过程不好收敛。
其他的创新点:
(1)比如数据增强这块,作者使用了数据库采样的操作;
(2)对于正负样本数量的极度不平衡问题,作者借鉴了RetinaNet中采用的Focal Loss。
网络结构
模型来自于VoxleNet,主要对于中间卷积层以及最后的RPN层进行改进。
原始VoxelNet结构:
SECOND结构:
原论文模型图:
3D稀疏卷积特征提取
提出原因
卷积神经网络已经被证明对于二维图像信号处理是非常有效的。然而,对于三维点云信号,额外的维数 z 显著增加了计算量。
另一方面,与普通图像不同的是,大多数三维点云的体素是空的,这使得三维体素中的点云数据通常是稀疏信号。
我们是否只能有效地计算稀疏数据的卷积,而不是扫描所有的图像像素或空间体素?否则这些空白区域带来的计算量太多余了。这就是 sparse convolution 提出的motivation。
模型中的使用
-
构建 Input Hash Table 和 Output Hash Table
模型输入:离散图像数据
模型输出结构:
一种是 regular output definition,就像普通的卷积一样,只要kernel 覆盖一个 active input site,就可以计算出output site。Sparse Output
另一个称为submanifold output definition。只有当kernel的中心覆盖一个 active input site时,卷积输出才会被计算。Submanifold Output
得到输出的卷积过程(Sparse Output):
后续卷积不产生有效结果:
卷积之后记录位置信息:
汇总位置信息:这里只记录了有价值,也就是卷积之后有值的位置。
-
构建 Rulebook
首先由输入信息得到输出信息,分别包括:
- 输入点索引
- 输入点位置
- 输出索引
- 输出位置
其次去得到原始点位置Pin与卷积中心的偏移GetOffset(Pin , P),
最后整合成为Rulebook,其中(i,j)表示偏移位置,由多个稀疏点的Pout对应偏移组成。
Rulebook:
第一列是一个索引
。
第二列是一个计数器
count,count记录来自于那个Pin,0为第一个Pin,1为第二个Pin,
第三列:v_in和 v_ out 分别是atomic operation的 input hash table 的 index,也就是第几个点和计数器一致,和 output hash tabel的index,代表Pout的索引,注意是整合后的。
3.卷积计算
输入图像,在(2,1)处为P1点,在(3,2)处为P2点,其余点都视为无价值点或零点,我们希望只对P1,P2所在 部分区域进行卷积。
P1点三个通道的值为[0.1, 0.1, 0.1],P2点三个通道的值为[0.2, 0.2, 0.2]
接下来将该图像进行稀疏卷积,输入通道为3,输出通道为2,卷积核尺寸为3X3,步长为1,不进行填充。
输入:(2 , 3 , 5 ,5)
卷积核: (in_c = 3,out_c = 2 , k = 3,s = 1 , p = 0)
输出: (2,2,3 ,3)
conv2D(kernel_size=3, out_channels=2, stride=1, padding=0)
稀疏卷积过程:
-
根据RuleBook索引去在卷积核上寻找对应位置的值,如红框所示,偏移位置为(-1,-1),这个偏移指的是卷积核中心位置与原始像素位置P1,P2的偏移,也就是说我当前P像素在我卷积核的位置。计算过程中,我需要将P1的值也就是[0.1,0.1,0.1]与卷积核对应位置也就是F0进行点乘。
-
根据RuleBook中i_in指引对应Hash in 中的0号索引点P1,我们知道此时偏移位置为(-1,-1)的点是P1,并且其输出位置i_out为5,对应Hash out中的(2,1)位置,也就是卷积后结果应该赋予卷积后特征图(2,1)位置。
-
同理对应偏移为(0,0)的且输出同样为Hash out 5号位置的点,进行同样上述计算,我们又得到一组计算结果,如图所示,深色为第一个卷积核计算结果,浅色为第二个卷积核计算结果。最后我们将这两个同样输入位置的值相加即可。得到的结果,输出的(3x3)特征图中(2,1)位置的值就确定了。
稀疏卷积小结
input/output hash tabel只维护那些真正有元素的条目。
所以说,稀疏卷积是非常 efficient的,因为我们只计算非零元素(元素指的是像素 或者 体素)的卷积,而不需要计算所有的元素。
虽然构建 rulebook 也是需要额外的计算开销的,但是这个构建过程也是可以在GPU上并行处理的。
方向回归
SECOND中还有一个重要的创新,就是对物体方向估计进行了重新的建模。
这里,作者在最后的RPN层(原来是两个分支,用来物体分类和位置回归)多引入了一个分支,用来对物体方向进行分类。为什么是分类不是回归呢?
这里我们简单聊聊在VoxelNet中是如何训练模型以达到确定方向的目的的。
在VoxelNet中,一个3D BBox被建模为一个7维向量表示,分别为(x,y,z,l,w,h)
训练过程中,对这7个变量采用Smooth L1损失进行回归训练。
这会造成什么问题呢?
大家设想下,当同一个3D检测框的预测方向恰好与真实方向相反的时候,上述的7个变量的前6个变量的回归损失较小,而最后一个方向的回归损失会很大,这其实并不利于模型训练。为了解决这个问题,作者引入了对方向角的回归损失,定义如下:
其中 Θ P 是预测角度, Θ t 是真实角度,计算过程两个角度相减再进行 s i n , s i n 函数在 0 − Π 内先单调递增再单调递减, 其中\Theta_P是预测角度,\Theta_t是真实角度,计算过程两个角度相减再进行sin,sin函数在0-\Pi内先单调递增再单调递减, 其中ΘP是预测角度,Θt是真实角度,计算过程两个角度相减再进行sin,sin函数在0−Π内先单调递增再单调递减,
也就是说如果两个预测角为 90 度时,该损失函数最大,两个预测角为 0 或 Π 时,损失值最小。 也就是说如果两个预测角为90度时,该损失函数最大,两个预测角为0或\Pi时,损失值最小。 也就是说如果两个预测角为90度时,该损失函数最大,两个预测角为0或Π时,损失值最小。
这时候还会产生一个问题,那么我两个预测相反时,也就是预测朝向和真是朝向相反,我损失函数依然不大,这不符合我们希望的结果。
这时候作者提出了另一种解决方法(也就是RPN中的direction classifer分支),作者将车头是否区分正确直接通过一个softmax loss来进行约束。如果theta>0则为正,theta<0则为负。那么这就是个简单的二分类问题了,也就是结构图中direction classifer。
简单来说就是对车头进行单独的分类,车头分类正确的情况下才继续进行方向交损失的计算,此时loss中只针对角度偏移为0-90的目标,也就是偏移越大损失越大,达到了我们希望的效果。
总结
SECOND模型算是VoxelNet模型的改进版本,作为3D点云检测中的单阶段模型,其速度能够达到实时的要求,并且应用了稀疏卷积来处理点云稀疏的痛点问题。另外还对损失函数进行了改进 ,模型能够学习到方向角相关信息。本文对于稀疏卷积和损失函数进行了简单的介绍。
引用
文中大部分图像引用于以下几篇文章,我这里进行了汇总和添加了一些自己的理解,更加详细的内容,推荐去看这几位大佬的文章。
通俗易懂的解释Sparse Convolution过程 - 知乎 (zhihu.com)