音频课程文档

CTC 架构

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始

CTC 架构

CTC 或连接主义时间分类是一种与仅编码器 Transformer 模型一起用于自动语音识别的技术。此类模型的示例包括 **Wav2Vec2**、**HuBERT** 和 **M-CTC-T**。

仅编码器 Transformer 是最简单的 Transformer,因为它只使用模型的编码器部分。编码器读取输入序列(音频波形)并将其映射到一系列隐藏状态,也称为输出嵌入。

在 CTC 模型中,我们在隐藏状态序列上应用额外的线性映射以获得类别标签预测。类别标签是 **字母表中的字符**(a、b、c 等)。这样,我们就可以使用一个小的分类头预测目标语言中的任何单词,因为词汇表只需要包含 26 个字符加上几个特殊标记。

Transformer encoder with a CTC head on top

到目前为止,这与我们在 NLP 中使用 BERT 之类的模型所做的事情非常相似:仅编码器 Transformer 模型将我们的文本标记映射到一系列编码器隐藏状态,然后我们应用线性映射以针对每个隐藏状态获得一个类别标签预测。

重点来了:在语音中,我们不知道音频输入和文本输出的 **对齐**。我们知道语音的说话顺序与文本转录的顺序相同(对齐方式被称为单调),但我们不知道转录中的字符如何与音频对齐。这就是 CTC 算法发挥作用的地方。

💡 在 NLP 模型中,词汇表通常由数千个标记组成,这些标记不仅描述单个字符,还描述单词的一部分甚至完整的单词。但是,对于 CTC,小的词汇表效果最好,我们通常会将其保持在 50 个字符以下。我们不关心字母的大小写,所以只使用大写(或只使用小写)就足够了。数字会被拼写出来,例如“`20`”变为“`twenty`”。除了字母外,我们至少需要一个单词分隔符标记(空格)和一个填充标记。就像 NLP 模型一样,填充标记允许我们将多个示例组合到批次中,但它也是模型在静默时会预测的标记。在英语中,保留 `'` 字符也很有用——毕竟,“`it's`”和“`its`”有截然不同的含义。

我的对齐在哪儿?

自动语音识别或 ASR 包括将音频作为输入并生成文本作为输出。我们有几种选择来预测文本

  • 作为单个字符
  • 作为音素
  • 作为词标记

ASR 模型是在包含 `(音频,文本)` 对的数据集上进行训练的,其中文本是音频文件的由人工制作的转录。一般来说,数据集不包含任何计时信息,说明哪个单词或音节出现在音频文件的哪个位置。由于我们无法在训练期间依赖计时信息,因此我们不知道输入和输出序列应该如何对齐。

假设我们的输入是一个持续一秒的音频文件。在 **Wav2Vec2** 中,模型首先使用 CNN 特征编码器对音频输入进行下采样,得到更短的隐藏状态序列,其中每 20 毫秒的音频有一个隐藏状态向量。对于持续一秒的音频,我们然后将一个包含 50 个隐藏状态的序列转发到 Transformer 编码器。(从输入序列中提取的音频片段部分重叠,因此即使每 20 毫秒发射一个隐藏状态向量,但每个隐藏状态实际上代表 25 毫秒的音频。)

Transformer 编码器为这些隐藏状态中的每一个预测一个特征表示,这意味着我们从 Transformer 接收一个包含 50 个输出的序列。这些输出中的每一个的维度为 768。因此,本例中 Transformer 编码器的输出序列的形状为 `(768, 50)`。由于这些预测中的每一个涵盖 25 毫秒的时间,这比音素的持续时间短,所以预测单个音素或字符而不是整个词是有意义的。CTC 在小型词汇表中效果最好,因此我们将预测字符。

The audio waveform gets mapped to a shorter sequence of hidden-states

为了进行文本预测,我们使用线性层(“CTC 头”)将 768 维编码器输出中的每一个映射到我们的字符标签。然后,模型预测一个包含 logits 的 `(50, 32)` 张量,其中 32 是词汇表中标记的数量。由于我们对序列中的每个特征进行一次预测,因此我们最终会对每秒音频产生 50 个字符预测。

但是,如果我们只是每 20 毫秒预测一个字符,我们的输出序列可能看起来像这样

BRIIONSAWWSOMEETHINGCLOSETOPANICONHHISOPPONENT'SSFAACEWHENTHEMANNFINALLLYRREECOGGNNIIZEDHHISSERRRRORR ...

