u++の備忘録

Kaggle Jigsawコンペ32位でした

KaggleのJigsawコンペにチーム参加して、32位で銀メダルでした。public 58位からは上昇しましたが、金メダル圏内にはもうひと押し足らずという結果でした。

f:id:upura:20190719104759p:plain

www.kaggle.com

discussionにチームメイトのKazSappさんが投稿した通り、解法は6モデルの重み付き平均です。

1. bert base uncased
2. rnn
3. rnn (data augmented by translation)
4. rnn (data augmented by old toxic competition)
5. bert base cased
6. bert base multilingual cased
w = [0.39193463, 0.14464678, 0.03892303, 0.06871146, 0.317778, 0.038006]

重みは、Kaggle Tokyo Meetup #5 の「Home Credit Default Risk - 2nd place solutions」で知った Scipy Nelder-Mead を用いて CV 最適化しています。

public kernel含めて多くのチームはidentity_columnsの欠損値を0で穴埋めしていたと思いますが、僕らのチームに特徴的なアプローチとしてRNNで予測した値で欠損値を補完していました。今回のデータセットにおける identity_columns の欠損値は単にアノテータ(評価者)がいなかったという意味で、必ずしも0を意味しないと考えたからです。このアイディアはKazSappさんが思いついたもので、こういった自分の手持ちにはなかった手法に辿りつけるのがチーム戦の良いところだなと改めて感じました。

同じくチームメイトのtakuokoさんも、embeddingに関する知見をdiscussion投稿しています。

金メダルを取れなかった点は悔やまれますが、Bertの強さを身に沁みて実感するなど、学びが多いコンペでした。

LightGBMでtargetをsqrt(target)に変換して予測する「reg_sqrt=True」

機械学習教師あり学習における一つのテクニックとして、学習時の target 変換があります。昨晩に LightGBM の documentation を読んでいたところ、sqrt 限定ですが、target の変換を自動で処理してくれる parameter "reg_sqrt" を(恥ずかしながら初めて)知りました。

本記事では、学習時の target 変換の概要を述べ、LightGBM の parameter "reg_sqrt" を紹介します。

学習時の target 変換とは

target の分布が偏ったり過度に広がっている場合などに効果を発揮し得る手法です。target の各データに対して、log, sqrt を取るなどの変換を加えることで、全体の分布を整える狙いがあります。

例えば筆者が先に参加した地震コンペでは "time_to_failure" という連続値が target になっていました。この target は小さい値のデータが多く、各データに対して sqrt を取ることで、全体の分布を正規分布に近づけることが可能でした。

f:id:upura:20190718115634p:plain

upura.hatenablog.com

学習時に target を変換した場合は、当然ですが test の値を予測した後に逆変換の処理が必要になります。例えば sqrt の場合は、予測値を二乗することになります。

target を変換した場合とそうでない場合では、予測の得意・苦手が変わってくる印象があります。例えば地震コンペの場合、sqrt を取った場合は高めの予測値が出づらくなっていました。学習時の target 変換は予測の多様性も生み出すので、アンサンブルの種を作る意味でも試す価値がある認識をしています。

LightGBM の parameter "reg_sqrt"

学習時の target 変換の処理は自分で書いてもさほど難しくないですが、そのせいもあってLightGBM に parameter が用意されているのを知りませんでした。予測値を二乗する処理も自動で行ってくれるので、処理し忘れで的外れなスコアを出すミスも避けられそうです。

  • reg_sqrt 🔗︎, default = false, type = bool
    • used only in regression application
    • used to fit sqrt(label) instead of original values and prediction result will be also automatically converted to prediction^2
    • might be useful in case of large-range labels

https://github.com/microsoft/LightGBM/blob/master/docs/Parameters.rst#reg_sqrt

おわりに

本記事では、学習時の target 変換の概要を述べ、LightGBM の parameter "reg_sqrt" を紹介しました。頻繁に使っている LightGBM ですが、改めて documentation を眺めると意外と認知していない parameter や機能追加に気付けるので面白いなと感じました。

「長さの近いデータを同じbatchに入れる」の性能劣化と速度

先のKaggle Tokyo Meetup #6 でのtksさんの発表で触れられた「長さの近いデータを同じbatchに入れる」について、チームで参加した「Jigsaw Unintended Bias in Toxicity Classification | Kaggle」にて同じような取り組みをしていました。

本記事では、Jigsawコンペにおける「長さの近いデータを同じbatchに入れる」処理について、性能劣化と速度の数字を紹介します。なお、あくまで筆者の事例に過ぎない点にはご留意ください。

TL;DR

「長さの近いデータを同じbatchに入れる」処理で、性能は多少落ちるが、速度が大きく向上する

JigsawコンペでのBERT学習時 性能(CVスコア) 速度(s)
処理前 0.9372215615637538 28000
処理後 0.9365093209503504 14000

