ディープラーニングでコード進行認識(2)

前回は音楽データを等間隔に分割して、一つずつラベル付けするだけのシステムを書きました。あの後DNNのハイパーパラメータを色々いじってみたのですが結局ラベル正解率は70%止まり(訓練・テストセット固定なんで厳密ではありませんが)。

だいたい1024サンプル(1/20秒くらい)の音声の欠片のみで分類しようというのがあまり合理的なやりかたではないので、70%はすでにたいへん頑張った結果と言えるでしょう。そもそもこんなちっぽけな情報量をディープに掘って何が出てくるのかと思うので、単体のDNNでは、これくらいが限界と考えてもいいでしょう。

元論文では、最後の隠れ層の出力をmean-variance poolingして、更に新たなDNNに投入したと書いています。これにより正解率が10%ほど上がっています。広い範囲の情報を一つにまとめて分類したいので、たぶんこのpoolingがキーになると思われますが、ちょっとやり方が分からないので後回し。

今回まずは欠けていたもう片方、すなわちラベル系列そのものの出現確率を教えてくれる「言語モデル」を作ってみます。

伝統的な手法では、HMMの状態遷移確率でモデル化してきたのですが、HMMはラベル系列がマルコフ性を持つと仮定しています。しかしこの仮定はちょっとキツすぎるのではないか、ということで、音声認識も含めて、言語モデルに回帰結合型ネットワーク(RNN)が使われてきています。

RNNはHMMを一般化したもの、とも言われていますが、とにかく前の隠れ層の出力も自分の入力に使う、というからくりで、過去のラベル系列全体が次のラベルの出力確率を影響します。

というわけで簡単なRNNをぱぱっと実装。ここでは、Chainerのチュートリアルを参考に、Long-Short Time Memory(LSTM)ユニットでできた隠れ層が一つある、シンプルなRNNを試してみます。

このモデルに、ビートルズ曲のコード進行(フレーム単位に分割したラベル系列)をぽいっと放り込んで学習させます。普通のMLPのように、誤差関数にsoftmax-crossentropyを使って、SGDで最適化できます。

入力と期待出力は同じラベル(25次元の01ベクトル)なので、教師なし学習な感じですね。

これで、とあるラベル系列について、その出力確率を教えてくれるモデルが出来上がりました。具体的には、ラベル系列を放り込んで、出力層をsoftmaxで活性化すれば、次のラベルの出力確率分布を得ることができます。

さて、このRNNと前述のDNNを組み合わせるには、どうすればいいでしょう。HMM時代の考え方と同じですね。

RNNはラベル系列そのものの確率、DNNは特徴ベクトル系列が与えられた場合の、ラベル系列の事後確率を教えてくれるので、時系列分類の枠組みに沿えば、二つの積を最大化する系列を探索する事になります。

RNNの最尤系列探索には、ビーム探索というアルゴリズムが使われているようです。ざっくり言うと探索の途中で低確率のルートを次々と枝刈りしてゆく(一定数のルートしか残さない)幅優先探索、って感じかな?

前回言及した論文では、Hashed Beam-searchという独自方法が提案されていたのですが、ちょっと複雑そうだったので、この論文を参考して動的計算法版のビーム探索を実装しました。

Bengio Y. et al. Audio Chord Recognition with Recurrent Neural Networks

この論文は深層信念ネットワークを使って特徴学習をしていますね。注目すべき違いは、このRNNは特徴量を入力として教師あり学習をしてるところです。この手法も、試してみていいと思いますね。

更に、RNNが有用か確かめるため、比較用にHMMを言語モデルとするものも作りました。遷移確率はラベル系列から統計し、DNNの出力を各状態の出力確率として、Viterbi探索するものです。

さて、どれだけ良くなるのか見てみましょう。

DNN単体の正解率:71.2%

DNN+HMMの正解率:80.8%

DNN+RNNの正解率:81.1%

RNNのハイパーパラメータをちょっといじってみたりもしましたがだいたい80%ちょっとという結果。

HMMとだいぶ同じという結果に。複数回学習させましたが80%~82%で揺れてる感じでした。単純なRNNだけでは良くならないということでしょうか。

考えられる原因は、フレーム単位でラベルを分割してるので、ラベル(コード)が変わらない確率だけ圧倒的に高くなってコード変化の性質が隠れてしまったこと。HMMもRNNも、ただのローパスに近い仕事しかしてない可能性があります。

しかもRNNの方は、認識にかかる時間が遅い。超遅い。たぶんリアルタイムの5倍くらいの時間がかかっています。それに比べてHMMは圧倒的に速い(1秒に4曲ほど)。

ビーム探索に使われていた優先度つきキューは、(Tupleを保存する為標準ライブラリが使えないので)自分でPythonで書いたものなので、こいつに足を引っ張られているかもしれません。

というわけで、過学習しただけの前回のDNNに続き、今回もRNNにちょっと黒星がつきました。ディープラーニングの道のりは険しい・・・自分は何か誤解してる可能性もある。もうちょっと論文を読もう。

次の目標は、フレーム単位の分類という問題を克服することです。音声フレーム単位の分類と言えば、音声認識の場合は音素分類(Phoneme classification)をやってますね。その上で単語を推論してゆくという。

現状のコード認識システムでは、音声フレームに直接コード記号を対応させているのがほとんどです。冒頭でも言いましたが、そこが非合理的なんですね。音声の音素に対応した、コード記号より細かい要素があれば、もっと音声認識システムの考え方に近づけそうですが・・・