Kaggle 新コンペ Santander Customer Transaction Prediction
とりあえず Starter Kerne 書いた。コンペ開催中はブログに何もかけないのが辛いですね。
www.kaggle.com
Quora コンペ入賞者手法まとめ
自分のコメントはかなり適当。後で更新するかも。
3rd
- 3rd place kernel | Kaggle
- Keras
- embedding load 時に stemmer and lemmetizer してできるだけ dictionary の中から見つける
- bidirectional GRU と LSTM の output の maxpool を concat
- max_length = 55 と短め
- Local solid CV to tune all the hyperparameters と書いてあるがどこだろう
13th
- 13th place solution | Kaggle
- Keras
- latex 記法クリーニング
- https/http/ftp クリーニング
- punct クリーニング
- Embedding:Glove0.64+ Params0.36
- 3 model の ensemble
- bidirectional LSTM and GRU の output をconcat して maxpool1D 後 Dense。
- bidirectional GRU + AttentionWeightedAverage
- bidirectional LSTM + CNN
20th
- Surprising 20th place - 2 models, various embeds, mixed loss | Kaggle
- PyTorch
- concat(GloVe, FastText) embedding + LSTM + TextCNN with kernel size [1, 2, 3, 4] + 2 dense layers, with some batch normalizations and dropout layers
- mean(GloVe, Para) embedding + LSTM + GRU + concat(GlobalAvgPool, GlobalMaxPool) + 2 dense layers, with some dropout layers
22nd
- 22nd Solution - 6 Models and POS Tagging | Kaggle
- Keras
- training 時間が短い軽量モデルで 70%のprediction をする。残りの30%の難しい分類は別のモデルで行う。
- 6 models
27th
- 27th kernel | Kaggle
- embedding load 時に stemmer and lemmetizer してできるだけ dictionary の中から見つける
- average blend of 5 models which includes all 4 embeddings with a local CV of 0.7028
- 長さなどの extra features
- tfidf
- Kernel のCell 出力が長すぎて読めない
70th
Transformer - Attention Is All You Need の概要が理解できるリンク
で教えていただいた [1706.03762] Attention Is All You Need。最初は論文そのものを読もうと思ったが挫折したので。概要を理解できるリンク集。Attention Is All You Need https://t.co/eUZ17XVu8L で提案された Transformer 以降は self-attention が主流な印象です。先日おおきな話題になった BERT も Transformer 系です。
— agatan (@agatan_) February 12, 2019
- 論文解説 Attention Is All You Need (Transformer) - ディープラーニングブログ
- 論文読み "Attention Is All You Need" - Qiita
- Attention Is All You Need · Issue #329 · arXivTimes/arXivTimes
- Google AI Blog: Transformer: A Novel Neural Network Architecture for Language Understanding
- The Annotated Transformer
- The Illustrated Transformer – Jay Alammar – Visualizing machine learning one concept at a time 英語に抵抗なければおすすめ
- [DL輪読会]Attention Is All You Need
今回のコンペでやるべきだったこと
今回のコンペでやるべきだったこと、次回のコンペで活かせることに絞って覚書。
- debug mode をつけるべきだった。train/test data のサイズを極端に小さくするモード。
- Kernel を commit する前に小さいデータで動作確認をすべき。特に自分は typo が多いので。
- public kernel を fork して、そこから派生していく時点で1行ずつ読み込んで自分のものにしておくべきだった。
- EDA 後に CV を安定させることに注力。
- Record 専用 Kernel を作って試行錯誤と score を記録。これはコンペ途中からやっていて有用だった。最初は各 Kernel に markdown としてうめこんでいたがパラレルでものを進めると簡単に破綻した。
Quora コンペ takuko さんのコード
Twitter で takuko さんが使用したスクリプトを公開してくださった。こういうのは本当にありがたい。
Quoraのスクリプトをまとめて、久々にgitでコードを公開しました!(requirementsとかREADMEとかめんどくさくて手をつけてないです。。。)https://t.co/jfhD7y2IZX
— takuoko (@takuoko1) February 11, 2019
自分なりに 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 の話もあった。別のコンペでもよくある議論だと思うのでここでまとめて理解を深める。
参考
- Cross-Validation | Kaggle
- Cross Validationはなぜ重要なのか【kaggle Advent Calendar 3日目】 - u++の備忘録
- validationの切り方いろいろ(sklearnの関数まとめ)【kaggle Advent Calendar 4日目】 - u++の備忘録
- cv strategy | Kaggle
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 の議論
- 背景
- 参照
- 前提 RNN を利用した Encoder& Decoder MNP モデル
- Attention
- PyTorch での Attention の実装例
- 問題とされた点
- 筆者の疑問点
- 間違いを見つけたら
背景
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 すると精度が上がるのは上記のような背景がある。
図
ここで
- は Endoder の timestep = t での hidden_state
- は Decoder の timestep = t' での hidden_state
Attention
理解のキーポイント
概要は C5W3L08 Attention Model - YouTube を見るのが良いと思う。入出力に注目すると
- Decoder は timestep = 1 の decode 時に hidden_state vector ではなく を受け取る。
- が timestep = t' のときにおける入力に pay attention すべき weight。 (すべて足し合わせると1)。
- は encoder の各 timestep における hidden_state の重み付きの和になっている。
- は を出力するときに にどれだけ注目 (pay attention) するべきかを表す。
- 直感的にはまさに下図のように Hi を出力しようとしているときには オッス:0.9 オラ:0.07 悟空:0.03 みたいな重みが提供されて(後述)。なるほどオッスがいちばん大事なのだなと分かるイメージ。
重み
上述の重みはどこからやってくるのか。ここを曖昧に理解していたのだが小さい Neural Network に学習させてしまおうというのが肝っぽい。 ここで下記のように なるものを導入して、重みの和が1 になるようにする。
この を Neural Network で下図のように学習する。
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 は上述の とは別物であることに注意。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 にお願いします。