2021年の振り返り

こんにちは。くるぴーです。

新卒SEから機械学習への転職を決意してから5年が経ちました。
普段あまりこういうブログは書かないのですが、今年を振り返りたくなったので雑に箇条書きで書いていきます。

kaggle

今年は3本のコンペに参加し、金2枚と銀1枚でした。チームを組んでくださった皆様、twitterで切磋琢磨?煽りあい?交流?に付き合ってくださった皆様、ありがとうございました!

1. Riiid Answer Correctness Prediction

概要

SANTAというTOEICの学習アプリを提供する会社のコンペ。
「出題された問題をユーザーが正解できるか」を予測するもので、学習データとして過去にユーザーが解いた問題が提供される。
特徴的なのはデータが1億行あること、Time Series API(※)での提出が求められること。
(※)ストリーミングデータのようなイメージで、数十行ごとのバッチでデータを受け取り予測を返す。

成績

チーム参加(takoiさん)
public 13/3395, private 13/3395(Gold)

解法

www.kaggle.com

全く整理しておらず見るに堪えないと思いますがコードは以下です
振り返ると600近く実験していたようです…
github.com

所感など

  • 推論速度・リソースとの闘いだった。
    • 1バッチあたり0.4~0.5秒で推論を返さないといけない制約が厳しかった。
    • Time Series APIでは、学習データに加えてストリーミングで受け取ったユーザーのデータを蓄積していく必要があります。1億行あるので工夫しないとすぐメモリーエラーになってしまいました。。
    • 対象ユーザーのデータを検索するのが大変でした。辞書で持つと検索は早いがハッシュでメモリを食うし、貪欲に探していくと推論速度全く間に合わない…
  • python(というかプログラム全般)について知れた。
    • (恥ずかしながら)なぜ辞書型はキーが多くなるとメモリを食うのか、すら知らなかった…
  • テーブルデータでTransformerを使う経験が詰めた。
    • 結局LightGBMよりも圧倒的に精度がよかった。
  • twitterでコンペ参加者と交流できたのがとても楽しかった。
    • 好奇心の刺激や経験を積むという観点で有意義かつ楽しいものの、この”ネトゲ感”が外れるとkaggleをやらない気がする

2. Shopee - Price Match Guarantee

概要

東南アジア・台湾で主要なECプラットフォームであるShopeeが開催したもの。Shopeeでは掲載商品に対して「最低価格保証」機能を提供している。この機能に必要なのが「プロダクトマッチング」。このコンペでは商品の画像とテキストのデータが与えられ、そのデータに類似した商品を予測する。

成績

チーム参加(kicchoさん、cpptakeさん)
public 6/2426, private 6/2426(Gold)

解法

www.kaggle.com

全く整理しておらず見るに堪えないと思いますがコード github.com

所感など

  • 距離学習、リコメンドを全く知らない状態だったため、勉強目的で参加した
    • 使い方や理論の理解が進み、成果も出せたので目的は達成できた
  • チームプレイがとても楽しいコンペだった
    • チームメイトであるkicchoさんがmlflowを解放して全員の実験管理を集約できた
    • 毎晩のようにペアプロやコードレビュー、ディスカッションをしていた
    • コンペ最終日の夜にはgoogle slideでサマリースライドをみんなで作ったのが一番楽しかった
  • マルチモーダルなモデル(textとimageをtransformerでいい感じにするとか)について論文をめちゃくちゃ試したけど全く当たらなかった
  • モデルの推論結果を目視確認・定性的に確認してFBできたのはよかった

3. CommonLit Readability Prize

概要

与えられた児童向け文章の対象年齢を当てるコンペ

成績

solo参加
public 6/3633, private 22/3633

解法

www.kaggle.com

コード

こちらも見るに堪えないですが以下にあります

github.com

所感など

  • takoiさんがpublicの1位にいるのを見て、一緒にGMになりたいと思い参加した
  • BERTのチューニングテクニックをかたっぱしから試した
    • paper:https://arxiv.org/pdf/2006.05987.pdf
    • この論文にも記載があるようにreinitializationが非常によく効いた
      • pretrain後のBERT最終層数層の重みを初期化する
  • discussion expertという裏目標は達成できた
  • メダルが変わるshakedownを初めて食らって悔しい...

総じて

  • それぞれのコンペで新しい技術を知ったりtwitterのみなさまとワイワイやれて楽しかった
  • まさかGMリーチまで来れるとは思ってもみなかった。CommonLitでGMになれなかったので、来年頑張る

仕事

  • 入社してからずっと携わっていたプロジェクトで社長賞がもらえた
    • MLの要件整理から導入運用効果出しまで現場の業務をキャッチアップしながらできたのは楽しかった
    • 多くの人とコミュニケーションをとる必要があり、コミュニケーションコストを意識することが前よりできるようになった気がする
      • パワポ芸が上達した(本も何冊か読んで勉強した)
  • また別のプロジェクトでは、非エンジニア2名と一緒にMLのシステムをチーム開発した。
    • テストドリブンな開発を導入した(誰に教わったわけでもないのでやり方があっているかは怪しい)
      • システムの改修を強気にできてとてもよい
      • 「テストコード書いてよかったです」と言ってもらえたのがうれしかった
    • システムの設計をあーだこーだ議論するの楽しかった
  • 工場系の分析やMLが多かったが今年は別のドメインでも少し仕事している
  • エンジニアリング、カスタマーサクセス(コンサル?)、機械学習(の上澄み)、今のところまんべんなくやっているけど、どの方向性に進みたいのかはずっとわからない
    • エンジニアリング
      • 設計を書いて、テストコードを書いて、テストコードが通るコードを書く、これが楽しい
    • カスタマーサクセス(コンサル?)
      • ユーザーや顧客の課題を聞いて、それを解決する仕組みを作るのも好き。SE時代からその傾向は強かった
      • 自分が技術的に貢献していると感じるのがどうやら大事な要素になっていると思う
        • そのためコンサルだけ、みたいなのはあまり興味がない(自分でもよくわからない)
    • 機械学習・データ分析
      • 明らかに素養やベースが理系院生の人と比べると全くかなわないなと感じる
      • テーブルデータから(ドメインも勉強して)特徴を作って、みたいなのは大好き
        • データを見ること自体が好きなよう
  • 自部署では意欲的かつ高い能力を持った人に囲まれていて、組織も寛大(スーパーフレックスが適用されている、裁量が大きくいわゆる「根回し」みたいなのが少ない)ので現状楽しく働けている。心理的安全性も高いと感じる。

副業

2021/11~ 副業を始めた

