たかいとの備忘録

自然言語処理や機械学習のことについて学んだことを忘れないように書いていけたらと思います.

2022年振り返り

はじめに

今年一年は,本当にあっという間の一年でした.

本業が忙しく,どのコンペも中途半端な結果となってしまったことが反省点です.

今年の良かった点を挙げるとすれば,オフラインでのイベントが増え,いろいろな方と直接お会いすることができたことかと思います.

今年の反省を活かして,来年は念願のkaggleでソロ金を獲得するためにも,簡単に振り返りをしておきたいと思います.

参加していたコンペ

kaggle

kaggle以外

コンペ振り返り

ちょっとデータを触っただけのコンペはもう少しあるのですが,それらを含めても,いいところまで行けたコンペが一つもないのが反省点です.

それなりに経験も溜まってきたので,そこそこの順位はとれるようになりつつありますが,金圏にいる参加者とは大きな実力の差を感じております.

とはいえ,実務に活かすことができたりもしているので,引き続き参加しながら少しずつ実力をつけていけたらと思います.

今年一年は,実力不足もありソロで参加を続けておりましたが,そろそろチームでも参加したいと思っておりますので,気軽にDMとかいただけると幸いです.

また,上記以外だとkaggle daysに参加しておりましたが,4hという限られた時間のコンペは新鮮でした.

コード管理などが雑になっているので,今後に向けて,コードの整備を進めようと思うきっかけになりました.

社会人としての振り返り

今年もあまり対外発表などを行えませんでしたが,来年はいろいろと取り組みを共有できたらと思っており,準備を進めております.

3月の言語処理学会では,金融・経済ドメインのための言語処理 のテーマセッションもあるので,いろいろとディスカッションできるのを楽しみにしております.

また,インターンの対応などを行いましたが,優秀な学生さんばかりで,刺激を受けることができました.

おわりに

忙しい一年だったなと思います.(おそろしく早い1年,オレでなきゃ見逃しちゃうね)

気づいたら一年が終わったので,来年は月ごとに目標も決めていきたいなと思っています.

これまでに比べて,長期的な目線で統計学や金融分野の勉強に取り組む時間も増えてきたので,来年は語学も加えたいなと思っております.

また,ブログの記事などをまったく挙げられずに一年が経過していたので,来年はもう少し何か書けたらと思っております.

あとは,あいかわらず引きこもり気味な一年だったので,来年はもっと多くの人とご飯とか行けたらいいなと思っていますので,よかったら声かけてください.

今年もたくさんの人にお世話になりましたが,来年もどうぞよろしくお願いいたします.

2021年振り返り

はじめに

今年一年は博士論文審査に始まり,都内での一人暮らし開始,社会人生活スタートなどあっという間の一年間でした.

今年の反省などを踏まえて2022年はより充実した一年を送れるように,今年一年を簡潔に振り返ることにしました.

参加していたコンペ

コンペ振り返り

ちょっとやっただけのコンペもあれば,全力で取り組んだコンペもありました.

全力で取り組んだコンペに関しては,記事書いたりもしているので,そちらを読んで頂ければ幸いです.

いろいろなコンペに参加してきましたが,今年一番参加して良かったと思ったのは,atmaCup#12だったと思います.

これから始めたいと思っている人にコンペを勧めたくても,シンプルなテーブルデータコンペが非常に少なくなっているので,コンペを始める取っ掛かりとなるようなコンペが今後も開催されるといいなと個人的には思っております.

今年一年のkaggleで開催されていたテーブルデータコンペも時系列的なデータのもので,自身はなかなか結果が出せず苦戦しました.

社会人一年目ということもあり,いろいろ忙しい中で頑張ったようにも見えますが,目標にしていたKaggleでのソロ金を取ることができておらず,11月からはあまり本腰入れて取り組めていませんでした.

コンペで結果を残せていない理由として,

  1. 深層学習
  2. 語学力,知識量
  3. 実装コード管理
  4. マシンパワー

が上位の参加者に比べて不足しているように感じております.

まず深層学習の層の数,ハイパラ,optimizerなどをどう設定すればいいのかが,あまりよくわからず戦えていないように,どのコンペに参加していても感じた一年でした.

今年から本腰を入れてkaggleを始めましたが,語学力&知識量の不足でディスカッションの内容を理解できないことが多く,敗因になっています.

また,kaggleは比較的に数か月間のコンペが多く,数週間経つと自身が何をやっていたかや,何のための実装なのかがわからなくなることが多く,後半まで続かないコンペが多くなってしまったため,コードの書き方や管理の仕方をしっかり考える必要を感じております.

来年はこれらの反省を活かして,戦っていきたいと思っており,勝率がもう少し上がったら,Google Colaboratoryに課金するかボーナスでGPU買いたいと思っています.

今年はコンペに参加することで,いろいろな方と関わる機会がありましたが,来年も続けていく予定ですので,引き続き対戦よろしくお願いいたします.

社会人としての振り返り

あんまり書けることがそもそもないですが,とりあえず長い学生生活で失った社会性を取り戻すことができつつあります.

来年はもう少しいろいろなことに挑戦し,外部発表なども行えるように成果を残していきたいと思っています.

その他

一人暮らしは特に問題なく生活できていますが,部屋が散らかる一方なのと,ネコのいない生活はずっとストレスになっています.

食事と運動だけは気を使って,何とか体重をキープできているので来年も引き続き意識した生活を心がけることができたらと思います.

11月くらいまでは,土日のほとんどの時間を自己研鑽に充てていましたが,コロナも落ち着いていたため,12月はコロナ落ち着いたらご飯会や飲み会しようと話していた人と会を開くことができて充実していました.

この調子でコロナが収束して,気軽に飲み行ける日常に戻ったらいいなと思いますし,来年はもっと多くの人と飲みに行けたらいいなと思っていますので,よかったら声かけてください.

おわりに

今年一年,プライベートの充実はなかったものの,やれることをやりきることができたかなと思います.

来年は結果を意識しつつも,長期的な成長のために統計などを基礎から学び直したいと思っています.

今年もたくさんの人にお世話になりましたが,来年もどうぞよろしくお願いいたします.

atmaCup#12参加レポート

はじめに

2021年10月15日(金)〜10月24日(日)に開催されたatmaCup#12に参加してました.

前回抽選に外れて参加できなかったatmaCup×Sansanコンペの第2回ということで,抽選通るか心配でしたが,今回は当選し参加することができました.

個人的に前回参加できなくて残念に思っていましたが,今回参加することができて様々なDiscussionを読めたことで,より前回参加できなかったことを残念に感じたので,参加枠を増やす or 前回コンペ上位33名は確定枠とかにしてもいいのではと少し思いました.

今回のコンペは,秘密保持契約(NDA)の関係上コンペ内容などはオープンにできないので,解法などにはほとんど触れないものとなっております.

この記事では,主に自身のお気持ちと,何が足りなかったのかを整理できたらと思っているので,もう少し実用的なものが読みたい方は,チトセナガノさんのatmaCup #12に参加して覚えたことメモ①特徴量作成atmaCup #12に参加して覚えたことメモ②lightGBM関係がまとまっていて参考になるかと思いますので,共有させて頂きます.

時系列でコンペを簡単に振り返る

序盤

初日サブする予定が,珍しく社会性を発揮して帰宅が深夜だったため,とりあえずスタートから24時間以内に1サブ. 今回,いろいろな方法を試せるように無駄サブをしないことを常に意識していました.

序盤は強い方が,安定の位置にいた印象でした. この時点では,takoiさんの0.80を意識して,手元のCVがある一定値を超えたらサブしようと思っていました.

月曜日,仕事から帰宅中にLB見たら,ベースラインがヤンチャしてて思わずツイートしてしまいました.

火曜日のサブで少しLBを上ることができましたが,なかなかベースラインが強敵でした. このときすでに,0.85出しているころんびあさんは,本当にすごいなと思います. ただ,自身もこのあたりで0.85出すための案はあったので,疲れた身体に鞭打って,ひたすら実装をしていました.

