post Image
TensorFlow製音楽生成プロジェクト「Magenta」でMIDIファイルを学習させ、曲を生成する。


はじめに

この記事では、Magentaの開発環境を準備した上で、手元のMIDIファイルを学習し、曲を作成するということを行います。

magentaのBasic RNNのREADMEの通りですので、そちらを読んでいただいてもよろしいかと思います。

用語等、不明な点もあるため、ご了承いただければと思います。

開発環境の準備はこちらの記事もご参考ください。

TensorFlow製音楽生成プロジェクト「Magenta」を開発環境の設定から曲生成までやってみる。


データセットを作る

手持ちにMIDIファイルを学習する前に、まずはTensorFlowで扱えるように、NoteSequencesという形式に変換する必要があります。

下記のスクリプトを実行します。

不正な形式のMIDIファイルを読み込んだ際にエラーを吐くことがあります。

解析できないMIDIファイルはスキップされるので安心して大丈夫なようです。



MIDI_DIRECTORY=<folder containing MIDI files. can have child folders.>

# TFRecord file that will contain NoteSequence protocol buffers.
SEQUENCES_TFRECORD=/tmp/notesequences.tfrecord

bazel run //magenta/scripts:convert_midi_dir_to_note_sequences -- \
--midi_dir=$MIDI_DIRECTORY \
--output_file=$SEQUENCES_TFRECORD \
--recursive

convert_midi_dir_to_note_sequences.pyと言うのを実行しているようですね。

下記のようなメッセージが表示されれば完了です。

..............

INFO: Found 1 target...
Target //magenta/scripts:convert_midi_dir_to_note_sequences up-to-date:
bazel-bin/magenta/scripts/convert_midi_dir_to_note_sequences
INFO: Elapsed time: 7.312s, Critical Path: 0.63s

(中略)

INFO:tensorflow:Could not parse 0 MIDI files.
INFO:tensorflow:Wrote 6 NoteSequence protos to '/tmp/notesequences.tfrecord'


学習する


メロディーを抽出する

basic_rnn_create_dataset.pyを実行します。

これは上記でMIDIファイルを元に作成したNoteSequence dataからメロディーを抽出するスクリプトです。

アウトプットはSequenceExampleprotosを含んだtfrecordファイルとして書き出されます。

basic_rnnモデルのTensorFlowの読み込みは、SequenceExample protosを直接モデルに読み込むことができます。

この例では、評価データセットを2つ目のtfrecordファイルとして作ります。

ですが、evaloutputevalratioフラグを削除することで省くことができます。

下記のようなメッセージが出ればOKです。

INFO: Found 1 target...

Target //magenta/models/basic_rnn:basic_rnn_create_dataset up-to-date:
bazel-bin/magenta/models/basic_rnn/basic_rnn_create_dataset
INFO: Elapsed time: 0.573s, Critical Path: 0.01s

INFO: Running command line: bazel-bin/magenta/models/basic_rnn/basic_rnn_create_dataset '--input=/tmp/notesequences.tfrecord' '--output_dir=/tmp/basic_rnn/sequence_examples' '--eval_ratio=0.10'
INFO:tensorflow:

Completed.

INFO:tensorflow:Processed 6 inputs total. Produced 31 outputs.
INFO:tensorflow:DAGPipeline_RandomPartition_training_melodies_count: 29
INFO:tensorflow:DAGPipeline_MonophonicMelodyExtractor_melodies_discarded_too_long: 0
INFO:tensorflow:DAGPipeline_RandomPartition_eval_melodies_count: 2
INFO:tensorflow:DAGPipeline_MonophonicMelodyExtractor_melody_lengths_in_bars:
[0,1): 10
[1,3): 6
[3,6): 17
[6,7): 2
[7,8): 1
[8,10): 4
[10,20): 21
[20,30): 5
[30,40): 6
[50,100): 4
INFO:tensorflow:DAGPipeline_MonophonicMelodyExtractor_melodies_discarded_too_short: 35
INFO:tensorflow:DAGPipeline_Quantizer_sequences_discarded_because_multiple_time_signatures: 5
INFO:tensorflow:DAGPipeline_MonophonicMelodyExtractor_melodies_truncated: 0
INFO:tensorflow:DAGPipeline_MonophonicMelodyExtractor_polyphonic_tracks_discarded: 43
INFO:tensorflow:DAGPipeline_MonophonicMelodyExtractor_melodies_discarded_too_few_pitches: 10

完了すると

/tmp/basic_rnn/sequence_examples/

