简介
本文算法在CVPR 2019自动驾驶Workshop 3D目标检测挑战赛中赢得了冠军。作者利用稀疏3D卷积提取丰富的语义特征,并将其输入到一个类别平衡的多头网络中进行3D目标检测。为了解决自动驾驶场景中天然存在的严重类别不平衡问题,作者设计了一个类别平衡采样和增强策略以生成一个更加平衡的数据分布。此外,作者还提出了平衡分组网络头,提升了具有相似形状类别的分类性能。本文提出的算法在所有评估指标上大幅优于PointPillars,在nuScenes数据集上达到SOTA的检测性能。
源代码:https://github.com/poodarchu/Det3D
- 提出了类别平衡采样策略,解决了nuScenes数据集中类别分布极端不平衡的问题;
- 设计了一个多头网络以使具有相似形状、大小的不同类别的分类互相促进,而不同形状或大小的类别不再互相影响;
- 结合对网络架构的改进,损失函数的设计以及训练过程,本文的方法在nuScenes数据集上达到了SOTA的性能
图1:nuScenes 数据集中类别的实例分布是长尾的,表现出常见和稀有对象类别示例数量极度不平衡。
数据增强
DS_Sampling
根据特定类别的样本在所有样本中的比例来复制一个类别的样本。一个类别的样本越少,复制该类别的样本越多,形成最终的训练数据集。要实现类平衡数据集,所有类别在训练拆分中的比例都应该接近,具体地说:
首先统计训练中存在特定类别的点云样本总数,然后将所有类别的样本加起来为
128106
个样本。从上述特定类别的样本中为每个类别随机抽取
128106
个点云样本中的10%
,将训练集从28130
个样本扩展到128100
个样本,大约是原始数据集的 4.5 倍。
总而言之,DS Sampling
可以看作是提高了训练拆分中稀有类的平均密度,可以有效缓解不平衡问题,如图 1 中的橙色列所示
代码参考:https://github.com/open-mmlab/OpenPCDet/blob/master/pcdet/datasets/nuscenes/nuscenes_dataset.py
def balanced_infos_resampling(self, infos):
"""
Class-balanced sampling of nuScenes dataset from https://arxiv.org/abs/1908.09492
"""
if self.class_names is None:
return infos
cls_infos = {name: [] for name in self.class_names}
for info in infos:
for name in set(info['gt_names']):
if name in self.class_names:
cls_infos[name].append(info)
# items以元组形式返回字典所有元素
# 计算特定类别的样本总数
duplicated_samples = sum([len(v) for _, v in cls_infos.items()])
# 统计每类的样本数占总样本数的比例
cls_dist = {k: len(v) / duplicated_samples for k, v in cls_infos.items()}
sampled_infos = []
# 差分比例:1/类别数=0.1
frac = 1.0 / len(self.class_names) # 0.1
# values以列表形式返回字典中所有值
# 每类扩增的比例:0.1除以每类数量实际占用的比例
ratios = [frac / v for v in cls_dist.values()]
# zip可将对象中的元素打包为一个个元组,然后返回由元组组成的列表
for cur_cls_infos, ratio in zip(list(cls_infos.values()), ratios):
# np.random.choice:从cur_cls_infos随机抽取int(len(cur_cls_infos) * ratio个数
# 将从每个类别随机采用的样本相加
sampled_infos += np.random.choice(
cur_cls_infos, int(len(cur_cls_infos) * ratio)
).tolist() # tolist:将数组或矩阵转为列表
self.logger.info('Total samples after balanced resampling: %s' % (len(sampled_infos)))
# 将采样的样本列表分类存储到字典中
cls_infos_new = {name: [] for name in self.class_names}
for info in sampled_infos:
for name in set(info['gt_names']):
if name in self.class_names:
cls_infos_new[name].append(info)
# 平衡采样后每类样本占总样本的比例
cls_dist_new = {k: len(v) / len(sampled_infos) for k, v in cls_infos_new.items()}
return sampled_infos
OpenPCDet代码里可以看出经balanced_infos_resampling
后,每个类别数量相同的,而从上图看出CBGS采样前后类别实例数量变化不明显
GT-AUG
使用 SECOND
中提出的 GT-AUG
策略从离线生成的标注数据库中采样ground truths
,并将这些采样框放入另一个点云中。
在正确放置对象框之前,需要计算点云样本的地平面位置。 利用最小二乘法和 RANSAC 来估计每个样本的地平面
图 2:地平面检测结果示例,可以用Ax + By + Cz + D = 0表示。平均而言,地平面沿z轴约为-1.82米。
网络结构
整体网络架构如下图所示,包含4个部分:输入模块,3D特征提取,区域提议网络,多组头网络。
图3 :网络架构。 3D 特征提取器由子流形和常规 3D 稀疏卷积组成。 3D 特征提取器的输出为 16 倍的缩小比例,沿输出轴展平并馈入后续区域提议网络以生成 8 倍特征图,然后由多组头网络生成最终预测。 头部组数根据grouping specification
设置
使用带有跳跃连接的稀疏 3D 卷积来为 3D 特征提取器网络构建类似 resnet
的架构。 对于一个 N × C × H × W N×C×H×W N×C×H×W的输入张量,特征提取器输出一个 N × l × C m × H n × W n N×l×\frac{C}{m}×\frac{H}{n}× \frac{W}{n} N×l×mC×nH×nW的特征图,m,n
分别是z,x,y
维度的缩小因子,l
是输出通道 3D 特征提取器的最后一层。 为了使该 3D 特征图更适合下面的 Region Proposal Network 和多组头,将特征图重塑为 N × C × l m × H n × W n N × C×\frac{l}{m} × \frac{H} {n} × \frac{W} {n} N×C×ml×nH×nW ,然后使用 区域提议网络执行常规 2D 卷积和反卷积以进一步聚合特征并获得更高分辨率的特征图。 基于这些特征图,多组头网络能够有效地检测不同类别的对象。
类平衡分组
不平衡的数据分布会使得模型被占多数的类别主导。由图2中可见,数据集对车的标注占据了43.7%,是自行车的40倍,故如果将车和自行车放在一起训练,在一个批次中基本没有自行车的数据,网络对自行车的分类效果就会很差。另一方面,如果将不同形状、大小的样本放在一起训练,回归目标会具有更大的类内差异,导致具有不同形状的类别互相干扰,这也是为什么网络在同时学习不同形状的类别时的性能不如分开单独训练的原因。直观上看,相似的形状具有相似的特征,放在一起训练可以互相促进。。两个主要的原则为:
按照一些原则将所有类别手动分为几组。对于多组头模块中的特定头,它只需要识别类并定位属于该组的类的对象。主要有 2 个原则指导有效地将 10 个类分成几组:
应将形状或大小相似的类别分组。相似形状的类通常具有许多共同的属性。例如,所有车辆看起来都相似,摩托车和自行车、交通锥和行人也有类似的关系。通过对形状或大小相似的类别进行分组,在逻辑上将分类分为两个步骤。首先,模型识别“超类”,即组,然后在每个组中,不同的类共享同一个头部。结果,不同的组学习对不同形状和大小的模式进行建模,而在特定的组中,网络被迫学习相似形状或大小的类间差异。
不同组的实例数应适当平衡。考虑到不同组的实例数不应该相差很大,这会使学习过程以大类为主。因此,将主要类别与形状或大小相似的组分开。例如,Car、Truck 和 Construction Vehicle 的形状和大小相似,但如果将这 3 个类放在一起,Car 将占主导地位,因此将 Car 作为一个单独的组,将 Truck 和 Construction Vehicle 放在一起作为一个组。这样,我们可以控制不同组的权重,进一步缓解不平衡问题
基于一定的原则手动将数据集中10个类别归为6个组:(Car), (Truck, Construction Vehicle), (Bus, Trailer), (Barrier), (Motorcycle, Bicycle), (Pedestrian, Traffic Cone)。 根据消融研究,如表 4 所示,类平衡分组对最终结果的贡献最大
损失函数
损失函数部分参照SECOND
, 如果运用SECOND
中方向分类, mAOE
会 非常高,许多预测的边界框的方向正好与地面实况相反 常见的问题如物体正反向问题(朝向相反),在这部份做了小改进,额外加入方向分类目标添加偏移量以消除方向模糊性。至于速度估计,与添加额外的归一化操作相比,没有归一化的回归可以达到最佳性能。
为了降低学习难度,使用了anchor机制,其他设置都SECOND类似,Focal loss做Classification, Smoothl1回归x, y, z, l, w, h, yaw, vx, vy,值得一提的是,每个分支用Uniform Scaling做学习权重。
除了 3D 对象检测所需的常规分类和边界框回归分支外,我们还添加了 SECOND[28] 中提出的方向分类分支。需要指出的是,根据我们的统计数据,大多数对象框都平行或垂直于 LiDAR 坐标轴。因此,如果在 SECOND 中应用方向分类,事实证明 mAOE 非常高,因为许多预测的边界框的方向正好与地面实况相反。因此,我们向方向分类目标添加偏移量以消除方向模糊性。至于速度估计,与添加额外的归一化操作相比,没有归一化的回归可以达到最佳性能。
为了降低学习难度,使用了anchor
机制。参照SECOND
,不同类别的锚点具有不同的高度和宽度配置,由类别均值决定。一个类别有 1 种尺寸配置和 2 个不同的方向。对于速度,锚点在 x 和 y 轴上都设置为 0,不需要估计 z 轴上的速度。
- 使用加权
Focal Loss
进行分类, - 使用
smooth-L1
损失用于 x 、 y 、 z 、 l 、 w 、 h 、 y a w 、 v x 、 v y x、y、z、l、w、h、yaw、v_x、v_y x、y、z、l、w、h、yaw、vx、vy 回归 - 使用
softmax
交叉熵损失进行方向分类。
在实验中,多组头被视为多任务学习过程,使用 Uniform Scaling 来配置不同分支的权重
实验结果
表 2:整体表现。 BRAVE 和 Tolist 是其他前三名的球队。 我们的方法在除 mAAE 指标之外的所有指标上都取得了最佳性能
表 3:按类别划分的 mAP 与 PointPillars 的比较。 我们的方法在尾类上显示出更具竞争力和平衡的性能。 例如,Bicycle 改进了 14 倍。 摩托车、工程车(Cons. Veh.)、拖车、交通锥(TC)提升2倍以上
表 4:我们的验证拆分方法中使用的不同组件的消融研究。 Database Sampling 和 Res-Encoder 对 mAP 的贡献最大
表 5:不同类别的 GT-AUG 等级。 对于每个类别,量级意味着放置到点云样本中的实例数
结果
本文提出的算法性能以73.1%的幅度优于baseline算法PointPillars,而对每个类别尤其是样本数较少的类别,本文的算法在平移(mATE)、比例(mASE)、方向(mAOE)、速度(mAVE)和属性(mAAE)方面的误差较小。
图 4:验证拆分中的检测结果示例。Ground truth
注释为绿色,检测结果为蓝色。 检测结果来自具有 51.9% mAP 和 62.5% NDS 的模型。 每个点云鸟瞰图像顶部的标记是其对应的样本数据标记。
结论
新发布的自动驾驶数据集nuScence
与kitti
其中一个不同点是类别变多,且其类别样本不平均,本篇文章主要提出新的类别不均衡解决方法,透过扩增数据集后,在随机采样以平衡较少的类别,并且将形状类似的分为一组,样本较少的类别能被形状类似的样本较多类别提升精度