Nvidia mellotron で日本語マルチ話者転移学習をやってみた。

「自分の好きな声優さんの音声合成作りたいなー」という純粋な欲望により最近音声合成について調べている者です。
#音声合成ってTacotron2でやるもんじゃないの？
[npaka](https://note.com/npaka)さんの[NVIDIA/tacotron2 で日本語の音声合成を試す (3) - つくよみちゃんコーパスで学習](https://note.com/npaka/n/n8c94da051c68)という記事を参考に、[某ツンデレ系声優さんの音声合成](https://www.nicovideo.jp/watch/sm38698439)を作ってみたのですが、転移学習といえどデータが少なすぎるため、どうしてもイントネーションがうまくいかないことが多かったんですよね...。
そこで調べてみるとnvidiaの[mellotron](https://github.com/NVIDIA/mellotron)だと**「ピッチ調整が可能で、マルチ話者対応のモデルが学習できるよ！」**[という情報](https://tosaka-mn.hatenablog.com/entry/2020/04/29/160050)を入手したので、「お、これで上手いことやれるんじゃね」って感じで今回の記事を書くに至るわけです。

私がmellotronで日本語学習したモデルを試せるgoogle colaboratryのサンプルコードを用意しました。
https://drive.google.com/file/d/1n6HTRWhXk1rpO35sN36TOCV0w3Thspr4/view?usp=sharing
試すには以下のセクションをすべて実行してください。

- ワークスペースの設定
- 環境構築
- 推論
 - 録音する場合
 - 学習済みモデルを読み込み、推論する
 - 生成音声
 
「録音する場合」のセクションの中に「録音」というセクションがあります。そこでテキスト入力とマイク入力を求められるので適宜操作を行ってください。
#学習について
**2段階で転移学習**
[npakaさんのTacotron2日本語学習](https://note.com/npaka/n/n8c94da051c68)での学習の流れを汲んで2段階に分けて学習を行いました。

1. 英語学習済みモデルからJSUT+JVSコーパスを用いて転移学習
2. 日本語転移学習モデルから目的話者+JSUT+JVSで転移学習

**実行環境**
OS : Ubuntu 20.4
GPU : GTX 1080 8GB

colabでやろうかと思ったんですが、

- データセットが結構でかくて(5.3GB)ドライブの容量が足らない
- なんやかんやランタイムが切断されて学習実行しなおしとかがめんどくさい
- 「Linuxの勉強がてらローカル環境で学習やってみるか。」

等の理由から、ローカルでやりました。

ローカルでの環境構築やらなんやらは、気が向いたら追記するかもしれませんが、今は書きません。

####1.英語から日本語の転移学習
**データセット**
データセットはJSUTコーパスとJVSコーパスの二つを合わせた22693文を使用しました。
22693のうち、17693を教師データ、5000をテストデータとしました。
[mellotronのcolabサンプルコード](https://colab.research.google.com/github/yhgon/mellotron/blob/master/inference_colab.ipynb)から必要な部分を抜粋してきて、データセットの部分を差し替えた形で実行しました。
mellotronように音声データやテキストファイルの整形をする必要があるのですが、[npakaさんの記事](https://note.com/npaka/n/n8c94da051c68)からその部分を抜き出し、JSUTとJVSに対応する形に改造して使いました。

この時ちょっと厄介だったのが、

- JSUTのテキストファイル名が「transcript_utf8.txt」なのに対して、JVSのテキストファイル名が「transcript **s** _utf8.txt」だったのでエラー吐かれた
- JVSの**テキストファイルに書かれているのに、音声ファイルがない**部分がある
- JSUTにもJVSにも**全く同じ音声ファイル名のデータ**(BASIC5000_xxxx.wav)があり、それぞれ話者が違う

といった学習以外の部分で手間取ってしまう要素が含まれてたことですね...。

**学習のパラメータ**
基本的にmellotronのサンプルコードそのままの値を使用しています。  
変更した個所は

- text_cleaner = "basic_cleaner"
- batch_size=4

の二つです。  
batch_sizeが小さすぎるという指摘があるかと思いますが、32だとGPUメモリ8GBでは足りなかったため4まで落としました。
**学習ステップ数**
batchが4なのであまりあてにならない気もしますが、22500ステップ学習させました。
このステップ数に特に意味はなくて、大体半日くらい回して打ち切ったときの数字というだけです。  

このモデルで生成した音声を聞く限り、まだ学習が足りない感じがしたので10万ステップ前後くらいは必要なのかなと思いました。

####2. 日本語モデルから目的話者への転移学習
**データセット**
1.のモデルを読み込んで、目的話者データを追加した22693+594文で学習。
22963+594のうち、17696+594を教師データ、5000+594をテストデータとしました。

**学習のパラメータ**
1.と同じく

- text_cleaner = "basic_cleaner"
- batch_size = 4

です。

**学習ステップ数**
日本語転移学習の時にステップ数が足りてないと感じたので、SSDの空き容量と相談して

- checkpoint = 1500
- ステップ数 81000
- 途中経過セーブデータ54個(約20GB)

となりました。

#結果
**「声の特徴をとらえた日本語が聞き取れる程度の音声」**
という品質でした。
ちゃんと発音できてない箇所があったり、全体的にエフェクターをかけたような、いわゆる「ケロケロボイス」のような仕上がりになった。

発音がうまくいってない箇所については、ピッチを少し変えてやると発音できるようになったりしたので、その話者の得意な音域に合わせてやると改善されるっぽい。

ケロケロ感については、学習不足なのか、データ不足なのか、ボコーダの品質なのか、あまり見当がついていないので、有識者の方がいらっしゃったらぜひご教授願いたい...。
#今後
ステップ数を増やして学習を進めている間に、[シロワニさんの機械学習ブログ](https://shirowanisan.com/)や[ESPNet](https://qiita.com/kan-bayashi/items/536acaf165344a6d6460)について調べて、品質の改善をしていこうと思ってます。
#参考
https://note.com/npaka/n/n8c94da051c68
https://github.com/NVIDIA/mellotron
https://tosaka-mn.hatenablog.com/entry/2020/04/29/160050
https://shirowanisan.com/
https://qiita.com/kan-bayashi/items/536acaf165344a6d6460
https://qiita.com/K2_ML/items/2804594454b39180c909