中盤

何とかベースラインを超すことができました!

終盤

最終日24日残り18時間を切ったところで,LB一位になりました.

みんな大好きBarChartRaceで後から確認したところprivateスコアも一時的に一位でした.

f:id:takaito0423:20211104224837p:plain
BarChartRace

そして,その12時間後くらいに...

流石に残りの時間で,このスコア差を詰める仕込みが自身にはありませんでした.

結果

1位 くろさん

2位 paoさん

3位 Pirototoさん

自身は念願のメダルに届きませんでした.

今回のコンペ一人振り返り

良かった点

一時的だが終盤にLB, privateで1位に飛び出せたこと

序盤スタートダッシュでLB1位は何回か経験したが,コンペ終盤に瞬間的にでも1位になれたのは初でしたので,正直嬉しかったです.

序盤にしっかり特徴量を作り込むことができた

短期間コンペで戦うにあたり,序盤で必要となる特徴量を一通り作ることができたおかげで,中盤以降はいろいろな工夫を考える時間&実装する時間をたくさん確保することができました. ただ,今回お題がシンプルなお題であったため,複雑な特徴量がたくさんあるコンペで戦うには,もう少しEDAの力を鍛える必要は感じています.

サブの温存

今回はチームを組む予定はありませんでしたが,チームを後半に組んだり,後から試したいことが沸いてきた時のために,CVのスコアなどからサブを温存することができました. 自身は上位にいるとき,サブ数に余裕がある人がLB上がってくるとプレッシャーを感じるタイプなので,プレッシャーをかける意味でも,サブ数温存は効果があると信じています(笑)

Discussionへの投稿

いつも勉強させて頂いてばかりなので,今回はDiscussionも積極的に投稿しました. いくつか投稿しましたが,多くのいいねを頂きとても励みになりました.

f:id:takaito0423:20211104231305p:plain
Discussion

いくつかDiscussionを挙げたのですが,一番多くいいねを頂いたのは,#10 [初心者歓迎!] atmaCup@pao さんが挙げていたコンペの戦い方を考えるというDiscussionを参考に作った「#12 Sansan × atmaCupの戦い方を考える」というDiscussionでした.

実際このDiscussionには,総合優勝&社会人優勝の くろさん,学生優勝のころんびあさんが使用している特徴量作り,モデル選択,工夫などにつながるヒントが多く含まれていて,いいものを投稿できたのではないかと,手ごたえを感じています.

反省点

NN系のモデルでの精度が出せない

モデルに対する理解が浅く,ハイパーパラメータなどの感覚がまったくわからないため,NN系の精度がまったく出せないのは,何とかしないとまずいなと感じています. 実力が伴っていないのに,贅沢欲張りセットでData Augmentationなども同時にやろうとして,うまくいかず,結果メダル圏内から追い出されてしまったので,これを機にNNを使えるように勉強し直そうと思います. あとは計算資源に乏しく,GPU温存してCPUで様子見ていて時間がかかっていたので,そのあたりのコンペ戦う環境も少し検討しています.(基本CPUで戦っているので)

油断

正直,最終日迎えた時点で0.87手前での戦いになると思っていたので,あたるかわからない大幅なスコア修正より,確実にでもわずかなスコア修正ができる無難な方法を試すことに切り替えてしまったのは,一つの反省点です.

感想

序盤,中盤,終盤と多くの方とLBで競うことができ,Discussionでコメントのやり取りもでき,とても楽しいコンペでした!

正直,メダルまで手が届きそうだったので,悲しい気持ちもありますが,自身の能力にまだ伸ばせる余地があると信じて,引き続き頑張りたいと思います.

コンペを通して,アイデアをすべて実装する力と計算資源があれば,もう少し戦えるようになるなと実感することができました.

このような機会を作って頂いたatmaさんとSansanさんに感謝感謝です. 第3回 atmaCup×Sansan楽しみにしております!

また,コンペに楽しく参加できたのは,他の参加者あってのことなので,DiscussionやTwitterでコメントのやり取りをしてくれた方々にも,本当に感謝しています.

再びコンペでいい戦いができるように,もっと強くなれるように頑張りますので,また対戦どうぞよろしくお願いいたします!

Kaggle参加レポート Google Smartphone Decimeter Challenge

はじめに

5/12~8/4の期間で開催されていた「Google Smartphone Decimeter Challenge」に参加したのでその参加レポートとなっております.

結果は金に0.01及ばずといった,悔しい思いをする結果となりましたが,自身の実力不足な面をしっかり受け止め,もっと確実に上位に入れるように成長したいと思いました.

この記事を作成した目的は,自身が後にこんなこともあったなと振り返れるようにもありますが,これからKaggleを始めようとしている人や,登録したもののハードルを感じて参加できずにいるような人に読んでもらえたらと思っています.

お恥ずかしながら,自身もKaggleに登録したものの1年くらいまともに手を出せずにいました.

これまでまともに参加できなかった理由は,まず仕組みがよくわからない,ディスカッションや公開コードが豊富だが,言語が英語であり,さらに数学的な知識が足りず理解ができないものが多い,そもそもの与えられたデータがよくわからない,データサイズ大き過ぎて...,などなど多くありました.

一応,大学院まで出ていますが,偏差値50程度の大学出身者としては,この記事を書いている今でもハードルが高いなと感じてはおります.

そんな自身ですが,今回のコンペはkaggleに登録して初めて真剣に取り組んだコンペであり,自身のように決して高度な数学に関する知識があるわけでもなく,英語が苦手でも,あと少しで金圏に入れるようなところまで戦うことができることもあることを知ってもらえたと思い記事を作成しました.

記事を読んだことで,kaggleに限らずコンペに参加するようになったよって人が一人でもいたら嬉しく思います.

コンペ概要

詳しくは直接ページを見に行ってもらいたいのですが,車の中にあるスマホの位置情報を推定するコンペでした.

indoorコンペと呼ばれる位置情報推定のコンペが終わった後に開催されたので,参加者からはoutdoorと呼ばれておりました.

データとしては衛星の情報やコンペのホストの方が計算した座標の推定値が与えられておりました(自身は最終的にこのデータと真の値しか使いませんでした).

序盤(5月)

とりあえず,参加申込をして取り組み始めました.

参加して最初に思ったことは,列の意味がよくわからないなってことでした(ドメイン&語学力不足).

公開notebookはカルマンフィルタ使っておりましたが,カルマンフィルタをよくわかっていなかったので少し勉強しましたが,しっかりとした知識のない中,今回のコンペ期間中にしっかり理解し,活かしきることができるかわからなかったので,まずはいったん使うのを辞めて,他の方法で何とかならないか試してみることにしました.

このあたりに関しては賛否両論あると思います.

こういったことを続けてしまっているので,未だにつよつよになれていないとも思いますので,実力をつけるという意味では,しっかり向き合うべきだなと思います.

ただ一方で,数式を理解できる能力や前提知識などには個人差があると思いますので,無理に公開されているものを全部理解しなくてはとなって,結果続かないよりは,多少のわりきりも必要なのかなと思います.

自身はLSTMのモデルをよく使用することもあり,それらのモデルを序盤は試しておりました.

個人的にですが,コンペ序盤は運よく上位に入れたりするので,モチベーションを保つ上でも序盤に一度手を付けるのをオススメしたいです(序盤でLBの結果だとしても,やっぱり上位に名前があるのは嬉しいものです).

あとは無難な後処理として,前後の値で平均を取る移動平均をとったりすることで少しスコアを伸ばしていきました.

5月には最初のチームを組むかどうかの葛藤がありました.

自身はソロ参加を選びましたが,チームを組んで参加するのも一つのモチベーションにもなると思います.

完全に余談ですが,ころんびあさん始め,優秀な学生の方が本当に多いので,自身ももっと頑張って実力をつけたいなとモチベに繋がっているので本当に感謝しています.

中盤(6月)

