Quora コンペ takuko さんのコード

Twitter で takuko さんが使用したスクリプトを公開してくださった。こういうのは本当にありがたい。

自分なりに public kernel を読みまくったので、public kernel と takuko さんの kernel で気づいた違いを列挙。

  • glove と para を mean ではなく 0.8:0.2 で足している。
    • なぜこの比なのか?Local CV で search した?
  • emb_mean, emb_std を定数で埋め込んでいる(速度のため?)
  • Gaussian noise regularizer を使っている
  • lstm と gru の max_pool, avg_pool (計4つ)も Input として使っている
    • どこかで書いたが max_pool が特徴量として効く理由が直感的に理解できていないのでここは将来 revisit で。list of LSTM state (len = max_len) から最大のものを選ぶことに意味があるのだろうか。不思議だ。
  • 追記:コメント欄参照

Kaggle における K-Fold CV まとめ

背景

先日 submission の締切が過ぎて終了フェーズの Quora Insincere Questions Classification | Kaggle。 local CV と pubic LB の相関についてたくさんの議論があった。また local CV vs train test split の話もあった。別のコンペでもよくある議論だと思うのでここでまとめて理解を深める。

参考

K-Fold CV と Train Test Split 違い

  • Train Test Split
    • Train data の量が少ないともったいない。
    • 大きいデータセットに向いている
  • Cross validation
    • 2つ以上の model を学習させるので時間がかかる
    • model の性能についてより正しい理解が得られる
    • 小さいデータセットのときは Cross validation 一択。
  • cv strategy | Kaggle の議論からのまとめ。全ての trainig data を使った single model と比べて、K-Fold CV のほうが良いのはなぜか?という疑問。
    • K-Fold は異なるデータセットから K 個の異なるモデルを作る。そのため各モデルは微妙に異なる prediction をする。それゆえに K 個のモデルからの prediction を平均して使うと頑丈で良い結果になるし overfit しにくくなる(筆者:なぜ?より diverse なものに強いから?)
    • K-Fold は全ての traing データを使うことができる。single model だと validation 用に holdout が必要になる。
      • これは必ずしも真ではない。holdout で validation して model のベストパラメータを見つけたあとに、全ての train データを使って1から学習させればよい。その際には epoch などを注意深く設定して overfit しないように気をつけないといけない。(とある grandmaster は epoch * 1.1 くらいを推奨している)
      • 上記の調節が難しいので K-Fold が好まれる事が多いらしい。

K-Fold CV 例

K-Fold (4- 6) で train データ全体に対して prediction をして validation score を出す(average など)。K-Fold 時に使ったモデルすべてを使って test prediction を行い。final submission を average などで出す。

K-Fold 亜種

validationの切り方いろいろ(sklearnの関数まとめ)【kaggle Advent Calendar 4日目】 - u++の備忘録 がとても良くまとまっている。特にデータに偏りがある場合の visualization が分かりやすい。

CV FAQ

Local CV の値が安定しない

PyTorch を使おう。Keras よりも PyTorch の方が Deterministic に出来るので好まれている模様。Deterministic neural networks using PyTorch | Kaggle を参照のこと。下記の seed_everything が肝。

# Written by Benjamin Minixhofer
def seed_everything(seed=1234):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True

Local CV と public LB で傾向が違う

例えば Local CV が改善したのに public LB が下がったとか。

考えられる理由1

validation, train, test セットの分布が異なる。EDA をきちんとやって適切な K-Fold 亜種を選ぶ。Adversarial validation という方法も。

考えられる理由2

それぞれが計算された方法が微妙に異なること。

  • Local CV は K 個のモデルからでた K 個のスコアを平均している
  • Public LB は K個のモデルから出た K 個の prediction を平均してスコアを計算している

A validation framework & impact of the random seed | Kaggle という手法がある。

Local CV と public LB どちらを信じるか

Local CV。通常 traing data の方が test data よりも大きいのでより信頼できる。

RNN Attention の理解と bias の議論

背景

Quora Insincere Questions Classification | Kaggle というコンペで public kernel で使われていた PyTorch Attention 実装に pitfall があったのではという指摘 Common pitfalls of public kernels | Kaggle があった。それを発端に Attention を正しく理解できていないことが分かったのでここにまとめる。

参照

前提 RNN を利用した Encoder& Decoder MNP モデル

