1.はじめに
以前、三輪さんの『「虹機械」はじまりのうた』を素材としたGoogle Magentaのmelody RNNモデルを用いた模倣の実験を行った結果を記事「Google Magentaを用いた『「虹機械」はじまりのうた』の学習実験ノート」で報告しました。本稿はその続報として、『「虹機械」はじまりのうた』および『「虹機械」公案-001』を素材にしてPythonのライブラリPyTorchのLSTMモデルを用いた模倣の実験を行い、模倣ができることを確認できたので、その結果を報告します。前回は模倣実験そのものの成否よりも、アルゴリズミック・コンポジションの中でも、決定論的な規則に従う離散力学系を作品の構成原理としている三輪さんの作品を機械学習の対象とすることに意味合いの考察に重点がありましたが、今回は、どのような設定で模倣に成功したかを報告することに主眼を置きます。実験の動機、意図や狙いなどについては前回の報告に記載しているものと基本的に同じですので、そちらをご覧い頂ければ幸いです。また今回は時系列データの機械学習のためにリカレント・ニューラルネットワークを用いますが、これについてはWeb、書籍等で様々な解説が行われているので、そちらに譲ることにして、ここでは具体的にどのタイプのリカレント・ニューラルネットワークを使って、どのようなモデルを構築して、どのように訓練をしたかを報告することにさせて頂きます。
[2024.10..30追記]その後、本稿の続編となる記事「続・「虹機械」機械学習実験ノート補遺:生成系列長を長くした場合について 」で報告した実験に際して、本稿で公開した出力結果のmidiファイルを作成するプログラムに不具合があり、同一音形のチャネルが重複した内容になっていることが判明しました。幸い前回報告の範囲ではチャネル数はごく普通に用いられるレベルですので恐らく実害はないものと思われますが、不要な負荷をかけることになるため、不具合を修正し、MIDIファイルとWAVファイルを修正した版で、本稿にて後述の公開アーカイブ(RainbowMachine_LSTM.zip)を更新しています。そのためお手数をおかけして申し訳ありませんが、前回報告の結果を取得された方は、更新版を再取得頂き、前回のものは破棄して今回のものに置き換えて頂ければ幸いです。なお、続編記載の追加実験をリクエストして頂き、また不具合発見に繋がる指摘をして頂いた三輪眞弘さんに御礼申し上げます。
2.実験のデザイン
2.1.実験の目的
今回の実験は、前回既に報告した通り、Google Colaboratory上でのMagentaのインストールが、依存しているライブラリの整合性の問題で失敗するようになり、実験の継続ができなくなり、長らく中断していたのに対し、ようやく自分で簡単なプログラムを作成して、MIDIファイルから必要なデータを抽出し、簡単なニューラルネットワークモデルを構築して機械学習の実験を再開できるようになったことから、まずは前回の実験を継続して模倣ができることを確認しようと企図したものです。
2.2.対象データ
実験の素材として用いた『「虹機械」はじまりのうた』および『「虹機械」公案-001』は基本的に「単旋律」です。旋律とはいっても歌謡のような滑らかな声部進行ではなく、ピアノで弾き通すにはヴィルトゥオジティが要求される跳躍進行を含む16分音符の高速なパッセージの連続ですが、譜面上は或る時点で鳴っている音は常に単音です(但し、休符は含まれます)。リアリゼーションにあたってはサステインペダルの指示によって「音響」の水準で音が重なった状態になる箇所がありますが、ここでは休符を含めた音の状態遷移系列を対象とします。
2.3.入力データの準備
そこでまず、作品のエミュレーション結果のMIDIファイルから、休符を含めた音の系列を抽出することにします。前回はMagenta任せでしたが今回は以前自作して、マーラーの作品の分析でも使用してきたMIDIファイルを解析するCのプログラムを使用し、ピアノロール形式(各時点――『「虹機械」はじまりのうた』『「虹機械」公案-001』とも16分音符が基本単位ですので16分音符単位で――MIDIノート0~127のうち鳴っていない音は0、鳴っている音は1を値とするベクトルで表現し、このベクトルを時系列に沿って並べたマトリクスの形式)のデータを作成して、これを入力として用い、ピアノロール形式のデータから休符を含む音の系列を抽出することにしました。ピアノロール形式のデータでは休符の箇所はMIDIノート0~127を表すベクトルの全ての要素が0ですが、一次元の音の系列に変換するにあたり、休符には一旦、0~127以外の任意の値(例えば128)を割り当てることにしました。
2.4.入力データ形式
次にニューラルネットへのデータの与え方ですが、前回もそうであったように、ここでの実験の最初の目的は所謂「学習」ではなく「模倣」です。「虹機械」の規則の学習にあたって、まずは原曲の音の系列を正しく再現できるかどうかを問題にするので、訓練用のデータセットと検証用のデータセットを分けることはせず、原曲を上記の入力系列長と次の1音の正解出力という形にして訓練を行うことにしました。例えば「虹機械 公案-001」の冒頭から16ステップ分のMIDIノートの系列を示すと以下のようになります。
[61, 53, 68, 61, 73, 66, 90, 71, 59, 76, 52, 59, 71, 76, 68, 63, …]
ここから入力の系列データ(系列長=4)と出力の正解データの対を以下のように作成していきます。
[61, 53, 68, 61]→73
[53, 68, 61, 73]→66
[68, 61, 73, 66]→90
[61, 73, 66, 90]→71
[73, 66, 90, 71]→59
[66, 90, 71, 59]→76
[90, 71, 59, 76]→52
[71, 59, 76, 52]→59
[59, 76, 52, 59]→71
[76, 52, 59, 71]→76
[52, 59, 71, 76]→68
[59, 71, 76, 68]→63
…
このようにして作品の全系列についてデータを作成します。系列長-5の入力データ→正解データのペアができ、これを1回通すのを1エポックとします。「虹機械 公案-001」が390小節あるのに対し、「虹機械 はじまりのうた」は260小節+1音(いずれも1小節に16分音符16個)で、作品の規模は「公案-001」が「はじまりのうた」の1.5倍の系列長を持ちますが、この割合はそのまま入力データの1エポックあたりのパターン数の割合になります。
(a)入力層入力として与える系列の長さについては、前の音と今の音から次の音を決めるという「虹機械」の基本的な状態遷移規則を念頭におけば長さ=2で十分な筈ですが、現実の作品は基本的な状態遷移規則だけが用いられているわけではありません。(この点については、例えば記事「「POC#20」にて三輪眞弘ピアノ作品を聴いて」の関連個所を参照頂ければ幸いです。)一方でリカレントネットワークは時間方向に展開して逆伝播を行いますが、展開する時系列が長くなり、層が深くなるにつれて勾配の誤差が積み重なってしまう、いわゆる「勾配消失」「勾配爆発」の問題があることが知られています。今回採用したLSTMはまさにその問題に対処するために改良されたものなのですが、系列長が長くなるにつれて学習が困難になり、また時間がかかるようになる点は変わらないため、まず系列長=4で実験を行い、その後比較対照のために、系列長=2の場合と系列長=8の場合についても実験を行う事にしました。(b)出力層出力層の各ノードを出現しうるMIDIノートと休符に対応づけ、それらのノードに対してsoftmax関数を用いることにしました。従って入力層のノード数は1とし、出力層のサイズは、対象となっている作品で出現しうるMIDIノートの最大値-最小値+2(休符用のノードが必要になるため)になります。(c)隠れ層隠れ層のサイズは一般に、対象とするデータや問題依存であり経験的に決定するものとされていますが、ここではMagentaではmelodyRNNのデフォルト値が128でしたので、それを参考にして128で実験を行って、その結果により、必要に応じて調整を行うことにしました。
- (再現実験)作品冒頭を入力として次の音を予測させる。予測された音を入力列の末尾に加えて、先頭を1ステップずらして、更に次の音を予測させる。これを32回ステップ(16分音符32個=2小節)繰り返す。
- (生成例)ランダムに開始位置を決めて、作品系列の任意の一部を入力として次の音を予測させる。以下、再現実験と同様の手順を繰り返す。
- A-0.主実験:入力文字列長=4, 隠れ層のサイズ=128, 学習率=0.001
- A-1.比較実験1:入力文字列長=2,隠れ層のサイズ=128, 学習率=0.001
- A-2.比較実験2:入力文字列長=8 隠れ層のサイズ=128 学習率=0.001
- A-3.比較実験3:入力文字列長=8 隠れ層のサイズ=256 学習率=0.001
- B-0.主実験:入力文字列長=4 隠れ層のサイズ=128, 学習率=0.001
- B-1.比較実験1:入力文字列長=2,隠れ層のサイズ=128, 学習率=0.001
- B-2.比較実験2:入力文字列長=8,隠れ層のサイズ=128, 学習率=0.001
- Epoch数=3000 → loss=0.3996
- Epoch数=5000 → loss=0.2829:再現=〇。
primer=[56, 75, 82, 46]
[77, 84, 72, 77, 84, 79, 55, 60, 72, 77, 29, 82, 51, 80, 75, 39, 82, 77, 65, 84, 77, 84, 60, 55, 67, 84, 36, 77, 58, 75, 80, 44]
[65, 77, 72, 79, 84, 77, 53, 58, 70, 75, 27, 82, 51, 80, 75, 39, 70, 82, 65, 84, 79, 84, 60, 53, 65, 82, 34, 75, 58, 75, 80, 44][77, 84, 72, 77, 84, 79, 55, 60, 72, 77, 29, 82, 51, 80, 75, 39, 82, 77, 65, 84, 77, 84, 60, 55, 67, 84, 36, 77, 58, 75, 80, 44][77, 84, 72, 77, 84, 79, 55, 60, 72, 77, 29, 82, 51, 80, 75, 39, 82, 77, 65, 84, 77, 84, 60, 55, 67, 84, 36, 77, 58, 75, 80, 44][77, 84, 72, 77, 84, 79, 55, 60, 72, 77, 29, 82, 51, 80, 75, 39, 82, 77, 65, 84, 77, 84, 60, 55, 67, 84, 36, 77, 58, 75, 80, 44]
primer:[71, 82, 69, 73]
[84, -1, 69, -1, 82, -1, 84, -1, 71, 69, 84, -1, 76, 78, 74, 78, 77, -1, 74, -1, 77, -1, -1, -1, 76, 74, 79, -1, 69, 73, 69, 71, 82, -1, 67, -1]
[84, -1, 69, -1, 82, -1, 84, -1, 71, 69, 84, -1, 76, 78, 74, 78, 77, -1, 74, -1, 77, -1, -1, -1, 76, 74, 79, -1, 69, 73, 69, 71, 82, -1, 67, -1]
- Epoch数=3000 → loss=2.0864
- Epoch数=5000 → loss=1.8669
- Epoch数=10000 → loss=1.6362:中断。
- Epoch数=3000 → loss=0.2947
- Epoch数=5000 → loss=0.1319:再現=×。
primer=[77, 29, 80, 53, 77, 58, 41, 65]
[84, 72, 77, 72, 77, 60, 53, 65, 82, 34, 53, 58, 82, 53, 48, 72, 77, 65, 84, 65, 84, 55, 60, 72, 77, 29, 58, 53, 77, 58, 41, 65]
[84, 72, 77, 72, 80, 60, 55, 67, 84, 36, 75, 58, 82, 53, 46, 70, 77, 65, 84, 65, 75, 53, 60, 72, 79, 31, 82, 53, 75, 58, 41, 65]
primer=[71, 82, 69, 73, 84, -1, 69, -1]
[82, -1, -1, -1, 71, 74, 79, -1, 76, 73, 74, -1, 84, -1, 76, 68, 69, 72, 78, 71, 66, 69, -1, 71, -1, 82, -1, -1, 83, 66, 67, 76]
[82, -1, 84, -1, 71, 69, 84, -1, 76, 78, 74, 78, 77, -1, 74, -1, 77, -1, -1, -1, 76, 74, 79, -1, 69, 73, 69, 71, 82, -1, 67, -1]
- Epoch数=3000 → loss=0.1106:再現=〇。
primer=[65, 82, 34, 51, 58, 82, 51, 46]
[70, 86, 70, 82, 63, 82, 53, 60, 72, 77, 29, 58, 51, 75, 58, 39, 63, 79, 65, 77, 70, 77, 58, 53, 65, 84, 36, 53, 60, 84, 53, 48]
[70, 86, 70, 82, 63, 84, 53, 60, 72, 77, 29, 58, 51, 75, 58, 39, 63, 79, 65, 77, 70, 77, 58, 53, 65, 84, 36, 53, 58, 82, 51, 46]
[82, -1, 84, -1, 71, 69, 84, -1, 76, 78, 74, 78, 77, -1, 74, -1, 77, -1, -1, -1, 76, 74, 79, -1, 69, 73, 69, 71, 82, -1, 67, -1]
[82, -1, 84, -1, 71, 69, 84, -1, 76, 78, 74, 78, 77, -1, 74, -1, 77, -1, -1, -1, 76, 74, 79, -1, 69, 73, 69, 71, 82, -1, 67, -1]
B.「虹機械 公案-001」
B-0. 「虹機械 公案-001」主実験:入力文字列長=4 隠れ層のサイズ=128, 学習率=0.001
- Epoch数=5000 → loss=0.6119
- Epoch数=10000 → loss=0.3532:再現=〇。
primer=[69, 64, 52, 59]
[-1, 78, 61, 73, 78, 66, 71, 52, 64, 69, -1, 74, -1, 69, 45, 76, 64, 71, 66, 78, 71, 59, 76, 45, 57, 74, -1, 69, -1, 76, 52, 71]
[-1, 78, 61, 69, 73, 59, 69, 50, 62, 67, -1, 62, 74, 57, 45, 64, -1, 71, 66, 76, 78, 63, 76, 45, 57, 74, -1, 55, 67, 62, 50, 57, -1, 76, 59, 71][-1, 78, 61, 73, 78, 66, 71, 52, 64, 69, -1, 62, 74, 57, 45, 64, -1, 71, 66, 78, 73, 61, 78, 47, 59, 76, -1, 57, 69, 62, 50, 57, -1, 76, 59, 71][-1, 78, 61, 73, 78, 66, 71, 52, 64, 69, -1, -1, 74, 57, 45, 64, -1, 71, 66, 78, 73, 61, 78, 47, 59, 76, -1, 67, 69, 62, 50, 57, -1, 76, 59, 71]
primer=[61, 53, 68, 61]
[73, 66, 90, 71, 59, 76, 52, 59, 71, 76, 68, 63, 68, 58, 63, 68, 80, 61, 85, 78, 66, 71, 47, 64, 76, 71, 61, 68, 63, 51, 67, 63, 75, 68, 92, 73]
[73, 66, 90, 71, 59, 76, 52, 59, 71, 76, 68, 63, 68, 58, 63, 68, 80, 61, 85, 78, 66, 71, 47, 64, 76, 71, 61, 68, 63, 51, 67, 63, 75, 68, 92, 73]
B-1. 「虹機械 公案-001」比較実験1:入力文字列長=2,隠れ層のサイズ=128, 学習率=0.001
- Epoch数=5000 → loss=2.2712
- Epoch数=10000 → loss=2.0701:中断。
B-2. 「虹機械 公案-001」比較実験2:入力文字列長=8,隠れ層のサイズ=128, 学習率=0.001
- Epoch数=3000 → loss=0.5833
- Epoch数=5000 → loss=0.2748:再現=〇。
primer=[96, 75, 70, 63, 78, 90, 93, 85]
[-1, 92, 58, 104, 80, 100, 95, -1, 93, 84, 67, 72, 75, 87, 102, 90, 85, 83, 49, 97, 78, 97, 102, -1, 100, 79, 74, 67, 82, 94, 97, 85]
[-1, 92, 58, 104, 69, 100, 93, -1, 91, 82, 65, 70, 73, 85, 100, 90, -1, 85, 51, 99, 73, 95, 100, -1, 98, 77, 72, 65, 80, 92, 95, 83]
primer=[61, 53, 68, 61, 73, 66, 90, 71]
[59, 76, 52, 59, 71, 76, 68, 63, 68, 58, 63, 68, 80, 61, 85, 78, 66, 71, 47, 64, 76, 71, 61, 68, 63, 51, 67, 63, 75, 68, 92, 73]
[59, 76, 52, 59, 71, 76, 68, 63, 68, 58, 63, 68, 80, 61, 85, 78, 66, 71, 47, 64, 76, 71, 61, 68, 63, 51, 67, 63, 75, 68, 92, 73]
- 「虹機械 はじまりのうた」「虹機械 公案-001」とも、入力文字列長=4 隠れ層のサイズ=128, 学習率=0.001の設定で元の作品の音の系列の再現に成功しました。但し、作品の規模の違いにより、「虹機械 はじまりのうた」では5000エポックでloss=0.2829に到達したのに対し、「虹機械 公案-001」ではloss=0.3532に達するのに10000エポックかかりました。
- 入力系列長を4から2に短くする比較実験1の設定では、「虹機械 はじまりのうた」「虹機械 公案-001」とも10000エポックの訓練を行ってもlossが1桁高い値のままで、目安とした0.3まで到達する見通しが立たないため、実験を中断しました。
- 入力系列長を4から8に長くした比較実験2の設定では、「虹機械 はじまりのうた」「虹機械 公案-001」ともlossの減少のスピードが上がり、「虹機械 はじまりのうた」では3000エポックでlossが0.3を切り、5000エポックでは0.1319まで減少した一方で、再現には失敗しましたが、「虹機械 公案-001」では5000エポックで0.2748まで減少し、再現にも成功しました。
- そこで「虹機械 はじまりのうた」については比較実験3を追加し、隠れ層のサイズを128から256に増やして、入力系列長8での実験を行ったところ、1エポックあたりの処理時間は増大したものの、3000エポックでloss=0.1106まで減少し、更に再現にも成功していることを確認できました。
「虹機械 はじまりのうた」「虹機械 公案-001」それぞれについて、入力ファイル(ピアノロール形式)と、参考としてニューラルネットへの入力系列・正解の系列の元となった、音および休符の系列のファイルの2種類が含まれます。
- 「虹機械 はじまりのうた」
- EM-Hamamatsu_PL.out:ピアノロール形式ファイル
- EM-Hamamatsu_seq.txt:音および休符の系列のファイル
- 「虹機械 公案-001」
- EM-Koan-001_PL.out:ピアノロール形式ファイル
- EM-Koan-001_seq.txt:音および休符の系列のファイル
各実験毎の、訓練終了ないし中断時のチェックポイントファイルが含まれます。
- 「虹機械 はじまりのうた」
- checkpoint_Hamamatsu-4.001.pt:主実験(5000エポック)
- checkpoint_Hamamatsu-2.001.pt:比較実験1(10000エポック)
- checkpoint_Hamamatsu-8.001.pt:比較実験2(5000エポック)
- checkpoint_Hamamatsu-8.001-256.pt:比較実験3(3000エポック)
- 「虹機械 公案-001」
- checkpoint_Koan-001-4.001:主実験(10000エポック)
- checkpoint_Koan-001-2.001:比較実験1(10000エポック)
- checkpoint_Koan-001-8.001:比較実験2(5000エポック)
各実験毎に、生成例と再現実験の結果それぞれについてmid, wavの2種類の形式が含まれます。但し、訓練を途中で打ち切って、検証を行わなかった比較実験2(入力文字列長=2)は含まれません。生成例(各条件につき、midとwavの2種類)
- 「虹機械 はじまりのうた」
- generated_Hamamatsu-4.001:主実験(入力系列長=4, 隠れ層のサイズ=128)
- generated_Hamamatsu-8.001:比較実験2(入力系列長=8,隠れ層のサイズ=128)
- generated_Hamamatsu-8.001-256:比較実験3(入力系列長=8 隠れ層のサイズ=256)
- 「虹機械 公案-001」
- generated_koan-001-4.001:主実験(入力系列長=4 隠れ層のサイズ=128)
- generated_koan-001-8.001:比較実験2(入力系列長=8,隠れ層のサイズ=128)
再現結果(各条件につき、midとwavの2種類)
- 「虹機械 はじまりのうた」
- generated_Hamamatsu-4.001-0:主実験(入力系列長=4, 隠れ層のサイズ=128)
- generated_Hamamatsu-8.001-0:比較実験2(入力系列長=8,隠れ層のサイズ=128)
- generated_Hamamatsu-8.001-0-256:比較実験3(入力系列長=8 隠れ層のサイズ=256)
- 「虹機械 公案-001」
- generated_koan-001-4.001-0:主実験(入力系列長=4 隠れ層のサイズ=128)
- generated_koan-001-8.001-0:比較実験2(入力系列長=8,隠れ層のサイズ=128)
