源码地址:https://github.com/tensorflow/models/tree/master/research/deep_speech
运行脚本
export PYTHONPATH="$PYTHONPATH:/home/luke/Download/tmp/models"
export TF_FORCE_GPU_ALLOW_GROWTH=true
python deep_speech.py --train_data_dir=/tmp/librispeech_data/final_train_dataset.csv --eval_data_dir=/tmp/librispeech_data/final_eval_dataset.csv --num_gpus=1 --wer_threshold=0.23 --seed=1
_______________________________________________
调试笔记:
我对 tf.estimator.Estimator 并不熟悉,之前并没有用过,不知道怎么可以像Keras一样,直接来个 model.summary() 就可以把模型做到心中有数,
所以还是想把各层的结构打印出来,
但是在TensorFlow下,打印也不是一件容易的事,不像常规的代码一样,直接print,很方便
所以想到了一个暴力调试办法,就是制造错误,
如在 deep_speech_model.py 中,我想要打印 DeepSpeech2 的 input 的结构,我添加一行代码,制造下面的错误:
def __call__(self, inputs, training):
inputs = tf.keras.layers.Conv1D(10, 20)(inputs)
# Two cnn layers.
inputs = _conv_bn_layer(
inputs, padding=(20, 5), filters=_CONV_FILTERS, kernel_size=(41, 11),
strides=(2, 2), layer_id=1, training=training)
然后开始训练,就会得到如下报错:
ValueError: Input 0 of layer conv1d is incompatible with the layer: expected ndim=3, found ndim=4. Full shape received: [None, None, 161, 1]
那么我就知道了,这个inputs的shape是 [None, 161, 1]
这样,把代码接着往下移动,就会打印出下面 _conv_bn_layer 之后的shape
[None, 81, 32]
接下来又是一个 _conv_bn_layer ,打印shape,
[None, 81, 32]
依次类似,想办法制造错误,就可以把各个层的结构调试出来
其中,里面有一个pad,参数padding的维度[0],和inputs的维度[0]应该一致,因为大部分demo中都是二维的,不熟悉的情况下有点萌,根据这里的代码大致可以理解为,原输入inputs结构为 [None, 161, 1],实际前面还有一个batch,所以,大致算是 [1,None, 161, 1],而paddings为[[0, 0], [20, 20], [5, 5], [0, 0]]的情况下,pad后的shape为[1, None + 20 + 20, 161 + 5 + 5, 1],而TensorFlow是channel-last,所以最后那个1是channel,pad后的结果为[1, None + 40, 171, 1],再卷积,卷积后大小为
(in_height+2pad-filter_height)/strides[1]+1
(171 + 0 - 11)/2 + 1 = 81
第二个卷积,pad后尺寸为(1, None, 81 + 5 + 5, 32),然后卷积,尺寸为
(91 + 0 - 11)/ 1 + 1 = 81
所以和上面调试结果一致
OK,我们现在要经历一个reshape,获取 feat_size = 81, _CONV_FILTERS = 32,那么reshape后的结构为:
[None, None, 2592]
2592 = 81 * 32
下面是_rnn_layer,之后的尺寸为[None, None, 1600], 其中1600就是rnn_hidden_size * 2,这里的2是因为在bidire