主成分分析を使って、DDRのレベル18の譜面の傾向を分析してみた

主成分分析を使って、DDRのレベル18の譜面の傾向を分析してみた

前書き

音ゲーのスコアを主成分分析して、プレイヤーや曲の傾向が求められるのではないか? と思ったので試してみた。
いま自分が一番やっている音ゲーはSOUND VOLTEXなのだが、みんなのスコアデータを取得してくる方法がないため、DDRで分析をやってみた。

注意事項:私はデータ分析についてそれほど熟練してるわけではない。しかも、DDRについてもそれほど熟練してるわけではない。(ごく少しのレベル18をギリギリクリアできる程度) 譜面についておかしな分析をしていたら、ご容赦ください。

データ収集

まずデータを収集する必要がある。すなわち、色々なプレイヤーのスコアを収集する。

有志が作成したSkill Attackというサイトがあり、そこからデータをスクレイピングした。
Skill Attackでは、個人がDDRのスコアデータを登録し、また他の人のスコアを閲覧することができる。
なお、登録しているスコアは譜面ごとの過去最高スコアである。
まずSkill Attack Difficulty Ranking (Level 18)のページを起点とした。
ここには各プレイヤーのレベル18のスコア合計・平均があるので、そこから容易にプレイ済み曲数を計算可能である。
ある程度上手い人、かつある程度曲を埋めている(=スコアを登録している)人を今回の分析対象とした。具体的には、レベル18のスコア平均値が95万点以上(満点は100万点)、プレイ済み曲数が30曲以上(曲数は全部で35曲)とした。この条件を満たした対象プレイヤーは94人である。
対象プレイヤーのスコア一覧をスクレイピングした。なお、スコアを登録していない曲については欠損値になることに注意。

データの収集(スクレイピング)は2018年8月1日の0:00頃に実施した。

データの一部は次のようになる。
f:id:soratokimitonoaidani:20180817002800j:plain
さて主成分分析……と行きたいところだが、前処理として2つの工程を実行する必要がある。
それは「不適当な曲の削除」と「欠損値の補完」である。

前処理(不適当な曲の削除)

まず「不適当な曲の削除」について。曲の特性(出現条件と出現タイミング)を考えて、データ分析するには不適当な曲があるので、その曲のデータを削除する必要がある。

「ACE FOR ACES 鬼」はレベル18なので今回の集計対象曲である。しかし、この譜面がプレイ可能になったのは7月26日と、データ収集をした僅か6日前であり、スコアデータを登録しているプレイヤーがほとんどいない。欠損値が大半であるため、この曲のデータは分析に使えないと判断し削除する。

レベル18の中で、「ACE FOR ACES 鬼」の次に新しい譜面は「ENDYMION 激」である。これは同日の7月26日から通常選曲できるようになった。それまでは4回ミスしたら即終了という条件下でプレイしなければならなかった。
この厳しい条件だとスコアは下がってしまうのか。それとも熟練のDDRプレイヤーたちはこの条件でも他のレベル18と変わらないスコアを出すのだろうか。
これを確認するため、箱ひげ図を用いて各曲のスコア分布状況を可視化する。

f:id:soratokimitonoaidani:20180817002735p:plain

明らかにENDYIONは他の曲と比べて傾向が違い、下方の外れ値も多く存在する(つまりスコアが極端に低いプレイヤーがいる)。 ENDYIONを分析に含めてしまうと、この曲の特殊条件の影響を強く受けてしまうため、分析が上手くできないと考えられる。したがって、「ENDYMION 激」も除外する。

(これによって 本当は2曲を除外したあとのスコア平均値が95万点以上、としたほうが合理的ではある。
しかしながら、この方法は集計対象プレイヤーがすぐには求まらないので複雑である。
今回は、ある程度の人数が集まればよしと思ってたので、ここについてはこだわらずに次に行く)

2曲を削除した後で箱ひげ図を再度描画してみた。

f:id:soratokimitonoaidani:20180817002741p:plain

Pluto The First 鬼」では明らかに外れ値が発生している。特に80万点を割っている人が2人いるのが気になる。しかし、この曲は最近出たというわけではない。除外せずに分析を続行する。