「長さの近いデータを同じbatchに入れる」とは

deep learningなどの機械学習アルゴリズムでは、扱うデータの長さが均一である必要があります。テキストデータは長さがバラバラなので、最大長のデータに合わせて適当な値でデータを埋める(padding)処理が実行されます。この処理は一般に、(下図の例では角丸四角で囲まれた)batch単位で行われます。

下図の左の例は、batch単位でのデータの長さがバラバラの場合を示します。このとき、長さの大小が様々なデータが同一のbatchに含まれており、長さの小さいデータでは最大長までpaddingが実施されています。

ここで事前に各データを長さ順にsortし「長さの近いデータを同じbatchに入れる」場合を考えましょう。各batchでの長さが比較的揃うことで、必要なpaddingの処理が少なくなっています。

f:id:upura:20190716123941p:plain

メリット

  • データのpaddingされた部分は、本来欠損している部分なので、機械学習アルゴリズムにおいて特別な処理が求められるので、データの処理時間に影響を与えます
  • 各batchでのpaddingの処理を少なくするとこで、全体での無駄が減り、実行時間が削減できるメリットがあります。

デメリット

  • 一方で、長さの近いデータのみを同一のbatchに収めてしまうことで、データに偏りが生じて性能劣化に繋がる可能性があります

実装・解説など

次のブログに、日本語での実装・解説が記載されています。なお末尾に次の文があり、本記事は数値検証の一つの実例としてまとめた側面があります。

余力があれば、
1 ) 精度面でどれだけ悪化するのか
2 ) どれだけ早くなるのか
を比較実験した記事も書きたいなと思います。

kaeru-nantoka.hatenablog.com

数値検証

Jigsawコンペの場合

学習時

冒頭に記載した通り、性能は多少落ちるが、速度が大きく向上するという結果になりました。

BERT学習時 性能(CVスコア) 速度(s)
処理前 0.9372215615637538 28000
処理後 0.9365093209503504 14000

なおJigsawコンペではAUCを拡張した少し複雑な評価指標が使われていました。AUCと同様に0-1の値を取り、大きいほど優れた評価指標になっています。

https://www.kaggle.com/c/jigsaw-unintended-bias-in-toxicity-classification/overview/evaluation

推論時

Jigsawコンペでは、モデルの推論をKaggle Kernel内でGPU 2時間 (7200s) に収める必要がありました。推論時にもデータのソートを実施したところ、推論時間が58min -> 25min に短縮されました。

Quoraコンペの場合

tksさんがMeetup後に数値検証した結果、性能は悪化したとのことでした。


おわりに

本記事では、Jigsawコンペにおける「長さの近いデータを同じbatchに入れる」処理について、性能劣化と速度の数字を紹介しました。あくまで筆者の事例における結果なので一概に結論を述べるのは難しいですが、一定の性能を犠牲にして高速化が実現できた結果となっています。

最近はKaggleにおいても実行時間の制限があるコンペが増えており、学習・推論の実行時間を短縮できるのは十分に価値のあることだと思います。単体モデルとしては性能劣化が生じるものの、例えば浮いた実行時間で複数モデルをアンサンブルするなど、総合的な性能向上が見込めそうです。実サービス運用においても、多少の性能を犠牲にして実行速度を改善したい場面はあり得るので、選択肢の一つに入ってくるかなと考えています。

Kaggle Tokyo Meetup #6 にて「PetFinder 2nd Place Solution」の題目で発表しました

「Kaggle Tokyo Meetup #6」に参加し、チーム Wodori の一員として「PetFinder 2nd Place Solution」の題目で発表もしました。

connpass.com

本記事では、各発表の簡単な感想などを述べます。twitterの #kaggle_tokyo や kaggler-ja slackの #event-live にも情報が転がっています。

togetter.com

「PetFinder 2nd Place Solution」(Wodori)


「iMet 7th Place Solution & 画像コンペのアプローチ」(phalanxさん)


  • 後半で述べていたphalanxさんなりの汎用的なmodel pipelineが素晴らしかった
    • yamlを書き換えるだけで学習・推論・ログ出力などが自動化されているらしい
    • 懇親会で別の画像の強い人とも話したが同様のpipelineを持っているらしく、自分もきちんとコードを整備したいと感じた

「Quora Insincere Questions 10th Place Solution & 昔話」(tksさん)

  • jigsawのsolutionとして公開されて気になっていた「exponential moving average」について話題になって、個人的にとても勉強になった
  • Kaggle昔話も、知らないことが多くて面白かった

「PLAsTiCC 3rd Place Solution」(nyanpさん)


  • コンペの意義から具体的な解法まで、情報量多い解説だった
  • 有効だが生成に時間がかかる特徴量を大量にインスタンスを立てて作成するなど、勝負どころでの力強さを感じた
  • adversarial pseudo labeling や カテゴリ変数がない場合のCatboostの利用など、将来のコンペで使ってみたいアイディアが多かった

