- 投稿日:2019-10-11T15:07:20+09:00
PyTorch/TensorFlow で書かれた音声スピーチ系ネットワークを C++ でモバイルで推論するためのメモ
背景
PyTorch/TensorFlow で書かれた音声スピーチ系ネットワーク(e.g. Tacotron, FastSpeech)をモバイルで推論したい.
TensorFlow-Lite などでは RNN 系などの対応が十分ではないので変換がうまくいかない.
(少なくとも TensorFlow tacotron は .pb から toco での変換は r1.14 時点では失敗する)libtensorflow を使う手もあるが, やりたいことに対して無駄が多すぎるし, ビルドも手間であり, また libtensorflow は Android には正式対応していない(モバイルでのオフィシャルな対応は tensorflow-lite に移行したっぽい)
libtorch もなかなかうまくいかない(ScriptModule で記述しても一部変換できない op がある)
tvm などの他のモバイル推論に特化したライブラリでも, RNN 系や音声系の対応は(2019 年 9 月時点)行われていないか, 非常に限られた対応となっている.
多少演算に時間がかかったとしても, モバイルで動かしたい.
Tacotron 系
T.B.W.
Transformer 系
使っているネットワーク op はそれほど多いわけではない.
たとえば, PyTorch 実装の FastSpeech(Transformer TTS) https://github.com/xcmyz/FastSpeech では, pytorch の op は
- torch.bmm(batch matmul)
- nn.Softmax
- nn.Conv1d
- nn.Linear
- nn.Dropout
- nn.LayerNorm
- nn.Embedding
- nn.ModuleList
あたりくらいしか使っていない.
waveglow を CUDA だけ(cuDNN は使っているが)で動かしていたりする既存の取り組みがある.
https://github.com/Saurabh-29/Waveglow_Inference_in_CUDA
=> C++ で自作したい!
PyTorch
推論(forward, inference)についての実装です.
torch.bmm
https://pytorch.org/docs/stable/torch.html#torch.bmm
行列をまとめて matmul すれば OK
nn.SoftMax, nn.Conv1d, nn.Linear
通常の NN のように実装すればよい. 特に特殊なことはなし.
nn.Embedding
https://pytorch.org/tutorials/beginner/nlp/word_embeddings_tutorial.html
word embedding などに使われる.
実装としては, int の配列(
[x]
)と重み行列(W
)を受け取り, float の配列(2 次元行列)を返す.一番簡単なのは,
W[x]
な感じで配列ルックアップする.重み行列が大きく, データが sparse な場合は
std::unordered_map
などを使ってルックアップするといいかも?(GPU で動かす場合はハッシュ or 二分木探索とか?)Chainer では
EmbedID
https://docs.chainer.org/en/stable/reference/generated/chainer.links.EmbedID.html に相当. ちなみに Chainer ではinitialW
が与えられなかった場合, 正規分布の乱数で weight 行列を初期化している.nn.Dropout
推論の場合はなにもしない(input をそのまま返す)
参考までに, dropout を実装したい場合は,
Chainer と TensorFlow の Dropout 実装メモ
https://qiita.com/syoyo/items/8b459cc5524eff6f54f3を参考に実装する. PyTorch(ATen での実装) はノイズ(乱数)にベルヌーイ分布を使っている.
nn.LayerNorm
https://pytorch.org/docs/stable/nn.html#torch.nn.LayerNorm
Aten に CPU 実装があるのでそれを参考に推論を実装.
特段特殊なことはしていない.nn.ModuleList
Module(op)をリストで保持できるようにしたもの.
MultiHeadAttension など
pytorch には
nn.MultiheadAttention
が 1.2 からあります(nn.Transformer
も 1.2 から導入). 必要に応じて参考にしましょう.https://pytorch.org/docs/master/nn.html#multiheadattention
その他
音声系は, ニューラルネットワークモジュールのほかにも, text の処理や wav の処理, fft などいろいろ周辺のコードも必要です.
librosa 相当や, FFT 処理
https://github.com/lighttransport/nanosnap
nanosnap にご期待ください.
stft
,mfcc
などがあります.
(少なくとも現時点で Tacotron のモバイル実行で必要なものはあるはず)wav 入出力
nanosnap か, nanosnap でも使っている dr_wav がおすすめ.
https://github.com/mackron/dr_libs
inflect
inflect の C++ 実装がほしい(とくに
number_to_words
)https://github.com/syoyo/tacotron-tts-cpp/tree/master/experiment/number_to_words
ご期待ください.
PyTorch のメモ
nn.init.normal_
など, アンダースコアで終わっている関数は in-place 関数.
PyTorch では in-place 関数の利用は推奨されないが, 乱数などでウェイトを初期化したいときとかは in-place 便利.What does the underscore suffix in PyTorch functions mean?
https://stackoverflow.com/questions/52920098/what-does-the-underscore-suffix-in-pytorch-functions-mean参考文献
その他参考になる文献です.
作って理解する Transformer / Attention
https://qiita.com/halhorn/items/c91497522be27bde17ceTODO
- AMDGraphX あたりでよろしく演算グラフを quantize して最適化する(https://github.com/ROCmSoftwarePlatform/AMDMIGraphX/wiki/Getting-started:-using-the-new-features-of-MIGraphX-0.4#bert-natural-language-processing-nlp-model)
- Torch model から直接 C++ コードを吐くのはどうか?
- chainer2tflite の参考 : https://qiita.com/syoyo/items/e84d66b2a938843c1594
- Torch JIT やら onnx に吐いてから変換は RNN 系が自動展開されてしまうのでうまくいかなさそう(すくなくとも torch jit はダメだった)