動機

  • 一度正社員+副業という働き方をやってみたかった
    • フリーランスと正社員の良いとこどりをしてみたかった
    • 自分の実力を知りたい、全然違う技術・業種で仕事してみたい
      • 社内では1プロジェクトにデータサイエンス1名となっていて個人商店感があり、人の仕事を見たりFBを受ける機会が少ない(風通しが悪いわけではなくざっくばらんに相談したりはする)
        • 誰に教わったわけでもなく我流で全部やっているのであっているか不安
      • 社内では主に工場系にアサインされることが多くほかのドメインをあまり知らない。いろんな業種を見てみたい

所感など

  • twitterのプロフィールに「副業募集」を記載したところ数件お声がけいただき、うち1社で2021年11月からお世話になることに
    • 徹底したドキュメント文化に感動した
      • わからないと思ったことがだいたいドキュメントを調べたらわかる
        • 自社のライブラリや固有のルールなどがあるはず
      • フルタイムじゃない&フルリモートの僕でも、メンターの手をあまり借りずにキャッチアップできた
    • 技術的なFBが的確で議論していて勉強になるし楽しい
    • 短い時間でアウトプットを出さなければいけないのは少なからず負荷になる(圧力をかけられたりといったことは一切ない)
  • 2か月の契約期間だったが無事継続をもらえたので、井の中の蛙ではないことがわかりちょっと安心した
  • 本業やめて副業だけ(もはや副業とは言わないが)で働き方をスローダウンしてみたい欲望がちょっとだけある
    • 現状本業の職場環境&仕事内容が良いので、環境が変わってしまったらちょっと考えるかも

仮想通貨bot

kaggleのshakedownに心が折れたのと自動取引やってみたいと思っていたので、9月ごろから仮想通貨bot開発をはじめた

動機

  • いろんな方向で収入が欲しい
  • 趣味でシステムを組む行為自体が好き(プラモデル的なイメージ)
    • うまくいけば実益も伴う

      所感など

  • 通算5回目となる自動取引プログラム
    • まともにクラス設計を業務でやったことがないがそれなりにできるようになったのは、5回のscrap&buildが大きいと思う
      • 1回目の自動取引プログラムは、新卒同期の超つよつよエンジニアに個別で何回かご指導をもらったのが実力向上に大きく寄与した気がする(ありがとう)
  • しっぽは掴んでいる気がする(とずっと言っている)が、まだ勝てるアルゴは組めていない
  • kaggleと違ってネトゲ感がないのでモチベが続かない
    • 2回/週で僕含め2名でもくもく会をしているのがモチベkeepの源泉になっている

その他

哲学

  • 1~3月、ちょっとだけ哲学の本を読んでた
  • twitterで話題に上がっていた哲学チャンネルをずっと見ていた
  • 「考える」ことが好きな人はきっと面白い気がする
  • kaggle参戦に伴い、哲学から離れていった…

www.youtube.com

mocri

  • mocriで朝もくもく会などをしていろんな人とお話しできた
  • 僕が非首都圏住みだったのもあり、ずっとFFだったのに話したことがない人と話すことができたりとよかった

サウナ

  • 何がキッカケだったか忘れたがサウナ少しハマっていってた
  • 整うことがなかなかできない&気軽に行けるサウナがなく、自然と遠ざかってしまった。。

ゲーム

ここ数年間でかなりゲームをやった年になった気がする - slay the spire - ローグライクカードゲーム - 風来のシレンをはじめとした不思議のダンジョンオタクにはたまらなく楽しく、ずっとやってた - 身一つで突っ込む、信じるのは己のスキルだけ、っていうのめっちゃ好き - ポケモンユナイト - 8月からずっと100時間/月稼働をずっと続けるくらいにドハマりしている - kaggler5名でチームを組んで大会にも出ている(最高3回戦) - 僕と相互フォローで興味ある人いたら声かけてください!!

日記

  • もう8年くらい、ほぼ毎日つけている
  • 年の瀬ということで読み返しましたがkaggleや仮想通貨botのメモ帳、勉強ノートになっていて、どんなことを考えてるのか全くわからない
    • 実は何も考えてないだけなのでは…

bybitのtickデータを引っこ抜いてくる

ちょっとカッコ悪いですが

import requests
import io
import pandas as pd
import numpy as np
import gzip
from datetime import datetime as dt
from datetime import timedelta
import os
import time


def download_currency_data(pair, date_range):
    """
    https://public.bybit.com/trading/ 

    :param pair:
    :param date_range:
    :return:
    """
    days = 0
    dfs = []
    while True:
        try:
            date = date_range[0] + timedelta(days=days)
            date = date.strftime("%Y-%m-%d")
            url = f"https://public.bybit.com/trading/{pair}/{pair}{date}.csv.gz"

            print(f"url = {url}")
            data = requests.get(url).content
            gzip_file = io.BytesIO(data)
            with gzip.open(gzip_file, 'rt') as f:
                csv_data = f.read()
            with open("work.csv", "w") as f:
                f.write(csv_data)

            df = pd.read_csv("work.csv")
            df = df[["timestamp", "size", "price", "trdMatchID"]]
            df["size"] = df["size"].astype(np.float32)
            df["price"] = df["price"].astype(np.float32)
            dfs.append(df)
            os.remove("work.csv")
        except Exception as e:
            print(e)
        days += 1
        if date_range[0] + timedelta(days=days) > date_range[1]:
            break
        time.sleep(3)

    dfs = pd.concat(dfs)
    os.makedirs("data/bybit", exist_ok=True)
    dfs.reset_index(drop=True).to_feather(f"data/bybit/{pair}.feather")


if __name__ == "__main__":
    download_currency_data(pair="BTCUSD",
                           date_range=(dt(2019, 10, 1), dt(2021, 11, 20)))
    download_currency_data(pair="ETHUSD",
                           date_range=(dt(2019, 10, 1), dt(2021, 11, 20)))

kaggle体験記:NFLコンペで70位/2038

こんにちは。@kurupicalです。

昨年の10月から12月にかけて開催されていたNFLコンペに@osciiartさん、@monnuさんと出場し、70位/2038をとることができました!チーム組んでいただきありがとうございました。m( )m

www.kaggle.com

f:id:kurupical:20200111154200p:plain

私が開催している以下もくもく会で取組を紹介したので、スライドをアップしました。
connpass.com

www.slideshare.net

個人的には、今までやったコンペの中でも1,2を争う面白さでした!
2枚目の金目指して引き続き頑張ります・・・!

Kaggle体験記:IEEE CIS Fraud Detectionで19位/6381

はじめに

こんにちは。くるぴー(@kurupical)です。

このたび、IEEE CIS Fraud Detectionコンペに、@pondelion1783さん、@HighGradeToppoさん、@TaTakoihirokazuさんと参加し、19位/6381の成績を残すことができました。
f:id:kurupical:20191005092325p:plain:w600