特徴

  • timestep t において過去の入力列は fixed size の vector として表現される。この vector は sentence embedding と呼ぶこともできる。つまり文章を embedding したもの。(word embedding との対比を考えるとわかりやすい)
  • 長い sequence に弱い。timestep = 1 のときの入力から max_seq_len step 後に decode が始めるので timestep = 1 のときの影響力が弱い。
    • 語順が似ている言語同士の翻訳だと入力を reverse すると精度が上がるのは上記のような背景がある。

f:id:higepon:20190209144944j:plain

ここで

  •  a^{\langle t\rangle} は Endoder の timestep = t での hidden_state
  •  s^{\langle t^{\prime}\rangle} は Decoder の timestep = t' での hidden_state

Attention

理解のキーポイント

概要は C5W3L08 Attention Model - YouTube を見るのが良いと思う。入出力に注目すると

  • Decoder は timestep = 1 の decode 時に hidden_state vector ではなく c^{<1>} =  \sum_{t^{\prime}} \alpha^{\langle1, t^{\prime}\rangle}a^{\langle t^{\prime}\rangle} を受け取る。
    •  \alpha^{\langle1, t^{\prime}\rangle} が timestep = t' のときにおける入力に pay attention すべき weight。 (すべて足し合わせると1)。
    •  c^{<1>} は encoder の各 timestep における hidden_state の重み付きの和になっている。
  •  \alpha^{\langle t, t^{\prime}\rangle} y^{\langle t\rangle} を出力するときに  a^{\langle t^\prime\rangle} にどれだけ注目 (pay attention) するべきかを表す。
  • 直感的にはまさに下図のように Hi を出力しようとしているときには オッス:0.9 オラ:0.07 悟空:0.03 みたいな重みが提供されて(後述)。なるほどオッスがいちばん大事なのだなと分かるイメージ。

f:id:higepon:20190209155106j:plain

重み

上述の重みはどこからやってくるのか。ここを曖昧に理解していたのだが小さい Neural Network に学習させてしまおうというのが肝っぽい。 ここで下記のように  e^{\langle t, t^{\prime}\rangle} なるものを導入して、重みの和が1 になるようにする。

 \alpha^{\langle t, t^{\prime}\rangle} = \frac{\exp(e^{\langle t, t^{\prime}\rangle} )}{\sum_{t^\prime}^{Tx}{\exp(e^{\langle t, t^{\prime}\rangle}})}

この  e^{\langle t, t^{\prime}\rangle} を Neural Network で下図のように学習する。 f:id:higepon:20190209154549j:plain

PyTorch での Attention の実装例

Common pitfalls of public kernels | Kaggle で触れられているがオリジナルの実装者はここ

# Written by Benjamin Minixhofer
# in https://www.kaggle.com/bminixhofer/deterministic-neural-networks-using-pytorch
class Attention(nn.Module):
    def __init__(self, feature_dim, step_dim, bias=True, **kwargs):
        super(Attention, self).__init__(**kwargs)
        
        self.supports_masking = True

        self.bias = bias
        self.feature_dim = feature_dim
        self.step_dim = step_dim
        self.features_dim = 0
        
        weight = torch.zeros(feature_dim, 1)
        nn.init.xavier_uniform_(weight)
        self.weight = nn.Parameter(weight)
        
        if bias:
            self.b = nn.Parameter(torch.zeros(step_dim))
        
    def forward(self, x, mask=None):
        feature_dim = self.feature_dim
        step_dim = self.step_dim

        eij = torch.mm(
            x.contiguous().view(-1, feature_dim), 
            self.weight
        ).view(-1, step_dim)
        
        if self.bias:
            eij = eij + self.b
            
        eij = torch.tanh(eij)
        a = torch.exp(eij)
        
        if mask is not None:
            a = a * mask

        a = a / torch.sum(a, 1, keepdim=True) + 1e-10

        weighted_input = x * torch.unsqueeze(a, -1)
        return torch.sum(weighted_input, 1)

コードの解説

上述の Attention の解説と実装ではいくつか異なる点がある(おそらく亜種)

  • eij の学習時に self.weight だけでなく self.bias も使っている
  • mask をサポートしている(おそらく各入力が長さ違いで pad されているときに pad を無視するため)

基本的には self.weight と self.b が先程の Neural Network を定義するもの。self.weight は上述の  \alpha とは別物であることに注意。NN の出力サイズが (-1, step_dim) なのは各 timestep ごとに e を求めたいから。

問題とされた点

bias 項が以下のように sequence の位置に対して、それぞれ異なる値が持てるように定義されていること。

self.b = nn.Parameter(torch.zeros(step_dim))

