第28名解决方案 - 使用Arcface并不简单
第28名解决方案 - 使用Arcface并不简单
作者: Wonjun, Dongjoo
发布日期: 2023-05-03
感谢Kaggle和Google主办这场比赛 :)
所有工作都与@ydjoo12共同完成
摘要
我们使用了5层Transformer编码器,结合交叉熵损失和子类Arcface损失,并集成了6个使用不同交叉熵和子类Arcface损失组合训练的模型。
数据预处理
数据增强
- 翻转姿势:
- 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()
训练
- 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率增加一倍
- 标签平滑:
- 超参数:
- 训练轮数:140
- 最大长度:64
- 批次大小:64
- 嵌入维度:256
- 头数:4
- 层数:5
- 使用AdamW和余弦退火重启(学习率1e-3)
模型集成
- 2个不同种子的加权交叉熵Transformer:
- 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作为元学习器的堆叠