チームのみなさまはとても優秀で、コンペに参加した2ヶ月の間とても刺激的な時間を過ごすことができ、いい経験になりました。
チーム目標であった「金メダル」も達成できてとても嬉しいです。本当にありがとうございました!

このブログでは、これからKaggleなどのデータ分析コンペ参加しようとしている方向けに、どのようにコンペに取り組んだのかという経緯を残しておきたいと思います。
何かのお役に立てれば幸いです。

もしよろしければ、1年前に書いたkaggle体験記もあわせてご覧ください。
kurupical.hatenablog.com


1. 参加のきっかけ

きっかけは、8/3(土)に開催されたatmaCupの懇親会でした。*1

atma.connpass.com

「関西のexpert以下のチームで金を取る」というお酒の勢いだけで4人チームを集め、結成しました。
「みんなテーブルコンペが得意」という理由だけで、そのとき唯一開催されていたIEEE CIS Fraud Detectionコンペに参加することを決めました。
この時点では、全員、ゼロサブどころか、コンペの概要を読んだ程度でした。

また、このオフラインコンペで@takuokoさんに公開いただいた上位ソリューション(PetFinder 2ndの知見の集合体)に感銘を受け、
何かテーブルコンペで自分でも試してみたいという気持ちがありました。

2. コンペ取り組み

2-1. コンペ説明

2-1-1. 課題設定

  • ユーザーの取引データから、「不正取引」を検出したい

2-1-2. データセット

  • train, testそれぞれ約50万行、約450列
  • うち「不正利用」とされるデータは3%。残り97%は不正利用ではない。
  • すべての項目名は匿名化されている。が、特徴の属性(カテゴリなのか日付なのかカウントなのか等)は項目名である程度わかるようになっている。
    例:項目名の頭にD→日付、C→カウント 等

詳しくは以下EDAカーネルをご参照ください

www.kaggle.com

2-2. 序盤

2-2-1. まずは1サブミット

機械学習させるコードを持っていない人にとって、何もない状態から1サブミットするのはかなりハードルが高く、ここでめんどくさくなって挫折してしまうケースが多いです。
逆に1サブミットさえしてしまえば、そこからスコアを伸ばすモチベーションが湧いてきて、2サブ目、3サブ目以降と続けやすくなると感じています。
この挫折を回避するために、自分は以下ルーチンを実施して「とりあえず1サブミット」を目指しています。(あくまで個人的な意見です)

  • 以下手順で良さそうなNotebookを探す
    f:id:kurupical:20191005094917p:plain
  • Notebookをコピーする
  • 1行でもいいので自分のオリジナルを加える(コピペではなく自分でやった感を出す)
  • サブミットする

2-2-2. EDA

まずは全特徴量の分布を、train, testでvisualizationしました。
f:id:kurupical:20191005161238p:plain:w500
上のvisualizationは、ProductCDという項目をtrain/testをそれぞれ時系列に3分割してヒストグラムを出したものです。
例えばこのグラフだと、ProductCD=Hが、trainの頭・testの末に多いことがわかるので、それを深堀していきました。
この例だと、Hは12月に多く、HはHobbyのHだと仮説を立てました。分析の結果12月は明らかに分布が違うこと、不正利用が少ないことがわかったので、12月フラグという特徴量を作りました。

2-2-3. 総当りで特徴量作成(Public:0.9423, 3000位/6381)

序盤は特徴が匿名化されているため、思考停止して特徴を作成しました。
「すべての特徴(400項目ほど)から2つを取って差・比を取る」総当り。12万ほどの特徴が作成されるので、
1000個ずつモデルに投入→top10項目を取る*120回 = 特に効いていると思われる1200特徴量を突っ込んでどうなるか、試しました。
全然効きませんでした。

2-3. 中盤

2-3-1. 仮説を立てた

総当り特徴の作成はリソースを無限に食うし、こういうやり方ではAutoML系サービスに明らかに分があります。
「50万行の中には、同一のユーザーがいるのではないか」「同一のユーザーを特定すれば、スコアがかなり上昇するのではないか」という仮説を立て、EDAを実施しました。

2-3-2. ユーザー特定のIDを見つけた(Public:0.9435, 2750位/6381)

同一ユーザー特定のヒントを得るため、同じユーザーと思われる行をまずは手作業で抜き出そうと考えました。
方法としては、カード会社等の属性などが入っている項目card1〜card6を結合して仮ユーザーIDとして、同じ仮ユーザーIDを持つものをまとめてcsv出力し、
Excelで縦横に流しながらざっと眺めました。

すると、明らかに特徴が似ている行たちがいました。
この「特徴が似ている行たち」だけを切り取って眺めていると、「D1」がカード作成からの経過日数?、
「D5」が前回取引からの経過日数らしきものであることがわかりました。
f:id:kurupical:20191005162613p:plain
目視で「多分同一人物だろうな」という人を黄色塗しました。
赤枠1+赤枠2=赤枠3。赤枠1は基準日から15日、赤枠3は19日経過した時点のデータ。赤枠2は、赤枠1の行から何日経過したか、ではないか?
※項目「DAY」はTransactionDTという経過秒を60×60×24で割って経過日にしたもの

これをチームメンバーに共有したところ、TransactionDay(取引した日)とD1(カード作成からの経過日数)の差を取れば、「カード作成日」という特徴が作れ、
ユーザーがかなり厳密に特定できるのでは?
と新たに示唆をいただきました。
さらに、カード作成日を加味し、カード情報+カード作成日というユーザーIDを使って、data.groupby("userID").mean()、data.groupby("userID").std()のような、
ユーザーIDごとの特徴量平均・標準偏差のような特徴を作って実験したところ、大幅にLBが向上した(Public0.9564, 85位/6381)という報告がありました。*2
同じことを自分の手元で試したのですがスコア伸びませんでした(Public0.9435止まり)。

2-3-3. ハイパーパラメータ調整(Public0.9477, 2195位/6381)

ハイパーパラメータを調整するだけで、Publicが0.9435→0.9477に向上しました。
もともと、HomeCreditコンペで使っていたmax_leaves=60, depth=10というパラメータで実験していましたが、一番強いNotebookに記載されているハイパーパラメータを一部参考にしました。
私のかってな推察なのですが、card1、card2の特徴量はユニーク数がかなり大きく(10000くらい?)、決定木の葉っぱの数であるnum_leavesが少ないと、枝分かれが十分にできないためにLBが低かったのではないかと思っています。
Notebookのハイパーパラメータはこういったところも加味してちゃんと設定されているのだなあと感動しました。*3

2-3-4. さらなる特徴作成(Public:0.9584, 64位/6381)