training_melodies.tfrecordeval_melodies.tfrecordの2つのファイルができます。

training_melodies.tfrecordは訓練用、eval_melodies.tfrecordは評価用のようです。


トレーニングのスクリプトを実行する

Magentaの開発者の方がスクリプトを作ってくださっています。

$EXPERIMENT_DIR=/tmp/basic_rnn/logdir

作業フォルダを指定します。

$HYPERPARAMETER_STRING=`{"rnn_layer_sizes":[50]}’

ハイパーパラメータの指定をします。

このように指定することで、LSTMモデルのサイズを指定することができるようです。

LSTMについては下記が参考になると思います(大作)。

わかるLSTM ~ 最近の動向と共に

LSTM(Long short-term memory)は、RNN(Recurrent Neural Network)の拡張として1995年に登場した、時系列データ(sequential data)に対するモデル、あるいは構造(architecture)の1種です。

 (中略)

LSTMのその最も大きな特長は、従来のRNNでは学習できなかった長期依存(long-term dependencies)を学習可能であるところにあります。

$NUM_TRAINING_STEPS=20000

訓練回数を指定します。Macだととても時間がかかるので、数百とかに減らすといいと思います。

$TRAIN_DATA=/tmp/basic_rnn/sequence_examples/training_melodies.tfrecord

上記で生成した訓練データのパスを記載します。

$EVAL_DATA=/tmp/basic_rnn/sequence_examples/eval_melodies.tfrecord

オプションとして、訓練データと並行して検証データも並行してはしらせることができるようです。

設定ができたら、スクリプトを実行します。

./run_basic_rnn_train.sh $EXPERIMENT_DIR $HYPERPARAMETER_STRING $NUM_TRAINING_STEPS $TRAIN_DATA [$EVAL_DATA]

下記のメッセージが出ます。

INFO: Found 1 target...

Target //magenta/models/basic_rnn:basic_rnn_train up-to-date:
bazel-bin/magenta/models/basic_rnn/basic_rnn_train
INFO: Elapsed time: 0.544s, Critical Path: 0.00s
INFO:tensorflow:hparams = {'rnn_layer_sizes': [50], 'decay_rate': 0.85, 'dropout_keep_prob': 0.5, 'batch_size': 128, 'decay_steps': 1000, 'clip_norm': 5, 'initial_learning_rate': 0.01, 'skip_first_n_losses': 0}
Starting TensorBoard 28 on port 6006
(You can navigate to http://10.200.3.144:6006)
INFO:tensorflow:Train dir: /tmp/melody_rnn/logdir/run1/train
INFO:tensorflow:Starting training loop...
INFO:tensorflow:global_step/sec: 0

(中略)

INFO:tensorflow:Global Step: 100 - Learning Rate: 0.01000 - Loss: 1.680 - Perplexity: 13.678 - Accuracy: 85.811
INFO:tensorflow:Training complete.


曲を生成する。

上記の訓練が完了すると、作業ディレクトリ/tmp/basic_rnn/logdir/run1/train/ の配下に、下記のようなファイルができると思います。

checkpoint                  model.ckpt-31

events.out.tfevents.1475664203.HTMac.local model.ckpt-31.meta
graph.pbtxt model.ckpt-39
model.ckpt-15 model.ckpt-39.meta
model.ckpt-15.meta model.ckpt-47
model.ckpt-23 model.ckpt-47.meta
model.ckpt-23.meta

checkpointというのはTensorFlowにおけるファイルの保存やロードに用いるもののようです。

Basic_RNNではこのうち、最後のcheckpoint(上記だとmodel.ckpt-47)を用いて曲を生成してくれるようです。

また、曲を生成するには、モデルにはじまりのメロディを与える必要があります。

曲生成はそのメロディを元に、次の音をどんどん予測して行って曲を延長していく、ということをするからです。準備するメロディはモノラルの(同タイミングに複数の音が鳴らない)メロディである必要があります。

任意に作成してもいいですし、サンプルとして

/magenta/models/shared/primer.midも準備されています。

ここではこのサンプルを用います。

PRIMER_PATH=<absolute path of your primer MIDI file>

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

最小の3小節はprimer.midを元に固定されています。

サンプル1

サンプル2

サカナクションさんを学習させましたが、雰囲気を感じることができました。


最後に

DeepLearningの知識、TensorFlowの知識、英語読解力の不足が原因で、ちょっと読み解けてない部分があります。

引き続き勉強します。。。

ありがとうございました。


『 Python 』Article List