Tensorflow を使用して、CTC 損失のある音声認識エンジンを実装したいと考えています。各音声発話の長さは可変であるため、入力特徴の長さは可変です。各転写が異なるため、ラベルの長さも可変です。フィーチャを手動でパディングしてバッチを作成し、モデルには tf.keras.layers.Masking() レイヤーを作成して、ネットワークを介してマスクを伝播します。また、パディングを使用してラベル バッチを作成します。
これはダミーの例です。それぞれ長さが 3 フレームと 5 フレームの 2 つの発話があるとします。各フレームは 1 つの機能で表されます (通常、これは 13 の MFCC になりますが、単純にするために 1 つに減らします)。バッチを作成するために、短い発話の最後に 0 を追加します。
features = np.array([1.5 2.3 4.6 0.0 0.0],
[1.7 2.6 3.4 2.3 1.0])
ラベルは、これらの発話を書き起こしたものです。長さがそれぞれ 2 と 3 であるとしましょう。ラベルのバッチ形状は [2, 3, 26] になります。ここで、バッチ サイズは 2、最大長は 3、英語の文字数は 26 (ワンホット エンコーディング) です。
モデルは次のとおりです。
input_ = tf.keras.Input(shape=(None,1))
x = tf.keras.layers.Masking()(input_)
x = tf.keras.layers.GRU(26, return_sequences=True)(input_)
output_ = tf.keras.layers.Softmax(axis=-1)(x)
model = tf.keras.Model(input_,output_)
損失関数は次のようなものです。
def ctc_loss(y_true, y_pred):
# Do something here to get logit_length and label_length?
# ...
loss = tf.keras.backend.ctc_batch_cost(y_true,y_pred,logit_length,label_length)
私の質問は、logit_length と label_length を取得する方法です。logit_length はマスクにエンコードされていると思いますが、y_pred._keras_mask を実行すると、結果は None になります。label_length については、情報はテンソル自体にありますが、それを取得する最も効率的な方法はわかりません。
ありがとう。
アップデート:
Tou You の回答に従って、tf.math.count_nonzero を使用して label_length を取得し、logit_length をロジット レイヤーの長さに設定します。
したがって、損失関数内の形状は (バッチ サイズ = 10) です。
y_true.shape = (10, None)
y_pred.shape = (10, None, 27)
label_length.shape = (10,1)
logit_lenght.shape = (10,1)
もちろん、y_true と y_pred の 'None' は同じではありません。一方はバッチの最大文字列長であり、もう一方はバッチの時間フレームの最大数であるためです。ただし、 model.fit() を呼び出して、これらのパラメーターを使用して損失 tf.keras.backend.ctc_batch_cost() を呼び出すと、エラーが発生します。
Traceback (most recent call last):
File "train.py", line 164, in <module>
model.fit(dataset, batch_size=batch_size, epochs=10)
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 66, in _method_wrapper
return method(self, *args, **kwargs)
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 848, in fit
tmp_logs = train_function(iterator)
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 580, in __call__
result = self._call(*args, **kwds)
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 644, in _call
return self._stateless_fn(*args, **kwds)
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 2420, in __call__
return graph_function._filtered_call(args, kwargs) # pylint: disable=protected-access
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 1661, in _filtered_call
return self._call_flat(
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 1745, in _call_flat
return self._build_call_outputs(self._inference_function.call(
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 593, in call
outputs = execute.execute(
File "/home/pablo/miniconda3/envs/lightvoice/lib/python3.8/site-packages/tensorflow/python/eager/execute.py", line 59, in quick_execute
tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
tensorflow.python.framework.errors_impl.InvalidArgumentError: 2 root error(s) found.
(0) Invalid argument: Incompatible shapes: [10,92] vs. [10,876]
[[node Equal (defined at train.py:164) ]]
(1) Invalid argument: Incompatible shapes: [10,92] vs. [10,876]
[[node Equal (defined at train.py:164) ]]
[[ctc_loss/Log/_62]]
0 successful operations.
0 derived errors ignored. [Op:__inference_train_function_3156]
Function call stack:
train_function -> train_function
y_true (92) の長さが y_pred (876) の長さと同じではないと不平を言っているようです。私は何が欠けていますか?