いろいろな特徴量を作りました。

  • userIDをベースに全特徴量の平均、標準偏差
  • userIDをベースに月ごと・週ごと・日ごと等で取引回数や取引金額の平均、標準偏差
  • あらたなuserIDを試す
  • 特徴量をいくつかのグループに分け、それぞれのグループの「最大/最小値」、「最大/最小をとった項目名」「欠損パターン」。
    例えば、以下V95,V101,V143,V167,V177,V279,V293あたりは挙動が似てるので一つのグループとしました。パターンはエクセル目視で確認しました。今思うと、特徴ごとのクラスタリングとか使ってスマートにやればよかったのですが…
    f:id:kurupical:20191005164423p:plain

2-4. 終盤

2-4-1. Negative Samplingによる実験の高速化

「不正利用」のデータ全部と「正常利用」のデータ2割で学習させても精度はそこまで変わらないので、実験が高速にできるよ!というDiscussionを読み、実践しました。
実験時間がかなり少なく済む、特徴量をたくさん入れてもMemoryErrorにならないなどかなりメリットが大きかったです。

2-4-2. 特徴選択

Negative Samplingをしたうえでfeature importanceが高い項目を採用しました。

2-4-3. 予測できていないデータの分析

自分のモデルが予測できていないデータを分析しました。結果、ProductCDがWの不正利用が検知されていないケースが多いことが判明しました。
この結果から、ProductCD=W、Cだけのモデルを作り、アンサンブルに加えました。(LB +0.001)
ProductCD=W, D1=0が不正利用検知できていないケースが多かったためこれもアンサンブルしたかったのですが、実験が間に合いませんでした...。

2-4-4. CatBoost

カテゴリがかなり多いのでCatBoostも効くのでは?という考えで、試しました。LBは低かったですが、アンサンブルでよく効きました。
パラメータ調整はdepthのみ行い、6,8,10,11あたりを試しました。結局depth=6が一番強かったです。
あと、変な特徴を入れるとCV0.960→LB0.951と出たり、挙動がよくわかりませんでした…
結局、CV0.955, LB0.955くらいまで伸ばしてアンサンブルしました。

2-4-5. seed averaging

モデルのseedを変えて学習させ、平均を取りました。

2-4-6. postprocess

厳しめに絞ったユーザーID(card1-6 + (D1-Day) + (D10-Day))を使って、以下を実施しました。

  • trainデータですべて不正利用、取引回数2回以上のID → 予想を1に書き換え
  • trainデータですべて不正利用ではない、取引回数5回以上のID → 予想を0に置き換え

Public+0.0007, Private+0.0003でした。

2-4-7. アンサンブル

StratifiedKFold(5), Timeseries(6)で全員のモデルを予測させ、最終foldのoofを使ってNelder-Mead法で重み付けしました。(全Foldのoofを使ったほうがPublicは低かったもののPrivateは0.001くらい高かったです。)
qiita.com

2-4-8. 最終サブの選定

2サブのうち1サブは安全にという気持ちで、Train/Testで分布が異なる特徴量を削除したモデルにしました。

2-5. 結果

全員のモデルをアンサンブルしてPublic0.9634(29位), Private 19位になりました。
チームメンバー全員、Publicで0.96を超えるSingle Modelはありませんでした。一番よくて0.9588くらいだった気がします。
そういう意味ではチームで勝つことができたのかなと思います!!

3. 振り返り

3-1. 良かったこと

  • 丁寧にEDAができ、EDAから得られた知見を特徴に落とし込めた。
    統計量やサマリーを見るのも大事ですが、同じくらい個々のデータを見るのも大事。ただ、いたずらに全部見るのではなく、いろいろな条件で絞り込む(IDとか、予測うまく行かなかったデータとか)とスマートにEDAできると思いました。Excel Masterになりましょう!
  • 新しいライブラリ(CatBoost)に触れることができた。
    新しいコンペに参加するごとに、公開されているNotebookからたくさん学んでいます。Masterになったら僕も少しずつ貢献していきたいです。
  • 行き詰まったら特徴作成コード全捨て
    強い人がやっているのを聞いて自分もやってみましたがかなりよかったです。
  • 酒の勢いで言った「チーム組みましょう」を、ノリで終わらせず、その場でちゃんとチームマージした。笑
    「チーム組みましょう。また明日以降対応しますね」じゃなくて、「とりあえずチーム組みましょう、その代わり後で気が変わってやる気なくなっても文句なしで!」という方針にしました笑
  • バージョン管理でgithubを使った。
    管理は超適当でしたが、無いよりマシでした。
    f:id:kurupical:20191005170442p:plain:w500

3-2. 反省点

  • 実験の効率化をするのが後回しになってしまった。
    コンペが進んでいくと技術的負債がすごい勢いで積み上がっていきますが、短期間だからと負債を抱えたまま走り切るより、途中途中でリファクタリングしたほうがよいと感じました。
  • 検証が十分でない実験結果をむやみに発言しない。
    チーム全体が誤った実験結果に引っ張られてしまい、時間が無駄になる。(終盤、脳が働かなくなって、発言を推敲する能力が著しく低下しました。。)
  • ログをあまり残さなかった。
    この実験なんだったっけ…どういうソースコードで、どういう特徴量を使ったんだっけ?とならないようにしたいです。(と思っていたが、結局最後まで着手せず、最低限のログしか残しませんでした…。)
  • 途中までテストコードを書かなかった。
    ガッツリ書く必要はありませんが、最低限確認したいことをassert文で書いたらよかった。バグで1週間進捗が止まったりして、結構しんどかったです。
  • 睡眠時間を削った結果、集中力が低下した。
    学習経過をぼーっと眺める、学習中のモデルを応援する(学習経緯を眺めながらauc上がれ!上がれ!と声をかけ始める等)ようになったら、集中力低下のサインです。kaggleやるときはkaggleやる、やらないときはやらない、メリハリをつけるのが大事だなと痛感しました。

3-3. かかった費用

16000円でした。他に趣味もないしこれくらいいいかな。

  • GCP: 9000円(CatBoostの深いdepth実験)
  • PCのメモリ32GB→48GBに増強 8000円。コスパめっちゃいいのでオススメです。50万件×2000特徴くらいまでは実験できました。

3-4. 所感

  • ユーザーIDを特定できた人とできなかった人で勝敗がわかれたコンペでした。個人情報の縛りがありユーザーID公開できなかったそうですが、この特定作業は若干不毛な作業でした。
    (そういう意味ではHomeCreditは良コンペだなと…)
  • 今回使ったモデルが実務で活きるのか不明。ユーザーIDを特徴に入れてしまっているので。
    Public/PrivateでPrivateスコアがかなり下がってしまっていることからも、Train/Publicにoverfitしていると思います。
    モデル作成が社会貢献につながってほしいので、次はそういうコンペを選びたい。

