TorToiSe TTSの個人的なメモ

github.com
nonint.com

とても良いと言われているTorToiSe TTSについて、作者のアーキテクチャデザイン資料とRedditの作者の発言を読んだ個人的なメモ。
推論等も混ざっていて間違っているかもしれないのであしからず。
図は基本的に作者のWebページから(図がすべて手書きなの趣深い)。

概要

TorToiSeはtext-to-speech(TTS)アプリケーションで、複数の人の声への対応とリアルさに重点をおいている。
2~4つほどの少量の音声データからターゲットとなる話者の声を模倣する。

現在は推論部分を提供しており、学習方法等については公開していない(公開予定もないそう)。

作者はスピーチ関連のリポジトリ名をモハーヴェ砂漠の動植物からとっているらしい。
モデルはautoregressive + diffusionでものすごく遅い。

アーキテクチャデザイン

アーキテクチャデザインについてはコードや以下の著者のドキュメントが公開されている。
nonint.com
TorToiSeは別々に学習された5つのネットワークから成り立っている。

The Autoregressive Decoder


デコーダは話者の埋め込みネットワークとメインのデコーダからなる。

図の左側、話者埋め込みネットワークはカーネルサイズ3のConv1d x 2とattention block x 5からなるVision Transformerと似たアーキテクチャで、ターゲット話者の複数の発話を入力し、そこからconditionになる話者ベクトルを生成する。
入力はメルスペクトログラム。出力は複数入力の平均を扱う。

メインデコーダがTTSの根幹になる。
音声データセットのテキストからBPEを学習しテキストを256個のトークンに変換する。これは入力になる。
BPEはByte Pair Encodingで未知語に対応するために単語をより細かい単位に分割する。
tokenizerというライブラリを使っていそう。

音声(メルスペクトログラム)はVQVAEを使って8192個のトークンに変換する。これが出力になる。

アーキテクチャはtransformerのデコーダで構成。デコーダのみにしたのはencoder-decoderの形式にしたらスケール(深さや幅)したときに収束しなかったから。

Huggingface TransformersライブラリのGPT2モデルを複数モダリティ対応のため少し変更して利用。
最終的に30層で、各層は16のattention headで中間特徴は1024次元。パラメータ数は420Mくらい。

このモデルの前に小さいモデルも学習したがマルチボイスには能力が不足していたらしい。

入力は[話者埋め込み, テキストトークン, 音声トークン]をconcatしたもの。トークンにはそれぞれSTARTとSTOPが含まれる。
テキストトークンと音声トークンの両方を予測でき、音声トークンはテキストトークンと音声のSTARTトークンを与えることで予測出来る。
実際に利用するときはテキストトークンの予測部分は破棄し、音声トークンの予測部分のみを利用する。

問題もいくつかある。
テキストと音声がどう関係しているかの確率論的な話(よくわからない)。
デコードが困難。単純にデコードすると「uhhhhhhhhh」といった長く伸びたものが生成される(autoregressive decodingなので)。
これを解決するのが次のCLVP

Contrastive Language-Voice Pretraining (CLVP)


CLVPはデコーダの出力から生成した複数の音声トークン列候補とテキストトークン列の距離を計算する。
CLIPの音声版。

autoregressive decoderの出力からnucleus samplingし、それに対してCLVPを適用し候補を絞る。

CLVPは12層のattentionからなる(512次元の8head)。
これにより与えられたテキストから、それに最も近い音声トークン列を得られるようになった。

Contrastive Voice-Voice Pretraining(CVVP)

生成した音声の品質を高めるためのもの。
CLVPがテキストと音声を近づけるのに対して、CVVPは音声と音声を近づける。
同じ話者の異なる発話で学習した。

TorToiSeへの貢献は小さく、なくてもいいかも?。
定量評価できないけど定性評価的には効果あり(聴き比べたら違いがわかる)。

The Diffusion Decoder


