返回列表

28th place solution - Using Arcface is not trivial.

546. Google - Isolated Sign Language Recognition | asl-signs

开始: 2023-02-23 结束: 2023-05-01 音视频处理 数据算法赛
第28名解决方案 - 使用Arcface并不简单

第28名解决方案 - 使用Arcface并不简单

作者: Wonjun, Dongjoo
发布日期: 2023-05-03

感谢Kaggle和Google主办这场比赛 :)
所有工作都与@ydjoo12共同完成

摘要

我们使用了5层Transformer编码器,结合交叉熵损失和子类Arcface损失,并集成了6个使用不同交叉熵和子类Arcface损失组合训练的模型。

数据预处理

  • 使用了129个关键点(每只手21个,嘴唇40个,姿势11个,每只眼睛16个,鼻子4个)
  • 仅使用x和y坐标
  • 处理流程:数据增强、帧采样、标准化、特征工程和NaN值的0填充
  • 帧采样:当长度超过最大长度时,按固定间隔采样至最大长度。这比中心裁剪在本地CV中表现更好,并且在减少最大长度的同时最小化了性能下降
    L = len(xyz)
    if L > max_len:
        step = (L - 1) // (max_len - 1)
        indices = [i * step for i in range(max_len)]
        xyz = xyz[indices]
    L = len(xyz)
  • 标准化:对x和y分别进行标准化
  • 特征工程:
    • 运动特征:当前xy - 未来xy
    • 手关节距离
    • 时间反向差分:xy - xy.flip(dims=[0]):在CV上提升0.004

数据增强

  • 翻转姿势:
    • x_new = f(-(x - 0.5) + 0.5),其中f是索引变换函数
    • 在Public LB上提升0.01
    • xy值在[0, 1]范围内。翻转前先减去0.5移动到原点,然后再加0.5回到原始坐标
    • 不移动到原点时没有性能提升
  • 旋转姿势:
    def rotate(xyz, theta):
        radian = np.radians(theta)
        mat = np.array(
            [[np.cos(radian), -np.sin(radian)], [np.sin(radian), np.cos(radian)]]
        )
        xyz[:, :, :2] = xyz[:, :, :2] - 0.5
        xyz_reshape = xyz.reshape(-1, 2)
        xyz_rotate = np.dot(xyz_reshape, mat).reshape(xyz.shape)
        return xyz_rotate[:, :, :2] + 0.5
  • 插值(上采样和下采样):
    xyz = F.interpolate(
            xyz, size=(V * C, resize), mode="bilinear", align_corners=False
    ).squeeze()
    • 上采样(下采样)到原始长度的125%(75%)

训练

  • 5层Transformer编码器 + 加权交叉熵:
    • 类别权重基于类别的表现
    • 在LB和CV上,堆叠4~5层时准确率持续提升:
      • 1层(5个种子):0.714
      • 2层(5个种子):0.738
      • 3层(5个种子):0.748
      • 4层(5个种子):0.751
    • 我们在自注意力和全连接层后添加了dropout层(基于PyTorch官方代码)
  • 5层Transformer编码器 + 加权交叉熵 + 子类Arcface损失:
    • loss = cross entropy + 0.2 * subclass(K=3) Arcface
    • loss = 0.2 * cross entropy + subclass(K=3) Arcface
  • Arcface:
    • 在Public LB上提升0.01
    • 单独使用Arcface会导致性能下降
    • Arcface与交叉熵结合比单独使用交叉熵收敛更快更好
    • 子类K=3,margin=0.2,scale=32
  • 计划性Dropout:
    • 在CV上提升0.002
    • 在训练一半后,最终[CLS]的dropout率增加一倍
  • 标签平滑:
    • 参数:0.2
    • 在CV上提升0.01
  • 超参数:
    • 训练轮数:140
    • 最大长度:64
    • 批次大小:64
    • 嵌入维度:256
    • 头数:4
    • 层数:5
    • 使用AdamW和余弦退火重启(学习率1e-3)

模型集成

  • 2个不同种子的加权交叉熵Transformer:
    • 单模型LB:0.75
  • 2个不同种子的加权交叉熵 + 0.2*子类(K=3) Arcface:
    • 推理:交叉熵和Arcface头的加权集成
    • 单模型LB:0.76
  • 2个不同种子的0.2*交叉熵 + 子类(K=3) Arcface:
    • 推理:交叉熵和Arcface头的加权集成
    • 单模型LB:0.75
  • 6个模型集成Public LB:0.779
  • 所有模型为fp16格式
  • 总大小:20MB
  • 延迟:60ms/样本

在CV上有效但未包含在最终提交中的方法

  • TTA:
    • 在CV上提升0.000x
    • 提交评分错误,可能是内存问题
  • 手臂骨骼之间的角度:
    • 在1折上提升0.000x,由于时间限制未能充分验证

无效的方法

  • 使用GCN嵌入层代替Linear层
  • 堆叠空间注意力与时间卷积块
  • 姿势关键点之间的距离
  • 移除异常值并重新训练:
    • 使用Arcface子类向量之间的角度
    • 移除约5%的样本(约4000个)
  • 使用更大Transformer的知识蒸馏
  • 随机权重平均
  • 使用每一层的所有[CLS] token
  • 使用所有token的平均值代替[CLS] token
  • 使用MLP作为元学习器的堆叠
同比赛其他方案