ちなみに、スコアが一番高い傾向にある曲は「Come to Life 鬼」だと分かる。
譜面動画見たけど結構キツくないか? 延々と16分滝を踏まされるから、クリアがギリギリの人の目線で見ると決して一番簡単には思えない。しかし、「リズムが全体的に分かりやすい」「全体BPMが180と低め」「低速部分に難解な配置がない」「同時押し絡みの強い配置がない」と考えていくと……上手い人にとってはスコアを出しやすいんだろう。多分。


前処理(欠損値の補完)

次に、欠損値の補完をする。
あるプレイヤーがある譜面をプレイしていない場合はデータがない欠損値になっている。主成分分析をするためには、これを何らかの値で埋める必要がある。
今回は単純に「その曲の平均値」で埋めることにした。
つまり、例えばあるプレイヤーAの「Elemental Creation 鬼」のスコアが無かった場合、「Elemental Creation 鬼」をプレーしているプレイヤーのスコア平均値で代用するのだ。

ただしこの手法では、そのプレイヤーAが上手いか下手かを無視している(プレイヤーAが上手ければ、スコア平均値よりももっと高いスコアを出すと推測される)。その分だけ分析の精度は悪くなる。
単に平均値を使うよりももっと複雑な処理が必要になってくる。
スコアについての何らかのモデルを考え、それに当てはめて欠損したスコアを推測するのが良いだろう。
より分析精度を上げるためにはより適切な欠損値補完の手法が必要であろう。

もともと30曲以上のスコアを登録している人に限定したのは、欠損値が数曲であればその影響も軽微であるためだ。
(35曲のうち10曲しかプレイしていない人のデータの場合、残り25曲の欠損値を埋める必要がある。この場合はデータの中身が欠損値の補完方法に大きく左右されてしまう。したがって、元々のデータの情報が少なすぎて上手く分析できないと考えた。)


主成分分析(その1)

以上の前処理をした後に、主成分分析を実行する。
下記は第1主成分のうち、それぞれの曲の成分を示したものである(値の順にソートしている)。
f:id:soratokimitonoaidani:20180818005809p:plain
第1主成分は全ての曲についてマイナス成分だ。
主成分は「ベクトルの方向」を示しているので、全体をマイナス1倍しても問題はなく、そうすると全ての曲の成分がプラスである。
どの曲についても、曲のスコアが増えれば第1主成分も増える。……すなわち、第1主成分はプレイヤーの上手さ、「実力」の成分であると解釈して問題ないだろう。


第2主成分は以下の通りである。
f:id:soratokimitonoaidani:20180818005816p:plain
絶対値が最大の曲は「Pluto The First 鬼」で、その値は-0.867である。
……他の曲と比べて値の絶対値が大きすぎる。

主成分は長さ(要素の二乗の和)が1になるようにスケーリングされている。
その中で、(-0.867)^2 = 0.751 が「Pluto The First 鬼」の成分である。……ほとんどPluto The Firstじゃねぇか!!!

一体何が起こっているのか。
それは第1・第2主成分を散布図でプロットすると判明する。
f:id:soratokimitonoaidani:20180818010221p:plain
先ほど見たように、「Pluto The First 鬼」……そろそろフルで呼ぶのが面倒になってきたので略称の「プルファス」を使う……プルファスのスコアが極端に低いプレイヤーが2人いた。
第2主成分のうちプルファスの成分は-0.867で、負である。すなわち、プルファスのスコアが低ければ第2主成分は大きくなる。
プルファスのスコアが低く、第2主成分が極端に大きい点が2つ存在する。

プルファスのスコアが低い人に合わせて主成分ベクトルを作ってしまう事態が起きているのだ。
データ分析の用語を使うと、主成分が外れ値に強く影響されている。

プルファスのスコアと第2主成分の相関係数は実に-0.752と、強い相関を示している。ほとんど「Pluto The First 鬼」のスコアだけで第2主成分が決まっているのだ。

……それでは反対側の成分が大きい曲はどうなっているだろうか。一定の傾向が出ているだろうか。

New Century 0.164
Cosy Catastrophe 0.150
888 0.133
POSSESSION 0.131
New Decade 0.130

あんまり共通点が感じられない……

第3を飛ばして、第4主成分を見てみると、なんとなく傾向があるように見える。

f:id:soratokimitonoaidani:20180818005813p:plain
★マークを付けたのは、BPM400の8分よりも速い滝を踏まなければいけない曲である。表の下のほうに固まっている。
この条件に該当する曲は

  • EGOISM 440
  • Over The Period
  • 888
  • MAX.(period)
  • Elemental Creation
  • Pluto The First
  • Astrogazer
  • 嘆きの樹

