570. Google - American Sign Language Fingerspelling Recognition | asl-fingerspelling
我们的解决方案基于单个编码器-解码器架构。编码器是Squeezeformer的显著改进版本,其中特征提取经过调整以处理MediaPipe地标而非语音信号。解码器是一个简单的2层Transformer。我们还预测了置信度分数来识别损坏的样本,这在后处理中很有用。此外,我们引入了高效且富有创意的增强方法来规范模型,其中最重要的包括CutMix、FingerDropout、TimeStretch和DecoderInput Masking。我们使用PyTorch开发和训练模型,然后手动转换模型架构并将权重移植到TensorFlow,从中导出为TF-Lite。
我们按手语者将训练数据分为4折。开始时,这种方法的CV分数与Public LB之间几乎完全相关。随着分数提高,CV上的改进在LB上反映得较少,主要是因为LB分数总是相对较高且更早饱和。大多数时候,我们只训练和跟踪fold0的分数,而不是所有折叠。
总共使用了130个关键点,包括每只手21个关键点、每只手臂6个姿态关键点,以及面部其余76个关键点(嘴唇、鼻子、眼睛)。本地将130个关键点缓存到.npy文件以实现快速数据加载。
在数据增强之前,数据通过标准差/均值进行归一化,并将NaN值填充为零。
增强方法对于防止过拟合、泛化到新 signer 和启用深度模型至关重要。我们使用了首届ASL竞赛中流行的增强方法,同时也提出了许多富有创意的新增强方法,其中一些被证明非常有效。
大多数增强应用于50%的样本,除了调整大小和空间仿射应用于约80%的样本。
增强后,超过384帧的样本沿时间轴调整大小,使用通道级线性插值。少于384帧的样本仅在训练时填充至384帧。TF-Lite在可变长度样本上运行。
预处理过程中不会丢弃任何帧。
总体而言,我们观察到更深的模型能带来显著提升(如果能防止过拟合)。因此,不仅正则化技术(如增强方法)至关重要,而且计算效率的每一项改进都为使用更深模型创造了空间,其重要性不亚于模型架构本身。
我们的模型由3个部分组成:特征提取、编码器、解码器,如下图所示:

我们将数据解释为类似3通道图像,其中宽度由帧数定义,高度由选定的130个地标数量定义,通道由原始xyz坐标定义。
特征提取基于2D卷积,后接批归一化和线性层,用于提取每帧的扁平化特征。我们有5个这样的特征提取模块:一个用于所有地标,一个用于每种地标类型(左手、右手、面部、姿态)。所有地标模块每帧输出208维向量,其他4个各输出52维向量,然后拼接成总共208维。因此我们每帧有两个208维向量,得到编码器的输入(batch_size x 384 x 208),其中384是我们选择的最大序列长度。
我们的模型的核心组件是从Squeezeformer架构改编而来的编码器。我们没有使用实际的"squeeze"思想(即时间维度的Unet),而是采用了Squeezeformer块的通用架构,这些块由MultiHeadSelfAttention(MHSA)、卷积和FeedForward模块组成。我们对该架构做了多项改进:
ASR conformer(和Squeezeformer)使用相对位置编码,使自注意力模块能更好地泛化到不同输入长度。相对位置编码计算量大且参数众多,因为每个层都单独存储。用Llama注意力(使用旋转嵌入)替代后,训练速度提升约2倍,TF-Lite推理速度提升约3倍,从而允许使用更大的模型。此外,我们将旋转嵌入一次性缓存并随输入数据送入每一层,避免在各层中重复。这使模型参数减少了20%。我们没有看到使用Squeezeformer引入的时间缩减有任何好处,因此模型所有层都保持与原始输入相同的序列长度。正如Squeezeformer论文所述,Macaron结构中的预层归一化是冗余的,我们将其替换为可学习的缩放层来缩放和偏移激活值。
对于解码,我们使用了简单的2层Transformer解码器,类似于Hugging Face的Speech2TextDecoder,输出序列预测。然后使用交叉熵损失进行端到端训练。我们还使用了反向序列的额外交叉熵辅助损失。因果解码器主要对序列开头和先前字符使用编码器交叉注意力,对末尾使用交叉注意力。为了提高模型准确性,我们在反向序列上使用单独的因果解码器作为辅助损失,使模型更依赖编码器交叉注意力来识别标签末尾。解码器推理时使用早期停止和过去键值缓存,显著加快了推理速度。需要注意的是,我们发现在计算效率至关重要的环境中,基于Transformer的解码器优于CTC解码。
此外,我们添加了一个单一线性层,用于提取编码器输出的第一个令牌的特征来预测置信度分数,这有助于识别垃圾数据并可用于后处理。对于此目标,我们使用先前良好模型的OOF预测的归一化Levenshtein距离,并裁剪到[0,1]范围。
我们在PyTorch中探索和训练所有模型,但每次认为模型足够好用于提交时,都会手动将每个组件转换为TensorFlow,并移植PyTorch模型的权重。
模型使用余弦学习率调度训练400个epoch,峰值学习率为0.0045,权重衰减为0.08,10个epoch的warmup,混合精度,有效批次大小为512个样本。Transformer编码器/解码器层使用0.1的dropout。训练时使用混合精度对于利用FP16推理而不损失性能至关重要。使用FP32训练并使用TF-Lite FP16推理会导致CV与LB之间约0.01的下降。
TF-Lite推理使用单个无填充样本,而模型训练使用时间填充的小批次。为避免模型学习填充数据并确保最佳推理运行时,特征提取器和Macaron结构编码器层在训练时进行了时间掩码。这需要在PyTorch中手动实现每一层,虽然花费了一些精力,但通过显著加快推理速度得到了回报。正如上一届ISL竞赛的第一名团队所解释的,这在TensorFlow中更容易实现,因为Keras有现成的掩码层。
模型训练和TF-Lite推理使用FP16,因此TF-Lite文件的大小几乎是FP32的一半。这很重要,因为40MB是我们的最终限制。两个最终模型种子大小为39988KB。
后处理的主要思想是用一个与训练/测试数据具有较小Levenshtein距离的虚拟短语替换较差预测。@anokas在他的notebook中展示了为什么'2 a-e -aroe'是一个很好的候选。大多数较差预测来自损坏的输入数据,通常只有几帧长。我们以模型预测的置信度分数为基础。当置信度分数低于0.15或序列短于15帧时,我们将预测替换为'2 a-e -aroe'。
我们仅从补充数据中获得了边际收益。我们认为主要原因是尽管补充数据有50k个样本,但只有500个不同的短语,因此模型更倾向于学习分类而非实际逐字符解码。我们尝试了很多方法,但只有一种方法带来了小幅提升(0.838 -> 0.839):
首先我们按短语对补充数据进行分组,只剩下500个组。在每个训练epoch中,我们从每组向训练集添加一个样本。这意味着每个epoch我们使用50k个训练数据样本和仅500个补充数据样本。
我们的最终提交是模型在完整训练数据(fullfit)上训练的2个种子集成。我们在每个解码步骤中对结果logits进行平均以实现集成。

https://github.com/ChristofHenkel/kaggle-asl-fingerspelling-1st-place-solution
待定。由于我们的方法具有新颖性,我们考虑将其总结为论文。
感谢您的阅读,欢迎提问!