0

我正在尝试使用连接主义时间分类为音频转录编写 Keras 模型。使用主要工作的逐帧分类模型和OCR 示例,我想出了下面给出的模型,我想训练该模型将德语句子的短时傅里叶变换映射到它们的音标。

我的训练数据实际上确实有时间信息,所以我可以用它来训练没有 CTC 的逐帧模型。没有 CTC 损失的逐帧预测模型运行良好(训练准确率 80%,验证准确率 50%)。然而,在没有时间信息的情况下,还有更多潜在的训练数据可用,所以我真的很想换一个 CTC。为了测试这一点,我从数据中删除了时间,将 NULL 类的输出大小增加了一倍,并添加了 CTC 损失函数。

这个 CTC 模型似乎没有学习。总体而言,损失并没有下降(在每个 80 个句子的十几个 epoch 中,它从 2000 下降到 180,但随后又回升至 430),并且它产生的最大似然输出在[nh每个句子周围都有所下降,这通常有大约六个单词和转录,例如[foːɐmʔɛsndʰaɪnəhɛndəvaʃn]-[]是序列的一部分,代表音频开始和结束时的停顿。

我发现在 Keras 中找到对 CTC 的好的解释有点困难,所以可能是我做了一些愚蠢的事情。我是否弄乱了模型,在某处混淆了参数的顺序?在给模型完整的句子之前,我是否需要更加小心地训练模型,从带有一个、两个或三个声音的音频片段开始?简而言之,

我如何让这个 CTC 模型学习?

connector = inputs
for l in [100, 100, 150]:
    lstmf, lstmb = Bidirectional(
        LSTM(
            units=l,
            dropout=0.1,
            return_sequences=True,
        ), merge_mode=None)(connector)

    connector = keras.layers.Concatenate(axis=-1)([lstmf, lstmb])

output = Dense(
    units=len(dataset.SEGMENTS)+1,
    activation=softmax)(connector)

loss_out = Lambda(
    ctc_lambda_func, output_shape=(1,),
    name='ctc')([output, labels, input_length, label_length])

ctc_model = Model(
    inputs=[inputs, labels, input_length, label_length],
    outputs=[loss_out])
ctc_model.compile(loss={'ctc': lambda y_true, y_pred: y_pred},
                  optimizer=SGD(
                      lr=0.02,
                      decay=1e-6,
                      momentum=0.9,
                      nesterov=True,
                      clipnorm=5))

ctc_lambda_function从预测中生成序列的代码来自 OCR 示例。

4

1 回答 1

0

从此处给出的代码中完全看不到它,但在其他地方 OP 提供了指向其Github 存储库的链接。错误实际上在于数据准备:

数据是对数频谱图。它们是非标准化的,并且大多是高度负面的。CTC 函数比 LSTM 层适应其输入偏差和输入权重要快得多,因此输入中的所有变化都被拉平了。当标签的边缘化分布尚未在全球范围内假设时,损失的局部最小值可能来自时代。

解决方案是缩放输入频谱图,使其包含正值和负值:

for i, file in enumerate(files):
    sg = numpy.load(file.with_suffix(".npy").open("rb"))
    spectrograms[i][:len(sg)] = 2 * (sg-sg.min())/(sg.max()-sg.min()) - 1
于 2018-12-09T13:49:53.197 回答