我正在尝试使用连接主义的时间分类对Keras模型进行音频转录编程。使用一个工作效率最高的框架分类模型和OCR example,我想到了下面给出的模型,我想训练该模型来将德语句子的短时傅立叶变换映射到其语音转录。
我的训练数据实际上具有时序信息,因此我可以使用它来训练没有CTC的逐帧模型。没有CTC损失的逐帧预测模型工作得很好(训练精度为80%,验证精度为50%)。 但是,在没有计时信息的情况下,还有更多潜在的训练数据可用,因此我真的想切换CTC。为了测试这一点,我从数据中删除了时序,将NULL类的输出大小增加了一个,并添加了CTC损失函数。
此CTC模型似乎无法学习。总体而言,损失并没有减少(从2000年的80个句子的十几个时期减少到180个,然后又增加到430个),并且它产生的最大似然输出都在[nh
周围爬行通常包含大约六个单词的句子中的[foːɐmʔɛsndʰaɪnəhɛndəvaʃn]
– []
等转录是序列的一部分,表示音频开始和结束处的停顿。
我发现很难在Keras中找到关于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示例。
答案 0 :(得分:0)
从这里给出的代码中完全看不到它,但是在其他地方,OP提供了指向其Github repository的链接。错误实际上在于数据准备:
数据是对数频谱图。他们是不规范的,而且大多是负面的。 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