
高速かつ高品質な音声合成ができるFastSpeech2を試してみた
こんにちは。株式会社IZAIエンジニアチームです。
今回は2020年にMicrosoft Research Lab - Asiaの研究チームによって発表され、翌年のICLR(機械学習分野のトップカンファレンス)に採択されたFastSpeech2を検証します。
FastSpeech2とは?
FastSpeech2 は、北京にあるマイクロソフトリサーチアジアの研究チームによって2020年6月8日に “FastSpeech 2: Fast and High-Quality End-to-End Text to Speech”(高速かつ高品質なエンドツーエンドのテキスト読み上げ) というタイトルでarXivに最初に投稿され、その後 2021年のICLRに採択されたEnd-to-Endの音声合成(Text-to-Speech, 以下 TTS)モデルです。
End-to-End・・・一般に、音声合成に必要な前処理や後処理をひとまとめにし、テキスト入力から最終的な音声出力までを一貫して学習・推論できる仕組みのこと。一意な定義は存在せず、FastSpeech2は真にEnd-to-Endではないとの見方もあります。
FastSpeech2は、従来手法と比較して、
・"非"自己回帰型モデルによって推論速度が大幅な向上した
・抑揚などの非テキスト情報が制御可能になった
の主に2点において従来手法比で注目されています。それぞれについて簡単に解説します。
1. "非"自己回帰型モデルによって推論速度が大幅な向上した
FastSpeech2は"非"自己回帰型モデルです。
これまでに提案されていた自己回帰型なモデル(Tacotron 2、Transformer TTS)に比べて非常に推論が速く、論文中の速度比較でも Tacotron 2 などと比べて 10〜20倍以上の速度差が示されています。
非自己回帰型 (Non-Autoregressive) とは?・・・
通常の音声合成モデルでは、「前のフレームをもとに次のフレームを生成する」という順番処理(自己回帰型)が多かったのに対し、非自己回帰型モデルは「複数のフレームを同時に」推論できるため、高速化しやすいという利点があります。
※ 音声認識ですがYahooさんの図解がわかりやすいです
(補足:ではなぜ今まで非自己回帰型が実現しなかったのかについては、後述するVariance Adaptorに含まれるDuration(持続時間)予測が関係するとのことですが今回は詳しく解説しません。)
2. 抑揚などの非テキスト情報が制御可能になった
テキスト音声合成では「one-to-many mapping(一対多マッピング)問題」がよく議論されます。これは、同じ文章でも話し手や感情、状況によって無数の読み方が生じる、という現象です。
例えば「おはようございます」というテキスト一つとっても、元気よく挨拶する場合と、寝起きでぼそっと話す場合では「声の高さ」、「話す速さ」、「声の強さ」など性質が全く異なります。誰が話すのかによってもその音声の性質は全く異なります。それぞれ、パラ言語情報や非言語情報(話者性)とも呼ばれます。
そこでFastSpeech 2 では、こうした音声の性質を取り込むために “Variance Adaptor(VA)”というモジュールを導入し、
「話す速さ(duration)」
「声の高さ(Pitch)」
「声の強さ(Energy)」
の要素を数値でコントロールできるようにしています。
初代 FastSpeech (2019年発表) において制御が限定的だった音声の抑揚や強弱(総称して「韻律」や「プロソディ」と呼ばれます)を、FastSpeech2ではVariance Adaptorモジュールによってより制御しやすくしています。
アーキテクチャの概要