4. まとめ

IEEE CIS Fraud Detectionコンペの活動記録をまとめました。
少しでもみなさまのお役に立てたなら幸いです。
長文となりましたが、最後まで読んでいただきありがとうございました。

*1:第2回も11/23に開催されるようです。初心者の方でも、開催者が手取り足取り教えてくださるので、初心者から上級者のみなさまにおすすめのイベントです! atma.connpass.com

*2:このキーを発見した方の名前にちなんで、弊チームではtakoiIDと読んでいました笑

*3:ハイパーパラメータの意味は以下ブログを参考にしました。nykergoto.hatenablog.jp
ハイパーパラメータ調整方法は以下ブログを参考にしました。(IEEEコンペ5位の@MLBear2さんのブログです。終盤MLBear2さんのチームと競ってたので、「敵に塩を送っちゃって大丈夫か〜〜〜?」と思いながら読んでいたのですが、結局大敗しました…)
naotaka1128.hatenadiary.jp

<メモ>Human Protein Atlas Image Classification上位解法を読んだのでまとめる

1. まえがき

2018年11月〜2019年1月にHuman Protein Atlas Image Classificationに挑戦しました。
www.kaggle.com
結果は122位/2172と、銀メダルに届きませんでした。。悔しい。
f:id:kurupical:20190210220746p:plain

自分がやった取り組みは余力があれば書くとして、今回は上位の皆様の解法を読んでまとめていきます。

2. コンペ

灰色文字は私の考察、それ以外は記事の記載内容と書き分けています。
訳しきれなかったところは、注釈で原文を入れています。

2-1. 概要

コンペの概要については、以下を参考にしてください。
tawara.hatenablog.com

2-2. 上位Solution

2-2-1. 1st place solution

www.kaggle.com

全体像は以下の通り。 ※ディスカッションより転載
f:id:kurupical:20190210162255p:plain

  • CVはMultilabel Stratification*2で切っている。
  • Augmentation
    • Rotate 90
    • flip
    • randomly crop 512x512 patches from 768x768 images(or crop 1024x1024 patches from 1536x1536 images)
  • 学習
    • 学習率のスケジュール:
lr = 30e-5
if epoch > 25:
    lr = 15e-5
if epoch > 30:
    lr = 7.5e-5
if epoch > 35:
    lr = 3e-5
if epoch > 40:
    lr = 1e-5
  • 損失関数

    • FocalLoss+Lovasz.
      Lovasz lossはSemantic segmentationのものでは?と思ったのですが、Lovasz lossの考え方はPrecision/Recallの考え方に一部適用できるということだそうです(Lovasz lossよくわかっていないです…)
  • NN

    • DenseNet121
      DenseNetについては以下が分かりやすかったです。
      qiita.com
      分類レイヤーは以下の通り。
  (1): AdaptiveConcatPool2d(
    (ap): AdaptiveAvgPool2d(output_size=(1, 1))
    (mp): AdaptiveMaxPool2d(output_size=(1, 1))
  )
  (2): Flatten()
  (3): BatchNorm1d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (4): Dropout(p=0.5)
  (5): Linear(in_features=2048, out_features=1024, bias=True)
  (6): ReLU()
  (7): BatchNorm1d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (8): Dropout(p=0.5)
  (9): Linear(in_features=1024, out_features=28, bias=True)

参考:DenseNetの元論文の構造*3
f:id:kurupical:20190210163224p:plain

原論文はAvgPoolingだけなのに対し、この解法はAdaptiveMaxPoolingも加えています。全体の情報に加えて、特徴的な情報も食わせることで、より「よしなに」やってくれる感じなんでしょうか。※AdaptiveXXXPool2d(output_size(1, 1))はGlobalXXXPooling2dと同義。

  • TTA

    • lossが一番低いepochのモデルを分類器とし、random cropで予想を4回作成→予測の最大値をpredictionとする?*4
  • Metric Learning ※筆者の解釈を多く含みます。間違っていたらご指摘ください。。
    」 ※(2/14追記:metric learningについては、以下がわかりやすいと情報いただきました。)
    techblog.zozo.com

    • Metric Learningとは、平たく言えば、testデータに対してtrainデータとの類似度を計算し、その類似度が一定以上であればtrainデータのラベルに書き換える処理?のようです 
      いくつか、デモがされていました。(ディスカッションより転載)

    f:id:kurupical:20190210194822p:plain f:id:kurupical:20190210195038p:plain f:id:kurupical:20190210195358p:plain

    一番左が「予想したいデータ」、一番左以外は、スコア(≒類似度)が高い画像から順に並べたものです。
    スコアのしきい値によって1000枚ほどの画像を書き換えたところ、LBのスコアが0.03以上向上したそうです。

    この「Metric Learning」ですが、スコアを向上する以外だけでなく、以下のように応用ができると述べられています。

    具体的にどのように画像間の距離を計算したのかが気になるところですが、「開催中の別コンペでも使っているのでまだ教えられない」ということでした。

  • 最後に
    if we compete only for win,we may loss,if we compete for learning and providing useful solution to the host,nothing to loss.

2-2.2. 3rd place solution

www.kaggle.com

  • CV
    • trainの10%を、アンサンブル検証用に除外(holdout)
    • 残り90%で5fold cv
    • 異なるfold間で類似の画像がないようにする。(ahashなどで画像をハッシュ化して調べた)
  • normalization.(officialデータとexternalデータで、画像の平均と分散が大きく異なったため)
  • Augmentation
    • AutoAugmentation*5を参考にした。最適なaugmentationの探索は、強化学習ではなくランダムサーチで行った。
  • 損失関数
    • FocalLoss(gamma=2)
  • Optimizer
    • Adam(lr=5e-4)
    • learning rate scheduling無し
  • 大きいモデルで大きい画像を扱うときは、32枚ごとに重みをupdateするようにした?※原文の意味が読み取れず…バッチサイズ32だとメモリ不足になるのでこの対応をしている?*6
  • 一番メジャーなクラスのF1スコアが減少したところで訓練を止めた(Early stopping)
  • 推論
    • 各訓練の最終10個のチェックポイントの重みの平均を使ったNN
    • 8 TTAs
    • weighted average ensemble
    • 分類のしきい値
      • validation setの予測割合とあうようにしきい値を選択
    • モデル(以下3つをアンサンブル)
      • 512*512
        • ResNet34(5fold ensemble)
      • 1024*1024
        • inceptionv3
        • se_resnext50
    • NN構造
      • 1024*1024だとglobal average poolingがworkしなかったので以下変更(よくわからなかったので原文)
        • remove global average pooling.
        • compute MxM logits using 1x1 convolution.
        • compute weight maps using 1x1 convolution followed by softmax.
        • using weight maps, compute weighted averaged logits.
          global average poolingの代わりに、セルの値×各セルの重みをsoftmaxで計算した感じなんでしょうか…。

