ichou1のブログ

主に音声認識、時々、データ分析のことを書く

音声認識メモ(DeepSpeech)その5

モデルのインプットとして使う特徴量を「MFCC」から「log-mel spectrum」へ変えてみる。

インプットとして使う特徴量を変えてみる

各Time-Stepごとの次元は、「26」次元(MFCC13次元にdelta特徴量を加えた分)から「128」次元(フィルタバンクチャネル数)に置き換わる。

def convert_raw2feature(filename):

    raw = np.fromfile(filename, dtype=">i2").astype(np.floating)
    raw /= 32768.0

    # Apply pre-emphasis
    preemp = 0.97
    raw = np.append(raw[0], raw[1:] - preemp * raw[:-1])

    # 特徴量(STFT)を求める
    stfts = get_stft_spectrogram(raw)

    # 特徴量(メルスペクトログラム)を求める
    mel_spectrograms = get_mel(stfts, 128)

    # 対数変換
    feature = tf.math.log(mel_spectrograms + 1e-6)
    # --> ([time_step, num_mel_bins])

    return feature


上記から呼び出している関数は以下のとおり。

SFTFの計算
# compute STFT
# INPUT : (sample_size, )
# OUTPUT: (frame_size, fft_size // 2 + 1)
def get_stft_spectrogram(data):
    # Input: A Tensor of [batch_size, num_samples]
    # mono PCM samples in the range [-1, 1]. 
    stfts = tf.signal.stft(data,
                           frame_length=480,
                           frame_step=160,
                           fft_length=512)

    # 振幅を求める
    spectrograms = tf.abs(stfts)
    # --> [(time-step, 257)]

    return spectrograms
メルスペクトログラムの計算
# compute mel-Frequency
# INPUT : (frame_size, fft_size // 2 + 1)
# OUTPUT: (frame_size, mel_bin_size)
def get_mel(stfts, n_mel_bin):

    # STFT-bin
    n_stft_bin = stfts.shape[-1]          # --> 257 (= FFT size / 2 + 1)

    linear_to_mel_weight_matrix = tf.signal.linear_to_mel_weight_matrix(
        num_mel_bins=n_mel_bin,
        num_spectrogram_bins=n_stft_bin,
        sample_rate=16000,
        lower_edge_hertz=0.0,
        upper_edge_hertz=8000.0
    )
    # --> [(257, 128)] = (FFT size / 2 + 1, num of mel bins)

    linear_to_mel_weight_matrix = tf.cast(linear_to_mel_weight_matrix, tf.float64)

    mel_spectrograms = tf.tensordot(
        stfts,                        # (1, time-step, 257) 
        linear_to_mel_weight_matrix,  # (257, 128)
        1)

    mel_spectrograms.set_shape(
        stfts.shape[:-1].concatenate(linear_to_mel_weight_matrix.shape[-1:])
    )
    # --> [(1, time-step, 128)]

    return mel_spectrograms

モデルのトレーニン

Inputレイヤの次元数を変更する。

input_data = Input(name='input', shape=(None, 128))

lossが「0.01」を切るまでモデルをトレーニング。

...
Epoch 498/500
15/15 [==============================] - 17s 1s/step - loss: 0.0064
Epoch 499/500
15/15 [==============================] - 17s 1s/step - loss: 0.0064
Epoch 500/500
15/15 [==============================] - 21s 1s/step - loss: 0.0063

認識結果

テストデータ1

ちいさなうなぎやに、ねっきのようなものがみなぎる。