5月の終わりにいろいろ試した結果,あまりスコア改善しなかったので,上位のスコアを考えると,根本的に方法を切り替える必要があるなと思い始めました.

ただ新卒で忙しいことなどもあり,少し目を離している間に順位がかなり落ちていました.

原因はスコアの良い公開notebookが公開されたのが理由だったので,それをとりあえず超えたいというモチベーションで取り組みました.

とりあえずスコアを更新したものの,上位とは未だ乖離がある状態でした.

このあたりの取り組みとしては,外れ値の除去やスタート地点とゴール地点を処理する方法をいろいろ試したり,ブレの大きい特定のエリア(学習データにおけるSJC)は,真の値で道がどのあたりにあるのかわかるので,その道の近くに補正するといった後処理を行っておりました.

f:id:takaito0423:20210807223610p:plain
上: 修正前,下: 修正後

ただ,根本的にこのままでは勝てないなと思い,いったん1から方法を考えなおすことにしました.

この土日で,もっとシンプルな方法でいろいろ試せることがあるなと思ったので,それらを手書きでノートにメモしておきました.

そこからは実装をコツコツ,平日の仕事終わりなどに行っていました.

終盤(7月)

ストックした方法をいろいろ試した結果,スコアを伸ばすことができました.

試したのは,まず速度を点と点の距離とそれにかかった時間から計算し,真の値の移動速度の最大値の1.5倍以上のものは外れ値判定をしました.

また,その前後3点も外れ値の近くで信頼できる情報か怪しいため外れ値判定をしました.

そして,それらの外れ値を除いた上で,残った点の中でぶれが大きそうな点の判定を行う関数を実装しました.

内容はいたってシンプルで,まずある点を含めて前後2点を用いて,時間を説明変数とし,各latDegとlngDegの値を目的変数とする単回帰を行い,その回帰直線との誤差をすべての点で計算して保存していきます.

これにより,スタート地点とゴール地点は3回分,それらの点の隣接点は4回分,他の全ての点は5回分の回帰の誤差があるため,それらの回数で誤差の合計を割ることで,その点の前後の点に対する当てはまりの良さを示す値を計算することができます.

この値が大きい値はすなわち誤差が大きい点であり,あまり信頼すべき点でないため,外れ値判定を行いました.

そしてこれら2つのステップで外した値を除いた上で,次の処理を行うことで,座標の修正と外れ値として外していた座標の値の推定を行いました.

まず,ある点を含めて前後5点を用いて,時間と時間の二乗を説明変数とし,各latDegとlngDegの値を目的変数とする重回帰を行い,その回帰曲線で各latDegとlngDegの値を推定します.

時間と時間の二乗を説明変数としているのは,正解データを確認した際に,直線よりも二次関数の方が当てはまりは良さそうな点が多いと思ったので,二次関数を利用しました.

以下に示した画像は,赤色の点がある時間での真の各座標の値を示しており,前後10か所の点を表示していますが,前後5点程度のさらに局所的な区間においては,二次関数で当てはめると良さげに見えるかなと思います.

f:id:takaito0423:20210807125144p:plain
X軸: 時間,Y軸: lngDeg

f:id:takaito0423:20210807125922p:plain
X軸: 時間,Y軸: latDeg

f:id:takaito0423:20210807130018p:plain
X軸: lngDeg,Y軸: latDeg

また,この重回帰に使用した前後5点の間に外れ値として除かれているデータがある場合には,時間の情報を入力することで各latDegとlngDegの値を推定することができます.

これをすべての点で行うことで,各点に推定した値がいくつかある状態になります.

後はそれらを各点で平均をとることで,ブレが小さくなった座標を得ることができました.

ここから機械学習を使用していくのですが,ここで一つ気になったのが,学習データの'2020-05-29-US-MTV-2'の存在です.

このデータはもともと与えられた予測値では途中で停止しているのですが,真の値を見ると動き続けており,testデータでもしこういった箇所があったとしても,予測するのは不可能だなと思い,学習データの最初のスタート地点付近とゴール地点において,真の値との誤差が異常に大きい点が連続し続けるような点があるデータに限っては,真の値と予測値の値がある程度の誤差になるところまでデータを除去するようにしました('2020-05-29-US-MTV-2'のみでした).

下の画像の赤い部分が真の値ですが,黒い部分は途中で止まってしまっています.

f:id:takaito0423:20210807131502p:plain
X軸: lngDeg,Y軸: latDeg (2020-05-29-US-MTV-2_Pixel4XL)

学習データの異常値も削除できたので,ここから第一段階の機械学習利用です.

この段階では先ほどのスタート地点とゴール地点のブレが非常に気になったので,停止しているのかどうかを予測する二値分類を行い,スタート地点付近の動き出しまでの点,ゴール地点で停止を開始した点を特定し,停止している間の点の平均値を算出,元の値と0.999 : 0.001の割合で加重平均を取りました.

二値分類はLightGBMを使用し,特徴量は推定値から計算した速度,加速度,進行方向の変化(cos, sin),前後の座標情報を使用した主成分分析の第一主成分と第二主成分と第一主成分÷第二主成分,これらを前後30点ほど予測に使用できるようにshift特徴量を用いました.

まず大切なことは,先に外れ値の処理などをかけておくことで,そうしないと速度の情報などの質が落ちてしまいます.

今回のコンペでは失敗した多くの方法を含めると50以上の処理を作成しましたが,処理をかける順番はいろいろと試行錯誤しました.

特徴量に関しては,cosの値はけっこうこの後も重宝しました.

今回は車の移動ということで,急激な方向の転換はほとんど真の値に存在しなかったため,この推定座標のcosの値は0.1未満のものはたいてい何か問題が起こっているので,そういった点を調整するための関数を後半はいろいろ作成しました.

f:id:takaito0423:20210807134557p:plain
X軸: lngDeg,Y軸: latDeg

座標を主成分分析したものを入れたお気持ちは,スピードを出してまっすぐ進んでいる最中の点は第一主成分は大きく,第二主成分が小さくなり,停止している点は第一主成分も第二主成分も小さくその割り算した結果も1に近くなるなど,いろいろ特徴を捉えることができるような気がして入れました.

多くの参加者はstop meanで停止している地点で平均をとっていたようでしたが,自身はスタート地点とゴール地点のみにしておりました.

理由は停止中に一度ほんの少し進んでまた停止することとかもある気がし(道を曲がるときとか),そのあたりがうまく捉えられて二か所の地点でstop meanできればいいが,できるとも限らないため,そのままにしていました.

もちろんstop meanしない代わりに他の調整をかける関数をこの後たくさん実装してます.

この次は,学習データのSJCの地点はブレがとても大きいため,この真の値を利用して道のある位置を特定し,その道上の点と元の値とを0.999 : 0.001の割合で加重平均し補正する処理を行いました.

最後に,collectionごとをまとめて調整しました.

こちらも二次関数で調整することに自身はしました.

collectionごとの処理は三段階構成となっています.

まずcollectionごとのある時間から,その前後 t 秒の推定した点を用いて,時間と時間の二乗を説明変数とし,各latDegとlngDegの値を目的変数とする重回帰を行い,その回帰曲線で各latDegとlngDegの値の誤差を推定し,誤差の二乗が一番大きい点の除きました.

その上で,もう一度重回帰を行い,その回帰曲線で各latDegとlngDegの値の誤差の二乗を推定し,各点の誤差の二乗を保存していきます.

これらのすべての点で行い,各点の誤差の二乗の値の平均をとり,その誤差を用いてweightを作成しました.

最後にcollectionごとのある時間から,その前後 t 秒の推定した点を用いて,時間と時間の二乗を説明変数とし,先ほど求めたweightを利用して,各latDegとlngDegの値を目的変数とする重回帰を行い,その回帰曲線で各latDegとlngDegの値を推定しました.

このcollectionごとの処理がとても大事でこれにより,スコアを大きく伸ばすことができました.

ただ,この頃には5.0を切ってもまだまだ上に参加者がたくさんいたので,金圏に戻れるように残っていたアイデアを実装し続けていました.