FastSpeech2は主に
・エンコーダ
・Variance Adaptor
・デコーダ
の 3 つのモジュールから構成されています。各要素について簡単に見ていきます。
0. 音素埋め込み(Phoneme Embedding)
テキスト入力(文章)を、音声を構成する最小単位である音素の列に分割し、その音素列を数値ベクトルの形に変換する工程です(音素埋め込み)。TTSでごく一般的に用いられる第一段階の処理です
・例)「こんにちは」→ [ ko, n, ni, chi, wa ] → 日本語の音素埋め込みベクトル
1. エンコーダ(Encoder)
音素埋め込みベクトルを受け取り、hidden sequence と呼ばれる中間表現に変換します。hidden sequence とは、ニューラルネットワーク内部で扱われる数値ベクトル列で、入力データ(音素列)から重要な特徴を抽出・保持したもので、本モデルでは Feed-Forward Transformer (FFT) を採用し、RNN を使わずに 自己注意機構 (Self-Attention) をベースとした処理を行うことで並列計算を可能にしています。
2.Variance Adaptor
前述した、本論文のコアモジュールです。
エンコーダから出力された hidden sequence に対して、以下のような韻律(いんりつ)情報を数値として明示的に加えます。
Pitch(ピッチ):声の高さ
Duration(持続時間):各音素をどれだけの長さ(フレーム数)話すか
Energy(エネルギー):声の大きさ・強さ
これによって、
・元気に明るく話す(ピッチ高め、エネルギー強め、速度速め)
・ゆっくり落ち着いて話す(ピッチ低め、エネルギー控えめ、速度遅め)
といった制御を可能にしています。
3. デコーダ(Decoder)
Variance Adaptorによって韻律情報が付与されたhidden sequenceを、メルスペクトログラムに変換します。最後に、このメルスペクトログラムを Vocoder(ボコーダ) と呼ばれるシステム(例:WaveNet、HiFi-GANなど)に入力し、実際の音声波形へ変換します。これでついに、聞き取れる形のオーディオが出力されます。

