カテゴリー別アーカイブ: programming

ライブラリのコードを理解するための環境整備

はてなブログに引っ越しましたので、そちらをご参照下さい
https://threecourse.hatenablog.com/entry/%3Fp%3D1186

=================

目的

xgboost等のPythonからC++を呼び出すライブラリの理解のため、printデバッグや改造をできるようにする

環境

Windowsなので、GCPでlinuxのインスタンスを立ち上げる。
CLion/Pycharmのリモート機能を利用する。(ローカルの方が楽だけどやむを得ない)

やること

1. コードを落とし、C++でコンパイルできることを確認する

git clone –recursive https://github.com/dmlc/xgboost
cd xgboost; make -j4

2. 読むべきPythonコード/C++コードのフォルダを確認する

xgboostの場合は以下のフォルダ。
Pythonコード: python-package
C++コード: src, include
どうやって読むべきフォルダを確認するか良く分からないのですが、Makefileを読む/雰囲気くらいか。

3. (pipなどでインストールしたものでない)対象のPythonライブラリを呼び出す

呼び出し元となるpythonスクリプトを作り、そこで
import sys
sys.path.insert(0, my_library_path)
とすると、対象のパスから優先的に読み込むことができる。

4. (pipなどでインストールしたものでない)対象のC++ライブラリを呼び出す

どのようにPythonからC++ライブラリを呼び出すかをまず確認する。
xgboostの場合は、python-package/xgboost/core.pyの_load_libメソッドでctypes.cdll.LoadLibraryにより呼び出している。
ここでライブラリのパスはpython-package/xgboost/libpath.pyのfind_lib_pathメソッドで取得している。
対象の相対パスは含まれているので、pipなどでインストールしたライブラリが読み込まれないよう、dll_path = dll_path[:-1]などとすれば良い。

5. 動作確認

確認対象のpythonモジュールが読み込まれているか、C++ライブラリが読み込まれているかをprintやstd::coutを差し込むことで確認する。


マラソンマッチの資料集

はてなブログに引っ越しましたので、そちらをご参照下さい

https://threecourse.hatenablog.com/entry/%3Fp%3D1164

============================

マラソンマッチ勉強会の予習ということで、少しまとめてみました。(2018/8/14 資料追加)
リンクはちょっと探した限りなので、他にもあったら教えて下さい。

全般

手法

他にもいろいろありそうですが、

  • いろんな探索(幅優先探索、深さ優先探索)、局所探索
  • 山登り、焼きなまし
  • 貪欲法
  • ビームサーチ
  • chokudaiサーチ

(参考)

ヴィジュアライザ

具体的にどのコンポーネントやフレームワークを使うのがいいのかな?

  • .NETのSystem.Drawingとかでぽちぽち書いていく
  • Siv3D
  • HTML + JavaScript

(参考)

過去問(と解法)

過去問とその解法をいっぱい持っておくことは役に立つと考える。

月刊: Kaggleは役に立たない

Kaggle Meetupのネタにでも、ふわっとした文章を書いてみる。
個人の意見です&ここ1-2年の状況変化は追えていないかも。

(追記:タイトルは「月刊競技プログラミングは役に立たない」という競プロ方面のネタから来ています)

どうでもいい技術、どうでもいくない技術

Kaggleで勝つための技術を書き連ねてみる:

  • Python, R, ライブラリの使い方
  • 特徴量の作成
  • データについての考察、EDA
  • モデルの使い方、パラメータチューニング
  • 評価指標についての考察
  • DiscussionやWinner’s interviewを読む英語力
  • 柔軟に作業や分析を回すためのクラス・ワークフロー・ログなどの実装
  • GCP, AWS, BigQueryといったサービスの運用
  • 論文を読んで手法を参考にしたり実装したりする力
  • 折れない心

改めてまとめてみると普通に学んで損のないものばかりな気がしてきた。

ただ、実際には、

  • 脳みそを空っぽにしていろんなモデルや特徴量を作ってアンサンブル
  • たくさんランを流してxgboostのscoreの流れをぼーっと眺める
  • 画像コンペでのトレーニングデータへのラベリング

とか、何やってんだろと思うこともあるのは確か。

Bestfitting氏のインタビュー

Profiling Top Kagglers: Bestfitting, Currently #1 in the World

現在のKaggle User Ranking 第1位のBestfittingのインタビュー。
ちゃんと自分を律しているなぁという印象。
人によって興味深いポイントはそれぞれだが、個人的にはコンペを始める前に類似のコンペのSolution(にとどまらず論文まで)をおさえることをきっちりやっているのは偉いと思った。
(どうやってその時間を捻出するのだろう…)

競プロとの違い

以下のTweetが本質を突いているのかなと思った。

私としては、

競プロ(特にアルゴリズム)

  • 「純粋」な印象。範囲が定められているが、深度が要求される。
  • 強い人には絶対かなわない感がある(逆に競プロが強い人がKaggleにアジャストすると楽に勝てるイメージ)

