予告:LassoのvariantsをADMMで実装するシリーズ
ADMMは迷わずに手続き的に更新則を導出できて実装も簡単で楽しい。
スパースモデリングの類には前から興味はあった。
が、コスト関数や正則化項の意味くらいはわかるものの、最適化手法がわからん、ということが多かった。必ずしもライブラリがあるわけでもないのでお手軽に試せず、実験結果とかを見てへーそうなのか、と思うくらいしかできなかった。
自分でやるならどうやって実装するか、というところにADMMという光明がさした。
金槌しか持っていなければ全てが釘に見えるので、今後Lassoの派生をADMMで実装することをやっていこうと思う。
本業と副業の片手間にやることになるので、遅々とした更新にはなると思うが、一応宣言しておく。
いちおう今現在考えているのは、
1. ElasticNetとその拡張
2. Total Variationなどのnon-separableな正則化
3. 非凸正則化(ちょっと自信ない)
4. コスト関数を変えたやつ(tuning parameter free系かなあ)
あたり。
正直前回の記事はADMMに関しての理解が浅かったので、見直したらミスがあったりちょっと意味のわからないところがあったりしたが、今後はちゃんとやれたらいいなあと思う。
いじょ
ロバストな損失関数でHouse Pricesをやる
※20210730追記
この記事はたぶんADMMに関して変なことをやっています。拡張ラグランジアンの係数は多分グリッドサーチとかでは調べないのと、notebookのElasticNetのsoft-thresholdingが間違ってます。
※追記ここまで
なんかコンペにでも参加しようか、と思うも程よい感じのが探せない。
でも何かしらはやりたいなと思うと、Titanicと同じくKaggle的にはチュートリアルだし、回帰から生まれた回帰太郎なのに回帰やってないしでHousePricesをやるかとなった。
……ものの、いくつかやってみた系の記事を眺めると、なかなか説明変数がだるい感じ。
いろいろと眺めて気になったのは目的変数のSalePriceの対数のヒストグラムを見て正規分布っぽいですねといってLassoなりを適用しているもの。
見た感じ(正規分布は日常的にとてもよく使うので)でも正規分布より裾が厚いし、実際
SalePriceの対数のQ-Qプロットを見ると裾の方はやはり直線からのずれがそれなりにある。たとえばこの方の記事など。
この方は外れ値に対してしっかり処理しているが、Lassoそのままぽい〜もそこそこ見かけたりした。
それで思ったのは、説明変数の前処理はもう適当に済ませてしまって、コスト関数をそれっぽくしたときに予測精度が上がるかを見ようか、ということ。
ロバストな損失関数といってもいろいろあるが、見た感じだと中央部分はガウスっぽいし裾だけそこそこ厚いからHuber lossがよさそうに見える。Tukeyとかε-感度損失とかだと指しすぎな感じがする。
それと正則化はがっつり入れたい。
こういうときにさくっと導出できて便利なのがADMMで
基本的にこれの6章と一緒。
本命をHuber+L1だと思うわけだけど
Least absolute deviations - Wikipedia
HuberがほとんどLADと一緒なので、LAD+L1の更新式を導出してちょっとずつ変えていった。
HuberないしLADの場合に正則化項をつける場合は上のpdfでの6.1に|x|_1の項がつくわけだけど、この場合は更にx - w = 0という条件をつけて拡張ラグランジアンをつくると解けるようになる。
というわけで実際に実装してやってみたのが下記リンクのnotebook。
https://github.com/tkimaizumi/HousePrice
pandasの処理が奇怪なことになっているのは手元の環境のせい。具体的にいうとnumpyのverのせいっぽい。対処方法を調べるとnumpyのverを下げろと出てきたもののそれも嫌だし別の環境つくるのも面倒だしということでそういうことになっている。
比較のためにElasticNet, LassoからはじめてLAD+L1,LAD+ElasticNet, Huber+ElasticNet, Huber+L1の順にやっていった。
マルチコあるからL2ノルム項を入れないと……と即思ってしまい、はじめはElasticNetでやったものの、よくよく考えると予測しかしないんだから関係ないじゃんと思いLassoでやったりなど結構場当たり的に進めた。
統計的に有意な差かはあやしいと思うものの、L1よりElasticNetのほうがよかった。理由を考えると、trainとtestを別々に標準化している分(trainのfitでtestをtransform)、trainとtestのマルチコの度合いが違ってElasticNetのほうがよくなるのかも知れない?
Kaggle的にはどうせtestの特徴量が与えられてるし実務とかじゃないのでマージして標準化するのが筋だとは思うもののそれは好きではないので仕方ない。
スコアそのものと説明変数に関しては今回まるで関心がないので数値型なら即標準化、それ以外はOne-Hot Encodingして標準化した。
でsubmitしてみたときのスコアが
ElasticNet: 0.13837
Lasso: 0.13864
LAD+L1: 0.13584
LAD+ElasticNet :0.13560
Huber + ElasticNet :0.13839
Huber + L1 :0.13857
HuberよりLADのほうがよかったですまる。
0.138台と0.135台は順位で見ると1000位くらい上がる感じの差っぽい。テストデータのサイズがトレーニングデータのサイズとほぼ一緒で1460くらいだから結構な差といってもいいのか……?
まとめ。
予想とはちがったけどもロバストな損失関数にすると一応スコアは改善されるっぽい。
雑感:
ADMM、導出と実装がとっても楽でよい。ただ収束判定とかが適当だったりするのでその辺はどうにか。
欲しい解があんまり動かなくなったらやめる方式にしていて、3パラメータのグリッドサーチなんだけども、LADだとCVが早めに終わったのにHuberだと結構時間かかった(つまりmax_iterまでやってる)ので多分収束してない。
ついでに色々と調べている過程でRanganがADMMはGAMP(Generalized)/VAMP(Vector Approximate Message Passing)でMAP推定する際の特殊な場合と言っていて信頼感が増した。
まあ非凸な場合はちょっとあやしいなと思うわけですが。
あと3-Blockに分割すると収束しないことがあるとか結構色々と知れてよかった。もうちょっとADMMに関して調べたい。
LADだとこのくらいのデータ1460×300くらいで25 msとか。MBPで10^3のグリッドサーチしても数分くらいという高速さよ。
とりあえずやったこと
ふわっとしたタイトルはよくない。
・とりあえずTitanicをやった
・Signateに使いまわした
・Signateの離職予測でintermediateになった
ツリー系のアルゴリズムは宗教上の理由で使いたくないので、色々あってFactorization Machines(FMs)にすることにした。polylearnを使った。
順序のないカテゴリ変数のOne-Hot Encodingとか、数値データだが分布の形がキモく目的変数の条件付き経験分布をみると大小よりもどの辺に属しているかが効いてそうとか、交互作用がありそう(TitanicでいえばPclassと女性)とか、マルチコがありそう(これはencodingで余計に作ってる)とか。
上の前から2つの理由で説明変数がまあまあスパースであり、交互作用自体をモデル化できること、まあマルチコはL2正則化でマイルドになると信じると、まあ無難な選択ではなかろうか。
欲を言うと交互作用項の重さをスパースにしたいが……
Titanicは0.78468。最初は80%超えとかを目標にしていたが案外難しい。敬称を使うTIPSとかを見たりもしたが名前情報を使うのは現代的には倫理的にどうかと思うしまあこのくらいでよかろうと思うことにした。
SignateのTitanicはカラム情報が減ってるだけでなく、簡単になってる気がする。
近頃はライブラリを使うよりベタ書きだけどフルスクラッチみたいなことが多かったので、sklearnとかpandasとかの使い方を結構忘れていた。その辺を思い出したり新しく知ったりできたのでよかった。
あと雑感。インターネッツ、CV周りに関してひどい記事が多い。
※20210730追記
CVでモデル選択をすると決めた限りは計算量の兼ね合いはありますがCVをそれなりに頑張るのは本質的です。具体的にいうとチューニングパラメータによって使う説明変数が変わる(つまり同時にモデル選択を行なっている場合)手法を使っている場合は、チューニングパラメータによって(決定木ベースと回線形帰ベースの違いみたいなレイヤーとはまた違うレイヤーで)モデルが完全に異なるものになっているからです。
※追記ここまで
いじょ
このブログについて:Kaggleとか統計検定とか
色々あって、これまで毛嫌いしていたKaggleと統計検定1級とをやろうと思う。
(統計検定の1級や準1級に関しては問題を眺めた感じいい試験だと思っているものの、そもそも資格というものに対してあまり……という感じ)
このブログについてだが、それにあたっての諸々を書いていこうかな、と思っている。
有用なTIPSのようなことを書ければいいと思うが、気が向いたときには今日はこれだけやったとかそういうことを書いたりすることもあると思う。
だいたい日記のようなものが長続きしない性質なので、思いたってまずブログを開設したものの、どういう記事を書くかはまだ自分でもよくわからない。