そして,7月の後半に1mの改善を達成し,金圏に一度戻ることができました.

この結果の大きな要因は2つあります.

まず1つ目の要因はスタート地点とゴール地点の処理までを行った後に,stop meanの代わりに下の画像に示すような速度が極端に遅い点のブレを調整することでした.

f:id:takaito0423:20210807211156p:plain
X軸: lngDeg,Y軸: latDeg

本当は下のような箇所も調整できるようにしたかったのですが,この時点ではカーブを曲がっているような箇所にも影響を与えてしまう方法しか思いつかず,このような点は最後のギリギリで調整する関数を実装しました.

f:id:takaito0423:20210807211748p:plain
X軸: lngDeg,Y軸: latDeg

これまでは時間との関係を見てきましたが,X軸: lngDeg,Y軸: latDegで明らかに直線で動いているはずがブレてしまっている点を直線上に調整する必要があるため,これらの点の集合とこれらの点の集合の前後の点との関係性から,直線上に補正するかどうかを判定します.

先ほどのLightGBMモデルで停止判定されている箇所で調整すべき点の候補はわかっているため,修正すべき点の連続している部分とその前後の点を特定します.

わかりにくいですが,さきほどの画像の緑色の点が調整すべき連続した点と隣接している点であり,青色が調整すべき点の開始点と終了点となっています.

真ん中あたりの黒い点は修正対象の点であり,北と南の黒い点は緑の点の前と後の点となっています.

まずこの青い点を結んでできる直線と緑色の点を結んでできる直線の交点を求めます.

求めた交点は,先ほどの図の赤い点となっています.この赤い点が緑の2点によって作られる長方形の中にあれば,この調整すべき点を調整することにしました.

まず調整その1として,ばらついている点を青い点と青い点の間をゆっくり移動しているようにしたかったので,中心に点が集まるように青い2点の直線上に,配置します.

例えば,6点をこの直線上に配置するのは,直線を4:3:2:1:2:3:4に分ける点に調整します.

このような調整を行ったのが以下の図になります.

f:id:takaito0423:20210807213552p:plain
調整その1

ここからさらに,止まっている点の情報自体があまり信用ならないので,緑の点の直線上に調整を行いました.

その調整を行ったのが以下の図です.

f:id:takaito0423:20210807214319p:plain
調整その2

もちろん,この青い点も実はあまり正確でないことが多いため,後半ではもう少し長期的なスパンで,調整を行いましたが,この時点ではこの程度にとどめておきました.

2つ目の要因は,この段階でLightGBMやCatBoostを使用して,座標のずれを修正しました.

collectionをまとめて,二次関数で補正した後にこれらのモデルを使おうとすると,学習データに似たようなデータばかりになり,過学習しやすく精度を上げることができなかったので,あえてこの段階でこれらのモデルを用いて,真の値と現在の推定値の各lngDegとlatDegがどの程度ずれているかを目的変数として予測し,その予測した値を用いて,調整を行いました.

そしてその後は,これまで通り,SJCエリアの真の道への補完を行い,collectionをまとめて,二次関数で補正した結果,大きくスコアを伸ばすことができました.

この後,上位の豪華メンバーチームからチームマージのお誘いがあり,どうするべきかとても悩みました.

自身がこの先忙しく,どこまでやれるかわからないことや,豪華チームにマージしてもらったことで,外から自身がどのくらいチームに寄与しているのかが見えないとも思い,ソロで最後まで走り切ることを決意しました(もう少し期間が残っていて,自身に取り組む時間があれば成長のためにチームマージをさせてもらった可能性はありました).

チームマージはしませんでしたが,チームマージのお誘いは本当に嬉しくて,個人的には泣きそうでした.

実力がもっとついて,しっかりとコンペ終盤にもアイデアをどんどん出せるように成長した暁には,尊敬つよつよ勢の方ともチームを組んで一緒にコンペを闘い抜いてみたいと思っているので,頑張って成長できたらと思っています.

最終盤(8月)

ない時間を無理矢理作って,いろいろ試していました.

ただ,そこまで大きな影響があったものはあまりないので,本当にざっくり有効だったものを挙げます.

直線補完

先ほど示した以下のような箇所がcollectionごとに処理した後にも残っていたので,こういった箇所を直線で調整しました.

f:id:takaito0423:20210807211748p:plain
X軸: lngDeg,Y軸: latDeg

先ほどは調整すべき候補の点と隣接している二点の青い点のみを用いていましたが,そこから距離が r 離れている点までを確認し,一番離れた点同士の進行方向がまず一緒かどうかをコサイン類似度で確認しました.

これにより,カーブしている点の近くが大きく真の値から外れることがなくなります.

あとは,これらの調整すべき点をどこの点の情報を用いて補完するのかをいろいろ試しました.

f:id:takaito0423:20210807235512p:plain
速度が遅い区間の直線補正

真の座標を道の情報として,道の上に補正を行う

まずSJCエリアは,かなりブレが大きく,単純に道の上に補正するだけだと,本来右に曲がっているのに,一度左に曲がってその後Uターンして右に向かうみたいなことになってしまっていたので,どこからどこに向かっているのかの情報を加味した道の上への調整を行うようにした.

このどこからどこに向かっているのかを判定するために,雑なノードをまず推定しました.

f:id:takaito0423:20210807224112p:plain
SJC

これで真の道がどこからどこへ向かっているのかがわかり,その動きと同じ動きをしている点をその道の上に調整することができました.

あとは学習データの'2021-04-29-US-MTV-1'のエリアもエリアとの一致度を計算することで,'2021-04-28-US-MTV-1','2021-04-29-US-MTV-1','2021-03-16-US-RWC-2','2021-04-21-US-MTV-1','2021-04-28-US-MTV-2','2021-04-29-US-MTV-2'は学習データの真の座標を用いて,極端に離れている点以外は,道の上に補正を行いました.

他のエリアはCV,LBともに悪化するため,いろいろ工夫を行いましたが,ここでstop meanを行っていなかったことにより,点の進行方向が不安定な箇所が残っており,本来正しくない反対車線の真の道などに調整されてしまうなどの対策が間に合わず,使えませんでした(SJC同様,ノード作成すればうまくいった可能性もあるかもしれないです).

collectionごとの二次曲線補正にスマホの精度情報をweightとして加える

もともと与えられていた座標の値とcollectionごとの二次曲線補正を行う前の座標の値の誤差を計算し,この誤差が同一collectionで大きいものと,一番小さいものを比較して,その割り算の結果が大きいものは,もともとの情報が不確かなため,その割り算の結果を利用してweightがさらに小さくなるように調整を行った.

アンサンブル

collectionごとの二次曲線補正をするための使用するデータの時間のレンジをいろいろ変えたり,二次関数を三次関数に変更したものなども似たような精度を出していたので,いくつか試したものをアンサンブルしました.

本当はもっと序盤の処理などもいろいろ値を変えて試して,アンサンブルに利用したかったが間に合わず.

結果

Public 19 / Private12

最後の方にPublicの順位上がらず,有給休暇をとるのを辞めてしまったことは後悔しています.

部署の先輩方に有給休暇とって臨めばいいのにって言われてましたが,金圏から押し出されていたのでそこまでするのは流石にと思っていました.

たぶんこれがLBで12位なら有給休暇とっていましたが,過ぎたことを嘆いてもしょうがないので,もっと強くなれるように頑張ります.

感想

初メダルで喜べるはずが,金圏にわずかに届かなかったことによりしばらくはショックが上回ってしまいました.

ただ,明らかに自身の実力以上の結果ですので,ここで慢心せず,もっと実力をつけるように天から12位を与えられたような気がします(精進してもっと強くなるしか).

コンペを走り切った感想としては,ソロで取り組むには,少ししんどさがあるコンペだったかなと思います.

自身は結局,GNSS周りのデータは全く使わず前処理,後処理で戦うことを決めましたが,こちらも使うには自身の場合,少なくとももう一か月必要でした(それでもそっちで結果出せていたかは...).