['sil', 'sil', 'sil', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'ch', 'ch', 'ch', '_', '_', '_', '_', 'i', 'i', 'i', 'i', '_', '_', 'i', 'i', 'i', 'i', '_', '_', '_', 's', 's', 's', 's', 's', '_', '_', '_', '_', '_', '_', 'a', 'a', 'a', 'a', '_', '_', '_', 'n', 'n', '_', '_', '_', '_', 'a', 'a', 'a', 'a', '_', 'u', 'u', 'u', 'u', 'u', '_', '_', '_', '_', '_', '_', '_', 'n', 'n', '_', '_', 'a', 'a', 'a', 'a', '_', '_', '_', '_', '_', '_', '_', '_', 'g', 'g', 'i', 'i', 'i', '_', '_', '_', '_', 'e', 'e', '_', '_', '_', '_', 'a', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'n', 'n', 'i', 'i', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'pau', 'pau', 'pau', 'pau', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'n', 'e', 'e', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'Q', 'Q', 'k', 'k', '_', '_', 'i', 'i', '_', '_', '_', '_', '_', '_', 'n', 'n', '_', '_', '_', '_', '_', '_', '_', '_', 'y', 'y', 'y', 'y', 'o', 'o', 'o', 'o', '_', '_', '_', 'o', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', 'n', 'n', '_', '_', '_', 'a', 'a', '_', '_', '_', 'm', 'm', 'm', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', 'n', 'n', 'n', 'o', 'o', '_', '_', '_', '_', '_', 'g', 'g', 'g', '_', '_', '_', '_', 'a', 'a', '_', '_', '_', '_', '_', '_', '_', 'm', 'm', 'i', 'i', 'i', '_', '_', '_', '_', '_', 'n', '_', '_', '_', '_', 'a', 'a', 'a', '_', '_', '_', '_', '_', '_', '_', 'g', 'g', 'i', 'i', 'i', '_', '_', '_', '_', '_', '_', '_', '_', 'r', 'r', 'u', 'u', 'u', '_', ..., '_', 'sil', 'sil']

"うなぎやに"のところで、'y'の音素が'e'になってしまっている。
この箇所に関しては、MFCCのモデルでは欠落していた。

テストデータ2

どろぼうでもはいったかと、いっしゅんぼくはおもった。

['sil', 'sil', 'sil', 'sil', 'sil', '_', '_', '_', 't', 'o', 'o', 'o', '_', '_', '_', '_', '_', 'r', 'r', 'r', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', '_', 'b', 'b', 'b', 'o', 'o', '_', '_', '_', '_', 'o', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', '_', 'd', 'd', 'e', 'e', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'm', 'm', 'm', '_', '_', '_', '_', '_', '_', 'h', 'h', 'h', 'h', 'h', '_', '_', '_', '_', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'Q', 'Q', 't', 't', '_', '_', 'a', 'a', '_', '_', '_', '_', 'k', 'k', 'k', 'k', '_', '_', '_', 'a', 'a', 'a', '_', '_', '_', '_', '_', '_', '_', 't', 't', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'pau', 'pau', 'pau', 'pau', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'i', 'i', 'i', 'i', 'i', '_', '_', '_', 'Q', 'Q', 'Q', 'sh', 'sh', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'u', 'u', '_', '_', '_', 'N', 'N', 'N', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'b', 'o', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'k', 'k', 'k', 'u', 'u', 'u', '_', '_', '_', '_', '_', '_', 'w', '_', '_', '_', 'a', 'a', '_', '_', '_', '_', '_', '_', 'o', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'm', 'm', 'm', 'o', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'Q', 'Q', 'Q', 'Q', 't', 't', '_', '_', '_', 'a', 'a', 'a', 'a', 'a', 'a', '_', ..., 'sil', 'sil']

"どろぼうでも"のところで、'd'の音素が't'になっている。
また、'm'-'o'となってほしいところで、'o'が欠落している。

コーパスの音声ファイル認識

「東北大‐松下 単語音声データベース (TMW)」の単語音声「さっぽろ」
http://research.nii.ac.jp/src/sample/TMW/sapporo.wav

['sil', 'sil', 'sil', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'a', 'a', 'a', 'a', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'n', 'o', 'o', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'r', 'r', 'o', 'o', 'o', '_', ..., , 'sil', 'sil']

「近畿大 児童の単語音声データベース (JWC)」の単語音声「ジェット機
http://research.nii.ac.jp/src/sample/JWC/2_648.wav

['sil', 'sil', 'sil', 'sil', 'sil', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 'k', '_', 'sil', 'sil']

違いはどこか

コーパスの認識結果は芳しくなかった。

スペクトログラムを出力してみる。

f:id:ichou1:20200806084933p:plainf:id:ichou1:20200806084942p:plain
(左)「ちいさなうなぎやに、ねっきのようなものがみなぎる。」
(右)「どろぼうでもはいったかと、いっしゅんぼくはおもった。」




f:id:ichou1:20200806083159p:plainf:id:ichou1:20200806083501p:plain
(左)「さっぽろ」
(右)「ジェット機


ジェット機」の縦軸を8000Hzまで広げてプロット。
f:id:ichou1:20200808085356p:plain
5000〜7000Hz帯で反応が出ている。

次回に続く。