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

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

我认为我了解的内容(如果我错了,请纠正我!)

总的来说,CTC损失会添加到经典网络的顶部,以便逐个元素地解码顺序的信息元素(文本或语音的字母和字母),而不是直接解码一个元素块(例如一个单词)。

假设我们将某些句子的发音作为MFCC输入。

使用CTC损失的目的是学习如何在每个时间步骤使每个字母与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_true,input_length和
label_length。有什么例子吗?
我应该以什么形式给网络贴标签?再次,有什么例子吗?

参考方案

这些是什么?

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

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

标签形式:

由于函数的文档要求输入形状(samples, length),因此格式为...每个句子中每个char的char索引。

如何使用呢?

有一些可能性。

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 GPU资源利用 - python

我有一个Python脚本在某些深度学习模型上运行推理。有什么办法可以找出GPU资源的利用率水平?例如,使用着色器,float16乘法器等。我似乎在网上找不到太多有关这些GPU资源的文档。谢谢! 参考方案 您可以尝试在像Renderdoc这样的GPU分析器中运行pyxthon应用程序。它将分析您的跑步情况。您将能够获得有关已使用资源,已用缓冲区,不同渲染状态上…

Python:图像处理可产生皱纹纸效果 - python

也许很难描述我的问题。我正在寻找Python中的算法,以在带有某些文本的白色图像上创建皱纹纸效果。我的第一个尝试是在带有文字的图像上添加一些真实的皱纹纸图像(具有透明度)。看起来不错,但副作用是文本没有真正起皱。所以我正在寻找更好的解决方案,有什么想法吗?谢谢 参考方案 除了使用透明性之外,假设您有两张相同尺寸的图像,一张在皱纹纸上明亮,一张在白色背景上有深…

keras中的自定义RMSPE损失函数 - python

我正在尝试在keras中定义我自己的损失函数,即均方根百分比误差。 RMSPE定义为:我已经将损失函数定义为:from keras import backend as K def rmspe(y_true, y_pred): sum = K.sqrt(K.mean(K.square( (y_true - y_pred) / K.clip(K.abs(y_tr…

Python uuid4,如何限制唯一字符的长度 - python

在Python中,我正在使用uuid4()方法创建唯一的字符集。但是我找不到将其限制为10或8个字符的方法。有什么办法吗?uuid4()ffc69c1b-9d87-4c19-8dac-c09ca857e3fc谢谢。 参考方案 尝试:x = uuid4() str(x)[:8] 输出:"ffc69c1b" Is there a way to…

Python sqlite3数据库已锁定 - python

我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…