ただ最終的には金圏にソロの方々がたくさん入っていたので,本当にすごいなと思います.

テストデータの推定値は可視化することができるので,それらのざっくりとしたチェックなどを行ったりもshakedown対策に必要でした.

特に深層学習モデルを学習させておくみたいなインターバルがないので,一生懸命コードを書いて実行を行うとすぐに結果が返ってくるため,それらの処理が有効そうかどうかのチェックなどを一息つく間もなく行い,次の処理を試すみたいな感じだったので,自身は大変でした.

上位の方々のように,ドメイン知識で取り組んで行けたら,また全然違った闘い方になると思います.

あとあまりにも最終盤時間がとれなかったため,最終日はオールで取り組んだのですが,あまりの眠さで=と==を書き間違えて,このミスに気がつくのに1時間以上かかってしまいました.

このあたりの時間のロスがなければ,もっと複数パターンの処理の組み合わせと,処理に使用するレンジを変えたものを試して,アンサンブルができたので,しっかり反省して次回は余裕をもった最終日を迎えられるようにできたらと思います.

おわりに

いろいろと書いてきましたが,この記事で伝えたいことは,コンペによっては,あまり難しいこと知らなくても,自身がちゃんと理解しているものをしっかり使えば戦えるし,ディスカッションに書いてあることを全部理解し実装する必要性も初心者のうちはないのかなってことです.

もちろん,上に書いたことができるに越したことはありませんが,誰もがそんなに最初から強いわけでもなく,それをハードルに感じてやめてしまうにはもったいないのかなと思います.

正直,お恥ずかしい話ですが,自身の最終的に提出したものは,回帰分析と主成分分析,コンペでは一般的なLightGBMくらいしか使用していませんし,ディスカッションも実はあまり追っていませんでした.

なので,難しいことを全部理解しないといけないのかとは思わず,自身が興味のあるものなどを中心に進めて行ければいいのかなと思います(流石に自身はそろそろ強くなるために,その段階を卒業すべきですが...).

そもそも,貴重な時間をコンペなどに割いている時点で十分すごいことだと思いますし,無理のない範囲でコンペに参加して楽しめたらいいのかなと思います.

いろいろあり,金圏に一時期は入れたりもしましたが,50位くらいに離されたり,最終盤LBスコア全然伸ばすことができなかったりと,挫けそうになる盤面も多かったですが,いろいろな方からの応援もあり,最後まで走り切ることができました.

コンペを一緒に走り切った方々,応援していただいた方々に感謝してこの記事を締めくくりたいと思います.

最後まで読んで頂きありがとうございました!

atmaCup#10参加レポート

はじめに

2021年3月5日(金)〜3月13日(土)に開催されたatmaCup#10に参加してました.

毎回,参加者同士のディスカッションなどが活発であり,学びがとても多いので今回も参加させていただきました.

他の方のsolutionを確認したところ,異なるアプローチでスコアを伸ばすことができたので,簡潔にまとめておきたいなと思い記事作成に至りました.

今回はチームを組んで参加したいと思っていましたが,最終的にソロ参加で終わってしまったので,この記事では思っていたことなども含めて,コンペを振り返れたらと思います.

また,いろいろなことを学んでいる最中なので,間違った記述などもあると思いますので,そっと教えてもらえたら幸いです.

開会式

開会式は3月5日の夕方でした.

印象的だったのは,コンペ開催前からディスカッションが投稿されていたことでした.

ちゃかぶ さん(@cha_kabu)

TabNetを使えるようになりたい【追記①lgbmとstacking(ちょっと上がる)】

しんちろ さん(@sinchir0)

お題予想

特に,ちゃかぶさんのディスカッションはとても詳細に記述がされており感動しました.

atmaCup開催期間は一週間と限られていたので,今回は実装することができませんでしたが,ゆっくりと理論や実装を学んでいきたいと思います.

序盤

初日submitを普段は目標にしていたのですが,今回はチームを組んでみたいと思っていたことから,無駄なsubmitを極力避けるために慎重にスタートを切りました.

特に今回は,データが複数テーブルにまたがっており,とりあえずの特徴量作りも一苦労でした.

コンペ課題は,美術作品の属性情報から,その作品がどのぐらい人々に評価されるのかを予測するものでしたが,使用することができるデータには,テキスト情報や色情報も含まれており,非常に自由度の高いコンペでした.

自身は,画像系の特徴量の取り扱い方がわからなかったので,まずは複数テーブルをひとつのテーブルにまとめることにしました.

作品の材料情報や作品制作者の生まれた場所など,様々なデータがあったのでOneHot表現にしたり,作品の制作開始日の欠損はほとんどなかったので,その値を利用することで,製作者の生まれた日や亡くなった日の欠損を回帰で補完したりなどしました.

CVの切り方は,trainとtestで'art_series_id'(シリーズものの作品ID)が被っていなかったので,CVはtrainとvalidに同じ'art_series_id'がないようにしました.

やっとの思いでテーブルデータをまとめることができたので,lightGBMで作成した特徴量を全部投入して学習を開始!(この時点ではテキストや色の特徴量は使用せず)

CV: 1.0418となかなか良さげな結果となって,3月7日にfirst submit.

しかし,結果は過学習しておりLB: 1.6027でした...

正直,かなり丁寧に特徴量を作ったつもりでしたが,LB悪くて絶望していました.

頑張って作成した特徴量を丁寧に取り除いていくことで,何とかLB: 1.0513にすることはできました.

しかし,特徴量を加えてはCVは下がるが,過学習によりLBは悪くなってしまいどうすればいいか何もわからなくなってしまいました.

当初は3月8日あたりでチームマージをしたいと思っていたのですが,CVとLBの関係も安定せず,LBスコアもあまり良い結果でなかったため,誰にも声をかけることができませんでした.

中盤

テキスト情報のembedding,何歳で作成した作品か(制作開始日 - 制作者の生年月日),亡くなる間際の作品か(製作者の命日 - 制作開始日),制作期間(制作終了日 - 制作開始日)などの特徴量を追加したり,製作者と材料情報をクロス集計し,主成分分析を利用した特徴量を作るなどいろいろ試したが,効果が出ず...

3月10日までに13 submitしましたが,LBスコア1.0を切ることができませんでした.

ドメイン知識もないので,どういった特徴量が効くのかも検討がまったくつきませんでした.

このままでは何もできないで終わってしまうと思い,「でぃ~ぷら~にんぐ」に全部お任せすることにしました.

実はこの部分が他の参加者と大きく手法が異なる部分であり,自身のスコアを大幅に改善する要因となったので,少し細かく紹介できたらと思います.

何をしたのか

先に結論ですが,やったことはテキストデータとカテゴリカルデータにTagを追加しながら連結することで,ひとつのsentenceにしました. このsentenceを入力とすることで,Self Attention Based BiLSTM Modelを学習させました.

Step1: sentenceの作成

まずは入力データを作成します.

全データの詳細な連結は細かくなるので省いて,メインの部分について説明できたらと思います.

例えば,以下のようなデータを連結させることを考えます.

  • 'material': oil print print canvas
  • 'maker_1': jan hackaert
  • 'birth': amsterdam
  • 'death': amsterdam
  • 'roles': painter
  • 'title': the avenue of 'UNK'
  • 'long_title': the avenue of 'UNK' jan hackaert 'No_4'
  • 'description': 'None'
  • 'acquisition_method': purchase
  • 'acquisition_credit_line': 'None'

これらのデータを連結して以下のようなsentenceを作成します.

'material' oil print print canvas 'maker_1' jan hackaert 'birth' amsterdam 'death' amsterdam 'roles' painter 'title' the avenue of 'UNK' 'long_title' the avenue of 'UNK' jan hackaert 'No_4' 'description' 'None' 'acquisition_method' purchase 'acquisition_credit_line' 'None'

まず,データが欠損していた場合には'None'で埋める.

