Tacotron2 入門 (3) - 音声合成モデルの学習
以下の記事を参考に書いてます。
前回
1. オーディオサンプル
このリポジトリを使用して学習したモデルで生成したオーディオサンプルはここで確認できます。
・1番目は、「LJ Speechデータセット」で441Kステップの学習を行いました。音声は約20Kステップで理解できるようになりはじめました。
・2番目は、「ナンシーコーパス」で140Kステップの学習を行いました。
2. 最近の更新
・@npuichigoは、ドロップアウトがプレネットに適用されていなかったバグを修正しました。
・@begeekmyfriendは、 Tacotron2の論文からlocation-sensitive attentionとのstop tokenを追加するフォークを作成しました。これにより、モデルの学習に必要なデータの量を大幅に減らすことができます。
2. インストール
(1) Python3の仮想環境の準備。
「Anaconda」で準備を行う時のコマンドは、次のとおりです。
$ conda create -n tacotron python=3.6
$ conda activate tacotron
(2) TensorFlowをインストール。
「TensorFlow 1.3」をインストールするコマンドは、次のとおりです。
$ pip install tensorflow==1.13.2
GPUが利用可能な場合はGPU版をインストールしてください。「TensorFlow 1.3」以降で動作します。
(3) keithito/tacotronのインストール
以下のコマンドを実行してください。
$ git clone https://github.com/keithito/tacotron.git
$ cd tacotron
$ pip install -r requirements.txt --use-feature=2020-resolver
3. 事前学習済みモデルの使用
(1) モデルのダウンロード。
$ curl https://data.keithito.com/data/speech/tacotron-20180906.tar.gz | tar xzC /tmp
(2) デモサーバーの実行。
$ python demo_server.py --checkpoint /tmp/tacotron-20180906/model.ckpt
【注意】自分の環境では、以下のエラーがでました。
TypeError: create_target_machine() got an unexpected keyword argument 'jitdebug'
以下のコマンドで解決しました。
pip install -U llvmlite==0.32.1
(3) ブラウザで「localhost:9000」を開いて、音声合成したいテキストを入力。
4. 学習
【注意】モデルを学習するには、少なくとも40GBの空きディスク容量が必要です。
(1) 音声データセットをダウンロード。
以下のデータセットがサポートされています。
・LJ Speech
・Blizzard 2012
適切な形式に変換すれば、他のデータセットを使用できます。詳しくは、TRAINING_DATA.mdを参照してください。
(2) データセットを「~/tacotron」に解凍。
「LJ Speech」のツリーは次のようになります。
tacotron
|- LJSpeech-1.1
|- metadata.csv
|- wavs
(3) データの前処理の実行。
$ python preprocess.py --dataset ljspeech
(4) モデルの学習の実行。
$ python train.py
調整可能なハイパーパラメータは「hparams.py」にあります。これらは、コマンドラインで「--hparams」フラグで調整できます(例:--hparams="batch_size=16,outputs_per_step=2")。
ハイパーパラメータは通常、学習時と評価時の両方で同じ値に設定する必要があります。「LJ Speech」およびその他の英語データには、デフォルトのハイパーパラメータが推奨されます。他の言語については、TRAINING_DATA.mdを参照してください。
(5) Tensorboardによる監視。(オプション)
$ tensorboard --logdir ~/tacotron/logs-tacotron
トレーナーは1000ステップごとに、オーディオとアライメントを「~/tacotron/logs-tacotron」にダンプします。
(6) チェックポイントを使って音声合成を実行。
$ python demo_server.py --checkpoint ~/tacotron/logs-tacotron/model.ckpt-185000
「185000」を使用するチェックポイント番号に置き換えてから、ブラウザで「localhost:9000」を開いて、音声合成したいテキストを入力します。
または、コマンドラインで「eval.py」を実行することもできます。
$ python eval.py --checkpoint ~/tacotron/logs-tacotron/model.ckpt-185000
学習時に「--hparams」フラグを設定した場合は、ここで同じ値を設定します。
5. 注意事項と一般的な問題
・「TCMalloc」は学習速度を改善し、デフォルトのアロケーターで見られる時折の速度低下を回避するようです。インストールして「LD_PRELOAD=/usr/lib/libtcmalloc.so」を設定することで有効にできます。「TCMalloc」を使用すると、GTX1080Tiで約1.1秒/ステップを取得できます。
・辞書を「~/tacotron/training」にダウンロードし、フラグ「--hparams="use_cmudict=True"」を「train.py」に渡すことで、「CMUDict」で学習できます。これにより、評価時に中括弧で囲まれたARPAbet音素を渡して、特定の発音を強制することができます(例 : Turn left on {HH AW1 S S T AH0 N} Street.)。
・「Slack incoming webhook URL」を「--slack_url」フラグとして「train.py」に渡すと、1000ステップごとに進行状況の更新が送信されます。
・評価および学習中、オーディオの長さは「max_iters * output_per_step * frame_shift_ms」ミリ秒に制限されます。デフォルト(max_iters = 200、outputs_per_step = 5、frame_shift_ms = 12.5)の場合、これは12.5秒です。
学習のサンプルが長い場合は、次のようなエラーが表示されます。
Incompatible shapes: [32,1340,80] vs. [32,1000,80]
これを修正するには、「--hparams="max_iters=300"」を「train.py」に渡すことで「max_iters」のより大きな値を設定できます("300"をオーディオの長さと上記の式に基づく値に置き換えます)。
・デフォルトのハイパーパラメータを使用して「LJ Speech」で学習した場合に予想される損失曲線は、次のとおりです。
6. その他の実装
・By Alex Barron : https://github.com/barronalex/Tacotron
・By Kyubyong Park : https://github.com/Kyubyong/tacotron
【おまけ】学習データ
このリポジトリは、次の音声データセットをサポートしています。
・LJ Speech
・Blizzard 2012
プリプロセッサを作成すれば、他のデータセットを使用できます。
◎プリプロセッサの作成
各学習サンプルは、次のもので構成されています。
・話されたテキスト
・オーディオのメルスケールスペクトログラム
・オーディオの線形スケールスペクトログラム
プリプロセッサはこれらを生成する責任があります。コメント付きのサンプルについては、「ljspeech.py」を参照してください。
学習サンプルごとに、プリプロセッサは次のことを行う必要があります。
(1) オーディオファイルのロード。
wav = audio.load_wav(wav_path)
(2) 線形スケールおよびメルスケールのスペクトログラム(float32 numpy配列)を計算。
spectrogram = audio.spectrogram(wav).astype(np.float32)
mel_spectrogram = audio.melspectrogram(wav).astype(np.float32)
(3) スペクトログラムをディスクに保存。
np.save(os.path.join(out_dir, spectrogram_filename), spectrogram.T, allow_pickle=False)
np.save(os.path.join(out_dir, mel_spectrogram_filename), mel_spectrogram.T, allow_pickle=False)
audio.spectrogramによって返される行列の転置は、時間優先形式になるように保存されることに注意してください。
(4) strain.txtに書き込むタプル(spectrogram_filename, mel_spectrogram_filename, n_frames, text)を生成します。
n_framesは、スペクトログラムの時間軸の長さです。
プリプロセッサを作成したら、そのファイル内の他のプリプロセッサのサンプルに従って、「preprocess.py」に追加できます。
◎ 英語以外の言語の学習データ
学習データが英語以外の言語である場合は、ハイパーパラメータ「cleaners」を設定して、テキストクリーナーを変更することをお勧めします。
・テキストがラテン文字であるか、Unidecodeライブラリを使用してASCIIに音訳できる場合は、ハイパーパラメータ「cleaners=transliteration_cleaners」を設定して音訳クリーナーを使用できます。
・文字変換したくない場合は、カスタム文字セットを定義できます。
これにより、データで使用されている文字セットを直接学習できます。
これを行うには、「symbols.py」を編集し、_characters変数をデータ内のUTF-8文字を含む文字列に変更します。次に、ハイパーパラメータ「cleaners=basic_cleaners」を設定します。
・使用するオプションがわからない場合は、次のように文字変換クリーナーを評価できます。
from text import cleaners
cleaners.transliteration_cleaners('Здравствуйте') # 試したいテキストに置き換える