神野さんに言われました。

読者です 読者をやめる 読者になる 読者になる

神野さんに言われました。

AIの勉強をしています @sesenosannko

水瀬声質変換の日誌

思い出したように書き始めました。実際には3月15日あたりから音声分析ライブラリ周りを実装したりしました。

3月36日

SI-ASR部分の製作を継続。BLSTMは全く学習できなかった。おそらく実装にミスがあると思う。

ひとまず一方向のLSTMで学習をしてみる。1000×576の学習データで以下の結果。実際に適用すると精度が極めて悪いが、少なくとも母音や空白の場所程度はそこそこ認識している。BLSTMは本当に全く何も学習されなくて泣いていたので、少し安心した。以下、左が教師、右が出力。良いところだけ切り出したけど、認識が全くできていないところもある。

Epoch 40/40 576/576 [==============================] - 138s - loss: 1.1735 - acc: 0.6890 - val_loss: 0.7237 - val_acc: 0.8278

BATCH_SIZE = 64
MFCC_SIZE = 40
HIDDEN_SIZE = 64
PHONEME_SIZE = 36

model = Sequential()
model.add(LSTM(HIDDEN_SIZE, input_dim=MFCC_SIZE, \
                  return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(HIDDEN_SIZE, return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(HIDDEN_SIZE, return_sequences=True))
model.add(Dropout(0.3))
model.add(Dense(PHONEME_SIZE))
model.add(Activation('softmax'))

es = EarlyStopping(monitor='val_loss', patience=10, verbose=0, mode='auto')
mc = ModelCheckpoint('lstm/newmodel/weights{epoch:02d}.hdf5', \
                                      monitor='val_loss', save_best_only=False, \
                                      save_weights_only=False, mode='auto')

model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=EPOCHS, batch_size=BATCH_SIZE,\
               validation_data=[x_test, y_test], callbacks=[es, mc], shuffle=True)

学習が止まったわけでは無いので学習を継続したが大きな変化はなし。

f:id:sesenosannko:20170326172403p:plain

改善できる点

  • データは50分程度しか使っていないので増やす
  • ネットワークは適当に書いたので改善の余地はある
  • データ事前処理

提案論文では音素認識の精度は70%とされる。val_accは見た目上0.8を超えているが、データの空白を除いていないので空白で精度が稼がれているらしい。なんとも言えないが、この精度だと音声生成には使えそうに無いので改善したい。

データの事前処理は平均0.5標準偏差1にしている。これに関しては何もわからないが、[0, 1]に正規化している例が多くあるので試している。

import scipy.stats as sp trainmfcc = sp.stats.zscore(trainmfcc, axis=0, ddof=1)+0.5

3月27日

昨日、いろいろと論文を読んでLSTMの構成を考えていた。あとデータを増やしていた。ということで新しいものを試す。

変更点

  • データを100分に増やした
  • 1データ2000フレーム(10秒)にした
  • 中間層を128ノードにして1層増やした
  • Dropoutを最終層のみに適用した(どっかに書いてあった)
  • 一般的な標準化(平均0、分散1)にした

元のデータを検査したら長すぎる音声について音素セグメンテーションがうまくいっていないものがあったので取り除いた。

上記のネットワークの結果としてはval_accが最高で0.901を超えた。出力結果としてもそれほど悪く無いように見える。半分空白だとしても7割くらいの正答率は出ているのでは無いだろうか。そのあとにいろいろと試した結果、Dropoutは全層に0.3かけた方が少し改善してval_accは0.909になった。まぁ誤差かもしれない。

f:id:sesenosannko:20170327131552p:plain

それなりにまともに認識された部分。「けども」と発話されている部分の一部で、左が出力で右が教師データ。子音は難しいようで、無音(sil)や似ている子音に判定される場合が非常に多い。無音と母音で正答率が稼がれているように感じられる。ただ、「do」が「無音to」と誤判定されるのは理解できる気もするので音声生成のデータとしては許容範囲なのかな。実際、話者認識も言語モデルを用いなければ使い物にならないらしいので、単純な音素認識ではある程度限界はあるのだとおもう。

水瀬いのりさんの声で試してみた。訓練データよりも明らかに早口(コーパスは比較的丁寧に話しているので)ということもあるからか、認識精度が壊滅的。音声生成に使えるとは思えないなぁ・・・

3月28日

BLSTMに再挑戦する。前回はStatefulにこだわったため実装に失敗したが、単純なものならばKerasではlayer wrapperで直ぐに作ることが出来る。そして、val_accは0.927を超えた。驚異的だ。訓練データではかなり精度が良い。しかしやはり水瀬いのりさんの声では、前回よりは改善したとはいえ難がありそう。しかしこれ以上の向上には根本的な改善(データ量など)が必要そうなので、とりあえず現状で音声生成が可能なのかを試してみる。

そういえば、KerassのBidirectionalにはバグがあるので注意しないといけない。

音声生成部についてはほぼ論文のままの構造。つまり、音素認識がまともならば可能なはず。結果は以下のようになっていた。上が出力、下が元のMCEP。

f:id:sesenosannko:20170328182925p:plain

正直、音素認識があれだけ低質だったので、一応まともな出力がされたことには驚いた。しかし、音声合成をすると全然ダメ。

これが元の音声。

以下が出力。ターゲットは水瀬いのりさん。

いのりさん以前にほとんど声になっていない。すごく頑張れば分からないでもないが、ほぼ基本周波数でもこれくらいの精度は出る気がする。ただ、音質がひどいのはsptkの問題もあると思うので他の音声分析アプリを使うことも検討したい。

3月29日

直接スペクトル包絡を出力してworldで変換するという手法も試してみたが、精度が向上しなかった。とりあえずはsptkに賭けることにする。

次に、入力にlogF0を追加してみる。logF0に適したMCEPを出力してくれるとありがたい。情報量としては大きいはず。logF0は平均と分散を水瀬いのりさんと合わせるだけなので、他の人からの変換時にももちろん入力することが出来る。logF0+PPGsで入力は37次元となる。logF0は水瀬いのりさんに平均と分散を合わせた上で、平均0標準偏差1に標準化する。

実は前回のlossが保存されていなかった。だからどれくらい改善されたのか数値ではわからない。頭が悪い。明確な改善とは言えないまでも形は良く再現されているように見られるが、平均も分散も合っていない。出力(教師データ)については良く分からなかったので標準化していないが、標準化が必要かもしれない。

f:id:sesenosannko:20170329234826p:plain

f:id:sesenosannko:20170329170333p:plain

まず、波形の再現度を確認するために平均と分散を無理やり合わせてみた。声質変換としてはあまり参考にならないが、以下のようになんとか水瀬いのりさんと判定できるような声になった。これ以上の精度は音素認識やデータ量の問題とかだと思うので、当面の目標はこれになりそう。

3月30日

出力の標準化をした。しかし、分散はやはり小さいままであった。そのため、無理やりで良くない手法ではあるが、出力結果について再度分散を1に変換した上で標準化の逆変換をすることにより分散を強制的に合わせることにした。どのような出力についても同じ変換をしている割には、波形を見るとうまくいっているように見える。

f:id:sesenosannko:20170330172950p:plain

水瀬さんの声を入力してみると、昨日の手動で合わせるものよりも良く再合成されている。これは出力の標準化によって精度が上がったと考えられる。というのも、出力(目標)を変えてしまうと誤差の値が変わってしまうので数値的には向上したのかが良く分からない。そして、子音がかなり変わってしまっているので、音素認識にも大きな問題があるということがわかってきた。後半の内容が支離滅裂。

f:id:sesenosannko:20170330171713p:plain

そして、これを使って変換した結果がこちら。上は僕の声。

合成音感や子音の精度の悪さが目立つが、言われれば水瀬いのりさんの声のようにも感じるのではないでしょうか?音声の課題では作っている人は音がそもそも出ない段階から聞いているから出力への評価が甘々になり、最終結果を他の人に聞かせると微妙な反応をされるというのはあるあるらしいので悲しいところですが。

疲れたし、学校が始まってしまうのでここで一区切りをつけることにする。