Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

実践多クラス分類 Kaggle Ottoから学んだこと

23,960 views

Published on

Kaggleのコンペに参加することで 色々な実践的ノウハウを学んだので そのノウハウを共有する
p.3~53 コンペ中に自分がやったこと p.54~99 ハイランカーがやっていたこと p.100~ ハイランカーかやっていたことを 自分も実際にやってみる

Published in: Education
  • Be the first to comment

実践多クラス分類 Kaggle Ottoから学んだこと

  1. 1. 実践 多クラス分類 西尾 泰和
  2. 2. この資料の目的 Kaggleのコンペに参加することで 色々な実践的ノウハウを学んだので そのノウハウを共有する p.3~53 コンペ中に自分がやったこと p.54~99 ハイランカーがやっていたこと p.100~ ハイランカーかやっていたことを 自分も実際にやってみる 2
  3. 3. kaggle Otto Group Product Classification Challenge IN:93個の特徴量、OUT:9クラスに分類 train.csv 61878行 test.csv 144368行 各クラスである確率を提出し、log lossで評価 3
  4. 4. クロスバリデーション 回答の投稿は1日に3回まで 手元でいろいろ試してよさそうなものを選びたい ↓ train.csvでのクロスバリデーション 4
  5. 5. Stratified K Fold train.csvは各クラスごとにデータが並んでいた →単純に分割してテストデータにしてはいけない →Scikit-learnが色々な方法を提供している 例: StratifiedKFold:クラス比率を保つように分割 5 def do_cross_validation(): model = make_model() cv = cross_validation.StratifiedKFold(ys) scores = cross_validation.cross_val_score( model, xs, ys, cv=cv, scoring='log_loss') print("Accuracy: %0.2f (+/- %0.2f)“ % (scores.mean(), scores.std() * 2)) http://scikit-learn.org/stable/modules/cross_validation.html#cross-validation
  6. 6. とりあえずロジスティック回帰 Accuracy: 0.76±0.01 所要時間 4分 6
  7. 7. とりあえずロジスティック回帰2 2個ずつの組み合わせで(93 * 92 / 2)の特徴を追加 0が多いのでscipy.sparse.lil_matrixを使った そのままLRに食わせられる/stdはない Accuracy: 0.79±0.01 (0.03アップ) 所要時間 45分 未解決課題:掛け算で大きな値に。スケール調整 が有効ではないかと思うが、スパース行列だから 「平均を引く」とかやると台無し。どうする? 7
  8. 8. sklearn.joblib train.csvをnumpy.arrayにするだけで9秒かかる 作ったarrayをjoblib.dumpでファイルに書き出す joblib.loadは1.5秒。 学習済みモデルとかもダンプできる!便利! (注意点:大量のファイルができるので 保存用のディレクトリを作るべきだった) 8
  9. 9. とりあえずRandomForest 複数の特徴量を組み合わせたい→決定木 Kaggleでは決定木の仲間のRandomForestと GBDT(Gradient Boosted Decision Tree)が 人気らしい(gbm, xgboostなど) 両方試してみよう 9 10 R Packages to Win Kaggle Competitions http://www.slideshare.net/DataRobot/final-10-r-xc-36610234
  10. 10. RF/GBDT trainの1/100のデータAと全データBとで比較 LR 0.76±0.01 - RF(A) 0.62±0.02 2秒 RF(B) 0.78±0.01 22秒 GBDT(A) 0.70±0.02 50秒 GBDT(B) 0.78±0.00 1時間15分! GBDTは勾配を推定してその情報を利用するため 2クラス分類しかできず、この例だと 36回の2クラス分類が行われて時間がかかる。 LRよりは良い性能になった。 10
  11. 11. submitしてみる スコアはLog lossなので小さい方がよい 1次のLR 0.66674 2次のLR 0.65391(best) RF 3.99786(えっ) ここまでAccuracyでモデルを評価していたけど、 ここでLog lossで評価しないとKaggleのスコアと の食い違いが大きいことに気が付く 11
  12. 12. scoringオプション cross_val_scoreはデフォルトでは正解率を返す scoringオプションでlog lossなど色々なものを 選ぶことができる 12 def do_cross_validation(): model = make_model() cv = cross_validation.StratifiedKFold(ys) scores = cross_validation.cross_val_score( model, xs, ys, cv=cv, scoring='log_loss') print("LogLoss: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2)) http://scikit-learn.org/stable/modules/model_evaluation.html#scoring-parameter
  13. 13. Log lossでのLRとRFの比較 RFはデフォルトで木が10本。変えて試す。 RF(10) -1.57±0.08 30秒 RF(20) -0.97±0.08 43秒 RF(40) -0.72±0.02 1分25秒 RF(100) -0.63±0.02 3分50秒 RF(200) -0.60±0.02 11分 RF(400) -0.59±0.01 14分 RF(600) -0.59±0.01 22分 RF(800) -0.59±0.01 - RF(1000) -0.60±0.02 - 1次のLR -0.67±0.00 1分30秒 13
  14. 14. Log lossでのLRとRFの比較 RF(400) Log loss -0.59±0.01 Accuracy 0.80±0.00 1次のLR Log loss -0.67±0.00 Accuracy 0.76±0.01 RF(400)は1次のLRよりは良いはずだ! 14
  15. 15. submitしてみる2 スコアはLog lossなので小さい方がよい 1次のLR 0.66674 2次のLR 0.65391(best) RF(10) 3.99786 RF(100) 1.27508 RF(400) 1.21971(あれれ?) Log lossを最適化する問題*に RFを使うのが筋悪なのかな?? 15 *追記:Kaggle Ottoは各クラスの確率値を提出させ、そのLog lossでランキングする課題
  16. 16. 合体 未解決課題:Log Lossを最適化する問題には何を 使うのがよいのだろうか? →RFよりはLRの方がマシかな? RFは「特徴量が閾値以上か」という二値分類機 を多段で組み合わせて決定木を作ってくれる。 LRは「特徴量をどんな重みで足し合わせると Log Lossが最小になるか」を求めてくれる →この2つを合体! 16
  17. 17. 合体:GBDT+LR GBDT(10)の予測した確率を特徴量に追加して LRを学習(以下GBCLR) LR -0.67±0.00 GBCLR -0.54±0.01 (大躍進!) Submitしてみた LR 0.66674 2次のLR 0.65391 GBCLR 0.58467 (大躍進!) 17 (2次のLRのCVの結果がないのはexpがoverflowして計算できなかったため)
  18. 18. LRの弱点をRFが補う LRは与えられた特徴量の線形結合なので 複数の特徴のANDの情報を使うには 掛け合わせるなどした特徴を作る必要がある 決定木系は閾値関数のANDを 人間の代わりに試行錯誤してくれる 作られた特徴量を入れる代わりに 9次元に潰された情報を入れただけで 性能がかなりアップした 18
  19. 19. LRの弱点をRFが補う2 LRは重みつき足し合わせなので スケールを適切に調整する必要がある RFは閾値でぶった切るのでスケールは無意味 今回のtrainデータは実は0に鋭いピークがあって 指数的に頻度が下がり大きい方の値は50とかも あるような「全然正規分布じゃない」分布 どうスケール調整するかは悩ましい問題だった 19
  20. 20. 合体路線の今後の案 GBRTの木の数を増やす(つまらない) GBRT全体での推測結果ではなく、 GBRTの各木の推測結果を特徴量にする GBRTの各木の各リーフをバイナリ特徴量にする (特徴量の数がとんでもないことになる) 20
  21. 21. 土台固め モデルの改善よりも 土台周りで色々見えてきた問題を 先に解決しておこう 21
  22. 22. --after 複数同時に走らせるとメモリが心配 次のを走らせるために、今走っている処理が 終わるのを人間が待つのは嫌 そこで--after=<pid>オプションを指定すると そのPIDのプロセスが死ぬまで待ってから 自分自身の処理を続行するようにした 22 def wait(pid): while True: try: os.kill(pid, 0) except OSError: return else: time.sleep(60) その後プロセスIDを手で打つのもたるいので --after=autoで一番新しいPythonを 対象にするようにした if args.after == "auto": pid = int( subprocess.check_output( "pgrep python", shell=True ).split()[-2])
  23. 23. joblib再び joblibの保存先をソースフォルダから分けた data/fooに保存するとdata/foo_2000.npyとか (特にRFだと)2000個のファイルが作られる 保存されたモデルを一覧で見づらい * 不要なものを削除するのも不安 ** data/foo/indexに保存して、消すときにはfooを ディレクトリごと消すのが吉かな (でも今から変えるのは既存の保存データの扱い が面倒。次回やる***) 23 * ls data | grep –v npy ** 富豪的に「消さない」ってのもありか *** forest-coverでやった。
  24. 24. 保存データの名前空間 今はフラットな名前空間にモデルも学習データも 混在して直置きされているが… 24 41252 43563 46334 GBC GBCLR LABELLR cross_lr rfc rfc10 rfc100 test_cross_data test_data train_GBC train_cross_data train_data train_labeled ←PIDで自動保存されたモデル、リネームされてないのは いらないやつだから消してもいいはずだが… ←自動保存されたモデルをリネームしたもの ←モデルの保存名をソースにハードコードしてた時代 ←モデルの種類とパラメータからモデルの保存名を 生成しようとしていた時代(データを変え始めて破綻) ←変換済みテストデータ(保存し忘れがある模様) (PIDでの自動保存をこっちにも追加すべきか) ←変換済み学習データ カオス!
  25. 25. 保存データの名前空間 「なんとなくな命名規則」で今まで進んできたが データの側をいじり始めて: 「モデルM1」 「モデルM1で特徴量を付加したtrain_M1」 「train_M1で学習したモデルM2…の名前は…」 きな臭いにおいがし始めている…。 (--train=train_foobar ってオプションも微妙) 25
  26. 26. --name --name=<name>が指定されているとき、 そのプロセスが作るすべてのファイル名に <name>が入る (例: 学習済みモデル<name>.npy, 投稿用データsubmit_<name>.csv) 指定されない時、モデル種別・元データ・PIDか ら一意な名前を生成して使う ・わかりやすい名前を付けることができる ・名前を付けなくても後から探しやすい ・事後的にmvで分かりやすい名前に変えられる ・適当にやっても既存のファイルを壊さない が実現される 26
  27. 27. データの指定 学習データをオプションで指定するのは 正しい設計だろうか?? ユースケース 「-c --train=train_fooでクロスバリデーション」 「うん、いい成果だ、submitしよう」 「-s --train=train_foo」 →テストデータが指定されていないため、デフォ ルトのものを使おうとして次数ミスマッチで死亡 27
  28. 28. データではなく変換を指定 オプションでデータを指定するのではなく 変換方法を指定すべきでは? (変換済みデータがない場合は生成・保存) 28
  29. 29. と思ったのだけど ユースケース: 4000次元×60000行のtrainデータは作れて学習も できたが、4000次元×140000行のtestデータは 作るときか使用するときにメモリ不足で死ぬ メモリ不足で死んだときには自動で 少しずつ作るモードにフォールバックすべき? 今は手書き個別対処 (どうせ1日に3件しかsubmitできないので) 29 追記:その後write_submit関数がテストデータのイテレータを取る設計に変更した
  30. 30. 行列の分割 arrayを少しずつ処理するためにnp.arrayを分割す るコード。numpy.array_splitという便利なもの があるのに今気づいた…。 30 def split_array(xs): N = len(xs) for start, end in split(N): yield xs[start:end] …… # deflate(inflate(xs))相当 new_xs = np.r_[tuple( deflate(inflate(xs_)) for xs_ in split_array(xs))] self.model.fit(new_xs, ys) def split(N, divide=10): M = N / divide for i in range(divide): start = i * M end = (i + 1) * M if i == divide - 1: end = N yield start, end
  31. 31. LabelBinarizer 特徴量に名義尺度のものが混ざっているという噂 分布を眺めてみたけどそれらしき分布は見つから ない…(でも名義尺度の頻度順ソートかも) 全特徴量をLabelBinarizer#fitしてLRしたら改善 LR -0.67±0.00 0.66674 LABELLR -0.61±0.00 0.59759 確かに名義尺度が 混ざっているのかも…。 31 for i in range(NUM_FEATURES): lb = preprocessing.LabelBinarizer() lb.fit(xs[:,i]) labels[i] = lb.transform(xs[:,i]) xs = np.c_[tuple([xs] + labels)]追記:np.c_[tuple(…)]はnp.hstackがよさそう→
  32. 32. 4053次元 全特徴を名義尺度とみなしたものを追加すると 特徴量は4053次元になる GBDT(10) 元データ -0.78±0.00 1時間15分 名義尺度 -1.08±0.01 2時間33分 GBDT(20) 名義尺度 -0.85±0.01 5時間04分 決定木の眷属は特徴量が多くなると 「うまい組み合わせを選べる確率」が下がって 性能が出なくなる?→LRをL1でつかう 32
  33. 33. L1による特徴選択 LogisticRegression(penalty=‘l1’, C=0.01)で 4053次元の名義尺度データを学習 model.transform(xs)で4053次元のデータを 低次元に投影→179次元になった 33
  34. 34. LB→LR(L1)→GBDT 元データA、LabelBinarizerしたデータB、 それをLR(L1)で圧縮したデータCについて: GBDT(10) A -0.78±0.00 1時間15分 B -1.08±0.01 2時間33分 C -1.08±0.01 7分14 GBDT(20) B -0.85±0.01 5時間04分 C -0.85±0.01 15分5 GDBT(40) C -0.71±0.01 26分49 34 時間の差の大きさに 一瞬戸惑ったが、 データの次元が22倍で 15分の22倍は5時間半だから 変というほどではないか? むしろGBDT(10)のAが変?
  35. 35. 全部入り(ICHI) 「オリジナルのtrain.csv +GBDT(100)で予測したクラス +LB→LR(L1)→GBDT(40)で予測したクラス」 を全部まとめてLRで学習させたモデル 略してICHI LR -0.67±0.00 0.66674 GBCLR -0.54±0.01 0.58467 LABELLR -0.61±0.00 0.59759 ICHI -0.53±0.00 0.55831 35
  36. 36. 全部入り(NII) ICHIの特徴量にRF(400)での推定結果を加えて学 習させたLR、略してNII RF(400) -0.59±0.01 ICHI -0.53±0.00 NII -0.01±0.00 (えっ?!) Submitしてみた ICHI 0.55831 NII 0.63648 (悪化…。) アンサンブル学習のやり方がまずい?保留。 36
  37. 37. PCAの効果 「PCAで次元削減して~するとよい」という噂 93次元しかないデータなのに、いきなり 「分散が小さい」って理由で何軸かの情報を 捨ててしまうとか、悪くなる気がする……。 でも、検証してみよう。 37
  38. 38. PCAの効果2 0:オリジナル 1:PCA掛けただけ 2:PCAで白色化 3:PCAで50次元に削減 4:30次元に削減 5:10次元に削減 RF(10) LR 0 -1.57±0.08 -0.67±0.00 1 -1.67±0.08 -0.67±0.00 2 -1.68±0.09 -0.68±0.00 3 -1.65±0.03 -0.71±0.00 4 -1.77±0.03 -0.78±0.00 5 -2.36±0.03 -1.06±0.01 次元削減のダメージは大きい 38
  39. 39. PCAの効果3 次元削減ではなく軸を回転することによって 「軸方向の分割」で構成されている決定木は 性能が向上する可能性がある。確かめてみよう。 RF(400) PCAなし -1.57±0.08 PCAあり -1.59±0.01 →目立った効果はない「PCA→RF(400)」の結果を 追加した「SAN」を作るつもりだったけどやめた 39
  40. 40. 分離が難しいクラス クラス2とクラス3の分離が難しいという噂 ・どうすれば自分でそれに気づけるか ・どう対処するか 作ったモデルで分類して、間違えて分類したもの に関する統計データが手軽に得られるべき ・クラス2と3だけのデータでモデルを学習した ら分離に適切な特徴量が出てくるのでは ・間違えて分類したものだけ選んで学習したらど うか(手動AdaBoostもどき) 40
  41. 41. sklearn.svm.SVC 当初、木やリーフの情報を特徴量にするつもりで RFをチョイスしていたけど、結局、推定結果を 特徴量にしているのでRFである必要はない RFで軸に沿ってまっすぐ切るのは既にやったか らどうせなら曲線で切りたい →じゃあサポートベクターマシン! 41
  42. 42. SVC 「SVCの計算量はデータの二乗よりでかいオー ダーだから10000以上だとつらいかもね」(意訳) とマニュアルに書いてある。測ってみる。 N=100 16ms N=200 54ms N=400 191ms N=1000 1.08s N=2000 3.7s N=4000 17s N=10000 102s 42
  43. 43. YON ICHIでtrain.csvをpredictしてLog Lossの大きい方 から10000件のデータを選んでSVCし、その predict結果を特徴量として追加。 ICHI -0.53±0.00 0.55831 NII -0.01±0.00 0.63648 YON -0.47±0.01 0.54944 (改善!) 43 # 2行目もっとうまく書ける? lp = model.predict_proba(xs) logloss = np.array([lp[i, ys[i] - 1] for i in range(len(xs))]) bad_items = logloss.argsort()[:N_BEST]
  44. 44. アンサンブル学習 アンサンブル学習について調べていたら [1][2][3] 、僕と同じLRに よるアンサンブルをやっているソースコード [4] を発見。彼は711 人中17位になったそうな。対象コンペ [5] は2クラス分類でLog Lossで評価される、今回のによく似たタイプ。 [1] How to ensemble different models? - Africa Soil Property Prediction Challenge | Kaggle https://www.kaggle.com/c/afsis-soil-properties/forums/t/10753/how-to-ensemble-different-models [2] Best Ensemble References? - Africa Soil Property Prediction Challenge | Kaggle https://www.kaggle.com/c/afsis-soil-properties/forums/t/10391/best-ensemble-references/54305 [3] Question about the process of ensemble learning - Predicting a Biological Response | Kaggle http://www.kaggle.com/c/bioresponse/forums/t/1889/question-about-the-process-of-ensemble- learning/10945 [4] kaggle_pbr/blend.py at master · emanuele/kaggle_pbr https://github.com/emanuele/kaggle_pbr/blob/master/blend.py [5] Description - Predicting a Biological Response | Kaggle http://www.kaggle.com/c/bioresponse 44
  45. 45. アンサンブラーの実装 given X, Y, Xsub, make Ysub M: モデルの個数 pp: Predict Probability 45
  46. 46. GO Ensamble(LR, GBDT(100), LB→LR(L1)→GBDT(40), RF(400), ICHI→LogLoss Top10000→SVC) をやりたいのだけど、スモールスタートで Ensamble(LR, GBDT(100), LB→LR(L1)→GBDT(40), RF(100), ICHI→LogLoss Top1000→SVC) をやった。2時間36分。 ICHI -0.53±0.00 0.55831 YON -0.47±0.01 0.54944 GO - 0.47977 (すごい改善!) 46
  47. 47. ROKU Ensamble(LR, GBDT(100), LB→LR(L1)→GBDT(40), RF(400), ICHI→LogLoss Top10000→SVC) 機械学習勉強会までに計算が終わるか終わらない か微妙なところ(朝9時現在) 10時間3分 GO 0.47977 ROKU 0.46783 (改善) Top10% 0.44371 (目標) 47 順位的には2301人中 631位→513位
  48. 48. アンサンブラーの高速化 個別のモデルに関する部分はメモ化できる。 少し手を加えれば普通のクロスバリデーションと しても使える。 クロスバリデーションで色々なモデルを試す過程 で、ブレンド用のデータを吐き出して置けば、そ れを束ねてLRするだけで良いのでは? 48
  49. 49. 以下追記 49
  50. 50. 写真1 50
  51. 51. 写真1 51 93*6万次元のXと1*6万次元のYと93*14万次元のXsubから9*14万次元のYsubを作る。 9はクラス数。10foldで9割のtrainと1割のtestにわけ、trainXとtrainYでモデルMを学習。 モデルMにtestXを入れて確率推定したものPを10個並べて9*6万のQができる。 それぞれのモデルにそれをしてM個並べて(9*M)*6万のRができ、RとYとでLRを学習。 またモデルMにXsubを入れて9*16万のS、SをM個平均してT、Tを並べてUを作る。 先ほど学習したLRにUを入れて確率推定したものがYsub。
  52. 52. 僕のアンサンブラー ICHIやNIIで使った僕のアンサンブラーも 各モデルの推定結果を特徴量にして LRを学習するところは同じ。 Foldしてないのが違い(過学習の原因) 52 アンサンブルしない普通のを この記法で描くとこう
  53. 53. 写真2 53 M個並べるのよりも手前はモデルごとに計算できるので、メモ化可能。 モデルにはKNNや各種カーネルのSVM、NBなど色々突っ込める。 後段で学習しているLRは各モデルの予測結果と正解から予測結果の良さを得て アンサンブルの際の混ぜあわせ重みを決定する役割を果たしている。
  54. 54. 追記2 コンペが終わったので ・最終的にどうなったか ・上位ランカーはどういう方法を使っていたか ・新しく知った手法を試してみる を追記 54
  55. 55. 1ページで前回のおさらい Kaggle Otto Group Product Classification Challenge IN:93個の特徴量、OUT:9クラスに分類 train.csv 61878行 test.csv 144368行 各クラスである確率を提出し、log lossで評価 西尾の戦略 RandomForestとかSVMとかで予測した結果を 特徴量としてLRでアンサンブル。特徴量を 5-fold CVで作るようにしたら性能0.54→0.47 55
  56. 56. 成果発表 西尾: public 0.45545 799位 private 0.45715 838位/3512 1位のチーム: public 0.38055 private 0.38243 アンサンブラ改善に匹敵する大きな差が。 上位入賞者がモデルを公開しているので よく読んで技術を盗もう! 56
  57. 57. 1位のチーム Gilberto Titericz & Stanislav Semenov 3層構造 1層目:33個のモデル(これの予測結果を2層目 の特徴量として使う)と8個の追加特徴量 2層目: GDBT(XGBoost) NN(Lasagna) AdaBoost(ScikitのExtraTree) 3層目:重み付き平均 57 https://www.kaggle.com/c/otto -group-product-classification- challenge/forums/t/14335/1st- place-winner-solution-gilberto- titericz-stanislav-semenov
  58. 58. 1層目のモデル -Model 1: RandomForest(R). Dataset: X -Model 2: Logistic Regression(scikit). Dataset: Log(X+1) -Model 3: Extra Trees Classifier(scikit). Dataset: Log(X+1) (but could be raw) -Model 4: KNeighborsClassifier(scikit). Dataset: Scale( Log(X+1) ) -Model 7: Multinomial Naive Bayes(scikit). Dataset: Log(X+1) Log(X+1)。これ計算してplotまではしたけど形が イマイチで特徴量として採用してなかった… 58
  59. 59. 1層目のモデル:FM -Model 5: libfm. Dataset: Sparse(X). Each feature value is a unique level. libfm*はSVDなどのような行列分解系の方法を SVMと組み合わせることによって、SVMが苦手 なスパースなデータに対してよい性能を出す Factorization Machines**の実装。 59 * http://www.libfm.org/ ** http://www.ismll.uni-hildesheim.de/pub/pdfs/Rendle2010FM.pdf
  60. 60. 1層目のモデル:NN -Model 6: H2O NN. Bag of 10 runs. Dataset: sqrt( X + 3/8) H2Oは多層のNN(いわゆるディープラーニング) の実装を容易にするライブラリ。 60 http://0xdata.com/product/
  61. 61. 1層目のモデル:NN -Model 8: Lasagne NN(CPU). Bag of 2 NN runs. First with Dataset Scale( Log(X+1) ) and second with Dataset Scale( X ) -Model 9: Lasagne NN(CPU). Bag of 6 runs. Dataset: Scale( Log(X+1) ) Lasagneは多層のニューラルネットを実装するこ とを容易にするライブラリ。Python。 61 http://lasagne.readthedocs.org/en/latest/index.html
  62. 62. 1層目のモデル:t-SNE -Model 10: T-sne. Dimension reduction to 3 dimensions. Also stacked 2 kmeans features using the T-sne 3 dimensions. Dataset: Log(X+1) t-SNEは” t-distributed stochastic neighbor embedding”の略。次元削減の方法。 62 t-distributed stochastic neighbor embedding - Wikipedia, the free encyclopedia http://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding sklearn.manifold.TSNE — scikit-learn 0.16.1 documentation http://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html
  63. 63. 1層目のモデル:Sofia -Model 11: Sofia(R). Dataset: one against all with learner_type="logreg-pegasos" and loop_type="balanced-stochastic". Dataset: Scale(X) -Model 12: Sofia(R). Trainned one against all with learner_type="logreg-pegasos" and loop_type="balanced-stochastic". Dataset: Scale(X, T- sne Dimension, some 3 level interactions between 13 most important features based in randomForest importance ) -Model 13: Sofia(R). Trainned one against all with learner_type="logreg-pegasos" and loop_type="combined-roc". Dataset: Log(1+X, T-sne Dimension, some 3 level interactions between 13 most important features based in randomForest importance ) 63
  64. 64. Sofia Sofia*色々なアルゴリズムの詰め合わせ。 パラメータでlogreg-pegasosを指定しているから >Logistic Regression (with Pegasos Projection) を使っているのだろう。 Pegasos**はSVMのSGDによる最適化部分を置き 換えることで収束速度を改善するもの。 ここではLRの最適化に流用している。 64 * https://code.google.com/p/sofia-ml/ ** Pegasos: Primal Estimated sub-GrAdient SOlver for SVM http://www.ee.oulu.fi/research/imag/courses/Vedaldi/ShalevSiSr07 .pdf
  65. 65. 1層目のモデル:xgboost -Model 14: Xgboost(R). Trainned one against all. Dataset: (X, feature sum(zeros) by row ). Replaced zeros with NA. -Model 15: Xgboost(R). Trainned Multiclass Soft-Prob. Dataset: (X, 7 Kmeans features with different number of clusters, rowSums(X==0), rowSums(Scale(X)>0.5), rowSums(Scale(X)< -0.5) ) -Model 16: Xgboost(R). Trainned Multiclass Soft-Prob. Dataset: (X, T-sne features, Some Kmeans clusters of X) -Model 17: Xgboost(R): Trainned Multiclass Soft-Prob. Dataset: (X, T-sne features, Some Kmeans clusters of log(1+X) ) -Model 18: Xgboost(R): Trainned Multiclass Soft-Prob. Dataset: (X, T-sne features, Some Kmeans clusters of Scale(X) ) 65 xgboostはGBDTの実装の一つ https://github.com/dmlc/xgboost
  66. 66. 1層目のモデル:NN(GPU) -Model 19: Lasagne NN(GPU). 2-Layer. Bag of 120 NN runs with different number of epochs. -Model 20: Lasagne NN(GPU). 3-Layer. Bag of 120 NN runs with different number of epochs. Lasagnaを使ってNNをGPU実装。 66
  67. 67. 1層目のモデル:xgboost -Model 21: XGboost. Trained on raw features. Extremely bagged (30 times averaged). 特に工夫なくxgboostを30回走らせて 結果を平均したもの。 データをダウンロードして、まず真っ先に 「xgboostを繰り返すプログラム」を 走らせてから他の実装を始めたと憶測 67
  68. 68. 1層目の特徴量:KNN -Model 22: KNN on features X + int(X == 0) -Model 23: KNN on features X + int(X == 0) + log(X + 1) -Model 24: KNN on raw with 2 neighbours -Model 25: KNN on raw with 4 neighbours : -Model 33: KNN on raw with 1024 neighbours モデル4にKNN(Scale( Log(X+1) ))があったけど 特徴量としても追加している。異なるチームメン バーが別個に実装したと憶測。 68
  69. 69. 1層目の特徴量:Distance -Feature 1: Distances to nearest neighbours of each classes -Feature 2: Sum of distances of 2 nearest neighbours of each classes -Feature 3: Sum of distances of 4 nearest neighbours of each classes -Feature 4: Distances to nearest neighbours of each classes in TFIDF space -Feature 5: Distances to nearest neighbours of each classed in T-SNE space (3 dimensions) 最寄りクラスタまでの距離 69
  70. 70. 1層目の特徴量:謎 -Feature 6: Clustering features of original dataset 何を意味しているのかよくわからない 70
  71. 71. 1層目の特徴量:非ゼロ -Feature 7: Number of non-zeros elements in each row 非ゼロの特徴の数 -Feature 8: X (That feature was used only in NN 2nd level training) 生データ 71
  72. 72. 2層目3層目 XGBOOST(GDBT): 250 runs. Lasagna(NN): 600 runs. ExtraTree(ADABOOST): 250 runs. 3層目でXGBOOSTとNNを0.65:0.35で幾何平均 その後ETと0.85:0.15で算術平均 平均の種類を変えてパラメータサーチすることが かえって過学習の原因にならないか疑問。 72
  73. 73. 自分の方法との比較 SVMがない(改善しないので捨てたらしい) →おそらくFMで十分カバーされている PCAがない(これも捨てたらしい) →おそらくt-SNEで十分カバーされている 非ゼロ個数を特徴に追加→同じ 距離を特徴に追加→その発想はなかった 73
  74. 74. 1層目は弱い学習機でもよい 1層目でPoorでも2層目の改善に貢献する > Interestingly some of our models scored very poorly at 1st level. But contributed in 2nd level. ex. Model 2 CV ~ 0.65, Model 5 CV ~ 0.55. Model2はLR、Model5はFM 74
  75. 75. 計算コスト > I used AWS Amazon CPU server with 32 cores for calculating XGboost, etc. And used AWS Amazon GPU server with 4 Nvidia Grid K520 for calculating NNs. Models on 2nd level is really computationally hard. 32コアなのはc3.8xlarge。1時間$1.68。 スポットインスタンスを利用して$0.256。 何時間走らせたのかは不明。 75
  76. 76. Leakage CVの際のLeakageを気にする声 一方、Leakageしない別のアプローチでは 計算コストが高くなりすぎることから 「悪くないトレードオフ」との指摘もある。 これはコードが公開されてから再確認が必要そう 76
  77. 77. 6位チーム “it seems like this competition was all about two things: finding ways to get different biases in the individual models, and having a good method for ensembling beyond just averaging.” 77 https://www.kaggle.com/c/otto-group-product-classification- challenge/forums/t/14296/competition-write-up-optimistically-convergent
  78. 78. アンサンブル 5-fold stratifiedでモデルを学習して、trainデータ 全体に対するpredictionを作る。 →ケース1: 5つでBaggingしてtestに対して使う →ケース2: 使わずに別途全データでtraining →最終的に: そのpred.を使ってアンサンブルのパ ラメータをfitting 大枠では僕のと同じ。彼らのアンサンブラはNN 78
  79. 79. ニューラルネット 全部ReLU。出力層はSoftmax。 LB=0.446: Input -> 0.13 Dropout -> 2500 -> 0.77 Dropout -> 1300 -> 0.35 Dropout -> 40 -> 0.1 Dropout -> Output (AdaGrad, 600 epochs, batch=1024, linear decreasing learning rate starting at 0.04, ending at 0.005) LB=0.441: Input -> 0.15 Drop -> 2000 -> 0.7 Drop -> 1200 -> 0.4 Drop -> 40 -> Output (AdaGrad, 400 epochs, batch = 512, learning rate from 0.04 to 0.001) LB=0.463: Input -> 0.15 Drop -> 180 -> 0.1 GaussianNoise -> 0.1 Drop -> 180 -> 0.05 Drop -> 180 -> 0.05 Drop -> 140 -> 0.05 Drop -> 140 -> 0.05 Drop -> 140 -> 0.1 Drop - > 140 -> 0.1 GaussianNoise -> 160 -> Output (AdaGrad, 100 epochs, batch=512, rate = 0.03 to 0.005) 79
  80. 80. ニューラルネット >One thing is that even though the network with 2000 nodes in the first layer had a better LB score, it ensembled significantly worse than the one with 2500 nodes. 入力層が2000個の方がLBでのスコアはよかった が、アンサンブル結果は2500個の方がよかった →2500個の側が運よくいい特徴を拾っていただけ ではないかと憶測 80
  81. 81. Boosted Neural Nets Input→0.15→2000→0.7→1200→0.4→40→Output をrate=0.02 .. 0.005で25エポックだけ学習 →Log lossが平均Log lossの2%より小さいRowを 削除して学習しなおす(僕がモデルYONでLogLoss の大きい方から1万件だけでSVCを学習したのと 同じようなアプローチ) →これを16回繰り返す(!) →0.433のNNができた(僕のスコアを超えた) 81
  82. 82. SGDで特徴探し SGDは最高で0.58程度だけど、シンプルな仕組み であるがゆえに「よい特徴を追加した」時に性能 が大きく上がるので特徴探しに便利。 「大きい方から4件の特徴の位置に1が立ってい る93次元ベクトル」 特徴AとBのインタラクションを「A*B」ではなく 「1 if A > B else 0」にした方がよい成績。 82
  83. 83. SVM カラムごとにスケールを調整するとよい。 83
  84. 84. キャリブレーション NNに対してCalibratedClassifierCVを使って キャリブレーションをすると大きく改善する。 10-fold isotonic calibrationで、0.443→0.435 84 http://scikit- learn.org/stable/modules/generated/sklearn.calibration.CalibratedClassifierCV.html
  85. 85. アンサンブル アンサンブルの手法が最も重要 このコンペはLog lossを問うものだから もしたくさんのものを平均しすぎると 平均回帰によってLog lossが悪化する →NN-basedアンサンブラ →0.58! 85
  86. 86. アンサンブル 2つのモデルをブレンドする際に、 まずその2つのモデルが同じクラスを返す確率 pXYを求め、モデル1の重みをbとして Pb = pXY * (P1*b + P2*(1-b) ) + (1- pXY)*( P1^(2*b) * P2^(2*(1-b)) ) / ( P1^(2*b) * P2^(2*(1-b)) + (1-P1)^(2*b) * (1-P2)^(2*(1-b)) ) でブレンド後の確率を求める。 この有用性に関してはよくわからない。 0.0007の改善になったらしい。 86
  87. 87. FE不要論 “Minimal feature engineering was needed, as all the features were count of some events not disclosed to participants” 「特徴量がイベントの回数である」という説明を 読み落としていた…。 これだとラベル化は筋悪ということになる。 87 https://kaggle2.blob.core.windows.net/forum-message- attachments/79384/2507/summary.pdf?sv=2012-02-12&se=2015-05- 28T02%3A29%3A24Z&sr=b&sp=r&sig=GSMFMgUpNYb%2B4xZaWtxF%2BNzT3s%2F Ve3kwvoHjHdqS9qM%3D
  88. 88. モデル XGBoost: scikit-learnの他のモデルとの一貫性の ためにラッパーを実装、0.44x NN: Lasagne使ってReLUとDropout、GPU。 Sparse AutoencoderとReLUで多層Perceptronとも 書いてあるけど、Lasagneでやったか不明* 0.44x SVM: RBFカーネルが一番 0.45x RF, Extra Trees: ETがRFよりも良い成績。キャリブ レーションがとても有効。0.44x あと2次のLRとKNN 88 * Referenceにkerasが載ってるからそっちかも
  89. 89. パラメータサーチ ・人力GD →収束カーブを見て「もっとDropoutが必要だ」 などと判断できるメリット ・グリッドサーチ パラメータの少ないSVCとかRFに有効 ・ランダムサーチ 何が重要なパラメータかわからない時に有用 89 Bergstra and Bengio(2012)“Random Search for Hyper-Parameter Optimization” http://www.jmlr.org/papers/volume13/bergstra12a/bergstra12a.pdf
  90. 90. ランダムサーチ 寄与の小さいパラメータがある場合、 Grid Layoutではその軸方向のサンプルが 無駄になってしまう 90 [Bergastra and Bengio 2012] から引用
  91. 91. ガウス過程によるパラメータサーチ 「良い結果が得られるパラメータを探す」は 関数の最大値を探す最適化問題 関数が滑らかである仮定をガウス過程として 導入することで、未探索の値に対してのUCBが 計算できるようになる UCBが最大となる点を探索していくことでRegret 最小の探索ができる(強化学習的発想) 91 Srinivas+ (2010) “Gaussian Process Optimization in the Bandit Setting: No Regret and Experimental Design” http://las.ethz.ch/files/srinivas10gaussian.pdf http://www.robots.ox.ac.uk/seminars/Extra/ 2012_30_08_MichaelOsborne.pdf p.82から
  92. 92. Random Direction 現在の最良のパラメータを中心として 正規分布で適当に選んで実験、 良くなっていたら採用、悪くなっていたら捨てる だんだん正規分布の分散を狭める (局所解にはまりそうな…) 92
  93. 93. 実験 XGBoostは5つのパラメータがある。 - 木の最大数 5..35 - shrinkage 0.4..1 - 最大深さ 4..10 - 行サブサンプリング 0.4..1 - 列サブサンプリング 0.4..1 これを上記4手法でパラメータサーチ 93
  94. 94. 結果 94 RDが意外といいけど、予想通りLocal Minimumにはまるケースが多く 分散が大きくなっている。GPは安定しているが、平均的にはRDに負けてる。 GP自体にハイパーパラメータがあり、それのチューニングはされていない。
  95. 95. アンサンブル まず単純平均を試してみた→まあまあ シグモイドの逆関数で変換(IST)してからLR→改善 最終的に:ISTしてから隠れ層1枚のNNでFittting NNのハイパーパラメータはGP UCBで決めた。 何度か異なる乱数シードで走らせると0.00xぐら い改善する 比較:自分のやったのは「ISTしないでLR」 95
  96. 96. 25位? xgboostでモデルを作ってGAでアンサンブル 特徴量:総和、非ゼロの個数、 1,2,3の個数、 最大値、最大値の場所、t-SNE、距離 今までで最良のモデルによる推定結果を 特徴量として追加する(僕と同じ) 96 https://www.kaggle.com/c/otto-group-product-classification- challenge/forums/t/14315/strategy-for-top-25-score
  97. 97. 距離 各行に対して、各クラスの中のすべての行との距 離を計算して、距離の分布を求め、その分布の 10, 25, 50, 75, 90th percentileを45次元の特徴量と して加える 1位チームの「各クラスの最も近い点への距離」 は0パーセンタイルだけを使っていることに相当 する。階層的クラスタリングでの、ある点がどの クラスタに最も近いかを判定する上で最も近い点 か最も遠い点かそれとも平均かセントロイドか… という議論*に似ている。 97 * http://en.wikipedia.org/wiki/Hierarchical_clustering のLinkage criteriaの節
  98. 98. GAでアンサンブル DEAP* を使う the gene was a vector length 20 composed of different model numbers. 20個以上あるモデルの中から20個のモデルをど う選ぶかを遺伝子にコーディングし、 選んだモデルを平均したののスコアを最適化する 98 * https://github.com/deap/deap
  99. 99. 112位相当:Meta-bagging “Meta-bagging”によって112位相当のスコアが 出せるという主張。“Meta-bagging”という言葉 は広く使われているものではない。 第1層でSVM、RF、GBM*などを学習した後、そ の結果の幾何平均と元データとを入力とするNN を50個学習してそれらをBaggingする 99 https://www.kaggle.com/c/otto-group-product-classification- challenge/forums/t/14295/41599-via-tsne-meta-bagging/79084 * GBM=Gradient Boosting Machine, たとえばxgboost
  100. 100. やってみる xgboost Lasagne Gaussian Process t-SNE 100
  101. 101. xgboost R用だけどPythonからでも叩ける xgb.train叩くだけ、予想外に楽&早かった Ottoのデータに対してCVして 他の方法と比べてみよう →Sklearnのインターフェイスと揃えるために ラッパーを自分で書いて少しトラぶった。 すでに書いて公開している人もいる。 これを使うのでもよかったかも。 101 https://gist.github.com/slaypni/b95cb69fd1c82ca4c2ff
  102. 102. xgboost Log Loss: -0.48 (+/- 0.01) Fit time: 2730.05 (+/- 548.52) Predict time: 769.46 (+/- 202.69) elapse 09h54m23s 参考 ICHI -0.53±0.00 0.55831 YON -0.47±0.01 0.54944 * GO - 0.47977 * アンサンブラ改良前最高性能と同程度 102
  103. 103. Lasagne ラザニアだからLasagnaと思ってたけどeが正解 宣言的にニューラルネットの層の間の接続を記述 すると中でTheanoが更新式を作り出して良しな に学習してくれるNN界の超高級言語 バージョン0.1devだけどKaggleで使われているの をよく見かけるライブラリの一つ ドキュメントがPoorなのでサンプルコードを読む 103
  104. 104. サンプル: mnist.py 104 この図に描いてあるようなことが ほぼそのままbuild_model関数の中に書いてある
  105. 105. 実行 Epoch 1 of 500 took 144.361s training loss: 1.344822 validation loss: 0.466205 validation accuracy: 87.58 %% Epoch 2 of 500 took 140.929s training loss: 0.592950 validation loss: 0.332910 validation accuracy: 90.45 %% 500ステップのうちの1ステップに2分掛かるということ は単純計算で全部終わるまでに17時間かかるよな…。 105
  106. 106. 実行中 約1時間後 Epoch 30 of 500 took 154.024s training loss: 0.130883 validation loss: 0.089886 validation accuracy: 97.31 %% 約2時間半後 Epoch 60 of 500 took 160.892s training loss: 0.077516 validation loss: 0.067623 validation accuracy: 97.86 %% 約3時間半後 Epoch 170 of 500 took 80.355s training loss: 0.026319 validation loss: 0.056770 validation accuracy: 98.43 %% 106
  107. 107. 学習終了 約15時間後 Epoch 500 of 500 took 157.920s training loss: 0.007425 validation loss: 0.064233 validation accuracy: 98.48 %% python mnist.py 40219.81s user 130.37s system 74% cpu 14:58:08.57 total でも一番性能がいいのは Epoch 397 of 500 took 94.733s training loss: 0.010540 validation loss: 0.061012 validation accuracy: 98.59 %% 107
  108. 108. ハイパーパラメータ Nesterov Momentum なんだか重要な役割をしているみたい 近いうちに調べておく 学習率、レイヤーのサイズ、ドロップアウト率 うーん、パラメータだらけだぞ 108
  109. 109. 考察 成績を見て適当なところで打ち切るか、 一番良いものを取っておくように実装する 必要がある 割と時間的コストが高い。 しかも、これたぶん並列に走らない ハイパーパラメータがたくさんあるので パラメータを変えて何度も走らせる必要が ある。ここを並列でやるのがよいか。 なんにせよラップトップにはつらい。 109
  110. 110. サンプル: mnist_conv.py 110
  111. 111. サンプル: mnist_conv_dnn.py Conv2DLayerがdnn.Conv2DDNNLayer MaxPool2DLayerがdnn.MaxPool2DDNNLayer になっている(ネーミングセンス…) これはNVIDIAの出しているcuDNNライブラリを Theano経由で叩く実装、つまりGPUを使う cnDNNではConvとPoolとSoftmaxしか実装されて なさげ→画像処理でないDNNには有用でない 111 sandbox.cuda.dnn – cuDNN — Theano 0.7 documentation http://deeplearning.net/software/theano/library/sandbox/cuda/dnn.html
  112. 112. 言及されていたもの色々 fchollet/keras 同じくTheanoベースのNNライブラリ Lasagneと比べてどうなの?ドキュメントどこ? https://github.com/fchollet/keras/tree/master/ker as IssamLaradji/NeuralNetworks SklearnベースのNNライブラリ、 Sparse Autoencoderの実装がある https://github.com/IssamLaradji/NeuralNetworks 112
  113. 113. Gaussian Process UCB GPはsklearnに実装がある fitしてpredictすると平均と分散が返ってくるので あらかじめ計算しておいた定数βを掛けてargmax 113 http://scikit-learn.org/stable/modules/gaussian_process.html http://scikit- learn.org/stable/modules/generated/sklearn.gaussian_process.GaussianProcess.html
  114. 114. GP-UCB-PE, TPE GP-UCBを改良したGP-UCB-PE*の実装が 改良した本人によって公開**されている(Matlab) Tree of Parzen Estimators (TPE)***が hyperoptというハイパーパラメータ最適化用の ライブラリで実装されている****(Python) 114 * Contal et al. (2013) “Parallel Gaussian Process Optimization with Upper Confidence Bound and Pure Exploration” http://arxiv.org/abs/1304.5350 ** Emile Contal - Homepage http://econtal.perso.math.cnrs.fr/software/ *** Bergstra et al. (2011) “Algorithms for Hyper-Parameter Optimization” http://papers.nips.cc/paper/4443-algorithms-for-hyper-parameter-optimization.pdf **** Hyperopt by hyperopt http://hyperopt.github.io/hyperopt/
  115. 115. ハイパーパラメータサーチ パラメータサーチしない <<<< グリッドサーチ <<< Randomized Grid < (GP-UCBとかTPEとか) という感じなのでTPEをツールとして使うので いいかなーと思っている 115
  116. 116. hyperopt git cloneしてsetup.py installだけだと動かない pip install networkxが必要 MongoDBが必要と書いてあるが、単一プロセス で使う上では必要でない 116
  117. 117. 実験 scipy.optimize.fmin(downhill simplex)と比較 目的関数を3次元 sin(x) + cos(y) + sin(0.123 + 0.456 * z) + 0.1 * ((x - 1) ** 2 + (y - 2) ** 2 + (z - 3) ** 2) scipyは(-10, -10, -10)から探索開始 hyperoptは(-10, 10)を各変数の値の範囲と指定 117
  118. 118. 結果 118 ←DS ↑TPE num trial func value
  119. 119. 疑問 -10と10の中点0はわりと正解に近い位置 scipyを(0, 0, 0)から探索開始したらどうなる? 119
  120. 120. 結果 120 ↑DS (0,0,0)スタート
  121. 121. さらに疑問 では逆に答えが(-9,-8,-7)のあたりの場合は? 目的関数を3次元 sin(x) + cos(y) + sin(0.123 + 0.456 * z) + 0.1 * ((x + 9) ** 2 + (y + 8) ** 2 + (z + 7) ** 2) 121
  122. 122. 結果 122 ↓local minimum に引っかかった ↑近くから探索を始めれば成果は出る ↓答えの場所によらず似たような成果
  123. 123. まとめ hyperoptのTree of Parzen Estimatorsと scipyのdownhill simplexとを比較すると ・TPEは答えの位置によらず似たような成果 ・DSは初期値が正解から離れていたり 運悪くLocal Minimumに引っかかったりすると TPEに比べてひどい結果になる TPEの方が時間はかかるけど現実的スケール 試行あたりの時間コストが高い最適化には TPEを使うのがいいんじゃないかな 123
  124. 124. t-SNE sklearnに実装がある。Manifold learningについて の解説ページもある。見た目的にはt-SNEは確か にきれいだが、軸に深い意味はないので後段に DTやKNNなどの空間を分割するタイプの分類機 を伴わないとイマイチじゃなかろうか。 2~3次元用とのことなので「新しいデータは とりあえずt-SNEで2次元にして眺めてみる→ きれいなら特徴量にも使う」がよいかも。 124 sklearn.manifold.TSNE — scikit-learn 0.16.1 documentation http://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html 2.2. Manifold learning — scikit-learn 0.16.1 documentation http://scikit-learn.org/stable/modules/manifold.html
  125. 125. t-SNE fitなしのtransformメソッドがない 学習データでfitしてテストデータをtransform することはどうすればできるのだろうか?* 61878*93のデータ→MemoryError 10分の1に削った(StratifiedKFold)→遅い 100分の1に削った 125 * こっちを使うべき? http://lvdmaaten.github.io/tsne/
  126. 126. 結果 126
  127. 127. まとめ、振り返り、次回に向けて RFには無用だからとスケール調整を無視して、 その後SVMとかやるときにも忘れたままだった。 データの解説は一字一句しっかり読む。 sklearnのGBDTが遅くて使うことをあきらめたが とりあえずXGBoostを一晩走らせるべき。 スパースなのでSVMの代わりにFMという案。 次元削減の目的にはPCAの代わりにmanifold系を 使う案。Isomapとか。今度試す。 127
  128. 128. まとめ、振り返り、次回に向けて アンサンブラは今ので悪くないがISTする。 余裕があればLRをNNに変えてhyperopt。 単体ではPoorな性能でもアンサンブルで化けるか もしれないので捨てない。 Boosted Neural Netsなど、うまくできないもの だけを取り出して学習するアプローチ。 距離、TopN、max、min、などの特徴量の追加。 128
  129. 129. まとめのまとめ Lasagne、XGBoost、hyperopt 129

×