Dmitriy Danevskiy さんは以下の2点を問題として挙げている。

  • 長さが異なる入力が想定されているのに step_dim が 70 として与えられている。これは長さが 70 の入力に対する bias になってしまう。truncate されていたり pad されていたりする場合に対応していない
  • bias が token の絶対的位置にひもづいているが、異なる入力 sequence に対して位置が重要なことはあまりない(本当?)

氏はそのかわり bias をすべての sequence element で共有するように定義すべきだと提案している。

筆者の疑問点

bias の値が token の位置に依存していなければ、学習によって bias の値はすべて同じような値になっていくので問題ないのではないか?

間違いを見つけたら

https://twitter.com/HigeponJa にお願いします。

Kaggle PLAsTiCC Astronomical Classification competition まとめ

先日終了したPLAsTiCC Astronomical Classification | Kaggleコンペ。上位のチームの解法のまとめ。自分は1097チーム中247位でした。Coursera で Kaggle コースをとったあとに途中から参加したコンペで、力及ばずだったので何が足りなかったのか知るためのまとめ。

できなかったこと・やらなかったこと

  • 天文系の domain knowledge 勉強
  • gradient boost 系のモデル。NN のみに集中した。
  • trivial でない feature engineering.

知りたいこと

  • domain knowledge はどの程度必要だったのか?
  • NN はどこまで健闘できたのか?
  • feature engineering はどの程度がんばればよいのか?

Top 5

1位

2位

3位

  • 3rd Place Part I -CNN | Kaggle
  • LGB + CatBoost + CNN
  • CNN is a Fully 1D Convolutional Neural Network with 256 * 8,5,3 convolution kernels followed by a GlobalMaxPulling
  • time series data と meta feature を handle する複数の NN

4位

  • 4th Place Solution with Github Repo | Kaggle
  • trained a model to predict hostgal specz using training set+ test set with hostgalspecz. Then used this model's predictions as a feature.
  • blend of LGB, NN and several stacking model
  • Class 99 は LB probe した

5位

結果

  • domain knowledge はどの程度必要だったのか?
    • データが何であるかを説明できるくらいには必要だった
  • NN はどこまで健闘できたのか?
    • 上位に NN モデル多し。詳細は Kernel を見たい。
  • feature engineering はどの程度がんばればよいのか?
    • モデルによるが大量の feature の人達もいる

Kaggle 今後の方針

Kaggle を初めて少し時間が経っていろいろ分かってきたので今後の方針をここで書きながら考える。

学び

  • Feature Engineering がんばらないと勝てないコンペ多い。
  • Tabular data だと NN よりも XGBoost 勢が人気で強い。
  • Kernel 書くとフィードバックもらえる
  • Kernel 読むの勉強になる。特に終わったコンペの上位 Kernel。
  • すぐにコピペできる資産が溜まってくると楽になる。Cross Validation, Hyper parameter tuning 等々。

始めた動機

  • DNN 周りですぐに手を動かすことができるように
  • RNN/LSTM 以外も詳しくなりたい
  • 毎日触る機会として使う

今後の方針

  • 入賞は nice to have
  • 1つのコンペに集中
  • Kernel を読んでその手法を取り入れる・理解するプロセスを繰り返す
  • ある程度コピペ資産が溜まったら整理する
  • 重点トピック
    • Cross Validation と高速化
    • Hyper parameter tuning の勘所
    • Keras API はほとんど理解できるように
  • Blog ドリブンで。

ホモ・デウス

ホモデウス読了。前作サピエンス全史同様に作者の深い洞察と鋭いマクロ視点が好き。特に人間の意識の話が面白かった。おすすめ。これからの世代は大変そうだ。

ホモ・デウス 上: テクノロジーとサピエンスの未来

ホモ・デウス 上: テクノロジーとサピエンスの未来

Clouderizer + Google Colab for Kaggle

HoxoMaxwell ❄️さんのツイートで見かけてToDoに入っていた Clouderizer + Google Colab を試した。手順は Kaggle Competition on Google Colab — how to easily import datasets and local files and access… にある通り。

この手の Cloud Service をラップするやつを使うのは初めてだが良いと思ったのは以下の点。

  • pip などで追加で入れるライブラリをプロジェクトテンプレートで指定できる。
  • とにかく Kaggle のデータが自動で設定されるのがとても便利。必要なのはプロジェクト名だけ。
  • Google Drive と連携するとファイルの persistence も面倒見てくれるっぽいので Colab のライフサイクル問題もそこまで辛くない。
  • 200 project hours まで無料 。登録にクレジットカード必要なかった。