LT①「Neural Network のご機嫌取りがしたい」(tawatawaraさん)

LT②「NLPチュートリアル」(tamakiさん)

www.kaggle.com

github.com

LT③「Freesound Audio Tagging 2019 4th Place Solution」(OUMed: Osciiartさん、jsatoさん)

LT④「Google Landmark Retrieval 2019 1st Place Solution」(smlyさん)


LT⑤「Santander Customer Transaction Prediction 2nd Place Solution」(onoderaさん)

To Be Written.

おわりに

昨年12月に開催された前回は、Kaggle Expertとして参加し、LTをしました。

upura.hatenablog.com

その後なかなかコンペで良い成績が出せず落ち込んでいた時期もあったのですが、良いチームメイトに恵まれ金メダルを獲得してmeetupで発表できたことは、本当に嬉しいです。

日本でのKaggleの人気・実力が高まっていてmeetup参加の難易度が上がっていますが、ぜひ次回も参加できるようKaggleに精進していきたいと思います。

運営の皆さん、会場スポンサーのDeNAさん、ありがとうございました!

f:id:upura:20190713173152j:plain

Dockerのコンテナのメモリ上限の拡張

下記ブログを参考にDockerでデータ分析環境を構築した後、Dockerのコンテナのメモリ上限の関係でエラーが発生したのでメモしておきます。

amalog.hateblo.jp

発生したエラー

The kernel appears to have died. It will restart automatically.

f:id:upura:20190712144821p:plain

原因

下記記事が、そのものズバリでした。

casualdevelopers.com

原因は、Docker for Macのコンテナのメモリ上限が2Gになっていることです。

f:id:upura:20190712145704p:plain

コンテナのメモリ上限が2Gのため、メモリ大きめのファイルを読み込もうとしたところ(Macbook Pro自体のメモリは16Gあるのに)処理落ちしてしまいました。

f:id:upura:20190712144850p:plain

解決策

「Preferences > Advanced」から、メモリ上限を拡張可能です。「Apply & Restart」で変更が反映されます。

f:id:upura:20190712150004p:plain

おわりに

本記事では、Dockerのコンテナのメモリ上限の関係で発生するエラーについて、原因と解決策を述べました。

同様の詰まりどころは、下記の記事で紹介されている通り、DockerでMeCabを導入しようとする場合にも発生し得ます。

sanshonoki.hatenablog.com

「Sports Analyst Meetup #3」を開催&LTしました #spoana

はじめに

「Sports Analyst Meetup #3」を開催しました。今回は自分自身もLTで発表しました。

spoana.connpass.com

発表資料

発表資料はこちらにまとまっています(今後、資料が公開され次第追加していきます)。

spoana.connpass.com

togetter

Twitterの #spoana タグの付いた投稿は、下記にまとめています。

togetter.com

ロングトークJリーグ導入事例から見えてきた、ダイナミックプライシングの未来」

萩元徹さん(ダイナミックプラス株式会社)

  • ダイナミックプラス株式会社にて、スポーツ・エンターティメント業界などでダイナミックプライシングの導入を支援している萩元さんのご講演
  • 技術的観点のみならず、ビジネス的観点からもダイナミックプライシングの具体的な課題や今後の展望を語っていただきました
  • 個人的には「チケットサイトが複数存在しているため、一つのサイトで導入しても意味がない」という点が、言われてみれば当たり前ですが、導入の難しさとして確実に存在しているなと気付かされました

LT

今回は18本ものLTが実施されました。全部面白くてあっという間に時間は過ぎたのですが、流石に脳みそへの負担も若干感じたので、量の調整は検討の余地があるかなと個人的に思っています。

LTの内容については、発表資料やtogetterをご参照ください。

自分の発表


おわりに

第3回の今回もたくさんの方にご参加いただき、多くの方に面白い発表をしていただきました。またダイナミックプラス株式会社の皆さまには、会場提供・ロングトーク・LT発表と、大変お世話になりました。皆さまにお礼申し上げます。

f:id:upura:20190630143955j:plain

Microsoft/interpret で Kaggle titanic

次のツイートを見かけて興味を持ったので、取りあえず使ってみました。使い方はGitHubのREADMEに記載がありますが、sklearnの機械学習モデルと同様に fit -> predict します。


Kaggle Kernel

www.kaggle.com

スコア

f:id:upura:20190628125318p:plain

※ 同じ特徴量で LogisticRegression(penalty='l2', solver="sag") を使った時のスコアは 0.66 程度でした

www.kaggle.com

おわりに

きちんと検証をしていないので、性能についてはあまり言及しませんが、そこそこ良さ気なスコアが出ています。解釈性のための手法を同一パッケージ内に搭載しており手軽に可視化できるのが利点なので、実務などでの選択肢の一つとして今後頭の片隅に置いておこうと思っています。