ニューラルネットワークで作曲をする! Magentaを動かす

#Magentaとは
この前、GoogleのMagentaという新プロジェクトがGithubにてオープンになりました。
https://github.com/tensorflow/magenta

Magentaというのは、ニューラルネットワークを使って、美術や音楽を生成するプロジェクトです。

機械学習のクリエイティビティを進化させるのと、アーティストと機械学習のコミュニティとなることを目的としています。

#作曲をするリカレントニューラルネットワーク
Magentaの第１弾として、作曲をするリカレントニューラルネットワーク(RNN)のモデルが公開されました。
LSTM(Long Short-Term Memory)という手法を取り入れたものです。
magenta公式サイト(http://magenta.tensorflow.org/ )によれば、
> It’s purposefully a simple model, so don’t expect stellar music results. We’ll post more complex models soon.
>これは意図的にシンプルにしたモデルで、傑出した音楽ができることは期待できません。しかし、これからより複雑なモデルを公開していきます。

とのことで、あくまで、導入としてこのモデルを動かすのがいいでしょう。

#準備
私はUbuntu環境でやっています。
Windowsに対応していないTensorflowが必要なので、MacかLinuxが必要です。

Githubからmagentaをcloneしてきて、Tensorflowとビルドツールであるbazelをインストールします。

#作曲モデルの構築
さて、ここから実際に作曲モデルを構築していきます。

モデルを構築するにあたり、曲のメロディが入ったMIDIデータが必要です。
MIDIデータがないときは、http://www.midiworld.com/files/142/ からとってくるといいとおすすめされていました。
~~使うMIDIデータは1つの方がいいでしょう。なぜか3つでやるとうまくいきませんでした。~~
（どうやらいけるMIDIファイルとだめなMIDIファイルがあるみたいです。）
今回はmidiファイルを/tmp/midiというディレクトリに入れました

ここからはターミナル(ubuntuならCtrl+Alt+T)にコマンドを打つことで作曲モデルを構築しMIDIを作っていきます。
中身はPythonでやっているのですが、実際にコードはいじりません。

まず、MIDIファイルはTensorflowが使うtfrecordフォーマットに変換します

```
MIDI_DIRECTORY=/tmp/midi
SEQUENCES_TFRECORD=/tmp/notesequences.tfrecord
bazel run //magenta/scripts:convert_midi_dir_to_note_sequences -- \
--midi_dir=$MIDI_DIRECTORY \
--output_file=$SEQUENCES_TFRECORD \
--recursive
```

次に生成したtfrecordファイルから、2つのtfrecordファイルを生成します。
これは訓練データ(Train data)と評価データ(Evaluation Data)というものに分けます。
今回使うのは訓練データだけです。

```
SEQUENCES_TFRECORD=/tmp/notesequences.tfrecord
DATASET_DIR=/tmp/basic_rnn/sequence_examples
TRAIN_DATA=$DATASET_DIR/training_melodies.tfrecord
EVAL_DATA=$DATASET_DIR/eval_melodies.tfrecord
EVAL_RATIO=0.10

bazel run //magenta/models/basic_rnn:basic_rnn_create_dataset -- \
--input=$SEQUENCES_TFRECORD \
--output_dir=$DATASET_DIR \
--eval_ratio=$EVAL_RATIO
```

訓練データを使って、RNNを学習していきます。
num_training_stepsは学習回数で、20000でかかりすぎてしまう場合は少なくしてください。
私のマシンはそれほど良くなかったので1000にしました。
とはいっても、学習の途中でも、10回ずつRNNの状態を記録しているようなので、MIDIを生成することはできます。

```
bazel build //magenta/models/basic_rnn:basic_rnn_train
./bazel-bin/magenta/models/basic_rnn/basic_rnn_train --run_dir=/tmp/basic_rnn/logdir/run1 --sequence_example_file=$TRAIN_DATA --hparams='{"rnn_layer_sizes":[50]}' --num_training_steps=20000
```

これが終われば、作曲モデルができあがりました。

#作曲MIDIファイルの生成
さて、最後にMIDIファイルを生成する前に、もう一つMIDIファイルを用意する必要があります。
というのもRNNはメロディの流れをMIDIファイルから学習しています。
つまり、「このメロディが前にあるから、次にこの音がくるな」ということを学習しています。
ので、前にメロディがなければそのあとに続くメロディが作れないわけです。
そのメロディが入ったmidiファイルが必要なわけです。
今回は適当に1小節のメロディを作って、primer.midという名前で、/tmpに置きました。

```
PRIMER_PATH=/tmp/primer.mid
bazel run //magenta/models/basic_rnn:basic_rnn_generate -- \
--run_dir=/tmp/basic_rnn/logdir/run1 \
--hparams='{"rnn_layer_sizes":[50]}' \
--output_dir=/tmp/basic_rnn/generated \
--num_outputs=10 \
--num_steps=128 \
--primer_midi=$PRIMER_PATH
```

このコマンドにより/tmp/basic_rnn_generatedにmidiファイルが16個できます。
それぞれprimer.midのメロディの後に4小節分くらいのメロディが続いています。

#あんまりよいメロディではなかった
できたメロディがこちらになります
https://soundcloud.com/ig4osq8tqokz/magenta1

あんまり良いメロディにはなりませんでした。
伴奏次第かもしれませんが...

良くなかった原因としては
・そもそもやっぱりモデルがそういうやつ
・訓練データとして使ったMIDIファイルがよくなかった(これに関しては、メロディだけが入ったMIDIファイルを使わなかった)
・学習回数が少ない

が考えられますが、とりあえずまあじっくりやっていきます。

#それと
学習にめちゃくちゃ時間がかかる。
学習10回にMIDI1曲当たり1分かかってしまう。
GPUを使えば改善できるのだろうか(そもそも持っていないが)