Kaggle

  • 「複線的」でいろんな方向から攻めなくてはいけない印象。
  • 実世界への適用が意識されている
  • 実力差があっても、攻め方や頑張りや運でワンチャンある感じ。

Kagglerは仕事ができる説

「Kagglerは仕事ができる」とか吹いても良いんじゃないかと思った。

  • 複線的でいろんな技術が要求される
  • どのモデルやどの特徴量から作るか、手元のCVスコアとPublic LeaderBoardのスコアが合わないときに何を疑うか、手を動かすのか情報収集をするのか、優先順位をつけて攻めていく必要がある
  • 計算時間やメモリ使用量だけでなく、睡眠時間や現実でのお仕事の状況を含めたリソース管理が要求される

楽しみ方はいろいろ

“ガチ勢”はgold medalを基本目指していると思いますが、他にもいろいろと楽しみ方はある。

金メダルを目指す

競技者としては、ここがベースになりそう。
ほぼ金メダル=Kaggle Masterであり、対外的にもなんか強そうな印象を与えられる。
hard workを積み重ねないとgold medalには届かないのはメルカリのceremonyでも共通意見だったか。
(たまにラッキーパンチが入るという噂もある)

銀メダルを目指す

そこまでガチではなく、単純に学びたいとか、データ分析と違う業種にいるけど実力を示したいとか、という場合には銀メダルを目指すのが良いと思う。
実力証明としては、銀メダル(できたら複数)で十分価値はありそう。
学びの場としても、ここに至るまでが一番費用対効果が高そう。

beat the benchmarkを自力で超えられる力をつける

銅メダルは入るための基準がコンペによってまちまちな印象があるので、これを目指すというのはあまりお勧めしないかも。
どのコンペでも大体誰か優しい人がbeat the benchmark(以下btb)と言われる、基本的なモデリングを行ったSolutionをKaggle Kernelに上げてくれるのですが、
銅メダルを目指すよりは、btbを自力で超えられる力をつけるということを目指して結果として銅メダルなどがついてくる方が良さそう。

上の順位を目指さない

こんな感じで、興味や軸をずらして参加してみるのもあり。

  • 可視化、EDAに絞ってkernelを眺めてみたりまとめてみる
  • 特定のモデル・ライブラリについて深く追う
  • Winners’ Interviewで人間ドラマを追う
  • Datasets AwardやKernels Awardを目指してみる

AOJ本の基本問題集

最近はatcoderの黄色を目指すべく、競プロの問題を解いています。
atcoderの過去問なども解いていますが、基本問題を整理しておきたいと思ったので、プログラミングコンテスト攻略のためのアルゴリズムとデータ構造をやっていました。

AOJ本の例題には、競プロには直接役に立ちづらいもの(stackの実装とか)もあるので、競プロに役立ちそうな基本問題をまとめてみます。

概要 問題番号
5 二分探索 ALDS1_4_B
6 DFS(組み合わせ列挙) ALDS1_5_A
11 DP(フィボナッチ) ALDS1_10_A
11 DP(連鎖行列積) ALDS1_10_B
11 DP(最長共通部分列) ALDS1_10_C
12 グラフDFS ALDS1_11_B
12 グラフBFS ALDS1_11_C
13 単一始点最短経路-ダイクストラ ALDS1_12_C
14 UnionFind DSL_1_A
15 全点対間最短距離-ワーシャルフロイド GRL_1_C
15 最小全域木-クラスカル法もしくはプリム法 GRL_2_A
15 単一始点最短経路-ベルマンフォード GRL_1_B
16 幾何 CGL_1_A, CGL_1_B, CGL_1_C
16 幾何 CGL_2_A, CGL_2_B , CGL_2_C, CGL_2_D
17 DP(コイン) DPL_1_A
17 DP(ナップサック) DPL_1_B
17 DP(最長部分増加列) DPL_1_D
17 DP(最大正方形) DPL_3_A
18 最大公約数 ALDS1_1_B
18 エストステネスの篩 ALDS1_1_C
18 繰り返し2乗法 NTL_1_B
19 ヒューリスティクス(8クイーン) ALDS1_13_A
19 ヒューリスティクス (8パズル) ALDS1_13_B

ユニクロコン 実装編

