近況
Qiitaに投稿しない理由なのですが、自分はQiitaを技術ナレッジのレポジトリのような使い方を想定してしていて、実際、多くの方が素晴らしい技術的なプラクティスを提供なさっています。
古い言葉でチラシの裏という表現がありますが、今回の私のは、ブログが良い選択肢であるの思うのです。十全な責任を持てない発信やSNSでの補足が必要になるレベルになるものに関してはブログを利用しています。
モチベーション
RNNという技術がなんともオワコンと言われているので、手向けに興味があった音楽の生成を行うことにしました。
機械学習が流行りだしてから、まるで機械学習といえば絵を描いたり、音楽を奏でたりということができるという認識がニュースで流行りだしたりしていて、実際にやってみた系の記事が、音楽であったでしょうか。Qiitaではありますが、あれは音楽をRNNに記録させて取り出したというもののような気がします。[0]
RNNといえども、基本はニューラルネットワークに情報の符号をモデルに刻み込んでいくスタイルなので、どうしてもある程度特徴量の抽出はするものの、そのまま覚え、覚えた内容をそのまま出力するという流れになりがちです。[1][2]
自然語処理の分野でも、他の方が自分の著書を書いて、その内容を記録させるということをしていますが、その著書の範囲のコンテンツしか創造能力が獲得できません。[11]
特段新しい手法ではない(と思うの)ですが、複数のモデルの結果を合成(この文脈ではアンサンブルと呼ぶ)することで創造能力の獲得を目指します。
CNNなどの識別タスクやGANなどの生成タスクでの応用などが考えられます。
前提
この世に完全なるオリジナルは存在しない
なんとも哲学的な題材なので、正直これについては述べたくなかったけど、これを最初に言っておかないと後が続かない気がするので言いますと、多くの芸術家が言っていることとして、オリジナルは存在しなく、創作物は何らかの参照と引用で構築されているという意見です。[3][4]
これは今の私には否定出来ないことなので、正しいと思うのです。
ピカソとポーラ・シェールの本質であるコンビナトリアル・クリエイティビティなど、ネットワーク化された知識です。私たちが真に創造し世界に貢献するためには、無数の点を結びつけ、豊かな分野のアイデアを相互に結びつけ、これらの要素を結合して再結合させ、新しい城を建設することができなければなりません。[4]
提案
複数音楽を学習したモデルを合成することで新規性を獲得する
人間がいくつかの経験をし、新たに直面する問題に対処するときは、おそらくそれまでの経験の幾つか思い出して手法を組み合わせて対処するかもしれません。それを真似しようという発想です。
RNNとは、過去の出力状態に依存した確率場を表現する出力をするものというものです。mutableなニューラルネットワークです。
もう何度も図示しましたが、中二チックに単語を選んだ図を再掲します。
引用になりますが、Conditional Random Fieldとも見れます。
ベイズ系の記事を読んだ時、ヒートマップで表現している方法が分かりやすかったです。
数式です。
アンサンブルは機械学習では特段珍しい手法ではないのですが、創造系のタスクでアンサンブルは珍しいと思います。
提案したいことは単純で、それぞれの時間系列 t+1に対して次の音が来る確率の中庸点(特定のモデルにバイアスをかけることもある)を求めます。
結果が確定したら、RNNの状態をアップデート(ステップを進める)して次に来る確率をまた予想します。
図では、2つのモデルの合成のみが示されていますが、実際には多くの音楽を学び、たくさんのモデルがあればその組み合わせはかなりの数になります。これは到底人間が一生かかって創造活動しても網羅できないレベルです。
実験環境
音の符号化
一番苦労した点はこの符号化の点であると感じています。音を記号で示すにはどうしたら良いでしょうか。WaveNet[5]や他の研究では音をそのまま波形として扱うこともあるのですが、精度は高いものの非常に生成するのに時間がかかるということで、よりかんたんなMML(Music Macro Language)を使用しました。
MMLはかなりの方言があり、一般的と呼ばれる記述を調べるのに非常に苦労しました。a~gのcharactorが音階になっていて、それを装飾するl, p, gなどの符号と量を示す数値で構成されているようだとわかりました。符号の粒度が分かれば、RNNで学習することができます。
いーあるふぁんくらぶの例 liarufanclub$ cat input.txt.org v100q25o5l1a a a a a a a l2a q100l8d c l4d l8.d d l16d d l8c d l2.d l8d c l4d l8d l16d l8d l8.d l8d f f f g f q66l4.d q100l16d c q50l4d q100l8.d d l16d d l8c d l2.d l16a a a a a a a a l8g g g g f l2^4.d l8d c l4d l8d l16d l8.d l8d c d l2.d l8d c l4d l8d l16d l8.d l8d d l16f f l8f f g f l4.d l16d c q50l4d q100l8.d l16d l8d ...
また、MIDIとMMLは一部互換性があるらしく、運がよいとMIDIをMMLに変化することができます。変換に使用したソフトは、テキスト音楽「サクラ」になります。[6]
これを自作のスクリプトでかなりアドホックですが、一つの素性の単位に分解します。コードは別途転載するので、必要な方は参照してください。[7]
RNNの学習
ざっくりとですがパラメータサーチを行った結果
epoch:200 batch:50 rnn_unit: 386 layer: 3 学習率: 2e-3
ぐらいが曲を丸ごと覚えられる感じだったので、採用しました。
loss errorは10^-3以下になります。
これを一曲一つのモデルで学習させていきます。
学習させた曲は、以下の通りです。
いーあるふぁんくらぶ(最初の冗長なイントロまで再現されています)
バッドアップル
ロストワンの号哭
千本桜
RNNのアンサンブルのコード
自然言語処理でどうしようもなく、精度が出ないときがあったのでアンサンブルの発想に至ったのですが、まぁ、普通に考えたらno free lunchの定理より、多くのモデルを混ぜると精度は改悪するので、idea賞というレベルのものを今回再利用しました。結構強引な改修を行ったのでコードが汚いです。[8]
結果
いーあるふぁんくらぶ、バッドアップル、ロストワンの号哭、千本桜を合成するのに、それぞれのウェイト(重要度のようなもの)を指定して、任意の割合で合成できるようにしました。
いーあるふぁんくらぶ50% + 千本桜50% ○ 新規性ありそう
いーあるふぁんくらぶ50% + Bad Apple50% △ 後半、いーあるふぁんくらぶ強くなってく
Bad Apple50% + 千本桜50% △ Bad Appleから入っていく感じ、似てるけど別物
ロストワンの号哭50% + いーあるふぁんくらぶ50% ○ そういう曲だと言われれば?
いーあるふぁんくらぶ90% + Bad Apple 90% + ロストワンの号哭 100% + 千本桜 100% ○なんか新しい曲調
色々良さそうな音楽を探索したいのもやまやまなんですが、疲れてきたのでこの辺にしときます。
コードを公開するので、自由にしてください。
結論
任意の組み合わせで、再生に耐えられる音楽を作り出すことはできました。しかし、これが歌詞や音楽を知っているから、違和感なく感じるのか、音楽のプロが見たらどう判断するのか正直なところわかっていないです。
自分に音楽の才能が著しくないことを理解しているので、どんどんやっていこうというモチベーションは出ないですが、人並みには興味があったのでやってみたというところが事実です。
途中に介入したり、Conditionalに指定の曲調を作り出すことも、まぁ、可能なのですがデータがないのと手がまわらないのでどうしようもない感じです。
音楽は画像生成タスクに比べれば楽という印象ですが、前処理、学習、評価、Webのアップロードだけでプライベートな時間の殆どを消費してしまいました。悲しい。
謝辞
これは前からあったアイディアで、プログラムを作るの結構めんどくさかったので、半ば放置していたのでした。そんな折、My name is HAPPY HARDCORE.という音楽に出会いまして、最後までプログラムを書き上げるために強制的にテンションを上げていただき、ありがとうございます。この音楽がなかったら、この発想は私の中で永久に検証する機会がなかったと思います。
参考文献
[0] http://qiita.com/komakomako/items/9ba38fc38f098c0e8b9b
[1] http://repository.dl.itc.u-tokyo.ac.jp/dspace/bitstream/2261/59449/1/48146440.pdf
[2] http://qiita.com/komakomako/items/9ba38fc38f098c0e8b9b
[3] http://www.lifehacker.jp/2016/07/160713misconceptions_about_creativity.html
[4] https://www.brainpickings.org/2011/08/01/networked-knowledge-combinatorial-creativity/
[5] https://deepmind.com/blog/wavenet-generative-model-raw-audio/
[6] http://oto.chu.jp/top/
[7] https://github.com/GINK03/KindleReferencedIndexScore/blob/master/query-expansion/chainer-chiptune-rnn/splitter.py
[8] https://github.com/GINK03/KindleReferencedIndexScore/blob/master/query-expansion/chainer-chiptune-rnn/EnsembleConditionalSampler.py
[9] https://www.youtube.com/watch?v=OxE-FFNB74M
[11] http://d.hatena.ne.jp/shi3z/20150831/1441003474