出現頻度が低い文字列(自身は10以下のもの)は'UNK'で置き換える.

数字は,桁数で対応するタグに置き換える(例: 1994 → 'No_4').

今思えば,4桁の数字は年代によって特徴を持つ可能性があったので,以下のディスカッションを参考に少し工夫の余地があるかもしれないなと思います.

Kien Y. Knot さん(@0_u0)

ドメイン知識(西洋絵画とオランダの画家)

上記に挙げたデータ以外も同様の方法で連結していきました.

連結のポイントは,関係のありそうなものを近くに連結するのが大事だと思います(この次のword2vecの学習時に多少影響が出るため).

例えば,材料と製作者名を近くに連結することで,ある製作者は特定の材料を使いやすいかどうかなどを学習させることができる(はず).

Step2: 分散表現の学習

付近に出現する文字列同士から,文字列の分散表現を学習させる.

分散表現の学習には,word2vecを用いた.

word2vecはSkip-gramを採用し,200次元の分散表現をwindow幅10で学習を行った.

Skip-gramの詳細な説明は省略するが,簡潔にまとめると,ある単語の付近に出現する単語を予測することで,単語の分散表現を獲得するモデルである.

f:id:takaito0423:20210316232759p:plain
skip-gram

Hidehisa Arai さん(@kaggle_araisan)がコンペ開催中に以下のようなディスカッションを投稿してくれていました.

Word2Vecを使ってmaterial, technique, object_collectionなどを特徴ベクトル化する

かえるるる さん(@kaeru_nantoka)もsolution読むと似たようなことをやっており,「めちゃくちゃ効きました」とのこと.

[Private 12th / Public 16th] Solution Summary

word2vecに関して,ハイパーパラメータをいじって確認したわけではありませんが,一般的にwindow幅を狭くすると文法を,window幅を広くするとトピックを学習させることができると言われているので,今回のような場合は,window幅を大きめに設定するのが有効である可能性が高いです.

Step3: Self Attention Based BiLSTM Modelの学習

自身のsolutionで,他の参加者と大きく異なるのは,この部分かと思います.

sentenceのどの部分が,目的変数の予測に有効かを自動で学習させるのに最適なモデルだと思い採用しました.

実装したモデルは,LSTMが双方向でattention layerを複数使用しましたが,説明のために単方向LSTM&single attentionの簡潔なモデルを以下に示します.

f:id:takaito0423:20210317000607p:plain
self attention based lstm model (single attention)

隠れ層を用いてattention(隠れ層の加重平均をとるための重み)を計算することで,入力の重要な部分と不要な部分を特定することが可能となっています.

これにより,'None'などの影響を小さくすることができるだけでなく,例えば,'description'の記述がなく'None'になっているデータの場合には,代わりに'long_title'などにattentionが多く集まったりするような効果が期待できます.

attention layerを複数実装することで,様々な加重平均を取ることが可能になり,モデルの柔軟性が向上が期待できると考え,attention layer×10で加重平均を計算しました. (あるattention layerは'material'を重視し,あるattention layerは制作者を重視したりしてくれたらいいなと)

細かい工夫としては,LSTMの出力に正規分布に従うノイズを付与したり,dropout層などを追加しています.

結果と考察

CVは序盤同様,Group K-Fold(K=10)で試したところCV: 1.0469でイマイチかなと思いましたが,ダメ元で提出したらLB: 0.9847でした.

これまでのコンペでも,NNは学習データやエポック数によるばらつきが大きいためか,CVよりも複数の学習器の結果を平均しているLBの結果が安定するためよくなるので,CVとLBの乖離はそれが原因かなと思います.

また,この予測にはyearや色情報を特徴量に加えていないので,それらの特徴量と掛け合わせることでより結果が良くなると考え,lightGBMに深層学習モデルの出力を入力として加えyearの特徴量と学習させたところ,LB: 0.9524を出すことができました.

lightGBMの入力に,NNの出力を加えるとよくなることが多いイメージでしたが,ここまで劇的によくなると思っていませんでした.

コンペ終了後に以下のようなtweetを拝見し,自身のモデルは'description'が欠損していた場合,他の'title'や'more_title'にattentionが集まることで,欠損をこれらで補完したときと同じような効果が期待できているのも効果が強かった要因なのかなとも思いました.(ちゃんと分析したい…)

終盤

この時点で,LBではかなり上位につけることができました.

しかし,このあたりから新生活の準備で思うように時間がとれないことがわかり,チームマージしたくてもあまりコミットできないため,消極的に募集を待つ形になってしまいました.

また,確かにLB上の結果は良かったのですが,CVとLBの乖離からshake downの可能性もあり積極的になれませんでした.

Attentionの重みから,どのinputが結果に影響を与えるのか分析もできたのですが,こちらも時間がとれず分析できませんでした(未だ分析できてない…).

時間もとれなかったことから,申し訳程度に色特徴量や,製作者の何番目くらいの作品かなどの特徴量を加えたり,Catboost試してみたり,presude labelingなどを試して多少スコアを伸ばしましたが,大幅な改善は見られず…

最後は,深層学習,lightGBM,Catboostの出力をアンサンブルしたものを提出しました.

予定もあったためコンペ終了ぎりぎりまでコミットできず,submitを19ほど残して後は神に祈ることにしました.

結果

帰宅後,自身の順位を確認したところ,LB: 0.9443でLB順位は12位でした.

そして,最終順位はshake downして17位でした.

f:id:takaito0423:20210317115035p:plain
atmaCup#10結果

感想

今回はいろいろなことができたがゆえに,まだまだできることはたくさんあったなと思います.

また,課題である根本的な特徴量を作る能力が足りておらず,モデルに救われただけでもあるので,他の方のsolutionからいろいろ学んでいけたらと思います.

ただ,テキストデータやカテゴリカルデータに対して,使用したモデルが有効である可能性があることを知れた経験はとても有意義なものでした.

この結果を得られただけでも意義があったと思いますし,今後のコンペでも活用していけたらと思います.

また,今回のコンペはチームマージしてみたいという意気込みがあったのですが,なかなか思うようにチームマージはできず,温存していたsubmit数も無駄になってしまったのも反省点です.

個人的に,参加し始めてからのチームマージは,タイミングが難しいと感じているので,コンペ参加前から組んで参加するところから始めてみたいなと思いました.

特に今回は,自身の方法が少し特殊だったので他の方とうまくチームを組んで,attentionの分析や色特徴や他のモデルの結果とstackingすることでもう少し上の順位が狙えたのかなと思いますし,行き詰っていた特徴量作りのアイデアが出ていたかも...と思いました.

このあたりまでが反省ですが,一時的にですが上位に付けることができていたり,ディスカッションが活発だったりと,とても楽しむことができました!

社会人になって,どこまで参加できるかわかりませんが,今後も自分のペースで参加していけたらと思いますので,同じコンペ参加することがあれば,よろしくお願いいたします!

他の参加者の公開solutionや参加記録

記事投稿するの遅くなってしまったので,可能な範囲で見つけたものを共有できたらと思います.

[Public 3rd/Private 1st] solution copasta さん(@copasta_)&HOKAGE さん(@HOKAGE149)&朱眠子 さん(@akaneko6922)

feature importanceを見ると,やはりword2vecが効いているようです.

[Public 2nd/Private 2nd] LGBM single model solution もーぐり さん(@tellmoogry)

テキストを翻訳して使用していたり,色のデータから丁寧に様々な温かみのある手作り特徴量を作成していて,にじみ出る強者感.

feature importanceは,テキスト情報を除くと,groupby特徴量がかなり上位に多い印象(このあたり参考にして次に活かしたい).

3rd place solution CALPIS10000 さん(@CALPIS10000)

CALPIS10000 さんは,Music×Analytics Meetupの発表が印象に残っています.

こちらもword2vecが,テキストや1対多のテーブルで効果が絶大だったようです.

Lab色空間などを特徴量に使用しているのが印象的でした.

