TensorFlow : Tutorials : Sequences : 単純な音声認識 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/16/2018
作成日時 : 06/05/2018
* TensorFlow 1.9 でドキュメント構成が変わりましたので調整しました。
* 本ページは、TensorFlow 本家サイトの Tutorials – Sequences – Simple Audio Recognition を翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、適宜、追加改変している場合もあります。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
このチュートリアルは 10 の異なる単語を認識する基本的な音声認識ネットワークをどのように構築するかを示します。実際の発話と音声認識システムは遥かにより複雑であることを知ることは重要ですが、画像のための MNIST のように、それは伴う技術の基本的な理解を貴方に与えるはずです。ひとたびこのチュートリアルを完了すれば、1 秒のオーディオクリップをサイレンス, 未知の単語, “yes”, “no”, “up”, “down”, “left”, “right”, “on”, “off”, “stop”, または “go” のいずれかとして分類しようとするモデルを持つでしょう。このモデルを取りそしてそれを Android アプリケーション内で実行することもまた可能です。
準備
TensorFlow がインストールされていることを確実にするべきです、そしてスクリプトは 1GB 超の訓練データをダウンロードしますので、良いインターネット接続とマシン上に十分な空き容量が必要です。訓練プロセス自身は数時間かかりますので、その間利用可能なマシンを持っていることを確認してください。
訓練
訓練プロセスを開始するには、TensorFlow ソースツリーに行って次を実行します :
python tensorflow/examples/speech_commands/train.py
スクリプトは Speech Commands データセット をダウンロードすることから始めます、これは 30 の異なる単語を話す人々の 65,000 WAVE オーディオ・ファイルから成ります。このデータは Google により収集されて CC BY ライセンスのもとにリリースされ、そして貴方は 貴方自身の声の 5 分間の貢献 によりそれを改良する手助けができます。アーカイブは 1GB 以上ありますので、この部分はしばらくかかるかもしれませんが、進捗ログを見るはずで、そしてひとたび一度ダウンロードされたのであれば、このステップを再度行なう必要はありません。
ひとたびダウンロードが完了すれば、このように見えるロギング情報を見るでしょう :
I0730 16:53:44.766740 55030 train.py:176] Training from step: 1 I0730 16:53:47.289078 55030 train.py:217] Step #1: rate 0.001000, accuracy 7.0%, cross entropy 2.611571
これは初期化プロセスが終了して訓練ループが始まったことを示します。それが総ての訓練ステップについて情報を出力することを見るでしょう。ここにそれが何を意味するかのブレークダウンがあります :
Step #1 は訓練ループの最初のステップ上にあることを示します。この場合全部で 18,000 ステップがありますので、それが終わりにどのくらい近いかを知るためにこのステップ数を見ることができます。
rate 0.001000 は学習率でネットワークの重み更新のスピードを制御しています。これの早期には比較的高い数字 (0.001) ですが、後の訓練サイクルのためにはそれは 10x, 0.0001 まで減少するでしょう。
accuracy 7.0% はこの訓練ステップで幾つのクラスが正しく予測されたかです。この値はしばしば大きく変動しますが、訓練が進むにつれて平均的には増加するはずです。モデルは数字の配列を出力します、各ラベルに一つです、そして各数字は入力がそのクラスであると予測された尤度です。予測されたラベルは最も高いスコアを持つエントリを選択することにより選び取られています。スコアは常にゼロと 1 の間で、より高い値は結果がより信頼できることを表します。
cross entropy 2.611571 は損失関数の結果で、これは訓練プロセスを導くために使用します。これは現在の訓練実行からのスコアのベクトルを正しいラベルと比較することにより得られるスコアで、これは訓練の間に下方に傾くはずです。
100 ステップ後、このような行を見るはずです :
I0730 16:54:41.813438 55030 train.py:252] Saving to "/tmp/speech_commands_train/conv.ckpt-100"
これは現在の訓練された重みをチェックポイント・ファイルにセーブしています。貴方の訓練スクリプトが中断された場合、最後にセーブされたチェックポイントを探してそれからそのポイントから開始するためにコマンド引数として –start_checkpoint=/tmp/speech_commands_train/conv.ckpt-100 を持つスクリプトを再起動することができます。
混同行列
400 ステップ後、この情報は次のようにログ出力されます :
I0730 16:57:38.073667 55030 train.py:243] Confusion Matrix: [[258 0 0 0 0 0 0 0 0 0 0 0] [ 7 6 26 94 7 49 1 15 40 2 0 11] [ 10 1 107 80 13 22 0 13 10 1 0 4] [ 1 3 16 163 6 48 0 5 10 1 0 17] [ 15 1 17 114 55 13 0 9 22 5 0 9] [ 1 1 6 97 3 87 1 12 46 0 0 10] [ 8 6 86 84 13 24 1 9 9 1 0 6] [ 9 3 32 112 9 26 1 36 19 0 0 9] [ 8 2 12 94 9 52 0 6 72 0 0 2] [ 16 1 39 74 29 42 0 6 37 9 0 3] [ 15 6 17 71 50 37 0 6 32 2 1 9] [ 11 1 6 151 5 42 0 8 16 0 0 20]]
最初のセクションは混同行列 (= confusion matrix) です。それが何を意味するかを理解するためには、最初に使用されているラベルを知る必要があります、この場合これらは “silence”, “unknown”, “yes”, “no”, “up”, “down”, “left”, “right”, “on”, “off”, “stop”, そして “go” です。各カラムは各ラベルとして予測されたサンプルのセットを表しますので、最初のカラムは silence と予測されたクリップ総てを表し、2 番目は unknown words として予測されたもの総てで、3 番目は “yes” です、等々。
各行は正しい、正解ラベルによるクリップを表します。最初の行は silence であったクリップ総てで、2 番目は unknown words であったクリップで、3 番目は “yes” です、等々。
この行列は単なる単一の精度スコアよりも有用であり得ます、何故ならばそれはネットワークが何の間違いをしたかの良い要約を与えるからです。この例では最初の行のエントリの総てが最初の一つを別にしてゼロであることが見て取れます。最初の行は実際に silence であるクリップ総てですから、これは単語として誤ってラベル付けされたものがないことを意味しますので、silence に対して false negative を持ちません。これはネットワークが既に単語から silence を非常に上手く識別していることを示します。
けれども最初のカラムを下に見れば、多くの非ゼロ値を見ます。カラムは silence として予測されたクリップ総てを表しますので、最初のセル外の正の数はエラーです。これは実際に発話された単語の幾つかのクリップは実際には silence として予測されたことを意味しますので、かなりの数の false positive を持ちます。
完全なモデルはエントリの総てが中心を通る対角線を別にしてゼロであるような混同行列を生成します。そのパターンからの逸脱を見分けることはモデルがどのように最も簡単に混乱するかの解明を助けることができて、そしてひとたび問題を識別したのであれば更なるデータを追加するかカテゴリーをクリーンアップすることによりそれらに対処できます。
検証
混同行列の後、このような行を見るはずです :
I0730 16:57:38.073777 55030 train.py:245] Step 400: Validation accuracy = 26.3% (N=3093)
貴方のデータセットを 3 つのカテゴリーに分割することは良い実践です。最大のもの (この場合データのおよそ 80%) はネットワークを訓練するために使用され、より小さいセット (ここでは 10 %、”検証 (= validation)” として知られます) は訓練の間の精度の評価のために取っておき、そしてもう一つのセット (最後の 10 %、”テスティング”) は訓練が完了した後に精度を一度評価するために使用されます。
この分割のための理由はネットワークが訓練の間に入力を記憶し始める危険が常にあるからです。検証セットを分割し続ければ、モデルが前に見ていないデータで動作することを確実にできます。テスティング・セットは、より広い範囲の入力ではないものの、訓練と検証セットの両者のために偶々動作する方法でモデルを調整していないことを確かなものとする追加の安全装置です。
訓練スクリプトはデータセットをこれら 3 つのカテゴリーに自動的に分割し、そして上のロギング行は検証セット上で実行するときのモデルの精度です。理想的には、これは訓練精度に非常に密接であり続けるべきです。訓練精度が増加しても検証 (精度) がそうでない場合、それはオーバーフィッティングが発生している兆候で、貴方のモデルは一般化されたより広いパターンではなく、訓練クリップについての何かを学習しているだけです。
Tensorboard
訓練がどのように進んでいるかを可視化する良い方法は Tensorboard の利用です。デフォルトでは、スクリプトはイベントを /tmp/retrain_logs にセーブして、それらを次を実行することによりロードできます :
tensorboard --logdir /tmp/retrain_logs
それからブラウザを http://localhost:6006 にナビゲートして、モデル進捗を示すチャートとグラフを見るでしょう。
訓練の終了
訓練の数時間後 (貴方のマシン速度に依拠します)、スクリプトは 18,000 ステップ総てを完了するはずです。テスティング・セット上で実行し、それは最終的な混同行列を精度スコアと一緒にプリントします。デフォルト設定では、85 % と 90% の間の精度を見るはずです。
音声認識はモバイル・デバイス上で特に有用ですから、次にそれらのプラットフォーム上で簡単に動作するコンパクトなフォーマットにそれをエクスポートします。それを行なうためには、このコマンド行を実行します :
python tensorflow/examples/speech_commands/freeze.py \ --start_checkpoint=/tmp/speech_commands_train/conv.ckpt-18000 \ --output_file=/tmp/my_frozen_graph.pb
ひとたび凍結されたモデルが作成されれば、label_wav.py でそれをテストできます、このようにです :
python tensorflow/examples/speech_commands/label_wav.py \ --graph=/tmp/my_frozen_graph.pb \ --labels=/tmp/speech_commands_train/conv_labels.txt \ --wav=/tmp/speech_dataset/left/a5d485dc_nohash_0.wav
これは 3 つのラベルをプリントするはずです :
left (score = 0.81477) right (score = 0.14139) _unknown_ (score = 0.03808)
上手くいけば “left” がトップスコアです、何故ならばそれが正しいラベルだからですが、訓練はランダムですのでそれは貴方が試す最初のファイルのためではないかもしれません。それがどのように上手くやるかを見るために同じフォルダの他の .wav ファイルの幾つかで実験してください。
スコアはゼロと 1 の間で、より高い値はモデルがその予測についてより信頼していることを示しています。
Android App でモデルを実行する
このモデルが実際のアプリケーションでどのように動作するかを見る最も簡単な方法は 事前ビルドされた Android デモ・アプリケーション をダウンロードして貴方のモバイルフォンにそれらをインストールすることです。app リストで ‘TF Speech’ が現れるのを見るでしょう、そしてそれを開くと私達が丁度訓練したアクション単語の同じリストが示され、 “Yes” と “No” で開始です。app にマイクロフォンを使用する許可をひとたび与えれば、それらの単語を発声して試してモデルがそれらの一つを認識するとき UI でそれらがハイライトされるのを見ることができます。
またこのアプリケーションを貴方自身でビルドすることもできます、何故ならばそれはオープンソースで github 上の TensorFlow レポジトリの一部として利用可能である からです。デフォルトではそれは tensorflow.org から事前訓練されたモデル をダウンロードしますが、それを 貴方が自身で訓練したモデルに置き換える ことが簡単にできます。これを行なう場合、主要な SpeechActivity Java ソースファイル 内の SAMPLE_RATE と SAMPLE_DURATION のような定数が訓練中にデフォルトに対して貴方が行なった任意の変更に適合することを確実にする必要があります。RecognizeCommands モジュールの Java バージョン があることもまた見るでしょう、これはこのチュートリアルの C++ バージョンに非常に似ています。そのためにパラメータを調整したのであれば、貴方のサーバ・テスティング内と同じ結果を得るために SpeechActivity でそれらを更新することもできます。
デモ app は凍結したグラフと一緒に貴方が assets にコピーしたラベル・テキストフィアルに基づいてその結果の UI リストを自動的に更新します、これはどのようなコード変更をする必要もなしに異なるモデルを簡単に試せることを意味しています。けれどもパスを変更する場合には追加したファイルをポイントするように LABEL_FILENAME と MODEL_FILENAME を更新する必要があります。
このモデルはどのように動作するのでしょう?
このチュートリアルで使用されているアーキテクチャはペーパー Convolutional Neural Networks for Small-footprint Keyword Spotting で説明されているものに基づいています。それが選択されたのは先端技術であることよりも、それが比較的単純で、迅速に訓練できて、理解するのも容易だからです。音声で動作するニューラルネットワーク・モデルを構築する多くの異なるアプローチがあり、それは リカレント・ネットワーク や dilated (atrous) convolutions を含みます。このチュートリアルは畳み込みネットワークの一種に基づきます、これは画像認識で作業したことのある人誰でも非常に精通しているでしょう。けれどもそれは最初は驚きかもしれません、何故ならば音声は生来的に時間に渡る 1-次元の連続したシグナルであり、2D 空間問題ではないからです。
その問題を、(話した単語がフィットすると信じる) 時間のウィンドウを定義して、そのウィンドウの音声シグナルを画像に変換することで解決します。これは、入ってくる音声サンプルを数ミリ秒長の短いセグメントにグループ化して、帯域のセットに渡る周波数の強さを計算することにより成されます。セグメントからの周波数の強さの各セットは数字のベクトルとして扱われて、それらのベクトルは 2-次元配列を形成するために時間順序で配置されます。そして値のこの配列は単一チャネル画像のように扱うことができて、スペクトログラムとして知られています。音声サンプルがどのような種類の画像を生成するかを見ることを望む場合、`wav_to_spectrogram ツールを実行することができます :
bazel run tensorflow/examples/wav_to_spectrogram:wav_to_spectrogram -- \ --input_wav=/tmp/speech_dataset/happy/ab00c4b2_nohash_0.wav \ --output_png=/tmp/spectrogram.png
/tmp/spectrogram.png をオープンすればこのような何かが見えるはずです :
TensorFlow のメモリ順序のため、時間が左から右へのスペクトログラムのための通常の変換とは異なり、この画像の時間はトップからボトムに増加していき、周波数は左から右へ進みます。貴方は 2 つの区別可能なパートを見ることができるはずで、最初の音節 “Ha” は “ppy” とは区別されます。
人間の耳はある周波数に対して他よりもより繊細ですので、発話認識ではこの表現に更なる処理を行なうのが伝統的で、それを Mel-Frequency Cepstral Coefficient あるいは短く MFCC のセットに変えます。これもまた 2-次元, 1-チャネル表現ですので、やはり画像のように取り扱うことができます。もし貴方が発話よりも一般的な音を対象とするのであればこのステップはスキップできてスペクトログラム上で直接演算できることを見い出すかもしれません。
これらの処理ステップで生成された画像はそれから (最後に softmax が続く完全結合層を伴う) 多層畳み込みニューラルネットワークに供給されます、この部分の定義は tensorflow/examples/speech_commands/models.py で見ることができます。
ストリーミング精度
殆どの音声認識アプリケーションは個別のクリップ上よりも音声の連続的なストリーム上で動作する必要があります。この環境でモデルを使用するための典型的な方法はそれを時間の異なるオフセットにおいて繰り返し適用してそして滑らかにされた予測を生成するために短いウィンドウに渡る結果を平均します。入力を画像として考える場合、それは時間軸に沿って連続的にスクロールしています。認識することを望む単語はいつでも始めることができるので、モデル内に供給する時間ウィンドウで発話の殆どを捕捉するアラインメントを持つ機会を持つためにスナップショットのシリーズを撮る必要があります。十分に高いレートでサンプリングすれば、複数のウィンドウで単語を捕捉する良い機会を持ちますので、結果を平均すれば予測の全体的な信頼度を改善します。
ストリーミング・データ上でモデルをどのように使用できるかのサンプルとして、test_streaming_accuracy.cc を見ることができます。これは 長い形式の入力音声を通して実行する RecognizeCommands クラスを使用し、単語に当たりをつけようとして、そしてそれらの予測をラベルと時間の正解リストに対して比較します。これは時間に渡る音声シグナルのストリームにモデルを適用する良いサンプルになります。
それをテストためには各単語がどこで話されたかを示すラベルと一緒に、長い音声ファイルが必要でしょう。貴方自身で一つを録音することを望まないのであれば、generate_streaming_test_wav ユティリティを使用して何某かの合成テストデータを生成できます。デフォルトではこれはおおよそ 3 秒毎の単語とともに 10 分間の .wav ファイルと、各単語がいつ話されたかの正解を含むテキストファイルを作成します。これらの単語は貴方の現在のデータセットのテスト部分から引っ張りだされていて、背景ノイズと一緒にミックスインされています。それを実行するためには、以下を使用してください :
bazel run tensorflow/examples/speech_commands:generate_streaming_test_wav
これは .wav ファイルを /tmp/speech_commands_train/streaming_test.wav に、そしてラベルをリスティングするテキストファイルを /tmp/speech_commands_train/streaming_test_labels.txt にセーブします。それから精度テスティングを以下で実行できます :
bazel run tensorflow/examples/speech_commands:test_streaming_accuracy -- \ --graph=/tmp/my_frozen_graph.pb \ --labels=/tmp/speech_commands_train/conv_labels.txt \ --wav=/tmp/speech_commands_train/streaming_test.wav \ --ground_truth=/tmp/speech_commands_train/streaming_test_labels.txt \ --verbose
これは正しく適合した単語の数や、誤ったラベルが幾つ与えられたか、そして実際に話された単語がないときにモデルが何回トリガーされたかについての情報を出力します。シグナルの平均化がどのように動作するか制御する様々なパラメータがあり、以下を含みます。–average_window_ms は結果に渡り平均するための時間の長さを設定し、–clip_stride_ms はモデルのアプリケーション間の時間で、–suppression_ms は初期の一つが見つかった後一定時間続く単語検出のトリガーを停止し、そして –detection_threshold はそれが確かな結果と考えられる前に平均スコアがどれほど高くなければならないかを制御します。
ストリーミング精度は訓練で使用された単なる 1 つのメトリックではなく、3 つの数字を出力することを見るでしょう。これは異なるアプリケーションは様々な要件を持つからで、あるものは実際の単語が見つかる限りは頻繁な正しくない結果に目をつぶることができる (高いリコール) 一方で、他のものは幾つかが検出されなくても予測されたラベルが高く正しくあることを確実にする (高い正確さ) ことにフォーカスされます。ツールからの数値はモデルがアプリケーションでどのように遂行するかの知見を貴方に与えるでしょう、そして望む種類のパフォーマンスを与えるためにシグナル平均パラメータの調整を試すことができます。貴方のアプリケーションのために正しいパラメータが何であるかを理解するあめに、トレードオフを理解する助けとなる ROC カーブ の生成を見ることができます。
RecognizeCommands
ストリーミング精度ツールは RecognizeCommands と呼ばれる小さな C++ クラスに含まれる単純なデコーダを使用します。このクラスは TensorFlow モデルを時間とともに実行した出力が供給され、それはシグナルを平均化し、認識された単語が見つかったと考えられる十分なエビデンスを持つときラベルについての情報を返します。実装は非常に小さく、単に最後の幾つかの予測を追跡し続けてそれらを平均するだけですので、必要な他のプラットフォームと言語にポートすることは簡単です。例えば、Android 上 java レベルや Raspberry Pi の Python で同様のことを行なうことは便利でしょう。これらの実装が同じロジックを共有する限りは、ストリーミング・テストツールを使用して平均化を制御するパラメータを調整して、そして同様の結果を得るためにそれらをアプリケーションへ転送することができます。
より進んだ訓練
訓練スクリプトのデフォルトは比較的小さいファイルで良い end to end の結果を生成するために設計されていますが、貴方自身の要件のために結果をカスタマイズするために変更可能な多くのオプションがあります。
カスタム訓練データ
デフォルトではスクリプトは Speech Commands データセット をダウンロードしますが、貴方自身の訓練データを供給することもまた可能です。貴方自身のデータ上で訓練するには、認識したい各音声の少なくとも数百のレコーディングを持って、それらをクラスでフォルダに配置することを確かにするべきです。例えば、もし貴方が猫の泣き声から犬の吠え声を認識することを試しているのであれば、animal_sounds と呼称するルート・フォルダとそれからその中に bark と miaou と呼ぶ 2 つのサブフォルダを作成します。それから貴方の音声ファイルを適切なフォルダに体系化します。
スクリプトに貴方の新しい音声ファイルをポイントさせるためには、Speech Commands データセットのダウンロードを無効にするために –data_url= を、貴方が作成したばかりのファイルを見つけるために –data_dir=/your/data/folder/ を設定する必要があります。
ファイル自身は 16-bit little-endian PCM-encoded WAVE フォーマットであるべきです。サンプリング・レートのデフォルトは 16,000 ですが、貴方の音声ファイルが一貫して同じレートである限りは (スクリプトはリサンプリングをサポートしません)、これを –sample_rate 引数で変更できます。クリップもまた総ておおよそ同じ時間であるべきです。デフォルトの想定される時間は 1 秒ですが、これを –clip_duration_ms フラグで設定できます。開始時に silence の可変な総量のクリップを持つ場合、それらを標準化するために単語アラインメント・ツールを見ることができます (ここに貴方が使用できる素早くダーティなアプローチがあります)。
警戒すべき一つの問題は貴方のデータセットで同じ音声の非常に類似した反復を持つかもしれないことで、これらが訓練、検証、そしてテストセットに渡り広がる場合、誤解されるメトリクスを与える可能性があります。例えば、Speech Commands セットは人々の同じ単語を複数回の反復を持ちます。それらの反復の各々の一つは多分他と非常に似ていますので、訓練がオーバーフィッティングしてそれを記憶する場合、テストセットで非常に類似したコピーを見たときにそれは非現実的に上手く遂行するかもしれません。この危険を回避するために、Speech Commands は、単一の人により話された同じ単語をフィーチャーした総てのクリップは同じパーティションに置かれることを確かなものにしようとしています。新しいクリップが追加されたときでも割り当てが堅固であり続けることを確かなものとしてそして任意の訓練サンプルが他のセットに移行することを回避することを確かなものとするために、クリップはファイル名のハッシュに基づいて訓練、テストそして検証セットに割り当てられます。総ての与えられた話者の単語が同じバケットにあることを確かなものとするために、割り当てを計算するときに ハッシング関数 は ‘nohash’ の後のファイル名はどれも無視します。これは、 pete_nohash_0.wav と pete_nohash_1.wav のようなファイル名を持つ場合、同じセットに入ることが保証されます。
未知のクラス
多分貴方のアプリケーションは訓練セットにない音を聞くでしょう、そしてモデルにはそれがそれらのクラスのノイズとして認識しないことを示すことを望むでしょう。何の音声を無視するべきかをネットワークが学習する助けとするために、貴方のクラスのどれでもない音声の幾つかのクリップを提供する必要があります。このため、quack, oink そして moo サブフォルダを作成してそれらにユーザが遭遇するかもしれない他の動物からのノイズを配置します。スクリプトへの –wanted_words 引数はどのクラスをケアするかを定義し、サブフォルダ名で参照される他の総ては訓練時に _unknown_ class に入れられるために使用されます。Speech Commands データセットはその未知のクラスとして 20 の単語を持ち、これは数字のゼロから 9 と “Shelia” のようなランダム名を含みます。デフォルトでは訓練サンプルの 10% が未知のクラスからピックアップされますが、これは –unknown_percentage フラグで制御可能です。これを増やすとモデルは未知の単語を望むものとして誤解しないようになりますが、それが大き過ぎれば、モデルは総ての単語を未知としてカテゴリー分けすることが最も安全と決定してしまい裏目に出るかもしれません。
背景ノイズ
実際のアプリケーションは環境で発生する他の無関係な音があるときでも音声を認識しなければなりません。この種の干渉に対して堅固であるモデルを構築するために、類似の特性を持つ録音された音声に対して訓練する必要があります。Speech Commands データセットのファイルは (スタジオではない) 多くの異なる環境でユーザにより様々なデバイス上で捕捉されました。そのため訓練に何某かのリアリズムを加える助けとなっています。更に追加するために、訓練入力に環境音声のランダムなセグメントをミックスインすることができます。 Speech Commands では _background_noise_ と呼ばれる特別なフォルダがあり、これはホワイト・ノイズと機械音そして日常の身近な活動の録音を伴う 1 分間の長さの WAVE ファイルを含みます。
これらのファイルの小さなスニペットはランダムに選ばれて訓練の間にクリップに低いボリュームで混在されます。音量もまたランダムに選ばれて 0 を silence、そして 1 をフルボリュームとする比率として–background_volume 引数により制御されます。総てのクリップについてバックグラウンドが追加はされませんので、–background_frequency フラグが何の比率でそれらをミックスインさせるかを制御します。
貴方自身のアプリケーションは、デフォルトとは異なる背景ノイズ・パターンを伴うそれ自身の環境で動作するかもしれませんので、貴方自身の音声クリップを _background_noise_ フォルダに供給することができます。これらは主要なデータセットと同じサンプリング・レートであるべきですが、しかし時間的には遥かに長いので、ランダム・セグメントの良いセットをそれらから選択することができます。
Silence
殆どの場合貴方ががケアする音声は断続的ですので、適合する音声がないときを知ることは重要です。これをサポートするため、モデルが興味深い何かを検出しないときを示す特別な _silence_ label があります。実際の環境では完全な静寂はありませんので、静かで無関係な音声を持つサンプルを実際に供給しなければなりません。このため、実際のクリップにも混在させた _background_noise_ フォルダを再利用し、音声データの短いセクションを引っ張り出し、それらを _silence_ の正解クラスとともに供給します。デフォルトでは訓練データの 10% がこのように供給されますが、–silence_percentage が比率を制御するために使用できます。未知の単語と同様に、これをより高く設定することはモデル結果を、単語に対する false negative を犠牲にして、silence について true positive に傾けます。しかし大きすぎる比率はそれを常に silence と推測する罠にはめる可能性があります。
タイムシフト
データセットのサイズを効果的に増やしてそして全体的な精度を上げるために背景ノイズの追加は現実的な方法で訓練データを変形させる一つの方法で、そしてタイムシフトはもう一つのものです。これは訓練サンプルデータの時間内のランダム・オフセットに関与して、最初か再度の小さな部分が切り取られて反対のセクションはゼロでパディングされます。これは訓練データにおける開始時間の自然なバリエーションを模倣し、–time_shift_ms フラグで制御されます、デフォルトは 100 ms です。この値を増やせば更にバリエーションが提供できますが、音声の重要な部分を切り落とすリスクもあります。データを現実的な歪みで増強する関係する方法は タイムストレッチとピッチ・スケーリング の使用によりますが、それはこのチュートリアルの範囲外です。
モデルをカスタマイズする
このスクリプトのために使用されるデフォルトモデルは非常に巨大で、各推論のために 8 億 FLOPs を引き受けて 940,000 重みパラメータを使用します。これはデスクトップ・マシンや現代的なモバイルフォン上では利用可能なスピードで動作しますが、より制限されたリソースを持つデバイス上でそれを対話的なスピードで実行するには多すぎる計算を伴います。これらのユースケースをサポートするために、利用可能な 2, 3 の選択肢があります :
low_latency_conv Convolutional Neural Networks for Small-footprint Keyword Spotting ペーパーで記述される ‘cnn-one-fstride4’ トポロジーに基づきます。精度は ‘conv’ よりも僅かに低くなりますが、重みパラメータの数はおおよそ同じくらいで、それは一つの予測を実行するために 1,100 万 FLOPs を必要とするだけで、それを遥かに速くします。このモデルを使用するためには、コマンド行で –model_architecture=low_latency_conv を指定します。訓練レートとステップ数も更新する必要がありますので、完全なコマンドは次のように見えます :
python tensorflow/examples/speech_commands/train \ --model_architecture=low_latency_conv \ --how_many_training_steps=20000,6000 \ --learning_rate=0.01,0.001
これはスクリプトに 20,000 ステップに対して 0.01 の学習率で訓練し、そして 6,000 ステップの再調整パスを 10x 小さいレートで行なうことを依頼します。
low_latency_svdf Compressing Deep Neural Networks using a Rank-Constrained Topology ペーパーで提案されているトポロジーに基づきます。精度は ‘conv’ よりもまた低いですが、それはおよそ 75 万パラメータを使用するだけで、最も重要なことに、それはテスト時に (i.e. 貴方のアプリケーションでそれを実際に使用するとき) 最適化された実行を可能にし、75 万 FLOPs という結果になります。
このモデルを使用するためには、コマンド行で –model_architecture=low_latency_svdf を指定し、そして訓練レートとステップ数を更新しますので、完全なコマンドは次のように見えます :
python tensorflow/examples/speech_commands/train \ --model_architecture=low_latency_svdf \ --how_many_training_steps=100000,35000 \ --learning_rate=0.01,0.005
前の 2 つのトポロジーよりも大きいステップ数を必要とするにもかかわらず、減じられた計算数は訓練はおおよそ同じ位の時間がかかるはずで、最後には 85% 前後の精度に達することを意味します。計算と精度のためにトポロジーを SVDF 層のこれらのパラメータを変更することにより非常に容易に更に調整することもできます :
- rank – 近似のランク (典型的にはより高ければより良くなりますが、より多い計算という結果になります)。
- num_units – 他の層タイプと同様で、層のノード数を指定します (より多いノードはより良い品質に、そしてより多い計算)。
ランタイムに関して、層は内部のニューラルネットワーク活性の何某かをキャッシュすることで最適化を可能にしますので、グラフを凍結するときとストリーミング・モード (e.g. test_streaming_accuracy.cc) でモデルを実行するときの両者で一貫したストライド (e.g. ‘clip_stride_ms’ フラグ) を使用することを確実にする必要があります。
カスタマイズするための他のパラメータ もしモデルのカスタマイズで実験することを望むのであれば、始める良い場所はスペクトログラム作成パラメータを調整することです。これはモデルへの入力画像のサイズを変更する効果を持ち、models.py の作成コードは異なる次元でフィットさせるために計算数と重みを自動的に調整します。入力をより小さくする場合、モデルはそれを処理するためにより少ない計算を必要としますので、何某かの精度を改善された遅延のためにトレードオフする良い方法となり得ます。–window_stride_ms は各周波数解析サンプルが前のものからどれだけ離れているかを制御します。もしこの値を増やす場合、与えられた時間のためにより少ないサンプリングが取られて、入力の時間軸は縮小します。–dct_coefficient_count フラグは周波数カウントのために幾つのバケットが使用されるかを制御しますので、これを減少させれば他の次元の入力を縮小します。–window_size_ms 引数はサイズへの影響はありませんが、各サンプルについてどのくらい広い領域が周波数を計算するために使用されるかを制御します。–clip_duration_ms により制御される、訓練サンプルの時間の減少も、貴方が探している音声が短いのであれば、役立つことができます、何故ならばそれもまた入力の時間次元を減らすからです。訓練データの総てがクリップの初期比率について正しい音声を含むことを確実にする必要がありますが。
貴方の問題に対して全く異なるモデルを持つことを考慮する場合には、それを models.py にプラグインしてスクリプトの残りに前処理と訓練メカニクスの総てを処理させることができます。貴方は create_model に新しい条項 (= clause) を追加して、アーキテクチャの名前を探して、そしてモデル作成関数を呼び出すでしょう。この関数には、スペクトログラム入力のサイズが他のモデル情報と一緒に与えられて、それを読み込み、出力予測ベクトルと (dropout レートを制御するための) プレースホルダを生成する TensorFlow ops を作成することが想定されます。スクリプトの残りはこのモデルをより大きいグラフへと統合し入力計算を行ないそしてそれを訓練するために softmx と損失関数を適用する処理をします。
モデルを調整してハイパーパラメータを訓練するときの一つの一般的な問題は、数値精度の問題のために非数値 (訳注: NaN) が入り込むかもしれないことです。一般的には学習率や重み初期化関数のようなものの大きさを減じることでこれらを解決できますが、それらが存在し続けるならばエラーのソースを追跡するために –check_nans フラグを有効にすることができます。これは TensorFlow の殆どの標準的な演算の間に check ops を挿入し、それらに遭遇したときには有用なエラーメッセージと共に訓練プロセスを中止します。
以上