目次
はじめに
beatmania IIDXのスコア指標を新たに考えてみたので、その構想と現時点での実験結果を書き記します。
実験結果はあまりよい結果にはならなかったので、「すぐに使える新しいスコア指標完成したって?!」と思った方の期待には応えられません。
研究途中のスコア指標の進捗報告という感じでお読みください。
注意事項
私は統計学および深層学習に関するプロフェッショナルではないため、言葉使いや手法の扱いなどの観点で誤用している可能性があります。その点、ご留意の上でお読みください。
なぜ新しいスコア指標を作ろうと思ったか
一言で言うと、BPIが破壊され始めてきたためです。
有名なスコア指標の一つにBPIがあります。
BPIは皆伝平均を0点、歴代スコアを100点としたスコア指標になります。BPIを求めるために必要な変数が皆伝平均と歴代スコアと指標を測定したいスコアの3つだけなので、比較的容易に計算することができ便利な指標です。
一方でBPIには問題点があります。それは、歴代スコアが更新されると自分の腕前が変わっていないにも関わらずBPIの値が落ちてしまうことです。
BPIのコンセプトを考えると仕様通りの挙動なのかもしれませんが、自分の腕前の変化に関わらずBPIの値が落ちてしまうのは腑に落ちないところがあります。
また、歴代スコアがおかしなことになると、一般人のBPIの値に多大な影響を与えます。最近ではEXUSIAのMAX-10が騒がれました。
上記のBPIの問題点を解消できるような新たなスコア指標を作れないかと思い、取り組んでみました。
新しいスコア指標のコンセプト
新しいスコア指標のコンセプトは『理論値は100点』です。
本記事で提案するスコア指標は、EXスコアレートが100%(理論値)なら100点、0%なら0点で、その間をいい感じに結ぶスコア指標になります。
BPIは歴代スコアとの相対的な指標だったために、歴代スコアが凄まじいスコアに更新されるとBPIが破壊される可能性を残していました。これを回避するために理論値を100点とする指標を作成します。
新しいスコア指標の構想
最も単純なスコア指標は、そのスコアがプレイヤー中の上位何%にあたるかから求めることでしょう。
例えば、全一なら最上位なのでスコア指標は100点で、スコアが0点なら最下位なのでスコア指標は0点になります。
これを元に新しいスコア指標を構築していきます。
ある譜面の全プレイヤーのスコアデータが手元にあるとします。
ここから、横軸をスコアレート、縦軸を累積プレイヤー数としたグラフを作成すると、下のようになります。

あるスコアレートで上位何番目かの計算は、総プレイヤー数からそのスコアレートまでの累積人数を引けば求められます(上図の赤矢印線)。
指標的には0から100の範囲で表せると分かりやすいので、割合を求めて100を掛ければ良いでしょう。
一見良さそうですが、問題点が2つあります。
- 全一のスコアレートが100%でなくとも、全一のスコアでスコア指標が100点となってしまう
- 1つの譜面のスコア指標を計算するために全プレイヤーのその譜面のスコアデータが必要となり、計算コストが高すぎる
これらを解消するために以下を実施します。
まず、1点目の問題ですが、これは、全プレイヤーのスコアデータから各譜面のスコアレートの確率分布を推定することで解消します。
次に、2点目の問題ですが、これは、確率分布のパラメーターを全プレイヤーのスコアデータからではなく、譜面から推定することによって解消します。
雑に絵を描くと下のような感じになります。

雑な絵の補足説明です。
- 全プレイヤーのスコアデータから譜面ごとのスコアレートの確率分布のパラメーターを推定します
- 入力データを譜面、出力データをその譜面の確率分布のパラメーターとなるような関数を学習するために、正解データを手順1で推定したパラメーターとして学習します
- 学習した関数を用いて譜面ごとの確率分布のパラメーターを求めます(新しい譜面もこの関数に入力して確率分布のパラメーターを求められます)
以上のようにして、譜面ごとのスコアレートの確率分布を推定します。
後は始めに説明したとおり、推定した累積人数からそのスコアレートが上位何%にあたるかを求め、それをスコア指標値に換算します。
ちゃんと書くと以下のように求めます。
スコアレートxのスコア指標値は、スコアレートの確率密度関数をf(x)、その累積分布関数をF(x)としたとき、(F(x) - F(0))/(F(1) - F(0)) * 100点となります。
F(0)を引いている部分は、確率密度関数の定義域が負の無限大から正の無限大までで定義されているのを補正しています。
スコア指標値の解釈は、ある譜面のスコア指標値がx点なら、その譜面で上位(100-x)%相当のスコアを保持している、という解釈になります。
譜面ごとのスコアレートの確率分布の推定
確率分布の推定には混合ガウスモデルを使用します。
混合ガウスモデルは、複数のガウス分布を様々な重みで足し合わせることで、分布を表現できるモデルです。
以下のサイトが直感的に理解できるかもしれません。
aizine.ai
混合ガウスモデルのパラメータは、混ぜ合わせるガウス分布の数をn個としたとき、ガウス分布の重み付け係数n個、ガウス分布の平均値n個、ガウス分布の分散n個の合計3n個となります。
譜面ごとにこの3n個のパラメーターを推定し、譜面ごとのスコアレートの確率分布を推定します。
パラメーター推定の際には、その譜面をプレイしている全プレイヤーのスコアデータを使用します。
譜面から確率分布のパラメーターの推定
譜面から確率分布のパラメーターを推定するのにはLSTM(Long Short Term Memory)を使用します。
LSTMは時系列データを扱うことのできるニューラルネットワークのひとつです。
以下の動画でなんとなく理解できるかもしれません。
www.youtube.com
譜面データを時系列データとして入力し、確率分布のパラメーターを出力するニューラルネットワークを構築します。
入力は譜面を96分まで識別できる粒度に分割し、各時刻で叩く鍵盤とそのときのBPMを与えます。
例えば、下の画像はAA[ANOTHER]の先頭1小節目です。

