Monthly Hacker's Blog

プログラミングや機械学習の記事を中心に書きます。

ClariNetの再現実装で得たParallel WaveNetのノウハウをまとめてみた。

できること

この記事では、次のことができるようになります。

  • Parallel WaveNetを使ったメルスペクトログラムボコーダーの学習

はじめに

こんにちは、dhgrsです。声優統計コーパスはいろいろと試行錯誤しているのですが、なかなかうまく行かないところが多く、停滞気味です。代わりと言ってはなんですが、ClariNetの再現実装をして得られたノウハウをまとめてみようと思います。
一応こちらの記事の姉妹記事ということで、初めてParallel WaveNetを扱う方(深層学習に詳しくない音声合成研究者/音声合成に詳しくない深層学習研究者)に向けた記事ということにしますが、どちらかというと音声合成に詳しくない深層学習研究者寄りかもしれません。

ソースコードはこちら。(starもお待ちしています)
github.com

デモ音源はこちら。(記事中にも同じ音源があります)



ClariNetとは

[1807.07281] ClariNet: Parallel Wave Generation in End-to-End Text-to-Speech

Baiduから出たTTS(Text-to-Speech)の論文です。この論文の中では、主に3つの手法が紹介されています。

  • Autoregressive WaveNet
  • Student Gaussian IAF
  • Text-to-Wave Model

このうち、一番下のText-to-Wave Modelは実装していない(予定もない)ので、簡単な解説のみですが、他2つは簡単な解説と実験する際のコツを紹介していきます。

Autoregressive WaveNet

こちらはStudent Gaussian IAFを学習させるための準備です。解説に入る前に、WaveNetとParallel WaveNetの違いを簡単に説明します。
WaveNetは高品質な音声を合成できるが、合成に時間が掛かるという欠点がありました。それはautoregressive(自己回帰)で1サンプルずつ波形を計算するからで、24kHzの音源を1秒合成するためにはWaveNetを24000回フォワード演算しなければいけないので、時間が掛かるわけです。以降、この普通のWaveNetをAutoregressive WaveNetと呼びます。

一方で、Parallel WaveNetでは波形のすべてのサンプルをparallel(並列)に計算してしまいます。WaveNetのフォワード演算は1回で済むので、私の使っている1080Tiでもリアルタイム合成(ここではn秒の音声を合成するのに掛かる時間がn秒以下という意味で使っています)が可能です。

詳しくは以前ICML2018読み会で発表した際のスライドをご覧ください。

www.slideshare.net

Parallel WaveNetには弱点があって、学習が難しいです。その理由はスライドの28ページ(と29ページ)に書いています。混合ロジスティック分布(Autoregressive WaveNetの出力)とロジスティック分布(Parallel WaveNetの出力)の交差エントロピーを最小化したいのですが、解析的に求められないので近似で代用しています。ClariNetはここに目を付けました。正規分布と正規分布の交差エントロピーなら解析的に求められるので近似がいらなくてみんなハッピーです。そこでAutoregressive WaveNetの章では、出力を従来の混合ロジスティック分布から正規分布に変えても学習がうまくいくことを示しています。こちらは自分で学習させたサンプルです。

注意点ですが、Parallel WaveNetのオリジナル論文では、学習がしやすいようにロスの計算時に波形を127.5倍していると書かれていました。ClariNetではこのスケーリングの有無が明記されていないものの、学習結果の正規分布のスケールの値が載っていて、こちらを見る限り127.5倍はしていないようです。また、オリジナルに比べてかなり小さいネットワークを使っています。そのため学習も1GPUで3日程度で終わります。(間隔が麻痺している気がする...)

Student Gaussian IAF

ClariNet独自の呼び方をしていますが、要はParallel WaveNetのことです。Parallel WaveNetは、(オリジナル論文に明記されているわけではなく個人的な解釈でが)合成した音声でAutoregressive WaveNetの損失関数を計算して、その値が小さくなるようにすることが発想の元です。しかし、これが意外と難しいのです。具体例としてホワイトノイズの合成を考えてみます。
ホワイトノイズも広義狭義と色々あるようですが、ここでは、すべてのサンプルが独立で同じスケールで、平均0の正規分布に従う波形とします。では、この条件のもと尤もホワイトノイズらしい波形は何かというと無音です。これは直感に反するので、確認してみましょう。まずすべてのサンプルが独立としたので、ある1サンプルについてのみ考えれば、同様の議論がすべてのサンプルについても言えます。ここで、ある1サンプルは平均0の正規分布に従うため、尤もらしい値は0です。これがすべてのサンプルについて言えるため、尤もホワイトノイズらしい波形は全サンプルが0の無音であると言えるわけです。

