lispmeetup #45 common lispで音声合成
TRANSCRIPT
これまでの発表
● #29: 線形分類器cl-online-learningの実装
– http://www.slideshare.net/masatoi0/lispmeetup29-c
lonlinelearning
● #39: ディープラーニング用ライブラリMGLの紹介
– http://www.slideshare.net/masatoi0/lispmeetup-39
-mgl
今回の目標
● ディープラーニングの応用として音声合成(テキスト読
み上げ)を試みる → 未完!
– ここまでの成果物: https://github.com/masatoi/cljtalk
● DNN音声合成の全体の流れを把握する
– Common Lispで実装するために必要な道具を揃える
● 音素アライメント → Julius、segmentation-kit
● 音声分析合成 → WORLD、cl-libworld
● メル周波数ケプストラム(MFCC) → libfftw3
色々なTTSシステム
● 波形接続型音声合成 (VOICEROID (結月ゆかり etc))
– 小さい音声の素片を連結して合成する
● 統計的音声合成
– HMM (CeVIO (さとうささら etc)、 Open JTalk)
● HMM(隠れマルコフモデル)を使うもの
– DNN
● 単純なFFNNを音声に適用 (簡単!)
– LSTM-RNN (Googleテキスト読み上げ)
● 再帰型ニューラルネット
– Wavenet (DeepMind) ← new!
色々なTTSシステム
● 統計的音声合成
– HMM
– DNN
– LSTM-RNN
– Wavenet
● ボコーダーを介さず直接音声を予測する
● 畳み込みニューラルネットで自己回帰(自分の予測を入力の一
部として与える)
● ボコーダーを使う
生の音声ではなく、音声を少数のパラメータに変換してそれを予測する
再合成時に劣化する
ボコーダー(音声分析合成)
● 生の音声からパラメータを取り出したり再合成したりする
● WORLD
– C++の音声分析合成ライブラリ
● cl-libworld
– https://github.com/masatoi/cl-libworld
– Common Lisp用のラッパーをCFFIで実装した
– WORLDのコードを丸抱えして、require時にLakeでビルドする
メル周波数ケプストラム
● 離散コサイン変換(DCT)する
– 低周波帯に情報が集まる
● 上の方は切ってもいい! → 13次元でカット
● ここまでやったもの: メル周波数ケプストラム係数(MFCC)
– DCTはCのライブラリFFTWを使う(CFFIでラップ)
DCT DCTの逆変換
入力データを作る
● 音素アライメント
– テキストデータと音声から音素の開始時間と終了時間を
推定する
– Juliusのsegmentation-kitが使える
0.0000000 0.0925000 silB0.0925000 0.2625000 a0.2625000 0.4125000 i0.4125000 0.5225000 u0.5225000 0.5825000 e0.5825000 0.7525000 o0.7525000 0.7825000 silE
あいうえお
入力データを作る
● 音素アライメント
– テキストデータと音声から音素の開始時間と終了時間を
推定する
0.0000000 0.0925000 silB0.0925000 0.2625000 a0.2625000 0.4125000 i0.4125000 0.5225000 u0.5225000 0.5825000 e0.5825000 0.7525000 o0.7525000 0.7825000 silE
入力データを作る
● 音素をフレームに割り当てる
– 一つのフレーム毎の特徴量
● どの音素に属しているか? → 38次元のバイナリ特徴
● その音素の継続時間(duration) 1→ 次元の実数
● その音素が割り当てられているフレームの中で何番目か
→ 1次元の整数
DNNの構造
“Deep Learning in Speech Synthesis” [H.Zen, 2013]
T個のフレームの特徴量を一列に並べてDNNの入出力とする
MGLとは
● Common Lisp用の機械学習ライブラリ
● ディープラーニングの割と最近の手法までカバー
● MGL-MATという行列演算ライブラリを使う
– cl-cuda、LLA(Lisp Linear Algebra)によって高速化
● cl-cudaがQuicklispに入ったことによりMGL-MATもQuicklispから入
るようになった!
MGLで回帰問題を解く
● 回帰のやり方はドキュメントが無いのでMGLのソースと格闘する
● まず簡単な2次元→1次元の関数を近似する
元の関数 近似結果
(defun rastrigin (xlist) (let ((n (length xlist))) (+ (* 10 n) (loop for xi in xlist summing
( (* xi xi) (* 10 (cos (* 2 pi xi))))))))
MGLで回帰問題を解く
● build-fnnマクロでネットワークの構造を指定してオブジェクトを生成
– 入力層2次元、1200次元の隠れ層が3層、出力層1次元
– 隠れ層の活性化関数はReLU、出力層の活性化関数は恒等写像、誤差関数は
二乗誤差
(defparameter fnnregression (buildfnn (:class 'regressionfnn :maxnstripes 100) ; バッチサイズ100 ;; Input Layer 2次元 (inputs (>input :size 2)) (f1activations (>activation inputs :name 'f1 :size 1200)) (f1 (>relu f1activations)) (f2activations (>activation f1 :name 'f2 :size 1200)) (f2 (>relu f2activations)) (f3activations (>activation f2 :name 'f3 :size 1200)) (f3 (>relu f3activations)) (predictionactivations (>activation f3 :name 'prediction :size 1)) ;; Output Lump: squareddifference 1→ 次元 (prediction (>loss (>squareddifference (activationsoutput predictionactivations) (>input :name 'targets :size 1)) :name 'prediction))))
DNN音声合成のためのモデルを作る
● 一度にDNNに与えるフレーム数Tを20とする
● 入力40*20=800次元、出力19*20=380次元
● しかしこれで学習してみると数値計算エラー!
(defparameter fnn (buildfnn (:class 'regressionfnn :maxnstripes 100) ;; Input Layer (inputs (>input :size 800)) (f1activations (>activation inputs :name 'f1 :size 512)) (f1 (>relu f1activations)) (f2activations (>activation f1 :name 'f2 :size 512)) (f2 (>relu f2activations)) (f3activations (>activation f2 :name 'f3 :size 512)) (f3 (>relu f3activations)) (predictionactivations (>activation f3 :name 'prediction :size 380)) ;; Output Lump: >squareddifference (prediction (>loss (>squareddifference (activationsoutput predictionactivations) (>input :name 'targets :size 380)) :name 'prediction))))