2-2-3. 4th place solution

www.kaggle.com

  • GAPNet*7を使った
    • GAPNetはmultiscaleの能力がある点で優位。→multiscaleのニュアンスは、画像全体(マクロ)と細かい点(ミクロ)の両方から判断できる、ということかなと解釈しています。
    • GAPNetの発想をResNet18+SE-Blocksに適用した。
  • Dual Loss ResNet
    • 30分格闘してさらにいろいろ教えてもらったのですが消化できなかったので、後で書きます。現時点では、何が分かってなきゃいけないのか分かってないです。。 f:id:kurupical:20190211113402p:plain

2-2-4. 5th place solution

www.kaggle.com

  • Augmentation
    • Rotation
    • Flip
    • Shear
    • Random Cropの代わりにFiveCrop*8が有効だった
  • NN
    • ImageNetでpretrainした重みを使用
    • 最終的に採用したのは
      • Inception-v3
      • Inception-v4
      • Xception
    • モデルの変更点
      • 最後のpooling層をglobal poolingに変更した→Inception-v4, Xceptionはもともとglobal average poolingになっているが、どういうニュアンスなんでしょうか?1st place solutionみたいに、global (average + max) pooling?
      • pooling層とoutput層の間に、dense(128)を加えた
      • 2-stage制にした
        • まず512サイズで訓練
        • その後650サイズ、800サイズで訓練
  • 10-fold CV
  • 損失関数
    • MultiLabelSoftMarginLoss
  • オプティマイザ
    • SGD(lr=0.05)
    • StepLR(gamma=0.1, step=6)
  • 25epochs(650か800サイズは15epoch程度でearly stopping)
  • lossが一番低いものを選択(F1scoreではない)
  • sampling weightを設定。(レアなクラスほどよくサンプリングされるように)
  • workしなかったもの
    • DenseNet
    • SENet
    • ResNet
    • 3-channel input
    • サイズ1024以上での訓練
    • focal loss
    • C3D
    • TTA
    • 古典的な機械学習手法:決定木やランダムフォレスト、SVMなど

2-2-5. 7th place solution

www.kaggle.com

  • RGB入力
  • 最後のpooling層を、concat([attention weighted average pooling*9, global max pooling, global std pooling])に変更
  • augmentation
    • contrast(各チャネル独立に)
    • rotate
    • scale
    • shear
    • shift
  • 損失関数:BCE loss
  • NN
    • ResNet18(1024*1024)
    • ResNet34(10241024, 768768)
    • inceptionv3(768*768)
  • trick
    • テストデータ間で重複している思われるものは、重複しているデータ間で予測の平均を取るようにしたところ、スコアが0.04-0.05が向上した

2-2-6. 8th place solution

www.kaggle.com

  • NN
    • SE-ResNext50(256, 512, 768)
    • InceptionV4(512)
    • BN-Inception(512)
    • Xception(512)
  • CyclicLR(最初のサイクルは長くして、逓減させる)
  • Focal Loss, LSEP loss*10
  • Augmentation:
    • Brightness
    • D4 and wrap transforms
  • 32TTAの平均

3. 感想

  • bestfitting氏、single modelで優勝スコアだわ、、実務への適用まで考えたソリューションを提案しているわでカッコ良すぎでした。
  • 多くのsolutionは、最後のpooling層はいくつかのGlobalXXXPoolingをconcatしていて(論文では単純にGlobalAveragePoolingが多い)、これが主流なのかな〜と思いました。(確かに、MaxPoolingも与えてあげるとよさそう)
  • externalデータはラベルの質がよくなかったようです。また、OfficialデータとExternalデータにいくつか重複があったり、分布が違ったり…というところは上位陣はしっかりおさえていました。ネットワークの調整だけでなくデータの質もしっかり見ることが大事ですね。
  • 最後のほう、力尽きました。(ごめんなさい)
  • solutionのまとめ記事書くだけでかなり勉強になりました。こうでもしないと流し読みして何も頭に入らないですね。

*1:https://www.kaggle.com/allunia/protein-atlas-exploration-and-baseline

*2:https://www.kaggle.com/c/human-protein-atlas-image-classification/discussion/67819

*3:https://arxiv.org/abs/1608.06993

*4:原文:I predicted the test set by using best focal loss epoch with 4 seeds to random crop 512x512 patches from 768x768 images, and got the max probs from the predictions.

*5:https://arxiv.org/pdf/1805.09501.pdf

*6:For the large model with 1024x1024 images, I used gradient accumulation so that weights are updated every 32 examples.

*7:https://openreview.net/pdf?id=ryl5khRcKm

*8:torchvision.transforms.FiveCrop(size) Crop the given PIL Image into four corners and the central crop

*9:3rdと同じ発想のよう。github.com

*10:https://arxiv.org/pdf/1704.03135.pdf

<実践>はじめてのKaggle体験記

機械学習を勉強し始めて1年が経ちました。
そろぞろ何か一つ目に見える実績を上げたいと思いたち、
5月から8月までHomeCreditというKaggleのコンペをやっていました。

Home Credit Default Risk | Kaggle

f:id:kurupical:20180902183535p:plain

最終的に、7198人中62位で終わることができました!

Kaggleをやってみようかなと思っている人向けに、自分の体験記を残しておこうと思います。

わからない用語は、Kaggle Words For Beginnerを参考にしてください。

もくじ

  1. スペックと前準備
  2. コンペ内容の確認
  3. コンペ参加
  4. 感想

0. スペックと前準備

スペック

前準備

コンペを始める前に(一部は始めてから)、Kaggleのノウハウを探りました。
いろいろな記事を読み*1、以下が大事なのかなと思いました。

  • 一番時間を費やすべきなのは特徴量*2作成。(特徴作成8:チューニング2くらい)
  • Discussion/Kernelはvoteが最低限沢山付いているものだけでも読む。
  • ドメイン知識(データ自身に対する専門知識)を入れる。
  • 最後まであきらめない。

1. コンペ内容と基本的な内容の確認

Kaggleの公式ページ

詳しいコンペの内容は割愛しますが、データから「ユーザーが契約したローンを、遅延なく返せるかどうか」を当てるコンペでした。
すごくざっくり説明すると下の図のような感じです。赤枠を当てるコンペです。
f:id:kurupical:20180908102220p:plain:w500

Titanicのように1ファイルではなく、複数ファイル(テーブル)でデータが与えられています。
また、実際には、たくさんの特徴量があります。
1ユーザーに対して複数行の情報があるため、機械学習にかける前にデータの集計が必要でした。

