通常情况下,语音识别都是基于时频分析后的语音谱完成的,而其中语音时频谱是具有结构特点的。
要想提高语音识别率,就是需要克服语音信号所面临各种各样的多样性,包括说话人的多样性(说话人自身、以及说话人间),环境的多样性等。
一个卷积神经网络提供在时间和空间上的平移不变性卷积,将卷积神经网络的思想应用到语音识别的声学建模中,则可以利用卷积的不变性来克服语音信号本身的多样性。
从这个角度来看,则可以认为是将整个语音信号分析得到的时频谱当作一张图像一样来处理,采用图像中广泛应用的深层卷积网络对其进行识别。
GPU上训练加速可使用:
问题:内存使用量很大,推理实践长,在CPU上单条推理事件1s左右,GPU上0.1s左右。
训练阶段
CPU:tf.contrib.rnn.LSTMBlockFusedCell
GPU:tf.contrib.cudnn_rnn.CudnnLSTM
部署阶段
tf lite部署(tfv1自己写的r1.14分支):tfv1.nn.rnn_cell.LSTMCell
正常部署:tf.contrib.rnn.LSTMBlockFusedCell
参考rnn性能:https://www.tensorflow.org/guide/performance/overview
BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。
使用好处:
①不仅仅极大提升了训练速度,收敛过程大大加快;
②还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果;
③另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等。
参考:https://www.cnblogs.com/guoyaohua/p/8724433.html
BN使用的坑
keras的BN解决方案:https://zhuanlan.zhihu.com/p/56225304
tensorflow的BN解决方案:https://www.jianshu.com/p/437fb1a5823e
之前的模型用的是momentum,baidu的代码里用的是SGD
参考文章:https://zhuanlan.zhihu.com/p/22252270
预训练选SGD,先保证其收敛。
Adam,训练过程比较智能,新手容易训练。
keras后端选择:theano
ctc.cpu_ctc_th(network_output, output_lens, label, label_lens)
参数:
调用:
ctc_cost = ctc.cpu_ctc_th(network_output, output_lens, label, label_lens).mean()
维度:
DimShuffle{1,0,2}.0
----------------------------------------
----------------------------------------
----------------------------------------
类型:
----------------------------------------
----------------------------------------
----------------------------------------
_, ctc_cost = train_fn([inputs, output_lengths, labels, label_lengths, True])
inputs.shape: (16, 169, 101) # 16是batch size,169是时间步,101是特征长度
----------------------------------------
output_lengths: [29, 32, 33, 36, 38, 39, 53, 62, 62, 66, 66, 68, 68, 71, 75, 80]
----------------------------------------
len(labels): 81
----------------------------------------
label_lengths: [2, 3, 3, 4, 3, 5, 7, 5, 4, 7, 7, 8, 6, 3, 5, 9]
keras后端选择:tensorflow
ctc_batch_cost(y_true, y_pred, input_length, label_length)
在batch上运行CTC损失算法
参数:
ctc_cost = K.mean(K.ctc_batch_cost(labels, network_output, ctc_input_lens, label_lens))
labels:Tensor("Placeholder_1:0", shape=(?, ?), dtype=int32)
----------------------------------------
network_output:Tensor("TimeDistributed/Reshape_1:0", shape=(?, ?, 5134), dtype=float32)
----------------------------------------
ctc_input_lens:Tensor("Placeholder:0", shape=(?, ?), dtype=int32)
----------------------------------------
label_lens:Tensor("Placeholder_2:0", shape=(?, ?), dtype=int32)
调用:
pred_texts, ctc_text = self.train_fn([inputs, ctc_input_lens, batch['y'], batch['label_lengths'], True])
ctc_cost = K.mean(K.ctc_batch_cost(label, network_output, ctc_input_lengths, label_lens))
维度:
inputs.shape: (16, 425, 161)
----------------------------------------
ctc_input_lens: [[94], [100], [70], [89], [157], [179], [103], [94], [170], [81], [108], [166], [208], [121], [139], [101]]
----------------------------------------
labels.shape: (16, 31)
----------------------------------------
label_lengths: [[4], [3], [8], [18], [31], [24], [20], [19], [26], [21], [2], [5], [6], [18], [4], [8]]
类型:
----------------------------------------
----------------------------------------
----------------------------------------
X: (16, 1600, 200, 1)
y: (16, 64)
input_length: (16, 1)
label_length: (16, 1)
labels: (16, 1)
出现这个warning/Error message 的原因就是 Y 的长度大于X 的长度, 导致CTC 无法计算。
解决方案就是检查训练集 中的label 和 实际内容是否相符。
比如,音频中是 hello, how are you doing。 而label 是 hello. 这样的训练集肯定会出问题的。
训练过程中loss出现NaN:
一开始的loss是NaN:
单向GRU/LSTM的算法只能捕获当前词之前词的特征,而双向的GRU/LSTM算法则能够同时捕获前后词的特征,实验证明双向的GRU/LSTM比单向的GRU/LSTM算法效果更佳。LSTM算法性能稍优于GRU算法,但是GRU算法训练速度要比LSTM算法快。