ホワイトノイズは極端な例のようですが、実際にParallel WaveNetを出力分布だけで学習させると無音あるいは小声になることが論文でも再現実装でも分かっています。つまり実データでも似た現象は十分にあり得るということです。そこでParallel WaveNetではオリジナルでもClariNetでも、スペクトログラムを使って損失関数を計算しています。この損失関数は再現実装をするうえでかなり重要です。

個人的な直感では、人の聴覚スケールにある程度寄せたlogスケールでスペクトログラムを計算したほうが良いと思っていましたが、それだと学習がうまくいきません。STFTして得られた複素数スペクトログラムの絶対値を取ると学習が安定しました。ClariNetの論文にも書いてあります。最初は結構納得がいっていなかったのですが、あくまでスペクトログラムは無音や小声を避けるためのもので、メインの学習はAutoregressive WaveNetとParallel WaveNetの出力の交差エントロピーを小さくすると考えると個人的にはすっきりしました。

また学習時の注意点ですが、学習が不安定です。何かあるとすぐNaNです。Gradient clippingや損失関数を閾値でclippingしてやるとマシになります。この辺りは僕ももう少し知見を集めたいと思っているところです。

ではここで再現実装のサンプルを。

ちょっとノイジーで低音質ですね。issueでも指摘されています。
github.com

気を遣っていただいて"a bit robotic"なんて表現してもらいましたが、a bitじゃないですね。しかし2つの後処理を入れたところ、かなり音質が改善しました。後処理を入れた結果がこちらです。

  • 分散の不使用
    • Parallel WaveNetの出力は正規分布なので平均と分散がありますが、この分散がノイズの原因になっている気がしたため、思い切って使っていません。平均をそのまま出力しています。
  • 音量が小さい部分を無音化
    • 無音であって欲しいところに小さいノイズが入っていたので、音量の閾値を適当にとって閾値以下の区間を無音で置き換えました。librosaの関数を使っています。
    • librosa.effects.split — librosa 0.6.2 documentation

WaveNetならもう少し高音質を目指せそうですが、

  • Exponential Moving Average
  • Autoregressive WaveNetとParallel WaveNetで同じデータセットを使う

という工夫を入れれば十分な音質になると思っています。Exponential Moving Averageは僕の別のWaveNet系リポジトリでは実装済みなので、導入は簡単かと思います。PRお待ちしています。
参考: GitHub - dhgrs/chainer-Fast-WaveNet: A Chainer implementation of Fast WaveNet(mel-spectrogram vocoder).

データセットの件ですが、最初は複数話者でやろうと思ってAutoregressive WaveNetを学習したのですが、Parallel WaveNetの学習が複数話者だと難しく、Autoregressive WaveNetを単一話者でやり直すのが面倒だったというだけの理由です。Issueを見ているとzuzana氏が両方単一話者で学習したようですので、近いうちにこちらの問題は解消するかもしれません。

Text-to-Wave Model

再現実装をしていないパートなのでさらっと。Tacotron2やDeep Voice3はメルスペクトログラムを予測するモデル(Attentionベース、以降encoderと呼ぶ)と、予測したメルスペクトログラムから波形を作るモデル(WaveNet)の2つに分かれています。学習時はgrand truthのメルスペクトログラムを使って、合成時は予測したメルスペクトログラムを使っていて、学習時と合成時に差が出てきてしまうという問題がありました。

ClariNetでは、encoderの中間層をWaveNetに直接入力すれば、学習時と合成時の差分が減らせるという発想の元、Text-to-Wave Modelを提案しています。ただし、そのままだと時間解像度やチャンネル数が合わないため、間にBridge Netというネットワークをかましています。これらの工夫により、音質が向上したようです。

さいごに

最近ようやくGoogleやBaidu以外からもWaveNet系の論文が出てくるようになって面白くなってきました。それでもParallel WaveNet系はまだあまり活発ではない気がしてます。この記事や実装が、少しでも音声合成分野の発展に役立ってくれれば幸いです。