である。(正確にはNeutrino、IXも該当するが、アクセントとしてごく一部に入っているだけなので除外しておく。)

こうしてみると最近の曲が多い。もしパラハデが最近登場していたら、絶対ラストの滝に三連符(12分)が混ざってたよな……

ともかく、第4主成分のうちこれらの曲の要素がマイナスになっているので、これらの曲のスコアが高いと第4主成分が下がる。したがって、「第4主成分が低いプレイヤーは、テンポの速い曲が得意」という傾向が導けた。第4主成分には何とか意味づけができそうだ。


主成分分析(その2)

最初の主成分分析ではあまり上手い分析ができなかった。これは全てプルファスが悪い。
あんなメチャクチャなショックアローが入っていて、あんなわけの分からない停止がある譜面が悪い。
……というわけで、プルファスの存在を除外して再度分析してみよう。

第1~第4主成分は以下の通りである。(左から第1、第2の順番)
f:id:soratokimitonoaidani:20180818005805p:plain

第1主成分は先ほどと同様、全ての成分が負であり、「プレイヤーの実力」を示している。

ここまでは同じだが、第2主成分は違ってくるはずで、一定の傾向がわかる……

絶対値が最大の曲は「Neutrino 鬼」で、その値は-0.678である。
……他の曲と比べて値の絶対値が大きすぎる。

主成分は長さ(要素の二乗の和)が1になるようにスケーリングされている。
その中で、(-0.678)^2 = 0.460 が「Neutrino 鬼」の成分である。……大きな部分を「Neutrino 鬼」が占めている。「Neutrino 鬼」のスコアと第2主成分の値の相関係数は-0.615で、強い相関を示している。

……はい。さっきのプルファスがNeutrinoに変わったような結果である。プルファスほど極端ではないけれど。

こうなる仕組み(原因)も同じで、Neutrinoにも下方の外れ値がいくつか存在したからである。外れ値の外れ方がプルファスよりも弱いので、傾向もプルファスほど極端ではない、という状況である。


なおも見ていくと、不思議なことに気がついた。
主成分のうち、絶対値の大きい要素には特定の曲が出現しやすい。このあたりの曲だ。
Cosy Catastrophe
Neutrino
DEAD END (GROOVE RADAR Special)
Tohoku EVOLVED

逆に、Come To Lifeや冥などは絶対値が小さい。
この理由は考えてみれば至極当然で、Cosy Catastropheなどの曲はスコアのばらつきが大きいからである。

それを揃え、データのばらつきを一定にするのがデータの正規化であり、分析前に実施しておく必要がある。今回は「どうせどれも100万点満点の曲のスコアなんだから同じようなもんだろう」と考えてしまって正規化をしなかったが、それが裏目に出たかっこうである。


課題:さらなる分析へ向けて

今回の分析では曲やプレイヤーの傾向を示すことが目的であったが、その目的は達成されていない。
現状では3つの課題があると考える。

課題1:外れ値の除外をしていないせいで、外れ値の影響を受けやすい

先ほどはプルファスのデータを削除した。すなわち曲(=特徴量)の方を削除していたが、外れ値の除去ではサンプルを除外するほうが一般的だ。極端に周りから離れたスコアを出しているプレイヤー(=サンプル、インスタンス)を除外したほうが良さそうだ。
最初にACE FOR ACESとENDYMIONという曲を削除した(これには正当な理由があるのだが)ので、それに引きづられて曲データを削除しようとしてしまった。

機械学習/データ分析では、その手法によって「外れ値に対して安定している・安定していない」という差が合る。
今回の主成分分析はその性質上、外れ値にとても弱い。外れ値のサンプルが1つだけでも、そこに適合させようとして主成分は変化してしまうので、これは上手く除外しなければならない。

課題2:データの正規化が必要

今の状態では、Come To Lifeや冥のデータが殆ど無視されている。これは曲ごとのスコアのばらつきに差があるためなので、分散を揃える必要がある。

課題3:欠損値の補完手法に改善の余地がある

1つ目の課題よりは重要度が低いと考える。先述の通り、単に中央値で埋めるよりももっと工夫をして欠損値を埋めたほうが、分析精度が上がるはずである。

……こうしてまとめてみると、全部データの前処理じゃないか! よく言われている「データ分析の大半は前処理だよ」を身をもって思い知った。次は前処理をちゃんとやって有意義な結果を導出したい。