オプトのユニクロコンペ(https://deepanalytics.jp/compe/36?tab=compedetail)について、もう少し実装のマニアックな話をしてみます。
コードはhttps://github.com/threecourse/opt-uniqlo-publicに上げています。

コードのインターフェイス

データ分析コンペ用のモデル構築用のクラスをどう作るかは長年の課題だったのですが、少しずつ固まってきました。

いろいろ考えた末、ベースとなるクラスはModel, Runnerに2つに分けた。

  • Modelはsklearnの各モデルをwrapするイメージ
  • Runnerは訓練や予測やクロスバリデーションなど一連の計算のもろもろ
  • 結構良い感じで、わりとモデル追加、クラスの拡張の際にストレス無くできた。
  • sklearnのインターフェイスがあまりしっくりこないのと、hyperoptに合わせたいこともあり、sklearnのベースクラスの継承はしていない。
  • データの読み込みをRunnerに持たせているが、微妙かもしれない。Modelに密接に結びついているので、そちらに定義させた方が良いかもしれない。
  • どう頑張っても時にはダーティーにやらなくてはいけないことがあるので、その時は諦める。
  • 型ヒントが効くようにちゃんとdocstring書いた方が良いかもしれない。

Model

  • Modelクラスはmodel.pyに定義。
  • 入力は、モデル名(とfold名)・データ・パラメータなど。
  • 責務は、訓練・予測・モデルの保存・モデルの読み込みなど。
  • 各foldごとに1つモデルのインスタンスが作成される。
  • baggingなどもこの中で処理することができる。

主なメソッドは以下のとおり。

シグネチャ 概要
__init__(run_fold_name) モデル名(とfold名)がないと不便。
train(prms, x_tr, y_tr, x_te, y_te) パラメータとtrainのx, yとvallidationのx, yを入力とし、モデルの訓練を行う。
train_without_validation(prms, x_tr, y_tr) パラメータとtrainのx, yを入力とし、モデルの訓練を行う。trainの全データで訓練したいとき用。
save_model() モデルを保存する。
load_model() モデルを読み込む。
predict(x_te) testやvalidationのxを入力とし、訓練されたモデルから予測値を返す。

Runner

  • Runnerクラスもmodel.pyに定義。
  • 入力は、モデル名・入力データのリスト・パラメータなど。
  • 責務は、データの読み込み、インデックスの読み込み、クロスバリデーションでの訓練(精度の出力も含む)、訓練されたモデルを使ってのテストデータの予測、hyperopt用の精度の出力など。
  • データの読み込みは単にファイル名の指定だけでなく細かく修正することが多いので、Runnerでそこだけ調整できるのは便利。
  • インデックスは複数に対応するようにしておかないと、後で面倒。
  • ログとクロスバリデーションの精度を標準出力とファイルに出力。
  • 動作確認用に少ないデータで流せるよう設計しておけば楽なのだが、対応が面倒なのであまり出来ていない。

主なメソッドは以下のとおり。
各Runnerで定義が必要なのはbuild_model, load_x_train, load_x_test。
ランなどで外部から使用する必要があるのはrun_train, run_test, run_hoptあたり。

シグネチャ 概要
__init__(run_name, flist, prms) モデル名、特徴量名(list)、パラメータ(dict)のセット。
build_model(run_fold_name) 使用するModelの定義。
load_x_train() trainのxの読み込み。
load_x_test() testのxの読み込み。
load_y_train() trainのyの読み込み。
load_w_train() trainのweightの読み込み。weightを変えて訓練したい場合に。
load_index_fold(i_fold) cv用インデックスの読み込み。(trainのidx, validationのidx)を返す。5foldの場合、基本はi_foldに0-4が入る。違うcv用インデックスで計算したい場合、”a0″や”a4″のように指定する。
load_x_fold(i_fold) foldを指定したxの読み込み。(trainのx, validationのx)を返す。
load_y_fold(i_fold) foldを指定したyの読み込み。(trainのy, validationのy)を返す。
load_w_fold(i_fold) foldを指定したweightの読み込み。(trainのweight, validationのweight)を返す。
train_fold(i_fold) 指定したfoldでの訓練を行い、訓練されたモデルを返す。
run_hopt(i_fold = “a0”) hyperopt用。指定したfoldでの訓練を行った後に、loss(と訓練されたモデル)を返す。
run_train() クロスバリデーションでの訓練を行う。とりあえず5cv固定。各foldのモデルの保存、精度のログ出力についても行う。
run_test() クロスバリデーションで訓練した各foldのモデルの平均により、testのyの予測を行う。
run_train_alltrain() trainの全データで訓練し、そのモデルを保存する。
run_test_alltrain() trainの全データで訓練したモデルにより、testのyの予測を行う。

パラメータチューニング

パラメータチューニングはhyperoptを用いて、5cvのうちの1foldのみで行い、メインの計算とは別のcv用インデックスで行った。
また、fit_generatorにより1epochを3000枚程度に小さくし、patience=3のearlystoppingで行った。
なお、訓練時はhyperoptの結果を元にepochを固定した。

  • コードはhopt/hopt_resnet.pyなどを参照。
  • 計算時間に余裕があり、精度のばらつきが激しい場合は5cvなどで評価した方が良いが、neural netだと計算時間はさすがにきつい。
  • 同じインデックスだと、hyperoptに使ったfoldだけoverfitすることがあるので、stackingを行う場合にちょっと気になる。気にし過ぎかもしれない。
  • epochをそのままだと、patience=3だとかなり行き過ぎてしまう感じ。
  • epochを固定するのではなく、early_stoppingでsave_best_onlyを使う方法もあるかもしれない。

kerasのジェネレータ、data augmemtation

頑張った。kerasのImageDataGeneratorは、場合によっては少し手を加えないと使いづらい。

  • コードはmodel_keras_util.py, model_keras_util_augmentation.pyなどを参照。
  • 汎用のジェネレータがサポートされていないようだったので、keras.preprocessing.imageのIteratorなどを参考に作成。
  • data augmentationも、ImageDataGeneratorを元に切り貼りして作成。

ログ

  • コードはutil_log.pyを参照。出力はlogフォルダを参照。
  • ログを標準出力とファイルの両方に出力するようにする。
  • 時間の情報を付加することにより、なんとなく時間のかかっている処理がわかる。
  • 一般的な情報とクロスバリデーションの精度の情報の2つに分ける。
  • クロスバリデーションの精度の情報はltsv形式で出力しておく。時々util_result.pyをランすることでモデルごとにまとめる。

ヴィジュアリゼーション、分析

  • コードはanalyzeフォルダを参照
  • 背景領域を0, それ以外を1としてベクトル化し、kmeansクラスタリングを行った。画像が整えられているので、単純だが結構きれいに商品カテゴリごとに分けられる。
  • 巡回サラリーマン問題を解いてカテゴリ間の距離が最小になるように並べた。近いカテゴリが近くにくるので見やすい。
  • カテゴリごとに画像・正解ラベルを並べたpdfを作った。(運営からの許可が出てないのでpdfはアップロードしてません)
  • どうもipython notebookは自分に合わなく、pdfを生成することが多い。

ユニクロコン 手法編

オプトのユニクロコンペ(https://deepanalytics.jp/compe/36?tab=comperank)に出ていました。
public 4th -> private 4thという結果で、運次第では賞金圏内もあったと思うので切ないですね。

0. 概要

基本データ

  • ユニクロの商品の色(24クラス)を判別する課題
  • Train:12399, Test:9801
  • 背景はちゃんと切り抜いてくれているので、わざわざwatershedなどで背景抽出をする必要が無い

課題

  • 色の判別はやや単純すぎる課題で、本来はCNNを使うのはオーバーキルな感じもある。
    ただ、後述のラベリングの微妙さも相まってコンペとしてはある意味おもしろい。
  • ラベリングが微妙。もはやどっちが正しいのかわからないの多数。特に3連靴下はなんだこれ。
  • 分析すると、女性物は同じような色でもオフホワイトになりやすかったり、ラベリングは服の種類に影響を受けていることがわかる
  • このコンペは色を判別するコンペではなく、人間がどのように色コードを設定するかを判別するコンペといえる。
  • train/testはrandom splitではなく、商品ラインごとのsplitをしている様子。
    なので、やりすぎるとtrainデータへのoverfitの危険もある

評価指標

  • balanced accuracyであることがポイント。比率の少ないものを間違えるとペナルティが大きい。
    完全に正しい確率を予測できているとするならば、確率÷正解ラベルの比率が最大となるものを予測するのが適切。
  • trainingデータのweightを変える方法も試したが、通常のweightで分類し上記の調整を行う方が精度が高かった。
  • balanced accuracyは安定しない、accuracyが良くても2番手以降の評価がいまいちだとスコアが出ないので、loglossを下げることに注力。

1. 特徴量抽出、分析

クラスタリングを少し試したが、結局モデリングには適用していない。

  • シルエットによるクラスタリング
    背景領域を0, それ以外を1としてベクトル化し、kmeansクラスタリング。
    画像が整えられているので、単純だが結構きれいに商品カテゴリごとに分けられる。

  • 分析、ヴィジュアライゼーション
    カテゴリ間の距離が最小になるように並べる(巡回サラリーマン問題を解く)と、近いカテゴリが近くなるので見やすい。
    カテゴリごとに画像を並べたPDFを作ったり、カテゴリごとの色の分布・正答率を見たりした。

  • 接続領域での分離
    繋がっている領域が何個あるかを求める(DFS)。3連靴下とかを綺麗にわけることができる。

  • その他
    SIFT、カラーヒストグラム、pretrained modelで予測したimagenetのカテゴリとか考えたが、結局使っていない。

2-1. モデリング

  • ニューラルネットのライブラリはkeras
  • ファインチューニングとスクラッチからのCNNの両方を行った。
  • テストデータには、5cvの平均を適用するようにした。
    ニューラルネットだと、trainの全データを使うとvalidation scoreが見れないので怖い。
  • パラメータ調整はhyperopt。ネットワーク構成、learning rate、optimizerの選択に大変役に立った。
  • 単発だとかなりぶれるので、10-20回回した平均をとった。
  • オプティマイザは、ファインチューニングはmomentum sgdで良さそうですが、スクラッチではadamが有効だった。
  • スクラッチから作る場合は、序盤に1*1フィルタを適用するモデルの精度が良かった。
  • 1epochで10000枚回すとearly stoppingの際に行き過ぎてしまうので、generatorを使うことで1 epochの枚数を制御した。
  • data augmentation, test-time augmentationを行った。
    左右反転・少し回転・少し拡大縮小させた。
    kerasのImageGeneratorは専用実装になっており、取り入れにくかったので、適宜コードをつぎはぎした。

2-2. 作成したモデル

ファインチューニング

  • vgg16
  • vgg16, augmentationあり
  • resnet
  • resnet, augmentationあり

スクラッチからのCNN

  • cnn1-5 : 序盤に1*1フィルタを適用したCNN(5種類)、augmentationあり
  • cnn0 : 1*1フィルタのみでピクセルの場所の情報を全く使用しないCNN

ネットワーク構造は以下のような感じ。怪しい。
Conv2d(filter=1 * 1) -> Conv2d(filter=1 * 1,stride=2) -> BN -> Maxpooling(2 * 2) ->
Conv2d(filter=2 * 2) -> Conv2d(filter=2 * 2,stride=2) -> BN -> MaxPooling(2 * 2) ->
Dense -> BN -> Prediction

各モデルのローカルのスコア(10-20個混ぜている)は以下のとおり。

model logloss balanced acc accuracy
vgg16 0.6876 0.7004 0.7695
vgg16_aug 0.6969 0.6910 0.7685
resnet 0.6687 0.6975 0.7747
resnet_aug 0.6462 0.7005 0.7809
cnn1-5 0.6548-0.6743 0.6993-0.7116 0.7672-0.7732
cnn0 0.7396 0.6624 0.7443

3. Ensemble、調整

  • 各モデルの加重平均をとる。
    加重平均を取る際には、loglossが最小になるような係数を探し、適用する。
  • スタッキングを行う。クラスが多いためか、スタッキングをしたモデル自体の精度はあまり良くない。
    スタッキングをしたモデルとの加重平均をとることで少し精度が上がる。
  • 最後の仕上げでloglossが最小になるように確率をn乗したり、色の比率のn乗を乗じた。
    この辺はいろいろやり方がありそう。

各モデルのローカルのスコアは以下のとおり。

model logloss balanced acc accuracy
加重平均 0.6154 0.7199 0.7880
スタッキング 0.6311 0.7154 0.7815
上2つの加重平均 0.6120 0.7213 0.7882
調整後 0.6069 0.7217 0.7874

Kaggle Prudential 自戦記

Kaggle Prudentialに参加していました。
順位はpublic 60th, private 30th/2715 でした。
かなり学びはあったので、それをまとめる意味でも書いておこうと思います。

概要

  • 保険申込者のレコードに対応する反応変数を推定する。反応変数は1-8。
  • ほとんどの項目名はわからないようになっている。(Product_Info, Insured_Infoなど大まかなくくりはわかる)
  • データはきれいで、ほとんどfeature engineeringする余地がなさそうに見える。

  • 評価基準はquadratic weighted kappa。
    これが曲者で、kappa用にクラス区切りのoptimizeをしないと勝負にならない。基本的なアプローチは反応変数を数値としてregressionをした後、optimizeしてクラス区切りを求めるという方法。

    • 素のxgboost -> 0.63くらい
    • クラスの区切りを改善 -> 0.665(btbは最終的には0.674まで行った)
    • トップのスコア -> 0.682
      といった感じのpublic LBで、運ゲーの香りが漂っており、実際かなりのshake upとなった。

  • 文献も漁ったが、残念ながらアクチュアリーのdomain knowledgeの出番は無かった。
  • linearでもわりと良い値が出るので、非線形の関係性はそこまで無さそうな感じ。

特徴量作成

  • 結構いろんな方法を試したが、xgboostには効果は無かった。(さすがにlinear regressionに利くものはあった)
    例)

    • BMIはWt/Ht^2だが、Wt/Ht^3などを作ってみる(WeightやHeightが変換されているので、推定して戻す必要がある)
    • t-sneで次元圧縮
    • Product_Info4 < 0.075のときは分類が特殊なので、それを特徴量にする
    • dummy変数やnullの個数のcount

  • 作成したfeatureの管理が結構時間をとられるところです。試行錯誤の末に、以下のような管理方法にしています。
    • 作ったfeatureはレコード数*要素数のnp.arrayとして表現
    • 前処理(OneHotEncodeとか)を柔軟に適用するために、
      モデルに投入するfeaturesの組を(タグ、featureのリスト、前処理手法のリスト)のリストで表現
    • もうちょっとシンプルで良い方法がありそう
       

パラメータ調整

  • パラメータ調整も結構時間のとられるところ。hyperoptを多用した。
  • hyperoptもやりすぎるとtrain dataにoverfitしてしまいそう。
    • 最終的には、別のfoldを作って、hyperoptはそちらのfoldで行うような方法にした。
    • このコンペだと、public LBの件数が少ないため、public LBでoverfitしているか判定するという方法は使えない。
  • もう少し頑張れば、ChenglongChen師匠のようにhyperoptしてそのままモデルをランすることができそう。

モデル・アンサンブル

  • 最終的には5foldで3層Stackingとなった。
    • 1層目
      • xgb, nn(keras, keras graph), ert, linear(vw), svmでregression
      • xgbでclassification
      • xgb, nn, ertでbinary classify(2以下のクラスか否か、6以上のクラスか否か)
    • 2層目
      • xgb(feature有/無), xgb classify(feature有/無) , ert, linear
    • 3層目
      • xgb, xgb classify, linear
    • 3層目をさらにlinearしたものが最終出力

  • インターフェース, feature, parameterが定まっていれば、モデル作成はただの作業。
    逆にいうと、インターフェースを整えたり、特徴量を管理したり、パラメータ調整したりというのが大変だった。

  • 層を重ねるのはそれなりに効果があった。
  • 3層構成にすると、2層目でoriginal feature有/無のstackingを試せたり、多少柔軟にできるように思う。
  • 他にもいろいろな方法があると思います。StackNetとかいう方法があるらしいですがどうやるんでしょう。
    http://blog.kaggle.com/2015/12/03/dato-winners-interview-1st-place-mad-professors/

AWS課金

  • c4.2xlarge(1時間0.5$)をメインに運用。xgboostが早すぎてノートPCには戻れ無さそう。。
  • インスタンスを起動しているとやらなきゃいけない気になるので、そんなメリットもある。
  • 後半は少しスポットインスタンスを活用。
    起動➡rsyncでコード送付➡s3 syncで必要なデータを取得➡ラン➡s3 syncでデータを保存➡shut down という流れを構築できればスポットインスタンスメインで開発ができそう。
    東京リージョンだとc4.2xlargeがたまに高騰するので、バージニア北部に移住予定。

いかにしてkaggleを解くか

Walmart2015については、CrowdFlowerのSolutionを参考にしながら、いろいろと考えながらやってました。
結局xgboostとneural netのstackingくらいしかできませんでしたが。。(38th/1047)

その中で、kaggleの問題に対して”解”を出すのにあたって、どういうポイントがあり、どのように進めていくべきかの”構造”を考えてみました。

kaggle masterだけど機械学習は素人なので、突っ込みどころはいっぱいあると思います。ご指摘やこんな資料があるなど、教えていただければ助かります。

1 – 特徴量作成・管理

何だかんだいっても特徴量作成は重要で、重要な特徴量を逃すと勝ち目はないでしょう。
逆に適切な特徴量が作れれば、xgboostだけで勝てることもあるようです。(cf. Rossmann)

  • 特徴量はN * M(N:ID, M:要素数)の数値の2次元配列として表現されます。
  • 最初からIDに対して各列の要素があるDataFrameになっていれば簡単ですが(Prudentialとか)、IDに対してレコードが複数あるようなデータの場合、集計する必要があります。
  • xgboostでは木なので何も考えなくて良い(しかもnanも受け入れてくれる)のですが、neural netやlinear regressionではカテゴリカル変数をダミー変数に直したり、logをとったり、標準化する必要があるようです。
  • 汎用的に行うには、各foldごとに、train data – validation dataをまとめて、特徴量を作成することが必要ではないかと思っています。
    (3foldの場合、各foldごとに同じように3回特徴量の作成を行う。また、submission用にはtrain data全体・test dataで同様に特徴量の作成を行う)
    (cf. CrowdFlower1stのドキュメント 4.1.2 Following the Same Logic)

    • TF-IDFなどを行う場合には、validation dataもまとめて処理しないと、変なことになってしまいそうです。
    • 教師ありで特徴量を作るときには、各foldのvalidation dataのlabelを使うとleakしてしまいそうです。
  • 特徴量をどんどん作っていくとだんだんわけが分からなくなってくるのですが、どうやって管理したらいいのでしょう?

2 – モデリング

モデルは特徴量やパラメータを変えたりして試行錯誤する必要があります。
ここで、モデルを(特徴量の組・モデルの種類・モデルパラメータ)を引数とし、 (モデル, validation dataの予測値, validation score)を返すようなインターフェイスで表現することで、
特徴量選択やパラメータチューニングの自動化に進めるのではないかと思っています。

2-1. 特徴量選択

特徴量をいっぱい作ると、その選択に悩まされることになります。理想的には、特徴量をどんどん作って、後はmodelに選んでもらうのだと思いますが、以下の手法などがあるようです。

untuned modelling

xgboostやERTなどの分類器のパラメータを固定し、特徴量の組を変えて試し、scoreが良い特徴量の組を選択する。
このようにして選択した特徴量を、複数の分類器に展開していくこともできる。
(cf. Microsoft Malware 2nd)

greedy forward selection

以下のような手順で行います。

  1. 要素がN個ある場合に、それぞれの要素を試す
  2. 最もスコアの上がるものを選び、採用する要素に加える。
  3. 1-2を繰り返す。
    (cf.smlyさんの講演資料

ただ、N^2のオーダーで時間がかかるので、ちょっと時間がかかりすぎな気がしますが、どうやってfeature selectionに適用するのでしょう?

特徴量が大量にある場合

以下の方法があるようです。

  • xgboostやrandom forestのimportanceの上位から選ぶ
    (cf. tksさん-walmart2015)
  • chi2やinformation gainで選ぶ
    (cf. Abhishek-walmart2015)
  • 出現数が一定以下の特徴量を落とす、まとめる

結局、当面の自分の方法は、特徴量の組のリストを手動で作成し、後はuntuned modellingで選ぶくらいになってしまいそうです。もっと汎用的な方法はあるのでしょうか?
また、分類器によって必要な特徴量が異なるので、全部の分類器を同じ特徴量で計算するわけにはいかず、なかなか難しいところです。

2-2. モデル選択

強そうなモデルから順に試していくしかない気がします。
私はとりあえずxgboost, neural net(keras), linear regression(vowpal wabbit)をある程度しっかり使えるようにしたいと思っています。
その次はscikit-learnのSVMやERT(Extremely Randomized Tree)でしょうか。

2-3 パラメータ選択

ハイパーパラメータによって大きく精度が変わる場合、どうしても多くの試行をする必要があります。
人の手で1つ1つ回してもしょうがないので、やはりこれも自動化したいところです。
pythonではhyperoptが人気のようです。(他には、baysien optimizationなどの方法もあるようですが)

hypetopt

Tree of Parzen Estimatorsという手法により良さげなパラメータを選んでくれます。
使ってみた感じだと、最低25-50回くらいは回さないと、使う意味がなさそうです。
CrowdFlowerの1stの解法では、hyperoptがふんだんに使われています。
てれかさんの記事も参考になります。

3 – アンサンブル

diverseなモデルを複数組み合わせると精度が上がるようです。その方法としては、stackingが基本のようです。

stacking

以下の流れになります。

  1. あるモデルで、k-foldで各foldのvalidation dataの予測値を作成する
  2. あるモデルで、train data 全体 – test dataでtest dataの予測値を作成する
  3. 1-2を組み合わせると、あるモデルの予測値でできた特徴量ができる
  4. 1-3を色んなモデルで組み合わせると、モデル数分の特徴量が作れる
  5. 元の特徴量と生成した特徴量を組み合わせたものを新たな特徴量として、ensemble用のモデルを用いて最終的な予測値を作成する。
  • ensemble用のモデルはとりあえずxgboostで良いような気がするのですが、NNやERTなどを使うメリットもあるのでしょうか?
  • kaggle ensemble guideではblendingという手法も紹介されています。ただ、例えば1/10をhold out setとして取っておくという方法なので、データ量が十分大きくないと、submissionはともかく手元のvalidation scoreの評価が難しいように思います。

(cf. kaggle ensemble guidepuyokwさんの記事)

4. その他

技術の優れた常連kaggle masterに対抗するには、データをちゃんと理解することが必要な気がします。
そのために、プロット、モデルから出力される変数重要度を見る、誤差の分析、泥臭さ などいろいろありそうですが、今回は割愛します。

Kaggle – 神々に近づくために

PyDataTokyoに触発されたので、Kaggleで上位を取るための戦略、そして神々に近づくための学習戦略を考えてみました。
kaggle master (自慢)ではありますが、kaggle歴は浅いので、いろんな突っ込みどころがあると思います。

1. 初参加 ~ top25%

  • まずはtitanicのtutorialを始めてみる
  • 終わったら、ちゃんとポイントのもらえる本番コンペに参加する
    • お遊びコンペだとなかなか気合いが入らないので(人によります)
    • いろんなコンペがあるが、とりあえず興味があるのに参加してみる
      • 無理そうならあきらめる
  • beat the benchmark(btb)というのがForumに出てくるので、まずはbeat the beat the benchmarkを目指す。これができればtop25%とか行けるのではなかろうか。
    • ツールの使い方を覚える良い機会
    • btbは特徴量をそんな真剣に作っていないと思うので、利く特徴量を1-3個作ればbeatできそう。(それが大変なのですが)
  • 基本の流れは、特徴量をくっつけてデータフレームを作る→ツールにぶっこむ。まずはxgboost。

2. top25% ~ top10%, top 10, kaggle master

以下のことを考えつつ、機械学習手法を覚えたり、特徴量作成技術を磨く。

  • 上位に行きやすいコンペを中心に参加する
    • 「なにかしら特殊で多くの人はどこかを間違えたりなにかが足りなかったりする問題を狙うといい」by nagadomiさん
    • 細かい精度を競う典型的な問題のコンペは神々たちの遊び場という説

  • 求められているタスクおよび評価基準を理解し、それに合致したアプローチをとることが重要。
    • 考えまくるのと、過去の優績者のドキュメントを見るしかないか
    • 時系列データに対して将来の値を予測に使うのは変だけど、使えるものは(ルールが許す限り)何でも使う心意気

  • train dataへのleakを逃さないことは重要
    Leakとは、本来は予測に使うことを想定していないけれど有用な情報の漏れ

    • Couponでは一部のtest couponのデータがvisit logに出ていた
    • KDD Cup 2015でも、leakyな特徴量がいくつか使われている
    • Caterpillarではtube ID自体が特徴量として有用だったそうな(kaggleちゃんと仕事しろ)
    • Forumをウォッチしましょう

  • public leaderboardへのleak
    • Couponではuserでpublic/privateが分割されているため、人気クーポンの情報が漏れ出る。
    • Caterpillarでは 同じtube IDで数量というパラメータが違うレコードがpublic/privateに分割されていたので、public LBの信頼度が高め (kaggleちゃんと仕事しろ)
    • わかっても使えなかったり、使いすぎて死亡することはあるが、local validationの妥当性を考察する上では役に立つ。

  • local validation
    • 問題によっては単純に分割するだけではダメ。train setがvalidation setの情報を持たないようにする。  
      • Caterpillarではtube IDごとに分けないとダメでした。
    • Couponなど、データ量によってはcrossさせる必要はないかも。
    • いまいちしっくりこないこともあるが、信頼できるlocal validationを持ってないと勝機は無さそう。

  • ソースコード管理(git)やタスク管理(私はevernoteを使っています)

3. kaggle master ~ 神

特殊なコンペだけでなく、典型的でensembleが利くようなコンペでも上位に入れるレベル。
ここに至るには、KDD CUP 2015で優勝チームがやった成果の1/5くらいを出せるようになれば良いと考える。
過去問で点数を取れれば本番でも点数を取れるはず理論。

  • 手法・ツールの学習
    KDD CUP 2015優勝チームが使用している手法は以下の通り。あとはt-SNEなどの次元削減手法か。
    Gradient Boost Machine(Xgboost), Neural Network, Factorization Machine, Logistic Regression, Kernel Ridge Regression, Extreme Trees, Random Forest, K-Nearest Neighbor

  • 特徴量作成技術のレベルアップ
    過去の優績者のドキュメント・コードを見るしかなさそう。

  • 環境構築・パラメータ調整
    hyperoptなどで自動的にパラメータ調整を行う技術を身に着ける必要がありそう。さらに、AWSでスポットインスタンスなどを利用して格安に高速で回せるようになる必要もありそう。
    必要そうなツール全部入りのマシンイメージ(Local PC用 および AWS用)を整えておきたいところ。(誰か作って…)

  • ensemble技術
    基本のensemble手法のいくつかをマスターし、overfitしないようにensembleできるようになる。

  • チームメンバーになれる英語力とコミュ力
    むりぽ

Material

http://blog.kaggle.com/
kaggleのブログ。入賞者のインタビューはちゃんと読みたい。
http://blog.kaggle.com/2015/06/22/profiling-top-kagglers-owen-zhang-currently-1-in-the-world/
Owenへのインタビュー。言っていることがいちいち納得感がある。
http://www.slideshare.net/OwenZhang2/winning-data-science-competitions
Owenのスライド
http://people.inf.ethz.ch/jaggim/meetup/slides/ML-meetup-9-vonRohr-kaggle.pdf
Mattさんという人のスライド。わりとKaggleの戦い方がまとまっている。
https://speakerdeck.com/smly/techniques-tricks-for-data-mining-competitions
smlyさんの京大での講演資料
https://kddcup2015.com/information-winners.html
KDD CUPの入賞者スライドまとめ
http://mlwave.com/kaggle-ensembling-guide/
Ensembleの技法について

http://blog.kaggle.com/2015/07/27/crowdflower-winners-interview-1st-place-chenglong-chen/
https://github.com/ChenglongChen/Kaggle_CrowdFlower
CrowdFlowerコン1stのinterviewと、そのコード。hyperoptを活用して多数のモデルをぶん回しているようで、近々研究しようと思っています。

http://blog.kaggle.com/2015/09/22/caterpillar-winners-interview-1st-place-gilberto-josef-leustagos-mario/
キャタピラコン1stのinterview
http://blog.kaggle.com/2015/10/21/recruit-coupon-purchase-winners-interview-2nd-place-halla-yang/
クーポンコン2ndのinterview

はじパタ4章の識別関数をpythonで作成してみる

はじパタのR実行例4.4にあるピマ・インディアンデータを用いた識別関数をpythonで作成してみました。
(R実行例と書いてあるが、コードはどこにも落ちていない…?)

コードは以下の通りです。
https://gist.github.com/threecourse/c06bb743662a6e4aae47

実行例は以下のようになります。
pima_classify

これだと、いまいち2次識別関数がちゃんと動いているかわからないので、分かりやすいデータを生成して試してみました。
testdataset_classify

確かに2次識別関数で上手く識別できていることがわかります。

pythonで行列演算をやるところで、縦ベクトルの扱いに結構悩みました。np.arrayの1次元配列はTで転置されないので、np.matrix(ary).Tのようにしておく必要があるようです。