人工知能時代の音楽制作への招待 - Google Magenta 解説&体験ハンズオン (自習編) -

音楽制作を行っていて人工知能技術に興味がある、あるいは機械学習をやっていて音楽が好きだ！そんな方に送る、機械学習による音楽生成のチュートリアル資料となります。本記事のみで、仕組みの理解から実際に音楽を生成して、SoundCloudで共有するまでの手順を網羅しています。

そして、本記事は先日実施した[人工知能時代の音楽制作への招待 - Google Magenta 解説&体験ハンズオン -](https://techcircle.connpass.com/event/54669/)の自習用資料でもあります。

![magenta.PNG](https://qiita-image-store.s3.amazonaws.com/0/25990/c2353777-6063-88d2-d96f-b1fe57d25264.png)

イベント自体は100名を超える方(開催前日の段階で倍率が5倍)に応募いただき、行きたかったけど行けなかった！という方も多いかと思うので、自習編にて内容に触れていただければと思います。
※なお、会場のキャパを広げられなかった代わりに撮影をしていただいたので、後日講義動画が上がればそちらも掲載させていただきます。

# ゴール

* 音楽生成とはそもそもどういう仕組みで、どんなアプローチが取られてきたのかを知る
* 音楽生成の歴史の中における、Google Magentaの立ち位置を理解する
* Google Magentaによる音楽生成の仕組みを知る
* Google Magentaを利用し、実際に音楽の学習と生成を行う手順を理解する
* 学習させたモデルと共同で音楽制作(セッション)を行い、作成した楽曲を[SoundCloud](https://soundcloud.com/)で共有する

# 講義資料

当日の講義資料がこちらになります。

[Tech Circle #23 Next Music Productionby Google Magenta](https://www.slideshare.net/takahirokubo7792/tech-circle-23-next-music-productionby-google-magenta)

# ハンズオン資料

## 0. Preparation

事前準備として、Magentaを動かせる環境を構築します。
また、学習に使いたいMIDIデータの用意(1-1)まで行っておいてください。なお、大量、あるいは長いMIDIファイルの場合時間がかかる場合があるため、1-2まで勧めておくとスムーズです。

それと、最後にMagentaとセッションした結果をSoundCloudにアップロードしていただこうと思うので、SoundCloudのアカウントを取得しておいて下さい。

[SoundCloud](https://soundcloud.com/stream)

### 0-1. リポジトリをダウンロード

[magenta_session](https://github.com/icoxfog417/magenta_session)のリポジトリをFolkし、Folkしたリポジトリをcloneによりダウンロードします。
(Starを頂けると励みになりますm(_ _)m)

```
https://github.com/your_github_account_name/magenta_session
```

以降は、cloneしてきたフォルダ上で作業(コマンドの実行)を行います。

### 0-2. Minicondaのインストール

[こちら](http://qiita.com/icoxfog417/items/950b8af9100b64c0d8f9)の記事を参考に、[Miniconda](https://conda.io/miniconda.html)の導入を行ってください(MinicondaはPython3のもので大丈夫です)。

* `conda --version`でMinicondaがインストールできていることが確認できたらokです。
* なお、Magentaの0.3.2から、Python3に対応したためWindowsネイティブで動かすことが可能になりました。もうbash on Windowsを使わなくても大丈夫です。


### 0-3. Magenta環境の作成

インストールしたMinicondaで、Magentaを動かすための環境(`magenta`)を作成します。

```
conda create -n magenta numpy scipy scikit-learn matplotlib jupyter pyyaml
```

作成後、この環境を有効化してさらに依存ライブラリをインストールします。

```
source activate magenta
pip install -r requirements.txt
```

※[pyenv](https://github.com/pyenv/pyenv)を利用している場合、`source activate`でシェルが落ちる場合があります。先ほどのMinicondaの導入手順にこの[回避方法を記載しています](http://qiita.com/icoxfog417/items/950b8af9100b64c0d8f9#maclinux)ので、参考にしてください。

`python -c "from __future__ import print_function;import magenta; print(magenta.__version__)"`
で、Magentaのバージョンが出力されれば環境構築はokです。

## 1.Magentaに音楽を学習させよう

では、いよいよMagentaに音楽を学習させていきます。プロセスの全体像は、以下のようになります。

![tech_circle_beat.png](https://qiita-image-store.s3.amazonaws.com/0/25990/470fbf34-b762-ebc2-df4e-1f60763168a2.png)


### 1-1. MIDIデータの収集

学習させたいMIDIデータを収集し、`data/raw`の中に格納します。以下のサイトが集め先としてよいと思います。

* [midiworld.com](http://www.midiworld.com/files/142/)
* [FreeMIDI.org](https://freemidi.org/)
* [The Lakh MIDI Dataset v0.1](http://colinraffel.com/projects/lmd/)

ゲーム音楽なら

* [Video Game Music Archive](http://www.vgmusic.com/)
* [THE MIDI SHRINE](http://www.midishrine.com/)

ロックなら

* [FREE ROCK MIDIS](http://rock.freemidis.net/index.php)

(THE MIDI SHRINEからダウンロード可能な[FF4の音源](http://www.midishrine.com/index.php?id=10)では動作確認しています。)

※少し試すだけなら、~30秒程度の曲を5~10曲程度揃える感じをおすすめします。

MIDIの再生は、WindowsだとデフォルトのMedia Playerで可能です。Macの場合は、[Garage Band](https://www.apple.com/jp/mac/garageband/)があれば再生可能です。
オンラインだと、[Online Sequencer](https://onlinesequencer.net/import)が利用可能です。

### 1-2. MIDIファイルからNoteSequenceを生成

収集したMIDIファイルを、NoteSequenceというMagentaが扱うファイル形式へ変換します。

```
python scripts/data/create_note_sequences.py
```

なお、読み取れなかったファイルはスキップされます(警告が出力されると思います)。実行が終了すると、`notesequences.tfrecord`が`data/interim`に生成されます。

### 1-3. NoteSequenceを学習用Datasetに変換

作成したNoteSequenceを基に、学習用のDatasetを作成します。モデルによっては、音以外の情報もデータに必要となるため(Lookbackでは繰り返しか否かが必要など)、この段階でモデルを指定する必要があります。

今回は[MelodyRNN](https://github.com/tensorflow/magenta/tree/master/magenta/models/melody_rnn#melody-rnn)を利用しているため、以下3つから選択します。

* basic_rnn
* lookback_rnn
* attention_rnn

```
python scripts/data/convert_to_melody_dataset.py  --config attention_rnn
```

Datasetを作成する際、併せて学習用と評価用にデータセットを分割します。この割合は、引数の`--eval_ratio`で調整可能です(デフォルトは`0.1`です).

学習用と評価用でデータを分けている理由については、テストに例えるとわかりやすいです。 評価も学習用データで行うということは、テストは必ず勉強に使っていた問題集から出題される、というようなものです。 これでは、本当に理解をしているのか、問題集の答えを覚えているだけなのかがあいまいになります。そのため、学習用と評価用でデータを分けているということです。
※ただ、誰かの楽曲を完全に再現したいケースなどでは、学習データを全部覚えることが重要になる場合があります。この辺りは機械学習の研究とは異なり、用途に応じた対応を取る必要があります。

### 1-4. モデルの学習・評価

データセットの準備ができたら、学習を開始します。

```
python scripts/models/train_model.py \
 --config attention_rnn \
 --hparams="batch_size=64,rnn_layer_sizes=[64,64]" \
 --num_training_steps=20000
```

学習を行う際に指定するパラメーターは、[公式ドキュメントと同様](https://github.com/tensorflow/magenta/tree/master/magenta/models/melody_rnn#train-and-evaluate-the-model)ですので、そちらもご参照ください。

幾つか、ポイントとなるパラメーターについて解説をしておきます。

* `batch_size`  
ネットワークに一度に学習させるデータの数です。問題集の中の、1ページあたりの問題数のようなものです。大きいほど一度の学習でよく学べますが、その分コンピューターのメモリが必要になります。 そのため、メモリ関連でエラーが発生する場合これを下げると良いです(デフォルトが128なので、半分の64にするなど。その分、以下のnum_training_stepsを上げるなどする)。
* `rnn_layer_sizes`  
ネットワークの大きさを決めるパラメーターです。[128, 128]なら、ノードの数が128の隠れ層を2つ重ねて作るということです。大きいほど複雑な曲を表現できますが、その分学習時間もかかりますし、汎用的でなくなりやすいというデメリットがあります。
* `num_training_steps`  
学習を行う回数です。

また、Attentionの場合はattn_lengthでどれくらい過去までを見るか指定することが可能です。

学習時には、もちろん学習状況の観測を行うことが重要です。これをTensorBoardを利用し行うことができます。
まず、学習と並行してモデルの評価を行う処理を、別途ウィンドウ(プロセス)を立ち上げて実行します(当然ですが、パラメーターは最後の`--eval`を除いて学習のパラメーターと同じにする必要があります)。

```
python scripts/models/train_model.py \
 --config attention_rnn \
 --hparams="batch_size=64,rnn_layer_sizes=[64,64]" 
--eval
```

その後、TensorBoardを立ち上げます。TensorBoardは、[`http://localhost:6006`](http://localhost:6006)からアクセスできます。

```
tensorboard --logdir=models/logdir
```

学習データに対する精度と、評価データに対する精度を確認できます。学習データに対する精度が高いけれども、評価データに対する精度が下がってきている場合は「本当に理解をせず、問題集を覚えている」状態になっているサインです(これを過学習と呼びます)。

![training.PNG](https://qiita-image-store.s3.amazonaws.com/0/25990/8b9b05e4-aeec-55ee-3799-fd0297689388.png)



### 1-5. モデルのパッケージ

学習が終わったら、学習したモデルをパッケージングして扱いやすい形にします。Magentaの場合、`.mag`ファイルにまとめることができます。
※学習が終わってなくても、checkpointファイルができていれば実行可能です(その時点の学習結果がパッケージングされます)。

```
python scripts/models/create_bundle.py --bundle_file my_model
```

スクリプトを実行すると、`models/`のフォルダに`my_model.mag`とこのモデルを作成した際のパラメーター`my_model.hparams`が作成されます(名前は自由につけていただいて構いません)。

### 1-6. MIDIファイルの生成

では、さっそく作成したモデルを利用してMIDIファイルを生成してみましょう！

```
python scripts/models/generate_midi.py \
 --bundle_file=my_model \
 --num_outputs=10 \
 --num_steps=128 \
 --primer_melody="[60]"
```

パラメーターについては[公式ドキュメント](https://github.com/tensorflow/magenta/tree/master/magenta/models/melody_rnn#generate-a-melody)の通りになりますが、幾つかのパラメーターについて解説をしておきます。

* `num_outputs`: 生成されるMIDIデータの数
* `num_steps`: 生成されるMIDIデータの長さ(16step=1小節換算です。例えば、128なら8小節分です)
* `primer_melody`: 出だしとなるメロディー

`primer_melody`はMIDIコードで指定を行います。MIDIのコードについては以下を参照してください(NoteOffは-2になります)。なお、指定は16分音符単位となるため、「四分音符のド」は`[60, -2, -2, -2]`となります。

![midi_codes.PNG](https://qiita-image-store.s3.amazonaws.com/0/25990/880dc9e8-71c9-26c9-d306-563ea924ec22.png)
[出典: MIDI numbering, the Helmholtz Pitch Notation System, and other octave numbering conventions used in music and music notation](http://www.theoreticallycorrect.com/Helmholtz-Pitch-Numbering/)
※半音が上がるのもカウントされるため、「ド」の次の「レ」は62になっています。

生成に成功すると、`data/generated`のフォルダに生成されたMIDIファイルができているはずです！


## 2.MagentaとSessionしよう

### 2-1. MagentaとのSession

単純にMIDIファイルを生成するだけでなく、Magentaと共演をしてみましょう。
まず、作成したモデルを使うために`MAGENTA_MODEL`の環境変数をセットします。

```
export MAGENTA_MODEL=my_model
# Windowsの場合
SET MAGENTA_MODEL=my_model
```

その後、Magenta Sessionのサーバーを起動します。

```
python server/server.py
```

デフォルトでは[http://localhost:8080](http://localhost:8080)で立ち上がるはずです。ぜひMagentaとのCall & Responseを試してみてください！

![magenta_session.PNG](https://qiita-image-store.s3.amazonaws.com/0/25990/863ff2e6-4208-3f7c-97be-30aa1bbf40b6.png)

MIDIコントローラーがある場合は、接続した後に画面の更新を行ってください。

* 1. Set Your Playing time: 自分の演奏時間を設定します
* 2. Set Magenta's playing time: Magentaの演奏時間を設定します(now: となっているのが現在使用していモデルです)
* 3. Connect MIDI instrument: MIDIコントローラーが接続されていれば、表示されます
* 4. Session Startでセッションを開始し、Session Stopで停止します。Session終了後、セッション結果のMIDIファイルをDownloadボタンからダウンロードできます。

### 2-2. MIDIをシェアしよう

作成したMIDIを、ぜひSoundCloudなどのクラウドサービスでシェアしましょう。

MIDIファイルは演奏方法の指示であって音源ファイルではないため、通常は音源ファイルへの変換が必要になります。ただ、以下のサイトではMIDIファイルをそのまま共有することが可能です。

[Picotune](http://picotune.me/?amAVRthU)

SoundCloudの場合は音源ファイルへの変換が必要となるため、以下のサイトなどを利用して変換を行いましょう。

[MIDI to MP3 Online Converter](https://solmire.com/)

変換を行ったら、SoundCloudへアップロードします。ぜひ #magenta_session のタグをつけて下さい。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">FF4の音楽を学習させたモデルで挑戦<br><br>Have you heard ‘Magenta Session with Game Sound trained model’ by icoxfog417 on <a href="https://twitter.com/hashtag/SoundCloud?src=hash">#SoundCloud</a>? <a href="https://twitter.com/hashtag/np?src=hash">#np</a> <a href="https://t.co/9JuSOKtgLK">https://t.co/9JuSOKtgLK</a></p>&mdash; piqcy (@icoxfog417) <a href="https://twitter.com/icoxfog417/status/853530744987107328">2017年4月16日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

いろんなMIDIで学習させた結果、またセッション結果をどしどしアップロードして頂ければ幸いです！