上位三名の方は,テキストと色の情報をきっちり使いこなしている印象を受けました.

4th Place Solution (チームマージはいいぞ) ころんびあ さん(@yurucamp_i)&tubo さん(@213tubo)

チームであることを最大限に活かし,モデルの多様性を意識して,様々なモデルを用いて予測した結果をstackingしていました(羨ましい!).

コメントにて,チームマージに関する質問にも答えていただきました.

自身はあまり,複数のモデルを実装したことがないので,使用しているモデルに関しては,実装できるようにしたいと思いました.

ここまでが物理メダル獲得者のsolutionでした.

おめでとうございます!

5th place solution suk1yak1 さん(@suk1yak1)

全特徴量(約2,000個)で学習させ,そのfeature importance上位に絞って学習するという方法が効いたとのことで,自身もこれくらい特徴量を作れるようになりたい.

6th place solution(yukiモデル+コメント欄にsqrt4kaidoモデルもあるよ) yuki さん(@yuki93753711)&rt4kaido さん(@sqrt4kaido)

yuki さんの単独モデルはPublic33rd/Private18thとのことなので,チームマージにより,異なる特徴量を用いたモデルを組み合わせることが有効であるいい例だと思いました.

チームで参加するときは,ディスカッションも大切だけど,各々で特徴量考えてモデル作成するのも大事なんだろうなと思いました.

7th place solution takoi さん(@TaTakoihirokazu)

palette系をkmeansでclusteringしている部分がこれまでの解法とは異なる部分なのかなと思いました.

clusteringによる特徴量作りは試したことないので,試してみたいなと思いました.

[Public 1st/Private 8th] Solution hiroshun さん(@h1r0shun)

rolesがpainterのmakerが関わっているか,materialがoil paintか,が効いた特徴量とのことで,油絵かどうかが予測に有効だったとのこと.

接戦の最終盤の中,Public 1stも本当にすごいなと思いました.

9th place solution masato8823 さん(@mst_8823)

4th Place Solution同様,stackingをしっかり行っています.

その他ぐるぐるに投稿されているsolution

[Private 12th / Public 16th] Solution Summary
13th place solution
16th place solution
19th solution
21st place solution
22nd place solution
25th place solution と取り組み方
26th place solution
27th place solution
Private 28th コンペに取り組む際のtips
TabNetメインに使ってみての振り返り
43rd place solution
65th place solution

参加レポート

atmaCup#10 で念願の物理メダル獲得した
君もatmaCupで俺と勝負!
【コンペ】atmaCup #10 参加録【コンペ】atmaCup#10 分析ステップ紹介
atmaCup第10回参加録とそのススメ
atmaCup#10参加記(pop-ketle版)
atmaCup第10回参加記録
atmaCup#10大反省会(Public: 137位/Private: 130位)
【atmaCup】初めてatmaCupに参加してきました。
コンペデビューの所感〜atmaCup#10〜
atmaCup#10あっという間に終了

atmaCup#8参加レポート

はじめに

2020年12月4日(金)〜12月13日(日)に開催されたatmaCup#8に参加してました.

atmaCup#5に参加し学びが多かったので,それ以降のatmaCup#6,atmaCup#7も参加したかったのですが,atmaCup#6は抽選落ち,atmaCup#7は社会人向けだったことや忙しかったこともあり参加できませんでした.

今回は初心者向けコンペとのことで気軽に参加しましたが,初心者向けとは?と思うくらいレベルが高く,とても勉強になりました.

博士論文の執筆に追われており,やったことや思ったことを全部書くのは難しいので,記事書くかどうかも迷ったのですが,簡潔にでもまとめておきたいなと思い記事作成に至りました.

使用した特徴量は,他の方のsolutionに記載されているので,それ以外の部分を中心にまとめることにしました.

開会式

開会式は12月4日の夕方でした.

コーヒーコンペと事前情報が書いてあったのですが,どんなタスクなのか気になっていましたが,フタを開けたらゲームの売上予測でした.

初心者向けコンペなので,タスクを簡単なものに変えたとのことでした.(コーヒーコンペ楽しみにしております.)

序盤

初日submitすることがひとつの目標でしたが,条件付き採録通った論文の回答書作成とかに追われていて,23時過ぎくらいからコンペスタート(汗)

とりあえず,テーブルデータのコンペとのことでlightGBM使って1st submit.

この時点での工夫としては,YouTube動画視聴回数予測のコンペと評価指標が一緒だったので,こちらのトピック参考にしてコードを作成しました.

RMSLE関係のディスカッション作ろうかなと思っていましたが,TawaraさんがRMSLE を最適化する小技というタイトルであげていたので断念.(速さが足りない)

次の日,チュートリアルの視聴と, takapyさんのカテゴリ値を持つカラムのベン図のディスカッションを読んで,trainとtestが'Publisher'によって分割されていることに気づくことができました.

この特徴から,CVのデータ分割を工夫して過学習防止&特徴量の選択に生かそうと,とりあえずtrainとvalidの分割をPublisherで行うことにしました.

ただ,分割によって学習が安定しないこともあり,いろいろ相談したいなと思い,Cross Validationについてのディスカッションを投稿しました.

さらに,次の日にチュートリアル2日目があり,後から視聴したのですが,簡潔にコメントをまとめると,

  • 'Publisher'でのGroup K Foldは,他のK Foldに比べ,validの予測が難しくなる.
  • 'Publisher'でのGroup K Foldにすると,分割によって結果のスコアが大きく異なる.
  • 分割により,学習が難しいものと,学習がそれなりにできているものがある場合,学習が難しいものは,ほとんど学習がまともにできていない可能性があり,結果の平均をとっていいか悩ましいところ.

みたいなコメントでした.

そこからしばらくは,完全ランダムにデータを分割する方法をしばらくは使用していました.

中盤

e-toppoさんやcha_kabuさんのディスカッションを参考にして,特徴量を増やしていきました.

それに伴い,CVはガンガン下がりましたが,LBとの乖離が目立ち始めました.

ここで改めて,CVのデータ分割を再検討しました.

多くのトピックでシリーズものの特定が,良好な結果につながるのではと考察されていました.

そこで自分は特定したシリーズで分割を行うことにしました.

シリーズの特定には,主に特徴量を作るためのものと,CVを決めるためのものの二種類を作成しました.

CVを決めるためのシリーズ特定方法は,'Name'同士のレーベンシュタイン距離を長さで0から1の範囲に正規化したものを使い,0.5を超えるものを同一シリーズとしてまとめていくことにしました.

事前学習済みモデルのembeddingを利用しなかったのは固有名詞が多いので,今回は古典的な手法を使用することにしました.

ただ,'Name'だけで距離を全組み合わせ計算するのは時間がかかることや,「スーパーマリオゴルフ」と「みんなのゴルフ」みたいなゲームが同じグループになったり,「スーパーマリオゴルフ」と「スーパーマリオ64」みたいなゲームはあえて違うシリーズを割り当てたいと思ったので,'Name'の距離を計算する対象は,'Publisher'と'Genre'を文字列連結して同一のもの同士のみでシリーズ特定を行いました.(これがいいかどうかはわかりませんが,結果として良好な結果でした)

この特定したシリーズをもとにデータを分割することで,CVが一気に安定しました.

CV:0.796, LB:0.8828 → CV:0.871, LB:0.8823

特に,lightGBMでは,LBに差異が出なかったのですが,CatBoostはカテゴリカル変数をTarget Encodingしていることもあり,ランダムにデータを分割するものよりもLBが高くなる傾向がありました.

個人的に今回の最終順位は,CV戦略によるtrainへの過学習防止と無駄なsubmitを控えることができたことが大きく貢献しています.

終盤

上位の圧倒的なスコアとデータの特徴からリークには少し気が付いていましたが,時間がなかったので愚直にできることをやることにしました.

後半はコードが複雑になってしまい,自身でも何の特徴量を作成しているかわからなくなりつつあったため,新たな特徴量作成は断念し,特徴量をCVとLBを参考によかったものを全ツッコミ.(正直他の人がsolutionに書いている画期的な特徴量は自身ではひとつも作れず…)