EDA

Kaggleには各コンペごとにフォーラムがあり、コンペ参加者がコードを公開する場(Kernel)、議論する場(Discussion)があります。
その中でもまず見るべきなのがEDA(Exploratory Data Analysis)です。
EDAのKernelでは、投稿者が行ったデータ分析の内容を投稿してくれています。
いろいろな投稿者がEDAを投稿しており、人によってデータの分析の角度や可視化のやり方が違います。
これらの記事を見ることで、HomeCreditに留まらずデータ分析のハウツーや可視化の引き出しを増やすことができました(デキる人からすれば常識的なスキルかもしれませんが)

今回は幸運なことに、人気のEDAの日本語訳が投稿されており、この記事*3にはお世話になりました。

ただ、公開されているEDA以外にも、自分自身でEDAをやる必要があったなと反省しています。

2. コンペ参加

コンペの活動履歴を綴っていきます。
()内は、その時点のだいたいの最終順位です。

とにかく1サブミット - 3特徴量だけを使う (6600位 / 7200)

Kaggleに限らず新しいことを始めるにあたって一番しんどいのは、最初の一歩を踏むことだと思います。
完璧主義を目指して挫折するよりも、まずはどんな手法でもいいから、「1サブミット」をすることを目標にしました。

Kernelをざっと見ると、明らかに大事そうな特徴「EXT_SOURCE_1,2,3」があることに気づきました。
この3特徴量を抽出して、RandomForest(自分が最近よく使ってた手法)で分類するモデルを作りました。

1ファイル全部使う+LightGBMにチャレンジ (6100位 / 7200)

f:id:kurupical:20180908102329p:plain:w500

次は、

  • 図の赤枠部分を使って予測すること
  • LightGBMを使うこと にチャレンジしました。

LightGBMは使ったことがなく理論もわからなかったのですが、Kernelを見ながらプログラムを書いていきました。
パラメータもKernelのものを使いました。
LightGBMの場合、欠損値はそのまま処理してくれますし、カテゴリ変数も指定してあげればonehotencodeしなくてもそのまま処理してくれるので、とても便利です。

特徴量作成

特徴量作成は、思いついたものは片っ端から作って、最後に絞り込む方針でやりました。

特徴量作成① 全ファイルを機械的に集計 (1500位 / 7200)

f:id:kurupical:20180908112138p:plain

次は、使っている全ファイルを機械的に集計することにしました。
LightGBM(に限らずほとんどの機械学習アルゴリズム)を使うとき、特徴量の数は固定でないといけません。
ユーザー1は購買履歴が3行、ユーザー2は購買履歴が10行・・・のように、各ユーザーごとにデータの特徴量が違うと都合が悪いので、図のような集計を全部の数値項目に対して行いました。

この発想は独自のものではなく、Kernelの丸パクリ*4です。

特徴量作成② 項目同士の突き合わせー数値編 ( - )

f:id:kurupical:20180908110337p:plain

次は、項目同士の突き合わせです。
木のアルゴリズムはif文の集まりであるため、項目同士の関係を捉えにくいようです。
なので、元の特徴量をもとに新しく特徴量を生成しました。
例えば図にあるように、年収と子供の数の比を見れば、その家族が支払える金額の指標になりえます。

項目の意味を考えて、様々な特徴量を作成しました。
特徴量を作成するには、その業界特有の知識(=ドメイン知識)が必要とされます。

私はドメイン知識がなかったので、特徴量の重要度(LightGBMが出力してくれる)を参照し、重要な特徴量同士を四則演算して特徴量を作成しました。

これも、基本的な発想はKernelの丸パクリ*5で、そこから自分のアイデアを肉付けしていく形にしました。

特徴量作成③ 項目同士の突き合わせーカテゴリ編 ( - )

項目同士の突き合わせですが、カテゴリ変数は割り算ができません。
ので、以下2つのアプローチで行いました。

TargetEncodingとは、カテゴリ変数をTargetの平均で埋めることです。(今回であれば支払遅延有無:1を「あり」とする)
f:id:kurupical:20180908112824p:plain

また、ドメイン(もしくは常識的な)知識によりカテゴリ変数を数値に変換しました。
f:id:kurupical:20180908111911p:plain

これらの処理を行うことで、数値特徴量とカテゴリ特徴量の四則演算が可能になります。

特徴量作成④ 時系列アプローチ ( - )

f:id:kurupical:20180910200457p:plain

また、時系列的な考え方も取り入れました。
普通に考えると、直近3ヶ月の履歴はそれより前の履歴よりその人の特性を表すと思ったからです。
例として、図のような特徴量を取り入れました。

また、過去30日金額÷過去90日金額など、直近の金額が過去と比べてどうであるか、のような特徴量も作りました。

このアプローチはこのdiscussion*6から自分で考えました。

特徴量選択 (600位 / 7200)

ここまでで作成した特徴量は、およそ1800個となりました。
「LightGBMは冗長な特徴量があっても大丈夫」という意見もありましたが、特徴量が多いとメモリが足りないという都合と、やっぱり特徴量絞ったほうがいい結果が出る実感があったので*7、特徴量を絞りました。

特徴量選択は、Kernelでも様々な手法が紹介されていましたが*8、自分が試したのは以下です。

  1. 相関が高い特徴量を削除
  2. LightGBMのfeature importance(gain/split)
  3. Null Importances*9
  4. SHAP*10

結局、1で相関係数>0.95のものは片方削除→4で重要度ベスト400,500,600をそれぞれ選び、モデルに学習させました。

パラメタチューニング① hyperopt/BayesianOptimization ( - )

LightGBMのパラメータの意味がわからなくとも自動的にパラメータチューニングしてくれるすごいライブラリの使い方がKernelに公開されていたので、試しました。

  1. hyperopt *11
  2. Bayesian Optimization *12

ただ、これらを使うには調整するパラメータの範囲や種類を指定しなければなりません。

  • 範囲や種類が多いほど時間がかかる。
  • 特徴量の数によっても、最適なパラメタは違う(らしい)。

しばらく試していたのですが、上記のような理由もあり、やっぱりある程度LightGBM、GBDTの簡単な理屈を知ったうえで手でチューニングしたほうがいいかなと思い、使うのをやめました。

実際、過去の似たようなコンペの上位解法を見ると、「パラメタチューニングは勘で決めました」であったり、「我々が時間を割くべきはパラメタチューニングではない」といった記述もありました。

パラメタチューニング② LightGBMの勉強 (150位 / 7200)

パラメタの意味を知るため、簡単にLightGBMの勉強をしました。
LightGBMを知るためにはxgboostを知ってる必要があり、xgboostを知るには勾配ブースティング木(GBDT)を知る必要があり、GBDTを知るには決定木を知る必要があるということがわかりました。

