かわいい声を目指して、ディープラーニングを使って声質変換する話
先駆者様 -> http://blog.hiroshiba.jp/became-yuduki-yukari-with-cycle-gan-power/
この記事は先駆者であるヒホ様(@hiho_karuta)から多大なるインスパイアを受けています。
目的
- 声をかわいくする。
- 既存の声質変換のモデルの性能を向上させる。
- できるだけ導入に楽をする
かわいい声とは?
個人的に結月ゆかりとかがいいかなと思ったのでそこで頑張る。
(将来的には声優さんの声に変換してみたい。)
結果から
結構結月ゆかりなのでは? pic.twitter.com/dfKYjppRjg
— NEXT_GENERATION (@nec_gene) 2018年12月22日
では具体的な話
ソースコードはこちら
##大まかに
-
ベースはCycleGAN(Generative Adversarial Network)を使います。
-
構造はresnet型で、64のフィルターで統一します。resnetは4ブロックでGLU構造を用います。複数の構造で実験してみた結果、この構造になりました。
-
変換の際にWORLDという音声分析変換合成システムを用いています。今回はpyworldライブラリをお借りします。
##データについて
学習させるデータは、以下のように意味づけしました。
- 音素を2つ並べた音素連鎖を日本語の範囲で全種類網羅した音声
音素は、言葉の発声するときの最小単位です。端的に言えばローマ字に直した時の文字に当たります。
しかし、人間は発声するとき口を動かします。動かす中間の音は音素では表現することができません。”柿(kaki)”と発音するときと”菓子(kasi)”と発音するときの"a"の口の動きは違うことから、微妙な音の違いが発生していると考えられます。
なので、文章を朗読する上で発生しうる2音素の列を全て網羅すればそれで充分なのではないかという予測に基づいています。”柿(kaki)”ならば、[-k,ka,ak,ki,i-]のように解釈します。(-は空白文字)
読み上げた文章は自作です。と、いうのもATR503文は文章的に長い(収録すると10分ぐらいになる)ので自作しました。(作り始めたときに存在を知らなかったなんて言えない。)
ちなみに怪文章になっています。
音声の合計時間は、11分47秒(自分:4分52秒、結月ゆかり:6分55秒)で全て16kHzです。
###Generatorネットワーク
生成側ネットワークです。(NHWCで表記)
入力:(1,52,1,513)
出力:(1,52,1,513)
前処理としてdio,stonemask,cheaptrick,d4cを使ってピッチ、スペクトラム包絡、非周期信号を取り出しますが入力はスペクトラム包絡のみです。
学習時は4096サンプルずつシフトして、等倍速と4倍速のスペクトラム包絡を使います。
推論時は4096サンプルのスペクトラム包絡を”そのまま”突っ込みます。
周波数軸はチャンネルとして扱います。
詳しい構造はソースコードをご覧ください。
###Discriminatorネットワーク
判定側ネットワークです。(NHWCで表記)
入力:(1,17,513,1)
出力:(1,17,1,3)
学習はGの更新前に1回行います。CycleGANの論文では、2つネットワークを用意していましたが今回は1つに統一しました。と、いうのも各ドメイン情報よりも"違い"を知っていたほうがGeneratorへの伝播が詳細になるという仮定に基づいています。
なお、今回はバッチノーマライゼーション層を避けたので、4種類の音声を1つのミニバッチとして扱います。そして、平均化対策として損失関数を4倍します。
また、こちらでは周波数軸を横軸として取ります。チャンネル方向にとると時間がかかる割に性能は向上しません。
##損失関数について
GANの損失関数にsoftmax_crossentropyを使います。
Cycleの損失関数はL2ノルムを使用します。
重みはGAN:CYCLE=1:100です。
##Optimizerについて
Adam
学習率:
4e-6 (0.001や2e-4も実験で試しましたが、崩壊を招くので不採用)
ベータの値:
0.5
学習はGTX1070で、2時間弱です。(100000イテレーション時)
##最後に
仕事をください。