412. NFL 1st and Future - Impact Detection | nfl-impact-detection
感谢主办方,并祝贺所有获奖者!
以下是我的解决方案:
视频被分割成形状为 8х224х224х3 的片段。作为正样本,我选择了包含撞击的帧及其前四帧和后三帧。使用固定步长的网格制作了大小为 224x224 的补丁。作为负样本,我选择了没有撞击的随机帧序列。此外,我还保存了每个帧序列的边界框位置和大小。
从一开始,我就使用了 3D CNN,即来自 SlowFast 的 I3D。我对其进行的唯一更改是在输入中添加了第四个通道,该通道对于第五帧始终为 1(不知道这是否有意义)。模型预测的是第五帧的边界框。然后,我附加了来自 pytorch_segmentation 的 FPN,具有六个输出通道且没有上采样。
来自主干网络第 2 到第 5 块的 3D 特征图使用 F.adaptive_avg_pool3d 转换为 2D 特征图,然后传递给 FPN。
FPN 生成大小为 6x56x56 的网格。网格的第一个通道负责网格特定单元格中是否存在边界框。接下来的四个通道负责边界框在网格单元内的位置和边界框的大小。最后一个通道预测单元格中是否存在撞击。所有这些预测仅针对八帧序列中的第五帧进行。总的来说,除了锚点之外,该网格类似于 YOLO 输出。
数据增强:
A.Compose([
A.HorizontalFlip(p=0.5),
A.OneOf([
A.ColorJitter(p=1),
A.HueSaturationValue(40, 60, 40, p=1),
A.RGBShift(60, 60, 60, p=1),
A.RandomGamma((20, 200), p=1)
], p=0.8),
A.OneOf([
A.GaussianBlur(p=1),
A.GaussNoise((10.0, 50.0), p=1),
A.MedianBlur(blur_limit=5, p=1),
A.MotionBlur(p=1),
], p=0.6),
A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=0,
border_mode=0, p=0.4),
# A.GridDistortion(p=0.2, border_mode=0),
])
我有几种训练损失配置。HuberLoss 用作边界框位置和大小的损失。FocalBinaryLoss 或带有不同 pos_weight 参数的 nn.BCEWithLogitsLoss 用于预测边界框和撞击的存在。
使用带有默认参数的 Adam 和多阶段学习率衰减 10 倍。共进行了 10 个 epoch。
对于每个 epoch,我选择所有正样本和 positive_count*2 个负样本。从第二个 epoch 开始使用难例挖掘。为此,我获取所有负样本的预测,并选择那些撞击置信度高于某个阈值(0.1)的样本。如果没有足够的难例,我会随机添加负样本。
我冻结了主干网络,仅在大小为 8x3x720x1280 的全图上训练 FPN 几个 epoch。增强和优化器与第一阶段相同。
四个此类模型的集成在我的本地验证中得分为 0.48。
然后我注意到头盔中心的检测效果不佳。它经常将护肩(我不知道确切叫什么)误认为是头盔,并给予其比某些头盔更高的置信度。
我认为这是因为边界框中心的真值数据仅包含点,而这些点并不总是位于头盔的中心,因此模型很难理解应该在哪里输出点。因此,我决定不使用边界框中心的点,而是预测直径等于边界框宽度和高度平均值的圆。这些圆向其边界逐渐消失。如图所示。