返回列表

[4th Place Solution] Conformer Encoder-Decoder Ensemble with beam search and edit_dist optimization

570. Google - American Sign Language Fingerspelling Recognition | asl-fingerspelling

开始: 2023-05-10 结束: 2023-08-24 计算机视觉 数据算法赛
第4名解决方案:Conformer编码器-解码器集成

[第4名解决方案] 使用beam search和edit_dist优化的Conformer编码器-解码器集成

作者:flg | 发布时间:2023-08-27 | 得票数:19

TLDR

我的解决方案是两个编码器-解码器模型的集成。编码器是一个12层适配的conformer,解码器是一个两层常规transformer。我添加了各种增强和训练技术,以使训练目标与编辑距离竞赛指标保持一致。对于解码,我为TFLite实现了一个(缓存的)beam search。

挑战与计划

竞赛的目标是翻译经过人体姿态识别预处理的手语拼写视频。提交内容是具有有限OPs集的TFLite模型,并使用Levenshtein编辑距离进行评估。

这些选择对建模有以下几个影响:

  • "诚实"预测通常不是编辑距离最优的,特别是当模型无法识别短语中的任何字符时,诚实预测""得分为0.0,而"2 a-e -aroe"得分为0.16,参见Anoka的静态贪心基线
  • 本次竞赛中的TFLite模型仅允许非常有限的操作集,这意味着例如beam_search和类似算法的所有本地实现都不被支持
  • 模型有时间和大小限制(40MB),使得如何"花费"参数成为一个重要的设计决策
  • 数据集中包含相当多样本,其中大部分或全部数据缺失

考虑到这些因素,我认为"编造"内容将成为良好预测的重要组成部分,而编码器-解码器架构似乎天然适合这一点。此外,拥有解码器可以抽象掉一个时间维度,这使得开发下游算法如beam search或集成变得更加容易。我早期的测试也表明编码器-解码器比CTC效果略好,所以我选择了这种架构。

数据

我的模型使用了214个输入:21个左手、21个右手、25个姿态、1个鼻子和40个嘴唇点,每个点使用x和y坐标。数据被归一化,NaN值用零填充,并使用了与t-1和t-2值的差值作为额外特征。训练期间最多使用500帧,更长的序列会被调整大小。

我应用了相当多的数据增强:

  • 左右翻转
  • 沿时间维度重采样
  • 缩放/平移/旋转
  • 屏蔽最多60%的帧(比屏蔽序列效果更好)
  • 空间剪除(类似于Hoyso48的第1名解决方案

所有这些方法都产生了显著影响。

除此之外,我还对token进行了转换。我利用了这样一个事实:当一个短语中的单个token被随机token替换时,真实值仍然是编辑距离最优的目标。这一改变带来了相当不错的+0.008提升(使用较小的模型)。我还添加了单个token的删除和插入,但它们的影响很小(如果有的话)。

我将数据分为五折,由于计算限制,我的大多数实验只使用一折来训练较小的模型。

模型

我的模型基础是一个深层的Conformer编码器,后接一个两层transformer解码器。编码器使用12层,维度为144。MHSA有4个头,每个头的维度为64,卷积使用大小为65的核。与原始公式一样,模型使用了两个macaron风格的前馈网络,扩展因子为4。我做了一些额外的小改动,比如改变BatchNorm的位置,并在Conformer的每个子模块中添加DropPath。模型几乎在所有地方使用0.1的drop率,仅在最终分类器前使用0.3。我使用same padding而不是因果padding,并显式地将填充部分置零。

在解码器方面,我测试了许多不同的配置,但最终使用了一个非常精简的两层transformer解码器。它使用4个注意力头,每个头的维度为32,前馈网络的扩展因子仅为2。这是我能训练的最小配置,而不会出现显著的性能下降。使用小型解码器很重要,因为自回归解码对性能要求很高。

训练

在我的本地3090上,单个12层编码器模型的完整训练运行大约需要两天。为了试验不同的架构、增强等方法,在竞赛的大部分时间里,我只使用约20%的数据训练较浅的模型。

最终训练使用交叉熵损失和RAdam优化器(但AdamW与warmup效果基本相同),峰值学习率为1e-3,使用余弦调度。使用2e-6的权重衰减和0.2的标签平滑(效果很小)进行正则化,并结合轻微的高斯权重噪声(在我的测试中与AWP效果相似,但开销更低)。我训练了300个epoch,其中前100个epoch使用了补充数据。

模型训练完成后,我使用了最小词错误率训练。其中基于字符的编辑距离被用作"词错误率"。该方法从收敛的模型开始,使用beam search生成前四个预测。然后计算每个预测的编辑距离,并将其用作模型预测概率的权重。例如参见《基于注意力的序列到序列模型的最小词错误率训练》。该方法的结果即使经过大量优化后仍然不稳定。然而,1-5个epoch的短期训练在早期测试中带来了非常可观的提升。不幸的是,在最终的大型集成模型上,它只有0.001-0.002的微小改进。

Beam search与推理时优化

使用两个模型的集成,很容易达到40MB的模型大小限制。为了在运行时间维度上也达到极限,我实现了一个与本次竞赛受限的TFLite操作集兼容的beam search算法。将其与缓存的自回归解码结合使用,使我能够使用5到6的beam size(有时使用6会超出5小时限制)。这在最终集成上带来了+0.005的提升(在早期较弱的模型上提升更大)。实现有点棘手,因为存在一些边缘情况,例如在beam改变时需要重新排序解码缓存等。为了防止beam search解码时的提前终止问题,我使用了0.15的线性长度惩罚。

除此之外,我意识到我的模型在低信息样本上实现了0.0的编辑距离(例如<50帧且显示手部的帧数<5帧)。但我们知道贪心预测如"2 a-e -aroe"能得到0.16的分数。由于这些低信息样本中的大多数似乎完全损坏,我只是用恒定预测替换模型在这些样本上的预测。我使用了" a-e -are",它与之前提到的贪心预测略有不同,因为我针对更短、低信息的序列进行了优化。

最后,添加这一行代码:

x = tf.cond(num_frames < 50 and num_hand_frames <= 3, lambda: tf.constant([[59, 0, 32, 12, 36, 0, 12, 32, 49, 36, 60]]), lambda: tf.identity(x))

在所有方面都带来了+0.005的提升(所有模型的本地评估、私有和公共排行榜)。这与整个beam search的提升相当...

有效和无效的方法

  • Beam search带来了不错的+0.005提升
  • 用恒定默认预测替换模型在损坏数据样本上的预测带来了+0.005提升
  • 更深的模型比更宽的模型效果更好
  • MWER训练带来了小幅提升(+0.001 - +0.002)- 然而,这是在beam search k=5的情况下,使用贪心解码时提升更大(本地评估中+0.005)
  • 用随机token替换单个输入token是一个不错的增强方法
  • CTC作为辅助损失没有帮助
  • 屏蔽解码器输入没有帮助(当使用随机token替换时)
  • z坐标没有帮助

和往常一样:非常期待阅读大家的解决方案。如果有任何问题,请告诉我。代码即将发布。

同比赛其他方案