gpt4 book ai didi

python - 了解 Keras 中语音识别的 CTC 损失

转载 作者:行者123 更新时间:2023-12-02 09:01:42 29 4
gpt4 key购买 nike

我试图了解 CTC 损失如何用于语音识别以及如何在 Keras 中实现它。

  1. 我认为我理解的内容(如果我错了,请纠正我!)
总体而言,CTC 损失被添加到经典网络之上,以便逐个元素(对于文本或语音而言逐个字母)解码顺序信息,而不是直接直接解码元素 block (例如单词)。

假设我们将一些句子的话语作为 MFCC 提供。

使用 CTC-loss 的目标是学习如何在每个时间步使每个字母与 MFCC 匹配。因此,Dense+softmax 输出层由与组成句子所需的元素数量一样多的神经元组成:

  • 字母(a、b、...、z)
  • 空白标记 (-)
  • 一个空格 (_) 和一个结束字符 (>)

然后,softmax 层有 29 个神经元(26 个用于字母表 + 一些特殊字符)。

为了实现它,我发现我可以做这样的事情:

# CTC implementation from Keras example found at https://github.com/keras- 
# team/keras/blob/master/examples/image_ocr.py

def ctc_lambda_func(args):
y_pred, labels, input_length, label_length = args
# the 2 is critical here since the first couple outputs of the RNN
# tend to be garbage:
# print "y_pred_shape: ", y_pred.shape
y_pred = y_pred[:, 2:, :]
# print "y_pred_shape: ", y_pred.shape
return K.ctc_batch_cost(labels, y_pred, input_length, label_length)



input_data = Input(shape=(1000, 20))
#let's say each MFCC is (1000 timestamps x 20 features)

x = Bidirectional(lstm(...,return_sequences=True))(input_data)

x = Bidirectional(lstm(...,return_sequences=True))(x)

y_pred = TimeDistributed(Dense(units=ALPHABET_LENGTH, activation='softmax'))(x)

loss_out = Lambda(function=ctc_lambda_func, name='ctc', output_shape=(1,))(
[y_pred, y_true, input_length, label_length])

model = Model(inputs=[input_data, y_true, input_length,label_length],
outputs=loss_out)

ALPHABET_LENGTH = 29(字母长度+特殊字符)

还有:

  • y_true:包含真值标签的张量(样本、max_string_length)。
  • y_pred:包含预测或 softmax 输出的张量(样本、time_steps、num_categories)。
  • input_length:张量(样本,1),包含 y_pred 中每个批处理项目的序列长度。
  • label_length:张量(样本,1),包含 y_true 中每个批处理项目的序列长度。

( source )

现在,我面临一些问题:

  • 我不明白
    • 这种植入是编码和使用 CTC 损失的正确方法吗?
    • 我不明白 y_trueinput_length标签长度。有什么例子吗?
    • 我应该以什么形式向网络提供标签?再说一遍,有什么例子吗?
  • 最佳答案

    这些是什么?

    • y_true 您的地面实况数据。您要与训练中模型的输出进行比较的数据。 (另一方面,y_pred 是模型的计算输出)
    • input_lengthy_pred 张量中每个样本(句子)的长度(以步骤为单位,在本例中为字符)(如所述 here )
    • label_lengthy_true(或标签)张量中每个样本(句子)的长度(以步骤为单位,在本例中为字符)。

    这种损失似乎期望模型的输出 (y_pred) 以及地面实况数据 (y_true) 具有不同的长度。这可能是为了避免在句子结束后计算垃圾字符的损失(因为您需要一个固定大小的张量来一次处理大量句子)

    标签的形式:

    由于函数的文档要求形状(样本,长度),因此格式是...每个句子中每个字符的字符索引。

    如何使用它?

    有一些可能性。

    1-如果你不关心长度:

    如果所有长度都相同,您可以轻松地将其用作常规损失:

    def ctc_loss(y_true, y_pred):

    return K.ctc_batch_cost(y_true, y_pred, input_length, label_length)
    #where input_length and label_length are constants you created previously
    #the easiest way here is to have a fixed batch size in training
    #the lengths should have the same batch size (see shapes in the link for ctc_cost)

    model.compile(loss=ctc_loss, ...)

    #here is how you pass the labels for training
    model.fit(input_data_X_train, ground_truth_data_Y_train, ....)

    2 - 如果您关心长度。

    这有点复杂,你需要你的模型以某种方式告诉你每个输出句子的长度。
    这样做还有几种创造性的形式:

    • 有一个“end_of_sentence”字符并检测它在句子中的位置。
    • 让模型的一个分支来计算这个数字并将其四舍五入为整数。
    • (硬核)如果您使用有状态手动训练循环,请获取您决定完成句子的迭代的索引

    我喜欢第一个想法,并将在这里举例说明。

    def ctc_find_eos(y_true, y_pred):

    #convert y_pred from one-hot to label indices
    y_pred_ind = K.argmax(y_pred, axis=-1)

    #to make sure y_pred has one end_of_sentence (to avoid errors)
    y_pred_end = K.concatenate([
    y_pred_ind[:,:-1],
    eos_index * K.ones_like(y_pred_ind[:,-1:])
    ], axis = 1)

    #to make sure the first occurrence of the char is more important than subsequent ones
    occurrence_weights = K.arange(start = max_length, stop=0, dtype=K.floatx())

    #is eos?
    is_eos_true = K.cast_to_floatx(K.equal(y_true, eos_index))
    is_eos_pred = K.cast_to_floatx(K.equal(y_pred_end, eos_index))

    #lengths
    true_lengths = 1 + K.argmax(occurrence_weights * is_eos_true, axis=1)
    pred_lengths = 1 + K.argmax(occurrence_weights * is_eos_pred, axis=1)

    #reshape
    true_lengths = K.reshape(true_lengths, (-1,1))
    pred_lengths = K.reshape(pred_lengths, (-1,1))

    return K.ctc_batch_cost(y_true, y_pred, pred_lengths, true_lengths)

    model.compile(loss=ctc_find_eos, ....)

    如果您使用其他选项,请使用模型分支来计算长度,将这些长度连接到输出的第一步或最后一步,并确保对地面实况数据中的真实长度执行相同的操作。然后,在损失函数中,只需取长度部分即可:

    def ctc_concatenated_length(y_true, y_pred):

    #assuming you concatenated the length in the first step
    true_lengths = y_true[:,:1] #may need to cast to int
    y_true = y_true[:, 1:]

    #since y_pred uses one-hot, you will need to concatenate to full size of the last axis,
    #thus the 0 here
    pred_lengths = K.cast(y_pred[:, :1, 0], "int32")
    y_pred = y_pred[:, 1:]

    return K.ctc_batch_cost(y_true, y_pred, pred_lengths, true_lengths)

    关于python - 了解 Keras 中语音识别的 CTC 损失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57292896/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com