mastAdCのために一ネタ用意しようとしたら失敗した話

この記事は、mast Another Advent Calendar 2018 の14日目の記事です。

adventar.org

13日目はゐゑ木さんのペンツール師匠への道|ゐゑ木|noteでした。

 

はじめまして、はっしーです。

 

こういう形で何かを公開するのは初めてなので軽く自己紹介すると、落単芸人で最近スマブラをやってます。

 

今回の記事執筆にあたって、コンテンツ性の足りない系人類なので自分語りをするより一ネタこなして技術系っぽい記事を書こうとしたけど、失敗しました。

あと数日ちゃんとやれば完成しそうな気もしますが自分で決めた締め切りを無視して数日後にオソクナリマシタガとか言って公開するのは一番かっこ悪い(別に誰かを攻撃してるわけではない)ので失敗した話をします。特に読者に伝えたいこととかはないです。たまに、はっしーは何やってるの?と聞かれることがあるのでその説明っぽいものにはなってます。

 

敗者に興味ない系の人はブラウザバック推奨です。

 

今回やろうとしたネタは大まかにいうと、音響情報処理です。約半年前当時Beatsaberというゲームが流行っていました。

僕もスマブラが発売するまではやってました。ここまで書くと勘のいい人は察すると思いますが、このゲームの譜面の自動生成です。

譜面の自動生成を始めたのも約半年前でそのときは精度は出なかったけれど、ネタはまあ面白いということであゆを食べました。

 このときは実装期間として2週間を与えられて当初はqiitaの記事にするつもりで実装したのですが、精度は出なかったのでお蔵入りになりました。実装方針としては音声をFFTしたものに3dConvolutional層を主とするニューラルネットワーク(時系列データだけど当時の僕にはLSTMを理解できなかったのでまとめて3dConvolutionalした)で直接その瞬間の譜を求めようとしてました。今思えば、ほとんどの時間の譜にはノーツは存在しないのでなんの工夫もしなければ入力にかかわらずノーツなしの譜を返すネットワークを学習することになるのは当然ですね。

 

大体この1週間後に太鼓の達人の記事を見て初めて、先行研究DanceDanceConvolutionの存在を知りました。

qiita.com

[1703.06891] Dance Dance Convolution

これを読んで初めて工夫をするということを知り、先行者がいるからこれをちゃんとやっても大したことにはならなそうということを察してやめました。

 

時は流れて2018/11/10です。mast Another Advent Calendar 2018の開催が決まりました。半年前のことを気にしていた僕は半年前とは違って1カ月もあるし、当時よりは成長しているからいけると思い軽い気持ちでこのネタをやることを決め、たまたま近くにいた後輩にその旨を宣言しました。

 

ここからはその後の1カ月でやっていたことを書きます。

 

BeatSaberには自作譜面を有志が公開しているサイトがあるのでそこから譜面を4500曲分スクレイピングし、難易度が低い譜面は取り除く処理をしました。譜面を学習に使うにはまず配列に直さなければならないので0.01秒単位での譜の情報をnumpy arrayにしました。先行手法の曲の前処理をまねて3種類の窓でFFTをかけて画像にしました。ここまでの前処理だけで1週間ぐらいかかった気がします。ここで作った画像を見てみるとこんな感じです。縦軸が周波数、横軸が時間です。

f:id:AH7965:20181214224230p:plain

1曲分丸々だと長すぎるので適当に1部分クロップしました。なんか綺麗ですね。綺麗だと思いませんか?そうですか…

 

当時の方針としては、先行記事を読んで譜面を生成するときは1段階目としてノーツが存在する場所を検出して、2段階目でそのノーツの種類を分類するという手法を使うことを知ったので対象とする時間の前後7フレームを合わせた64 * 15 * 3の画像に対して2dConvolutionalしてその瞬間にあるかないかを2値判別しようとしてました。当然失敗しました。データのほとんどが0なので入力にかかわらず0が返ってくるようになりました。モデルを定義して実際に学習させてテストするのに2週間ぐらいかかった気がします。

 

うまくいかないのでDanceDanceConvolutionを読み始めました。論文にはニューラルネットワークだけで検出したのではなく、ある程度の区間にノーツが存在するかだけをニューラルネットワーク(CNNとLSTM)で確認し、存在した場合にはニューラルネットワークを使わない手法でその区間内の正確な位置を求めるということをやってることを知りました。

残念ながら僕はちゃんと音響処理を学んだわけではないので多段階のニューラルネットワーク(依然としてLSTMはよくわからないから使えない)を学習させることにしました。データセットに偏りがあるとうまく学習できないのでまずデータセット全体に対してどの程度の長さの区間をとればその区間内に存在するかが1:1の割合になるかを調べると24フレーム(0.24秒)ということがわかったので1段階目は24フレームで判別します、2段階目は12フレーム、3段階目は6フレーム、4段階目は3フレームで前後1フレームは誤差(勝手に僕が決めた)という感じで学習させました。これも1週間ぐらいやりました。

 

うまくいかなかったです。学習データに対する結果のグラフを下に貼っときます。橙が答え、青がネットワークの出力です。1フレーム前後に1があれば1/2、2フレーム前後にあれば1/4のスコアを与えるようになってます。

f:id:AH7965:20181214232020p:plain

前後2フレームまで正解として計算してもIoUは平均0.1ぐらいになりました。学習データに対する結果なのでほぼ1ぐらいになってほしいのでこれはごみです。

f:id:AH7965:20181214232712j:plain

 

ここまで終わったのが大体12/5ぐらいのことで、締め切りには間に合わないことを察し始めたので12/7まではoptuna対応とかしてました。

ハイパーパラメータ自動最適化ツール「Optuna」公開 | Preferred Research

qiita.com

 

12/7 スマブラ発売しました。もう終わりです。ほかの何にも手がつかなくなりました。

 ただ、しばらくやってたら全キャラ開放できたので12/11からはLSTMを勉強し始めました(ようやく)。

昨日あたりにLSTM完全理解したマンになって今はLSTMを組み込んだネットワークで学習中です。もしこれでうまくいったらqiitaに記事書きます。1週間後にqiitaに記事公開してなかったら察してください。

 

今日の22:00ぐらいに公開しようと思って21:30にアカウントを作っていたら、書き終わりは23:45ぐらいになりました。14日の間に公開できて満足です。

 

これが僕の1カ月になります。僕はモチベーションが長く続くタイプではないので大体1カ月ぐらいのサイクルで新しいネタ始めたり前ほっぽり出したネタを再開したり、飽きてやめたりしてます。最初の方に自分語り糞つまらんとか書いておきながら結局自分語りになりました。推敲してると14日が終わるので公開します。誤字脱字、論理破綻があっても許してください。