Closed2

「google/speech-embedding」を試す

kun432kun432

以下で試したウェイクワード実装で使用されていた。

https://zenn.dev/kun432/scraps/0aa637b6547a25

Kaggleで公開されていて、2020年と結構古め。

https://www.kaggle.com/models/google/speech-embedding

概要

このモジュールは、16kHzのサンプリングレートを使用してオーディオから埋め込みベクトルを生成します。

入力特徴

必要なオーディオ入力:

  • Tensor バッチサイズ × サンプル数
  • サンプリングレート: 16kHz
  • 各サンプルは-1から1の間の32ビット浮動小数点数である必要があります。

このモジュールは、提供されたオーディオサンプルから以下のパラメーターを使用して独自の32次元ログメル特徴量を計算します:

  • STFTウィンドウサイズ: 25ms
  • STFTウィンドウステップ: 10ms
  • メルバンド範囲: 60Hz - 3800Hz
  • メル周波数ビン: 32

アーキテクチャ

音声埋め込みモジュールは、5つの畳み込みブロックのスタックを使用します。各畳み込みブロックは5つの層から構成されます:

  • 1x3畳み込み層
  • 3x1畳み込み層
  • 最大プール層
  • 1x3畳み込み層
  • 3x1畳み込み層

詳細な情報は当社の論文から入手可能です:James Lin, Kevin Kilgour, Dominik Roblek, Matthew Sharifi 「Training Keyword Spotters with Limited and Synthesized Speech Data

このアーキテクチャにより、最初の埋め込みには12400サンプル(775msまたは76特徴ベクトル)が必要です。以降の埋め込みベクトルは、さらに1280サンプル(80msまたは8特徴ベクトル)が必要です。

以下のスニペットは、予想される埋め込み長を計算します。

embedding_length = 1 + (sample_length - 12400) // 1280

微調整

モジュールは、trainable=True に設定し、バッチ正規化をトレーニングモードに設定するタグ {"train"} を付けたグラフバージョンをインポートすることで、タスクに合わせて微調整可能です。

module = hub.Module(
   "https://kaggle.com/models/google/speech-embedding/frameworks/TensorFlow1/variations/speech-embedding/versions/1",
   trainable=True,
   tags={"train"}
)

サンプルのColaboratoryノートブック

以下のサンプルのColaboratoryノートブックでモジュールの動作を確認してください:

  • speech_commands.ipynb は、音声コマンドデータセットでキーワード検出モデルを訓練する方法を示します。
  • record_train.ipynb は、自分の音声でキーワード検出モデルを訓練する方法を示します(マイクが必要です)。
kun432kun432

UsageはどうやらTensorFlow 1系らしく、また用意されているノートブックもトレーニング用途らしいので、上のウェイクワード実装である「local-wake」のコードも参考にするのが良さそう。このあたり。

https://github.com/st-matskevich/local-wake/blob/main/features.py

https://github.com/st-matskevich/local-wake/blob/main/compare.py

今回はColaboratoryで。

まず、パッケージ。ミニマムでこの辺りが必要になるが、Colaboratoryだとデフォルトでインストールされている。

!pip freeze | egrep -i "librosa|tensorflow|tensorflow_hub"
出力
librosa==0.11.0
tensorflow==2.19.0
tensorflow-datasets==4.9.9
tensorflow-hub==0.16.1
tensorflow-io-gcs-filesystem==0.37.1
tensorflow-metadata==1.17.2
tensorflow-probability==0.25.0
tensorflow-text==2.19.0
tensorflow_decision_forests==1.12.0

オーディオファイルを用意する。今回は上の「local-wake」を試した際に作成したウェイクワード(「ラズパイ」)が含まれる3秒ほどのWAVファイルを用意した。

!ffprobe -i sample-1.wav
出力
(snip)
Input #0, wav, from 'sample-1.wav':
  Duration: 00:00:03.00, bitrate: 256 kb/s
  Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, 1 channels, s16, 256 kb/s

3秒の16bit PCM WAVファイルで、チャネルはモノラル、サンプリングレートは16kHzとなっている。

モデルに入力可能なオーディオファイルの要件は、

必要なオーディオ入力:

  • Tensor バッチサイズ × サンプル数
  • サンプリングレート: 16kHz
  • 各サンプルは-1から1の間の32ビット浮動小数点数である必要があります。

このアーキテクチャにより、最初の埋め込みには12400サンプル(775msまたは76特徴ベクトル)が必要です。以降の埋め込みベクトルは、さらに1280サンプル(80msまたは8特徴ベクトル)が必要です。

とある。

local-wakeのコードを見ると、librosaを使って16kHz・モノラルにリサンプリングして、32 bit floatのNumPy配列が取得されるので、ここは良しなにやってくれるのだが、オーディオの長さは最低775ms必要でそれ以下だとエラーになるという点には注意が必要。local-wake試した時にあまりに短いWAVファイルを渡すとエラーになっていたのは多分これだよね。

ということで、オーディオファイルからEmbeddingを求めるコードは以下のような感じ。

import librosa
import tensorflow as tf
import tensorflow_hub as hub
import numpy as np

# オーディオファイル
audio_path = "sample-1.wav"

# 音声ファイルの読み込み(16kHz・モノラルにリサンプリング)
y, sr = librosa.load(audio_path, sr=16000)

# embeddingモデルのロード
model = hub.load("https://tfhub.dev/google/speech_embedding/1")
inference_fn = model.signatures['default']

# embeddingの計算
emb = inference_fn(default=tf.constant(y[None, :], dtype=tf.float32))['default']
print(emb)
出力
tf.Tensor(
[[[[ -8.671426   17.906559    7.225528  ... -23.824432    1.7396173
     35.309944 ]]

  [[ -5.3996644   4.4622955   8.968074  ... -20.414099    7.92331
     28.593588 ]]

  [[-14.496883   -3.4124908  16.138592  ... -22.974033    2.1091504
     38.288452 ]]

  ...

  [[ -5.343011   24.865768    9.801123  ... -28.247948    5.7232685
     30.055325 ]]

  [[ -3.5368233  23.01561    10.9588585 ... -26.216942    3.9106688
     35.337685 ]]

  [[ -4.8235335  23.340744    8.02408   ... -25.619957    2.7081103
     32.932022 ]]]], shape=(1, 28, 1, 96), dtype=float32)

28フレーム × 96次元 の時系列埋め込みとなっている様子。

このスクラップは26日前にクローズされました