参考になった資料のリンクを貼っておきます。(自分が読んだ順)

概要

NIPS2017読み会 LightGBM: A Highly Efficient Gradient Boosting Decision T…
Overview of tree algorithms from decision tree to xgboost

大事なパラメタとその意味を調査

Complete Guide to Parameter Tuning in Gradient Boosting (GBM) in Python
XGBoostやパラメータチューニングの仕方に関する調査 | かものはしの分析ブログ
Santander Product RecommendationのアプローチとXGBoostの小ネタ - Speaker Deck
XGBoostにDart boosterを追加しました - お勉強メモ
Laurae++: xgboost / LightGBM - Parameters
LightGBM/Parameters.rst at master · Microsoft/LightGBM · GitHub

論文

xgboost http://www.kdd.org/kdd2016/papers/files/rfp0697-chenAemb.pdf
lightgbm https://papers.nips.cc/paper/6907-lightgbm-a-highly-efficient-gradient-boosting-decision-tree.pdf
dart https://arxiv.org/pdf/1505.01866.pdf

論文全然わかんなかったので参照

Gradient Boosting と XGBoost | ZABURO app

過去コンペのパラメタ参照

Kaggle Past Competitions
Porto Seguroとか見ました。

結局

いろいろ見て、(結局半分も理解できませんでしたが)以下の方針を立てました。

  • モデルをロバストにする
    • colsample_bytree 0.05-0.2くらい -> 0.05がよかった
    • lamdba_l1とl2をそれぞれ0.1,1,5,10,20で組み合わせて試す -> l1=1, l2=20がよかった
    • subsample 0.9で決め打ち
  • 木の形はわからんからとりあえずいろいろ試す
    • max_depthは-1とsqrt(max_leaves) * 2、max_leavesは30〜130くらいを試した -> max_depth=-1, max_leaves=30がよかった
  • gbdt, dart, gossはわからんからそれぞれ試した -> dartメイン、gbdtもちょっと使った
    • 精度; dart>gbdt>goss
    • 計算時間: dart>gbdt>goss
  • learning_rateは0.0025〜0.05まで試した -> アンサンブル考えると(後述)、以下がよかった。
    • gbdt: 0.0025
    • dart: 0.01

※この方針はあまりよくなかった気もしています。実際、2位のikiri_DSのonoderaさんのgithub見てみると*13、colsample_bytree 0.9くらいなので・・・

アンサンブル/スタッキング① アンサンブル ( 62位 / 7200 )

最後にアンサンブルをしました。
「◯×クイズに60%正解する人が3人。3人の答えがそれぞれ独立だとすると、3人のうち多数決を取ったときのクイズの正解率は?」
答え:
3人とも正解:0.6 * 3 = 0.216、2人が正解: 3 * 0.6 ^ 2 * 0.4 = 0.432なので、0.216 + 0.432 = 0.648
正解率は一人の時より上がります!!

つまり、いろんなモデルを作って多数決をさせることで、それぞれのモデルよりよい性能が出る可能性があります。
ただし重要なのは、「モデル同士の予想の相関が低いこと」です。

モデル同士の予想の相関を低くするために、以下を行いました。

  • 異なるアルゴリズムを使う(Neural Network) -> 精度が全く出ず断念
  • 異なるパラメータを使う -> LightGBMのdart,gbdtを組み合わせることで精度が良くなった。
  • 異なるseedを使ってK-Foldする -> 単一モデルより精度が良くなった
  • 低すぎるlearning_rateを使わない(単一モデルの精度はよいが、異なるseedを使っても多様性がなく、アンサンブルの効果が薄くなった)

    相関と精度を見て、最終的に、dart(500特徴量)・dart(400特徴量)・gbdt(500特徴量)のアンサンブルを組みました。(これが最終順位62位のサブミットでした)

アンサンブル/スタッキング② スタッキング ( - )

「スタッキング」とは、「複数のモデルが出した予想値」を入力にしてもう一度学習させ、最終的な予想を行うことです。
スタッキングもやったのですが、アンサンブル以上に精度が出なかったので断念しました。

結果

LB: 498位→PB:62位
LBの順位は低かったですが、公開されているソースよりもCVが高かったので、Trust Your CV*14の精神で耐えました。
CV0.794->LB0.804のようなLBにOverfitしてると思われるものもありましたが、自分はCV0.8018 -> LB0.802でした。

3. 感想

とても勉強になりましたし、楽しかったです。
データの分析の仕方もLightGBMもわからない状態でスタートしましたが、ほとんどKernelに助けられながら、最後までできました。
実際、Kernelを全く見ないでやったら、半分より上にも行けなかったと思います。
scikit-learnあたりの使い方が少しわかってきたけど次何すればよいか・・・という人には、Kaggleを強くおすすめします!

また、コンペ参加中は、データ分析をみんなで一緒にやってる気持ちでした。
discussionを読みながら、時々参加したり。
リーダーボード(ランキング)をみて、「自分はこのスコアが限界だと思ってたけど、もっと伸びるのか」と、分析を投げずに最後までがんばれたり。
中だるみもありましたが、充実した3ヶ月でした。

自分自身が、Kaggleに参加する前とした後で変わったことは以下かなと思っています。

  • 特徴量作成が超大事だと分かった。(データを入れたら答えが帰ってくるわけじゃない)
  • 「テーブルデータの分類モデルの構築をどこから始めたらよいか」が分かった。
  • 特徴量作成の定石を少し覚えた。
  • LightGBMの分類が使えるようになった。(ある程度パラメータも理解できた)
  • GCPの使い方がわかった*15

泥臭い部分も含めたノウハウを、少しだけ、Kaggleを通じて習得できたかなと思います!

超長くなってしまいましたが、最後まで読んで頂きありがとうございましたm(_ _)m

<メモ>tensorflowのimport時のエラー(libcublas.so.9.0が見つからない)

tensorflowのimport時にlibcublas.so.9.0: cannot open shared object file: No such file or directoryと出る時の対処法メモ

環境

  • CUDA 9.0
  • tensorflow 1.8.0
  • Pycharm community 2018.1

状況

解決方法

Pycharmを開き、[Run] => [Edit Configurations] => Python-[自分が動かしてるプログラム]を選択
Environment variablesに、LD_LIBRARY_PATH: /usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATHを追加

f:id:kurupical:20180817101146p:plain

defaults→python→Environment variablesにLD_LIBRARY_PATHをセットしても動かなかったので、自分のプログラムにパスを通しました。

CUDAの環境まわりなどちゃんと入れてるのに何故かちゃんと動いてくれない・・・というときは、開発環境を疑ってみるとよいと思います。

参考記事:
github.com