これの1拍目を時系列データに起こすと以下のようになります。
1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154
各行が1時刻になります。各時刻あたり17要素あり、1要素目から7要素目までが1鍵盤から7鍵盤、8要素目がスクラッチ、9要素目から15要素目までが1鍵盤から7鍵盤のCNまたはHCN、16要素目がBSS、17要素目がBPMに対応しています。
要素について説明したところで内容を少し読み解いていきましょう。
まず1行目ですが、1時刻目、すなわち譜面の先頭で1,3,5,7鍵盤をBPM154で叩いていることが読めると思います。
その6時刻後(7行目)に2鍵盤を叩いています。この時系列データは96分を識別できる粒度で作成しているため、1時刻進むごとに"96分"分譜面が進みます。今回は6時刻分進んでいるので96÷6=16で1時刻目から"16分"分譜面が進んだところで2鍵盤を叩いていると解釈できます。
実際の譜面を見てみると、1,3,5,7鍵盤から2鍵盤へは16分の譜面になっていることが分かります。
このように1譜面分符号化したものをニューラルネットワークへの入力にします。
正解のパラメーターは、事前に混合ガウスモデルで推定したものを与え、学習を行います。
何をやっているのかというと、ニューラルネットワークに譜面を擬似的にプレイさせて、実際のプレイヤーたちが作るスコアの分布を再現させようとしています。
学習の結果、新規の譜面に対しても、確率分布のパラメーターを出力するニューラルネットワークが構築されることになります。
実験
以上が理論で以下は実験です。
私の手元にある最新のデータが、SINOBUZ終了時点での皆伝取得者と忍者ランク100位以上のプレイヤーの☆12のスコアデータのため、これを使います。
譜面ごとのスコアレートのヒストグラムと、推定した分布が以下になります。
drive.google.com
混ぜたガウス分布の数は、いろいろ試した結果5個にしました。例として記事では2譜面だけ取り上げます。
AAの推定分布(赤線)と実際の分布(黒線)

Go Beyond!!の推定分布(赤線)と実際の分布(黒線)

AAのような一般的な譜面はかなり精度が高いと思います。Go Beyond!!のようなハード落ちなどが多そうな譜面は低スコアレート帯では若干精度が落ちていますが、スコアレートが60%を超えてくると実際の分布とほぼ重なります。
全体として、推定した分布が実際の分布にいい精度で沿っているのが見て取れると思います。
次にニューラルネットワークによる譜面からパラメーターの推定の実験です。
特徴の異なる以下の譜面をテストデータとしました。
- AA (一般的☆12)
- Confiserie (発狂)
- DIAMOND CROSSING (チャージ)
- Snake Stick (皿)
- ICARUS (ソフラン)
上記以外の譜面をトレーニングデータとしました。
学習にかなり時間がかかるため、とりあえずミニバッチサイズを10、エポック数を5でニューラルネットワークを学習させました。
そのニューラルネットワークによるパラメーターで描画したスコア分布が以下になります。

学習が足りないのか、そもそも構築が悪いのか精度がとても悪いです。すべての譜面でグラフの形がほぼ同じになっているので、譜面に対して分布を学習できたという感じがしません。
さいごに
混合ガウスモデルでのパラメーター推定まではいい感じでしたが、ニューラルネットワークによる譜面からのパラメーター推定が残念な結果になりました。
深層学習に詳しくないため、とりあえずで実装して学習してくれないかなあと思ってやってみましたが、そう甘くないですね。お勉強しなくては。
ニューラルネットワークの譜面の学習は裏で回しつつ、問題点があれば潰していこうと思います。
使用したコードや材料はgithubに置いておいたので、弄ってみたい方はどうぞ。
また、深層学習有識ニキ/ネキから精度改善のためのアドバイスをいただけると嬉しいです。
github.com
HEROIC VERSEの皆伝とスコアラーのスコアデータが手に入れば、そのデータでやってみたいですが、SINOBUZのときに収集するのが相当骨が折れたのであまりやりたくありません。どなたかください。
弐寺の分析をするたびに、KONAMIの課金プランにビートアナリストコースを作って、データに自由にアクセスできるようにしてくれと思いますが需要が低すぎますね。