LightGBMとCatBoostの結果がそれなりに良かったので,終わりにしようと思いましたが,submitが20近く余っていたので,時間かけずにできることをすることに.

結果のアンサンブルも考えたのですが,lightGBMとCatBoostの結果が両方とも良好だが,微妙に異なっていたので,CatBoostのtestデータの出力を疑似的な目的変数として,LightGBMでtrainとtestを7:3くらいで重み付けしてモデルを学習させたところLBが気持ち上がり,このlightGBMのtestデータの出力を再び疑似的な目的変数として,CatBoostを学習させることで,気持ちスコアが上がりました.

あとはもともとのLightGBMとCatBoostの出力と,testデータ混ぜて学習させたlightGBMとCatBoostの出力を平均した結果をsubmitしたところスコアがさらに良くなりました.

ダメ押しで,適当に作ったNNモデルに上記のsubmitでtestデータに疑似的な目的変数を追加したものを加えて学習させてみました.

ここで,10fold分学習させるはずが,時間が足りず...

時間内に学習させることができた5つのNNモデルで,目的変数を予測し,submitしたところあまり良いスコアではなかったのですが,アンサンブルは多様性が大事かなと思って,この結果も最後はアンサンブルに追加し,submitすることにしました.

結果

最後にLBは上がっていたものの,test全体が良くなっている保証もなかったので,最終submitのひとつは保険をかけて,CVとLBのよかったCatBoostのシングルモデルを選択.

もうひとつのsubmitは,もともとのLightGBMとCatBoostの出力と,testデータ混ぜて学習させたlightGBMとCatBoostの出力を平均した結果に,気持ち上記のNNの結果を混ぜたもの(0.9:0.1)を選びました.

その結果…

敢闘賞10位,全体12位でした!

感想

正直,ディスカッションに助けられた感じが強く,特徴量作成能力が根本的に足りていないなと感じました.(ディスカッションなかったら0.87切れていないかも…)

ただ,コンペを通してどういう風に特徴量を作っていけばいいのかを,今回のコンペでは参加しながら実際に経験することができたので,今後のコンペに生かしていきたいなと思います.

自分自身の取組みとして,CVに工夫ができた初めてのコンペでした.

最初から良いスコアが出せてないのもありますが,41回のsubmit中,16回も緑の画面(LBスコア更新時に見れる画面)が見れたのは嬉しかったです.

データ解析コンペに参加し始めて,もう数ヵ月で一年になりますが,少しずつ結果につながり始めているので,今後も積極的に参加していけたらと思っています.

次回のatmaCupも楽しみにしています!

コンペの開催ありがとうございました.

Prob Space 対戦ゲームデータ分析甲子園(スプラコンペ) 参加レポート(最終順位11位)

はじめに

2020年8月19日(水)〜2020年10月18日(日)に開催されたProb Spaceの対戦ゲームデータ分析甲子園に参加してました.

高校入学以降テレビゲームで遊んでいないため,ドメイン知識はほとんどありませんでしたが,テーブルデータのコンペやりたかったのでこのコンペを選びました.

コンペの概要

Prob Spaceでは,様々なデータ解析のコンペがこれまでも開催されてきたようです.

対戦ゲームデータ分析甲子園の概要

本コンペでは、オンライン大会があることでも有名なゲームの対戦データを用いて、勝敗予測モデルの開発にチャレンジいただきます。

背景課題・目的

eスポーツは、2019年時点で既に$957.5M、2023年には~$1,600Mにまで拡大が予想されている急成長市場です。

国内では任天堂コナミといった企業が発売している、スプラトゥーンウイニングイレブン等が有名で、スプラトゥーンにおいてはスプラトゥーン甲子園、プレミアリーグが開催されるほどの大きな広がりを見せています。

そこで本コンペにおいては、ある有名ゲームのオンライン対戦データを用いて、勝敗を予測するアルゴリズム開発にチャレンジいただきます。

学習データの中には、ステージ、武器、ウデマエ、レベル、勝敗といった情報が含まれております。

対戦を優位に進めるために、どの武器を選択すべきか、今後の対戦に役立てられるようモデル化できればと思います。

今までプレイ経験のない方も、ぜひこのコンペをきっかけに参戦いただけますと幸いです。

その他

勝敗の予測(勝or負)である二値分類をaccuracyで評価.

最終スコアは,submitしたものの一番スコアが良かったものが自動で選ばれる(サブが多い方が多少有利).

自身の取組み

ドメイン知識なかったので,前処理とかはかなり雑です.

前処理

  • ランクは13段階に数値化

  • 各チームのレベルを合計したものを「A-total-level」,「B-total-level」として追加(その差や,割ったのをlogとったものとかも特徴量に追加)

  • ステージは,ステージ面積で数値化

  • 武器は,使用頻度で数値化(使用頻度が高い=強いかも?)

  • modeは,One hot Encoding

  • Catboostでは,武器はLabel Encoding使用

工夫点

AチームとBチームのデータを逆にし,勝敗フラグを変えることで,データ数を倍に増やしました.

これが原因で,A1プレイヤーの特徴を加味したモデルの作成を断念してしまいました.

立ち上げたトピック(情報共有&質問&雑談)で,A1プレイヤーについての言及があったので,同一プレイヤーの参加している試合の特定などもしていたのですが,上記の方法でデータ数を倍にするとその情報が入れられないので,早々に切ってしまいました(汗)

このあたり時間あれば,もっといろいろやれたのかなと思っています.

プレイヤー関係に着目したものだと,最終順位2位の TASSANさん の使っていた特徴量,なるほど感が強かったです.(効いた特徴量について(Public3位、Private2位)).

また,A1~A4やB1~B4のデータを混ぜ混ぜしても,精度向上にはつながりませんでした. 理由はいろいろ考えましたが,プレイヤーの列を変えても,チーム間のレベル差などは変わらないため,そちらを重要視してしまい,個別の武器情報が予測に与える影響が小さくなっているような気がしました(勝手な考察).

シングルモデル

LightGBM -> CV: 0.558~0.562, LB: 0.558~0.563, Private: 0.558~0.561

Catboost -> CV: 0.559~0.563, LB: 0.557~0.562, Private: 0.557~0.561

NN -> CV: あんまりよくない, LB: 0.547~0.556, Private: 0.532~0.551

NNは,スケーリングとかいろいろ試しましたが精度出ませんでした.

一番良かったsubmit

LightGBMとCatboostのアンサンブル.

LB: 0.560903, Private: 0.562738 (11位)

ちなみにこれは二番目に選ぼうと思っていたsubでした.

もし最終サブを決める必要があり,一つしかサブが選べない場合は,

LB: 0.564291, Private: 0.559445

でしたので,今回はコンペルールに救われました.

ただ,どちらも何週間も前に出したものなので,毎日のお供えサブ(適当に特徴量,ハイパラ,seedを変えたものをグリッドサーチしたときに大量生産されたもの)は,残念ながら何の意味もありませんでした.

感想

やはり,ゴミみたいな特徴量を使っている限り,一桁順位には届かないなと実感しました.

そもそも今回のような予測が難しい問題は,コンペの順位も運みたいなところが少しあるかなと参加した当初は思っていましたが,LBスコアが0.58超えた参加者が現れた時点で,負けを確信しました.

当初は弱学習器の多数決で何とかならないかなと思っていましたが,どのモデルの出力も相関が高くなってしまったため,特徴量作成の重要性を再認識したコンペでした.

また,コンペ開催中に初めてトピック(discussion)を作りましたが,多くの方からコメントなどをもらえたことで,ドメイン知識はないものの,いつもよりはデータの中身を多方面から見ることができました.

atamCupの抽選落ちたので,しばらくは資格取得の勉強と博士論文の作成に集中しようと思っておりますが,一段落したらまた何かしらのコンペに参加しようと思っています.

最後まで読んでいただきありがとうございました.