霞と側杖を食らう

ほしいものです。なにかいただけるとしあわせです。[https://www.amazon.jp/hz/wishlist/ls/2EIEFTV4IKSIJ?ref_=wl_share]

Jリーグコンペの後日譚々

結論だけ、書く。  

失敗した失敗した失敗した失敗した失敗した失敗した失敗した失敗した    失敗した失敗した失敗した失敗した失敗した失敗した失敗した失敗した    失敗した失敗した失敗した失敗した失敗した  

あたしは失敗した失敗した失敗した失敗した失敗した失敗した失敗した    失敗した失敗した失敗したあたしは失敗した失敗  

今は、西暦2018年の、12月13日です。  

  

 我々は二つの大きな失敗を犯した。我々というのは、大学の後輩と二人でチームを組み、【学生限定】マイナビ × SIGNATE Student Cup 2018: Jリーグの観客動員数予測 のコンペ(Jリーグコンペ)に参加していたためだ。私が基礎分析や特徴量の考案、最終決断等を担当して、チームメイトにモデルのチューニングやコーディングを担当してもらった。二人とも、このコンペが、まともに参加する初めてのコンペであった。最初は、経験値を積むくらいの目的で軽い気持ちで参加していたのだが、順位争いができるところまで来て、躍起になって戦った。以下で、このJリーグコンペに参加した後日譚、我々の二つの主な失敗と我々の解法について述べる。

 

一つ目の失敗

 一つ目の大きな失敗は、live期間の欠損値(未来の値)の代入に関するミスだ。二つの特徴量について、代入のコードにミスがあった。正しく代入できていなかったのだ。特徴量の代入に関して、確認をするべきであった。このチェックをする余裕が無かったのは、後で述べるが、特徴量として使用していたgoogleトレンドの再現性の確保が完璧にできないことに、コンペの最終盤で気付いて、思考のリソースがそちらに完全に奪われていたためであった。もし、次にデータ分析コンペに参加したときは、欠損値の代入後のチェックを怠らないようにしたい。  

 

二つ目の失敗

 最後に提出するモデルを選ぶとき、2つのモデルで迷っていた。googleトレンドを使用しているモデルと、それを使用していないモデルだ(モデルの説明については後で述べる)。最後に選んだのは、使用する方のモデルだった。これが二つ目の失敗だ。こちらのモデルを選んだのは、提出したときに返ってきたスコアがそちらの方が良かったからだ。ぶっちぎりの1位のスコアが出てしまったのだ。浮かれてしまった。勝負は熱く振る舞っても思考は冷静に保たなければならないというのは分かっていたはずなのにだ。googleトレンドありのモデルの悪かった点は、googleトレンド値の予測をした上で、観客数を予測しないといけない点だ。googleトレンドは未来に余計なイベントが起きてしまうと全然違う値になる。今回で言えば、第33節でトーレスが得点したことや、第34節目前に神戸がビジャを獲得したことは予想外のイベントであった。このあたりが、googleトレンドの予測を大きく外した原因に思える。live期間は2節分だけで、2週間程度なので、そこまで、大きな変化は起きないだろうと高を括っていた。もう少しlive期間が長ければ外す決断をしていたかもしれない。外す可能性も考えながらも、googleトレンドありのモデルを提出する決断をしてしまった。  当たれば、とてつもないスコアが出るのではないかという甘い蜜に唆されて、冷静さを欠いてしまった。  

 

失敗と教訓

 以上の二つの失敗を反省できたのは、test期間による暫定順位は1位だったのに、live期間を含めた最終結果は47位と暴落していたからだ。live期間のスコアも、そんなはずないと思うくらいの低さだった。そんなに過学習してしまったのかと疑ったのと、もう一つのモデル(googleトレンドなしのモデル)のスコアも気になったので、予測値と実際の値で評価し直してみた。このとき、特徴量の代入にミスがあることに気が付いた。正しく代入をし直した結果、提出したモデル(googleトレンドありのモデル)でスコアを出すと、test期間は0.181(これは暫定順位に載っていたものと同じ)、live期間は0.221であった。つまり、第一の失敗を克服しても、入賞可能圏内には届かない。ところが、googleトレンドなしのモデルで試してみると、test期間は0.189、live期間は0.172となった。この計算結果を知って、脳みそが凍りついてしまった。第一の失敗と第二の失敗を両方とも犯していなければ、スコアでの評価は二位になっていたのだ。もちろん、このスコアが出ていたところでコードレビューやレポートチェックがあることも分かっているし、歴史にIFはなく、今更どうすることもできないことも分かっている。ただの負け犬の遠吠えにしかならないのも分かっている。分かっているけれど、できることなら、一か月前の自分宛てにDメールを送信したい。ママーと叫びながら、電子レンジにバナナを突っ込んでボタンを連打した。  

 こんな失敗をして、ただただ嘆いていても仕方がない。冷静さを欠いてはいけない。ブレスレットブレスレット。今回の件から我々が得るべき第一の教訓は、欠損値は埋めた後、要約統計量やプロットによって、チェックをするべきだということだ。それを怠ったため、第一の失敗が生じた。第二の教訓は、勝負事で冷静さを失ったら負けてしまうということだ。びっくりするような良いスコアが出たからといって浮かれずに、予測を使った予測の危うさ、とくに最初の予測が精度を担保しきれない場合の予測の危うさについて、もう少し冷静に考慮できていれば、第二の失敗は防げたかもしれない。どちらの失敗もコンペ経験の浅さが大きな原因だと思われる。そういう意味で言えば、当初の目的であった経験値を積むということは、かなり達成されたと言えるのではないだろうか。ガリレオフィガロ~。  

 

その他の反省点

 コンペ経験の無さゆえ、できてないことが他にもいくつかあった。  

 公開ランキングでの戦い方もよく分からなかった。早めにランキングで高いスコアを叩き出してしまうと他の強い方々が奮起してしまったら怖いなんて思ったりしたので、最終日に狙い撃ちした(他にも同じことを考える人はいるだろうと思ったし、実際いた)。フォーラムでの議論の仕方もよく分からなかった。自分のやっていることを公開して議論できるってすごいと思った。個人的に機械学習の技能に全く自信がなかったので、ドメイン知識を増やして、観客(潜在的な観客も含め)の気持ちになりきって、特徴量を考案してコンペを戦うしかないと思っていた。自分のアイデアを渡したら、機械学習つよい人たちにボコボコにされてしまうだろうと怯えていた。ランキングの狙い撃ちなどせず、フォーラムで議論できるくらいに強くありたいと思った(一方で、制度設計の問題でもあるように思わなくもない。それらを行うインセンティブがあまり働かないとは思った。強いてメリットを言うなら、フォーラムに投げることで自分がやっていることが正しいかを他人の反応でチェックできるということは挙げられる。それでも、我々のようにコンペ経験浅い人には難しい)。  

 また、再現性の確保をこまめに確認するべきであった。コンペ終盤になって、自分たちが入賞候補に入れそうだと分かって、レポートの準備を始めてから、googleトレンドが完璧に再現できないことに気付いた。スクレイピングに時間がかかるため、手元に保存していたファイルでずっと作業していた結果、スクレイピングから再現しなおすと完全に再現できないことに気付くのが遅くなってしまった。googleトレンドが完璧に再現できない点については、何度か実験してみた結果、おそらくgoogleのサービス側でわずかに変化してしまうということが分かった。大きく値が変わることはないが、取り直してみるとわずかに異なる値が得られた。このことについて、コンペ最終盤の締め切りギリギリまで悩まされた。このことをレポートに盛り込めばなんとかなるだろうというピンチの中での僅かな楽観的な安堵を求めて藁をもすがる気持ちもあって、googleトレンドありのモデルを選択してしまった。再現性のチェックもコンペでは重要だと気付かされた。
  

 我々の解法

 ヤムチャ目線でフォーラムで何もできなかった分、ここで我々の解法について書いていく。手法はXgboostを用いているが、これはチームメイトが担当していたので、とくに、特徴量の説明について詳しく書く。
 提出したスライド8枚を以下に載せる。

f:id:moratoriamuo271:20181213022503j:plain
スライド1

f:id:moratoriamuo271:20181213022558j:plain
スライド2

f:id:moratoriamuo271:20181213022637j:plain
スライド3

f:id:moratoriamuo271:20181213022700j:plain
スライド4

f:id:moratoriamuo271:20181213022725j:plain
スライド5

f:id:moratoriamuo271:20181213022746j:plain
スライド6

f:id:moratoriamuo271:20181213022803j:plain
スライド7

f:id:moratoriamuo271:20181213022820j:plain
スライド8

 メインとなる仮説はスライド3の下の方に書いてあるような情報が影響するというものだ。マクロに考えるより、ミクロに考えて、各個人が試合を観に行くか行かないかの選択をすることを想像し、その観戦者を積み上げた集計値が観戦者数となると考えればよいと思った。Jリーグによく行く人に話を聞いてみたりして、Jリーグへの熱中度が違うと、観戦の選択に関して、全然異なる振る舞いをするということ(異質性の存在)も理解できてきた。それらを意識しながら、特徴量の考案を行った。
 特徴量の一覧はスライド5とスライド6に簡単な説明や意図とともに載せてある。ここでは、おそらく他の方々が作っていないであろう特徴量についてのみ解説する。ホーム拠点とアウェイ拠点間の距離やチーム別総年俸は思いついている人はいたと思うが、スライド7に書いたように、ワールドカップの影響や災害の影響を考慮した特徴量を作った人はあまりいないのではないだろうか。
 まず、ワールドカップの影響を考慮した特徴量 Wcup_deltaについて説明する。ワールドカップはサッカーの世界最高峰の大会なのだから、情報を入れないといけないと考えた。今回のデータの期間では2006,2010,2014,2018年の4回、ワールドカップが開催されていた。ワールドカップの観客数への影響を調べてみると、ワールドカップ始まる前は観客数が増え、終わると観客数が減る傾向にあるようだ。終わった後に減るというのは予想外であった。メディア露出の増減によるものだという解釈がスライド2に挙げた日経新聞の記事に書いてあったように思うが、他の解釈としてはJリーグを応援している熱烈なサッカーファンがワールドカップ観戦で海外に行くと、そこにお金を使ったり有休を使ったりして、ワールドカップが終わった後、日本でサッカー観戦に行きにくくなるのではないかというものを考えた。他にも解釈は考えたが、このへんの解釈は因果推論の担当で、これ以上踏み込むのは止めた。
 さて、このワールドカップの影響の情報をもった特徴量のレシピを説明する。最初に、ワールドカップの開催期間の真ん中の日にそれぞれ1とフラグを立てる(ちなみに、調べてみたら、ワールドカップ開催期間はJリーグは試合を組んでいなかった。そのため、ワールドカップがある年は最終節が12月になっていることが多い。今年もそうであった)。次に、各日がその日から何日離れているか算出する。ワールドカップ前で負の値ならば、1.03をその値でべき乗し、ワールドカップ後で正の値ならば、0.97をその値でべき乗する。値が0なら1でよい。こうして作ったものをプロットしてみると、以下のグラフのような値が得られる。

f:id:moratoriamuo271:20181213032015j:plain
Wcup_deltaの下ごしらえ
こうして、ワールドカップが近づくにつれて増え、終わって時間が経つにつれて減っていくような数列が手に入る。ある程度離れるとほぼ0になっているところが味噌である。この数列を各ワールドカップに対して計算して和をとってWcup_deltaという特徴量は完成する。上に挙げたグラフのような波が4つある数列になる。これを試合の日程とマッチングさせればよい。スライド8にあるように、予測に結構効いている。
 次に、災害の影響を考慮した特徴量 disasterについて説明する。2011年の東日本大震災の影響がまず最初に思い浮かんでいたが、これを盛り込む方法がなかなか思いつかずにコンペ終盤に差し掛かっていた。特徴量考案のために、マッチレポートを読んでみたりしていたら、死者が出る規模の自然災害の後の試合では、試合前に追悼が行われることに気付いた。そこで自然災害、とくに死者が出るレベルの災害は観客数の減少させるはずで、死者数はその災害の規模の情報を持っているという考えに至り、これを自然災害から時間が経つにつれ、減衰していくような特徴量を作って、その地域とスタジアムにマッチさせれば上手くいくというアイデアが思い浮かんだ(そういえば、今年の漢字は「災」に決まったようだ)。
 このアイデアを特徴量に落とし込むレシピはWcup_deltaとほとんど似ている。ただ、災害が起きる前は、通常の大雨なら予報である程度の情報が漏れているかもしれないが、地震ゲリラ豪雨、死者が出るような災害であれば、予想ができないため情報がない。この点がWcup_deltaとは異なる。まずは、Wikipediaの日本の災害リストから、死者が出ている自然災害をピックアップし、災害発生日(死者数がある程度分かっているであろう日にち)と死者数とその地域の情報を抽出する。
f:id:moratoriamuo271:20181213041006p:plain
災害情報
この地域とチーム(ホームとアウェイ別)で照合して、災害発生日翌日に死者数の値を代入する。あとは1日経つにつれて0.98を乗じていき、数列を作って、試合日とマッチングさせればよい。これもまた、スライド8にあるように予測に効いている。

 以上の2つは、レシピ含め、独創性があるのではないかと思っている。1.03や0.97, 0.98のような値は減衰率と我々は呼んでいた。この考えは他の特徴量にも使っている。値は、効果の影響がどれくらい残るかを想像しながら、何通りか試してCVで決定した。減衰率の発想は、経済学の動学モデルで、割引現在価値や利子率の考慮をよくするので、思いついた。特徴量考案は、私が社会科学の畑の出身で(チームメイトは工学の畑出身)、人間の選択について考える訓練を積んでいたからか、やりやすく、思い付いた特徴量を入れると予測精度が予想通り上がっていく様はとても痛快であった。人間の行動に関する予測や分析は社会科学や人文科学の人間をチームに入れると良いのではないだろうか。画像のコンペや自然科学寄りのコンペでは、少なくとも私は戦力になりにくそうだと思った。そう思ったし、今回はチャンスだったんだと思った。勝ちたかった。ドラゴンボールはどこにあるのだろうか。

我々のモデルの限界と未実行の解法

 以上のような解法で今回のコンペに挑んだ。googleトレンドについては上に書いた通り限界なのは分かっている。他に、終盤の優勝争いや残留争いの情報を明示的に取り込めていなかった。順位争いは入れていたが、優勝争いと残留争いの効果を明示的に取り込めるような特徴量が思いつかなかった。とくに今回残留争いが激しかったので、それを組み込めれば、もっと良い予測精度を叩き出せただろう。live期間は33節と34節なのだから、そこにもっと思考のリソースを割くべきだった。シーズン途中に加入してきた選手の情報を上手く組み込む特徴量があれば良かったのだが、それをgoogleトレンドに頼ってしまった。他にもっと良い策があったかもしれないが思い付かなかった。
 未遂に終わった解法が一つあって、それは、マッチレポートをスクレイピングしてテキストマイニングを行うというものだ。災害の特徴量を思いつくきっかけになったのはマッチレポートであったと書いたが、あれを早いうちに気付いて、マッチレポートから単語の頻度分析など行えば、特徴量考案に一役二役買っていたかもしれない。これを実行する時間と余裕がなかった。発想としては面白いし、こんな解法を思いついた人はいないのではないかと思い、ここに記しておく。あとはタイムマシンの作成か。

終わりに

 つらつらと後日譚を書いてきましたが、こんな量を一気に書きあげてしまうくらい反省しており、反省から大反省へ、そしてその大反省は大猛省へと昇華させました。この大猛省を活かして、今後の人生を歩んでいきたいと思います。また、データ分析コンペの難しさ(仕事しながらコンペいくつも参加している人の凄さに驚きました。半端ないって。)に加えて、面白さ、奥深さを知ることができました。やってみないと分からないですね、これは。食わず嫌いせずに参加してみてよかったと思っています。
 この機会を与えてくださったSIGNATEさん、マイナビさん、ありがとうございました。感謝です。そして、入賞した皆さま、おめでとうございます。参加した皆さま、お疲れ様でした。もしもお会いする機会があれば、後日譚をお話ししたいと思っています。さらば読者よ、命あらばまた他日。元気で行かう。絶望するな。では、失敬。