如果你仔细观察,它有点像英语,但许多字符都被重复了。这是因为模型需要为输入序列中的每 20 毫秒的音频输出某些东西,如果一个字符在超过 20 毫秒的时间段内被分散,那么它将在输出中多次出现。无法避免这种情况,特别是在训练期间我们不知道转录的计时信息。CTC 是一种过滤掉这些重复项的方法。

(实际上,预测的序列中还包含许多填充标记,用于模型不太确定声音代表什么,或者用于字符之间的空隙。为了清晰起见,我们从示例中删除了这些填充标记。音频片段之间的部分重叠是字符在输出中重复的另一个原因。)

CTC 算法

CTC 算法的关键是使用一个特殊的标记,通常称为 **空白标记**。这只是模型将预测的另一个标记,它是词汇表的一部分。在本例中,空白标记显示为 `_`。此特殊标记用作字符组之间的硬边界。

CTC 模型的完整输出可能如下所示

B_R_II_O_N_||_S_AWW_|||||_S_OMEE_TH_ING_||_C_L_O_S_E||TO|_P_A_N_I_C_||_ON||HHI_S||_OP_P_O_N_EN_T_'SS||_F_AA_C_E||_W_H_EN||THE||M_A_NN_||||_F_I_N_AL_LL_Y||||_RREE_C_O_GG_NN_II_Z_ED|||HHISS|||_ER_RRR_ORR||||

`|` 标记是单词分隔符字符。在本例中,我们使用 `|` 而不是空格,这使得更容易发现单词断裂的位置,但它的作用相同。

CTC 空白字符使得过滤掉重复的字符成为可能。例如,让我们看看预测序列中的最后一个词 `_ER_RRR_ORR`。如果没有 CTC 空白标记,该词看起来像这样

ERRRRORR

如果我们只是删除重复的字符,它将变为 `EROR`。这显然不是正确的拼写。但是使用 CTC 空白标记,我们可以删除每个组中的重复项,以便

_ER_RRR_ORR

变为

_ER_R_OR

现在我们移除_空白标记,以获得最终的单词

ERROR

如果我们将此逻辑应用于整个文本,包括|,并将保留的|字符替换为空格,则最终的 CTC 解码输出为

BRION SAW SOMETHING CLOSE TO PANIC ON HIS OPPONENT'S FACE WHEN THE MAN FINALLY RECOGNIZED HIS ERROR

回顾一下,模型每 20 毫秒从输入波形中预测一个标记(字符),这些波形是(部分重叠)的音频。这会产生很多重复项。由于 CTC 空白标记,我们可以轻松地移除这些重复项,而不会破坏单词的正确拼写。这是一种非常简单方便的方法来解决将输出文本与输入音频对齐的问题。

💡 在实际的 Wav2Vec2 模型中,CTC 空白标记与填充标记相同。例如,当没有清晰的字符可以预测当前 20 毫秒的音频时,模型将预测许多这些标记。将同一个标记用于填充和 CTC 空白化简化了解码算法,并有助于保持词汇表的小尺寸。

在 Transformer 编码器模型中添加 CTC 很容易:编码器的输出序列进入一个线性层,该线性层将声学特征投影到词汇表中。该模型使用特殊的 CTC 损失进行训练。

CTC 的一个缺点是它可能会输出听起来正确的词,但拼写不正确。毕竟,CTC 头只考虑单个字符,而不是完整的单词。改进音频转录质量的一种方法是使用外部语言模型。这个语言模型本质上充当 CTC 输出的拼写检查器。

Wav2Vec2、HuBERT、M-CTC-T 之间的区别是什么?

所有基于 Transformer 的 CTC 模型都具有非常相似的架构:它们使用 Transformer 编码器(但不使用解码器),顶部带有 CTC 头。在架构上,它们更相似而不是不同。

Wav2Vec2 和 M-CTC-T 之间的区别在于前者处理原始音频波形,而后者使用梅尔谱图作为输入。这些模型也针对不同的目的进行训练。例如,M-CTC-T 针对多语言语音识别进行了训练,因此它具有一个相对较大的 CTC 头,除了其他字母表之外,还包括汉字。

Wav2Vec2 和 HuBERT 使用完全相同的架构,但训练方式截然不同。Wav2Vec2 像 BERT 的掩码语言建模一样进行预训练,通过预测音频中被掩盖部分的语音单元。HuBERT 进一步借鉴了 BERT 的灵感,学习预测“离散语音单元”,这些单元类似于文本句子中的标记,以便可以使用已建立的 NLP 技术处理语音。

为了澄清,这里突出显示的模型并不是唯一基于 Transformer 的 CTC 模型。还有很多其他的模型,但现在您知道它们的工作原理都类似。