【論文読解】Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech Synthesis

# 概要

訓練中に存在しない話者の数秒の音声をもとに、Zero-shotなText-to-Speechを実現する手法であるSV2TTSを提案している2018年の論文で、[GoogleのTacotronチーム](https://google.github.io/tacotron/index.html)による研究です。

[Real-Time-Voice-Cloning](https://github.com/CorentinJ/Real-Time-Voice-Cloning)という本手法の非公式実装であるリポジトリがなかなか盛り上がっているのを見つけたので、どんなもんかなと思って読んでみました。

SVTTSは大きく3つのモジュールから成り立っています。

- Speaker Encoder：話者認証のモデルをベースとした話者の埋め込み表現抽出器
- Synthesizer：テキストと話者の埋め込み表現からメルスペクトログラムを推定するTacotron2ベースの合成器
- Vocoder：メルスペクトログラムを音声波形に変換するWaveNetベースのボコーダー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/ec384fe7-5a52-d954-b0ce-cdd7043a7804.png)

この図だけでだいたいどんなことをやっているかはわかりますが、少し深堀してみようと思います。

# 書誌情報

- Jia, Ye, et al. "Transfer learning from speaker verification to multispeaker text-to-speech synthesis." Advances in neural information processing systems 31 (2018): 4480-4490.
- https://arxiv.org/abs/1806.04558
- [出力音声サンプルページ](https://google.github.io/tacotron/publications/speaker_adaptation/index.html)

# Speaker Encoder

Speaker Encoderは、未知の話者による数秒の音声から、その話者の特徴を抽出し、固定次元の埋め込み表現を得ることを目的としているモジュールです。本手法では、そのために話者認証（Speaker Verification）の手法を使っています。話者認証は、数秒の音声から特定の話者であることを特定するための特徴を抽出する必要があるタスクですので、今回のZero-shotの問題設定と相性が良いといえます。

ベースとなっている手法を提案している論文[^ge2e]を読んでみると、ネットワークはシンプルなLSTMで、損失関数を工夫することで効果的な訓練ができるということが示されています。

下図はその処理の過程を描いたものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/0952464e-e7d2-910d-4e6e-ec8f1ddcdd3e.png)


[^ge2e]: Wan, Li, et al. "Generalized end-to-end loss for speaker verification." 2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2018.

まず、入力された音声波からlog-mel spectrogramフレーム系列を抽出します。log-mel spectrogramは、音声波形に対して短時間フーリエ解析を適用して得られる振幅スペクトログラムに対して、メルフィルタバンクを用いた周波数ビンのグループ化を適用し、対数スケールに圧縮したものです。メルスペクトログラムまわりの細かい処理については[参考記事](https://qiita.com/tmtakashi_dist/items/eecb705ea48260db0b62)等をご覧ください。torchaudioだと、一発で得られるような[MelSpectrogramクラス](https://pytorch.org/audio/stable/transforms.html#melspectrogram)が用意されています。

このような特徴抽出を複数の人の複数の音声に対して適用し、バッチを構築します。音声の長さが異なる場合は、時間を適当に決めたのち、その時間分のデータを各音声のランダムな位置で切りとって長さを揃えます。このバッチをLSTMに通し、出力に対してL2正規化を施すことで、各音声に対する埋め込み表現が得られます。

各話者での埋め込み表現の平均と各音声の埋め込み表現を比較し、同一の話者であれば距離が近く、異なる話者であれば距離が遠くなるような表現になるような損失関数を適用し、ネットワークを訓練していきます。ここで、画像検索などでおなじみのTriplet Lossのような損失関数が使われます。

埋め込み表現の類似度は、以下のように計算されます。ここで、$j,k$は話者を表すインデックスで、$i$は各話者の何番目の音声であるかを表しています。$\mathbf{e}\_{j i}$は話者$j$の$i$番目の音声から得られた埋め込み表現、$\mathbf{c}_{k}$は話者$k$の埋め込み表現の平均です。また、$w, b$は訓練対象のパラメータです。

```math
\mathbf{S}_{j i, k}=w \cdot \cos \left(\mathbf{e}_{j i}, \mathbf{c}_{k}\right)+b
```

この類似度を用いて、損失関数であるGE2Eは以下のように定義されます。

```math
L\left(\mathbf{e}_{j i}\right)=1-\sigma\left(\mathbf{S}_{j i, j}\right)+\max _{1 \leq k \leq N \atop k \neq j} \sigma\left(\mathbf{S}_{j i, k}\right)
```

# Synthesizer

Synthesizerは、入力されたテキストからlog-mel spectrogramを出力するモジュールです。単一話者のText-to-SpeechモデルであるTacotron2をベースとし、任意の話者特徴を途中でから挿入することで、条件付きの出力ができるように改良されています。

Tacotron2は元論文[^tacotron2]によると、以下のような構成になっています（下図は元論文中の図を説明のために加工しています）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/53d8a739-987f-d289-3642-06c7dfd6a054.png)


- Encoder：入力された文字列から、文字レベルの埋め込み表現系列を作成し、1次元のConv層を通して、双方向LSTMへと入力されます。LSTMの隠れ層の系列が出力となります。1次元のConv層は、周囲の文字の情報を効率的に取り込む、N-gram風の効果が期待されています。
- Decoder: Encoderの出力系列を適宜参照しながら、LSTMによってmel spectrogramを出力する、Attention機構を備えたデコーダーになっています。音声の生成におけるAttention機構では、すでに出力した部分にAttentionがあまりかからないようにする必要があるため、過去のAttentionの和も考慮しながら、次のAttentionを決めるといったLocal Sensitive Attentionが採用されています。LSTMの出力は、mel spectrogramに関わる部分以外に、音声の終わりを決めるためのStop Tokenを出力するLinear層にも入力されます。
- PostNet：Decoderの出力するmel spectrogramからも十分に聴ける音声を出力できますが、より自然な音声にするために、Post-Netによって補正をかけます。この補正結果と元の出力を足し合わせて最終的な出力が得られます。

SVTTSでは、各モジュールについて少し異なる実装が採用されています。

- Encoder: 入力するテキストは、一度音素(phoneme)系列へと変換されます。音声との対応関係が単純な文字列よりも良いため、収束が早まるとのことです。論文には、どうやってこれを実現しているかが書かれていないように見えますが、[非公式実装](https://github.com/CorentinJ/Real-Time-Voice-Cloning)では[CMU Pronouncing Dictionary](http://www.speech.cs.cmu.edu/cgi-bin/cmudict)が使われています。
- Decoder：LSTMに入力する際に、Speaker Encoderによって得られた埋め込み表現を結合します。

[^tacotron2]: Shen, Jonathan, et al. "Natural tts synthesis by conditioning wavenet on mel spectrogram predictions." 2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2018.

# Vocoder

Vocoderはmel spectrogramから音声波への復元を行うモジュールで、レガシーな手法としては、Griffin–Limなどが知られています。深層学習の時代になり、いくつかのNeural Vocoderが提案されていますが、本論文ではWaveNetベースのVocoderを使用しています。[非公式実装](https://github.com/CorentinJ/Real-Time-Voice-Cloning)では推論速度を重視しているため、VocoderとしてWaveRNNやGriffin-Limが選択できるようになっており、別の手法に付け替えることが可能です。

本論文で使用しているWaveNetベースのVocoderは、Tacotron2で使われていたVocoderと同じアーキテクチャが採用されています。WaveNetそのものについては、以下の解説記事が参考になります。

https://qiita.com/MasaEguchi/items/cd5f7e9735a120f27e2a

オリジナルのWaveNetでは、$\mu$-law companding transformationによる量子化された値をターゲットとし、分類損失をもとにモデルを訓練します。Tactron2では、そのような量子化は行わず、10個の成分からなる混合ロジスティック分布（Mixture of Logistic Distributions: MoL）を推定し、負の対数尤度を損失関数として、モデルを訓練します。

# モデルの訓練とデータセット
本手法で使われる3つのモジュールは、エンドツーエンドではなく、個別に訓練されます。ある論文[^ref]に掲載されている図が非常にわかりやすかったので以下に引用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4010/cd32a1ea-48e6-214c-4b1a-dc67ddea7b5a.png)

[^ref]: https://matheo.uliege.be/bitstream/2268.2/6801/5/s123578Jemine2019.pdf

本手法の訓練には、大きく2種類のデータセットが必要です。

1つ目は、上図でDataset1と書かれているもので、大量の話者による音声が含まれたデータセットです。Speaker Encoderの訓練に使用するため、各音声がどの話者によるものなのかというラベルが必要で、話者数が多ければ多いほど、高品質なSpeaker Encoderが得られます。一方で、音声の内容であるトランスクリプトは不要ですし、多少のノイズは許容されます。
本論文では、18K人の英語話者による3.9秒程度の36M音声からなるデータセットが使われています。このデータセットはおそらく未公開のものですが、この量のデータの揃え方は、さすがGoogleだなという規模感です。

2つ目は、上図でDataset2と書かれているもので、比較的高品質な音声とトランスクリプトがペアになったデータセットです。このデータセットは、SynthesizerとVocoderの訓練に使用されます。
Synthesizerは、テキスト系列と訓練済みのSpeaker Encoderから得られる埋め込み表現を用いて推定されるlog-mel spectrogramを、元の音声から得られるlog-mel spectrogramに近づけられるように訓練されます。損失関数として、log-mel spectrogramのL1誤差とL2誤差が使用されます。
Vocoderの訓練では、訓練済みのSpeaker EncoderとSynthesizerを通してlog-mel spectrogramを推定し、それを元の音声に復元できるように訓練します。データセットが非常に高品質で、環境音などを含まない場合は、わざわざSynthesizerの推定結果を使用せずに、音声から抽出したlog-mel spectrogramを直接音声に復元できるように訓練することも可能です。
本論文では、Dataset2に該当するデータセットとして、VCTKとLibriSpeechを使用しています。前者は非常に高品質な音声なので、Vocoderの訓練に直接使用できますが、後者はやや環境音が含まれれる関係上、ノイズ除去を行った上で、さらにSynthesizerを通して得られるlog-mel spectrogramを用いてVocoderを訓練します。

ちなみに、[非公式実装における英語以外への対応に関する議論](https://github.com/CorentinJ/Real-Time-Voice-Cloning/issues/30)を眺めてみると、Speaker Encoderは言語に依存しないある程度汎用的なものができているためDataset1はを改めて用意する必要はないだろうが、SynthesizerやVocoderは各言語ごとに訓練する必要があるため、Dataset2についてはおよそ300時間程度の高品質な音声とトランスクリプトが必要であろう、とされています。

# まとめ
Zero-shotの音声合成を実現するSVTTSについてまとめてみました。少し古いのですが、Text-to-Speech系の手法の入門として読んでみました。

音声処理まわりは超初心者なので、何か間違いがありましたらご指摘ください。