Shopee参加記1
kaggleのshopeeのコンペに参加しました。このコンペで学んだことを書きたいと思います。コンペはJaneStreet, Ranzcrに引き続き, 3回目の挑戦でした。
Privateで1278位でした。
概要
Shopeeが持っている商品のデータから同じクラスに属する商品を予測するコンペでした。データとしては主に商品の画像とタイトルが与えられており
, その二つを主に用いて同じクラスの商品を予測します。
あらかじめ与えられたクラスに分類するような問題はクラス分類ですが, ここではクラスは与えられていません。ラベルが同じものが近く, 異なるものが遠くなるように予測することが目的です。このように学習することを距離学習(Metric Learning)といいます。
CV
CVはlabelと画像をGroupとした, GroupKFold(K = 5)でした。画像が同じでもlabelが異なるものがあったため, 画像も考慮してGroupを作りました*1。 わりとCVとLBの相関は常に取れていました。solutionをチラッと見た感じ, data全体を使って学習させるとよかったと書いてあるものもあった*2ため, それもやってみてもよかったのかなと思いました。
自分が試した手法
ArcFace Loss
距離学習で用いられる手法でネットワーク自体は普通のクラス分類の場合と同じですが, lossを普通のcross_entropy()からArcfaceというlossを用います。ネットワークの出力を として, クラスごとの重みをとします。これらをL2ノルムで正規化してから内積をとると類似度がはかれますが, この類似度をが属するクラスについてはのように変えてからsoftmaxに入れます。
上記のようにすることで, が属するクラスについて他のクラスとの角度が以上離れて, かつ が1に近づくように学習することになります。このはマージンと呼ばれます。下の記事が詳しいです。
このlossを使うとモデルの中心部分は普通のクラス分類で用いたものを使うことができるのでたとえばEffcientnetやDensenetなどのpretrained modelの重みを使ってfine tuningすることができ, そのような手法を使いました。notebookやdiscussionを見る限り, わりと多くの参加者が使っていたと思います。
自分はeffcientnet_b3, effcientnet_b1, densenet_121, eca_nfnet_l0の4つを試しました。eca_nfnet_l0は自分で学習させるといろいろパラメータを変えてみてもlossがnanにしかならず学習させることができませんでした。ほかのかたのnotebookを見る限りnfnetはよいスコアを出せていたので自分で学習させられなかったのは悔しいところです。
それ以外は effcientnet_b1 < effcientnet_b3 densenet_121 という感じでした。effcientnet_b4,b5も試したかったのですが, timmのpretrained weightが見つからず, (どこにあるのかわからず)できませんでした...
Symmetric Loss
このコンペのラベルは少々noisyであることがdiscussionなどで報告されていました。よくわからないですが, e-commerceのデータはラベル付けがまちがっていることが多いかららしい(?)です。そのためnoisyなラベルを処理することが大事なのではないかと思いました。Cassavaコンペは出てはいませんでしたが, noisy labelだったらしく以下の記事を参考にしてやってみたのがSymmetric Lossでした。
Noisy label 対抗記~Cassava Leaf Disease Classification~ / Diary against the noisy label - Speaker Deck
Symmetric Lossは要するにCross Entropyのlabelが真の分布を表すことだけではなく, predictionもある程度真の分布を表すことを考慮したlossです。
普通のcross entropyとtargetとpredictionを逆にしたcross entropyの平均をとるような感じです。
これは少しCVが向上しました。
Tfidf
こちらは商品のタイトルの分類で使いました。tfidfでタイトルをベクトル化し, そのタイトルの類似度を測りました。タイトルをみたところ絵文字が多いのでそれを除去したり, インドネシア語など様々な言語が含まれていたのでdiscussionにあったインドネシア語と英語を対応させたdictionaryを使って翻訳してから...とかやりましたが, ほとんどCVに寄与しませんでした...
いらない記号(+,-,!,?)や絵文字などを除去してから翻訳したものはすこしCVが上昇しましたが, LBは変わらずでした。
Word2vec
CVが全然良くなかったので採用しませんでした。英語やインドネシア語などその他いろいろな言語があったので, あまり役に立たなかったのではないかと思います。
Bert
bertはdiscussionやnotebookで紹介されていたので使ってみようと思い, 学習済みモデルのfine tuningをしようとしました。しかし, CVで全く精度がでませんでした。discussionを見ている限り多くの人がこれを使っていそうで, しかもtfidfだけよりも精度がでていたらしいのでこれをちゃんと学習させることはメダルを取るには必要だと感じました。
原因不明ですが, 英語の学習済みモデルを使っていたので多言語学習済みモデルを使えばよかったのかなと思います。英語の学習済みモデルで精度が出ている人がいるのだから, これの調節をすればうまく学習するはずだとおもっていたのが間違いで, いろいろな選択肢を試すのが先だったような気がします。
単位について
手元のtrain-validの予測で間違っていたものを確認していたのですが, わりとimageではこの二つの画像の差を見分けるのは(人間にも)無理そうなものがありました。これらはなぜ異なるラベルが付けられているのだろうと考えたところ, 微妙な機種や, サイズ(100gと200g)などの違いであることがタイトルとあわせて見ることでわかりました。
これをなんとか利用しようと, タイトルから単位部分を抽出してその数値を比較することで同じ単位で違う数字を持っているもの(15cmと20cmなど)は絶対に同じ商品としないとしました。これもCVで機能しませんでした。「絶対に同じにしない」だと強すぎるのかなと思いました。単位だけ取ってきたものでtfidfをして類似度を測るということもやってみましたが, それもうまくいきませんでした。
OCR
OCRで画像からテキスト情報を取り出し, その情報を利用する方法です。過去の同様なコンペで使われていたようです。しかし, これを使ってtfidfをしてみてまともに使えなかったので使用しませんでした。過去コンペのsolutionでも本やCDなどの形ではなく, テキスト情報のほうが判別に重要と考えられる画像について用いており, ただ使えばいいというものでもないのできちんとした意図があって使わないと意味がないのかなと思いました。
今回のコンペのsolutionでもあまり使われていなかったように思います。
全結合にしたい
AとBが同じ商品で, BとCが同じ商品ならAとCも同じ商品であるべきです。これはつまりAとBが同じ商品であるときにAとBの間に辺を貼ったようなグラフを考えると、これが完全グラフになるべきだということです。
そのためこのようにする後処理をしました。このためには類似度を測る閾値を少し小さめにして全結合にするということをすべきだと思いました。 閾値を調整しましたが, この後処理をしてもCV、LBともに向上しませんでした。
やれなかったもの
Siamese net
概念を理解する時間がなく, 公開notebookを一回動かしただけでほとんど何もできませんでした。
その他反省
この記事を書いていて気づいたのですが, いろいろな情報がdiscussionなどに流れている中, それをあまり活用し切れていないなと思いました。初期のころに取り組んだアプローチ(今回の場合はarcface loss, tfidfなど)に執着してしまい, そのアプローチの微調整などに力を入れてしまうことが多かったです. 確かにそうするとコードの管理などは楽になるのですが, 成長していないのであまりスコアも伸びません。
また, これもこの記事を書いていて気づいたことですが異なる手法に取り組んだとしてもそれがうまくいくまでやらないと意味がないのでそういう根気が必要だということを実感しました。
notebookやdiscussionを追って, 新しいアプローチを理解してその方法も自分のCVできちんと確かめるというサイクルを作ることでスコアも伸びやすくなるのかもしれないと思いました. notebookやdiscussionから流れてくる情報を把握して有用かどうか, きちんと確かめることをこれからのコンペでは意識したいと思いました。
上位のsolutionをみてより学びたいと思います。