用語解説
・Feed-Forward Transformer (FFT) ブロック
Attention層と1D Conv層で構成されたブロックです。詳しくはFastSpeechをご参照ください。
・メルスペクトログラム
スペクトログラムを、周波数をメル尺度に変換したものです。メル尺度とは人間の直感に基づいた周波数尺度のことです。
※メルスペクトログラムの生成とVocoderによる波形生成を省略し、テキストから直接波形を生成するFastSpeech 2sも紹介されています。より真のEnd-to-Endに近いアーキテクチャです。興味のある方は元論文を是非ご覧ください。
検証する
検証環境
OS : Windows 11 Pro
CPU:Intel Core i9-13900K
GPU : NVIDIA GeForce RTX 3090
RAM:DDR5 64GB
Python3.7
1. リポジトリのクローン
git clone https://github.com/ming024/FastSpeech2.git
cd FastSpeech2
2. 依存パッケージのインストール
pip install -r requirements.txt
3. データセットの用意
FastSpeech2では次の3つのデータセットが紹介されています。
LJSpeech : 単一話者の英語データセット。女性話者による7冊のノンフィクション書籍の読み上げの13,100個の短い音声クリップ。合計で約24時間・
AISHELL-3 : 男性と女性の話者218名による中国語TTSデータセット。合計で約85時間
LibriTTS : 2,456名の話者による585時間のスピーチを含む複数話者の英語データセット
本記事では単一話者の英語データセットとして最もよく使われるものの一つであるLJSpeechを使用します。
データセットをダウンロードしたら、FastSpeech2\dataset\LJSpeech-1.1を作成して展開しましょう。
4. configの設定とprepare_align.pyの実行
FastSpeech2\config\LJSpeech内のpreprocess.yaml
を開き、corpus_pathを展開したデータセットがあるパスに変更します。
dataset: "LJSpeech"
path:
corpus_path: "/home/ming/Data/LJSpeech-1.1" #データセットのパスに変更
lexicon_path: "lexicon/librispeech-lexicon.txt"
raw_path: "./raw_data/LJSpeech"
preprocessed_path: "./preprocessed_data/LJSpeech"
#(省略)
パスを変更したら、次のコマンドを実行します。これでデータの前処理時に必要なフォルダが作成されます。
python prepare_align.py config/LJSpeech/preprocess.yaml
5. データの前処理
データセットに対応するアライメントを取得します。こちらからダウンロード可能です。今回はLJSpeech.zipをダウンロードします。
ダウンロードしたアライメントは、FastSpeech2/preprocessed_data/LJSpeech/TextGrid内に展開します。
展開したらpreprocess.pyを実行し、データの前処理を行います。
python preprocess.py config/LJSpeech/preprocess.yaml
6. 学習
次のコマンドで学習を開始します。
python train.py -p config/LJSpeech/preprocess.yaml -m config/LJSpeech/model.yaml -t config/LJSpeech/train.yaml
7. 音声生成の結果
学習したモデルを用いて音声生成をしてみましょう。
生成の前に、次の2つをやっておきます。
出力結果を保存するディレクトリFastSpeech2\output\result\LJSpeechを作成しておきます。
FastSpeech2\hifigan内のgenerator_LJSpeech.pth.tar.zip、generator_universal.pth.tar.zipを展開しておきます。
それではコマンドを実行してテキストから音声に変換してみましょう。
python synthesize.py --text "YOUR_DESIRED_TEXT" --restore_step 900000 --mode single -p config/LJSpeech/preprocess.yaml -m config/LJSpeech/model.yaml -t config/LJSpeech/train.yaml
"YOUR_DESIRED_TEXT"の箇所に、音声生成したいテキストを入力します。
今回は"It can convert text to speech quickly and with high quality"というテキストを音声に変換します。
処理が完了すると先ほど作成したFastSpeech2\output\result\LJSpeech内に(入力したテキスト).wavと対応するメルスペクトログラムの画像ファイルが生成されます。
女性の声に変換できました。
今回のテキストから変換される3秒程度の音声の生成にかかった時間は1.250 秒程度でした。
FastSpeech2では生成する音声について、energy、pitch、durationの3つを調整できます。それぞれ調整した結果を見てみましょう。指定なしの場合は全て1に設定されています。
energy:発話全体のエネルギーを制御。値が大きいほど音量が大きい。
python synthesize.py --text "It can convert text to speech fast and with high quality." --restore_step 900000 --mode single -p config/LJSpeech/preprocess.yaml -m config/LJSpeech/model.yaml -t config/LJSpeech/train.yaml --energy_control 0.5
生成結果 energy = 0.5
生成結果 energy = 3.0
pitch:発話全体のピッチを制御。値が大きいほどピッチが高い。
python synthesize.py --text "It can convert text to speech fast and with high quality" --restore_step 900000 --mode single -p config/LJSpeech/preprocess.yaml -m config/LJSpeech/model.yaml -t config/LJSpeech/train.yaml --pitch_control 0.5
生成結果 pitch = 0.5
生成結果 pitch = 3.0
duration:発話全体の速度を制御。値が大きいほど発話速度が遅くなる。
python synthesize.py --text "It can convert text to speech fast and with high quality" --restore_step 900000 --mode single -p config/LJSpeech/preprocess.yaml -m config/LJSpeech/model.yaml -t config/LJSpeech/train.yaml --duration_control 0.5
生成結果 duration = 0.5
生成結果 duration = 3.0
特にpitchやdurationの変化は分かりやすいですね。
まとめ
以上、FastSpeech2を試してみました。自然な会話を実現するには高速な音声生成は必要不可欠な要素です。FastSpeech2はオープンソースで公開されていますので、皆様も是非試してみてください。
最後に
株式会社IZAIでは音声認識や音声合成に関する研究開発・サービス開発を行っています。興味のあるエンジニア、学生、企業様などいらっしゃいましたらお気軽にお問い合わせください。
参考になった方、興味のある方はぜひ「いいね」をよろしくお願いいたします。それではまた!
参考文献
github : https://github.com/ming024/FastSpeech2?tab=readme-ov-file
FastSpeech2元論文 : https://arxiv.org/abs/2006.04558v1
FastSpeech元論文 : https://arxiv.org/abs/1905.09263