音声トークンから音声波形にするのにメルスペクトログラムを介す。音声トークンは大きく圧縮されているので非常に難しいところ。
Diffusion modelを採用し、autoregressive decoderの出力(音声トークン)とターゲット話者の発話からメルスペクトログラムを生成する。
超解像モデルともいえるし生成モデルともいえる。

音声トークンは4層のattention blockと3つのattention/resnet blockで前処理が行われる。
これを"code"と呼ぶ

図の上の方はデコーダの話者埋め込みネットワークと同じようにでターゲット話者の発話を埋め込む。
埋め込みネットワークはautoregressiveとは別モデルを使用している様子。
これによって得られた特徴を"conditioning latent"と呼ぶ。

conditioning latentを使ってcodeをスケール・シフトする(AdaIN)。
スケール・シフトしたcodeと元のcodeにConv1dしたものconcatして再度Conv1dでチャンネル数を戻してdiffusion modelに入力する。
diffusion modelは最後の層がattentionのU-Net。

Vocoder

ここまででテキストと条件となる音声からメルスペクトログラムを生成できたので、それを音声波形に変換する必要がある。
ここではunivnetを採用した。univnetは高速で精度もwaveglowと同等レベルなので。

ただオープンソースのunivnetは24kHzで、TorToiSeは22kHzなのでNVIDIA tacotronのコードを利用したらしい。ちょっとよくわかっていない。

Why Use a Vocoder at All?

diffusion modelには音声波形を直接生成出来る能力があるのになぜVocoderを噛ませたのか?

時間をかけて色々実験した結果以下のことがわかった

  • U-Netで波形生成したら最終的に採用したアーキテクチャに比べパフォーマンスが落ちる
  • diffusionのU-Netの上位層のチャンネルが少なくなりパフォーマンスが落ちる(どういうこと?)
  • diffusionでのconvolutionのコストが高い
  • Vocoderはそれらに関してめっちゃ性能が良い

とのこと

System Level Description


システムをまとめると
1) テキストとターゲット話者の音声を入力し、音声トークンの確率を取得。nucleus samplingでトークン列候補を複数選出。
2) CLVPとCVVPでトークン列の候補を絞り、トークン列を選択
3) diffusion decoderでトークン列からメルスペクトログラムを生成
4) vocoderでメルスペクトログラムを音声波形に変換

データセットや学習

はじめに述べた通り学習方法については今の所公開予定はなし。
データセットは約50k時間のスピーチデータを使用。数エポックしか回していないのでunderfitしているかも(収束もまだ)。
話者は10kくらい(定量化できない)?
audiobookのもので、作者のお手製の音声認識でラベルをつけた?
データセットはアンバランスなので、生成が難しいものもある。

作者いわく

  • いい感じ正則化を導入すれば1桁少ないデータセットでも出来るのは?
  • 重要なのは多様な声を入力すること(難しいけど)

とのこと


データセットについても権利的な問題で、こちらは公開予定はしない。

所感

正直、英語だと聞いてもどれだけ性能が良いのかわからないがReddit等を見る感じかなり良いらしい。
他のZero-shot VC系論文で論文内での定量評価ではなく、デモやOSSのコードを触った結果の一般ユーザーの定性評価的に良いとされるものに関していくつか共通した特徴があると感じた(ここでは多くは語らないが)。

VQVAEは良さそうだけど学習が難しそう。どれだけ苦労したんだろうか。
直接音声を生成するよりはVocoderを介すのが良いというのは自分も感じた。やはりVocoderは優秀で、学習時にデノイジング等もすれば生成されたメルスペクトログラム等にもしっかり対応できる。

自分はTTSでのVCは直接しない派(別にTTSモデルとVCモデルを組み合わせればいい)なのでVCに興味があった。

話者特徴を足すのではなく、BERTとかのクラストークンのように頭に追加するのは思いつかなかった。どちらがいいのか。

学習方法等の説明は無いが、試行錯誤の記録等、有益な情報が多かった。