ドコモの落合です。ドコモR&DではAI・データサイエンス分野での実力向上のために毎年KDD CUPに参加しています。KDD CUPはデータマイニングの国際学術会議であるKDDで開催されている、1997年からの歴史がある世界最高峰のデータ分析コンペです。
今年のKDD CUPは、Baiduが主催するSpatial Dynamic Wind Power Forecasting Challengeという風力発電量の予測タスクと、Amazonが主催する ESCI Challenge for Improving Product Searchというオンラインショッピングにおける検索のタスクでした。Amazonのタスクはさらに3つに分かれており、オンラインショッピングにおける検索ランキングの精度改善(Task1)、ユーザーの検索キーワードと検索結果の商品の関係性分類(Task2)、検索結果の商品が代替品として使えるかの分類(Task3)というタスクがありました。AmazonのTask2とTask3が問題設定が似ていたので、私たちのチーム(チーム名:NTT-DOCOMO-LABS-GREEN 1、メンバー:落合、福島、劉、若元、内村)ではこの2つのタスクに挑戦しました。Amazonのタスクには世界中から約1700名、約270チームが参加し、ドコモチームはTask2で12位、Task3で9位に入賞することができました!10位以内に入るとKDD2022で開催されるKDD CUP Workshopでの発表権が得られます。
2016年からKDD CUPへの参加を始め、2016年はファイナリスト、2019年は1位、2020年は複数部門で入賞(最高3位)という成績で、今回の入賞は2年ぶり4回目の入賞です。
それでは、タスクの詳細と私たちのチームの解法を紹介していきます。
ESCI Challenge for Improving Product Search: タスクの詳細
Amazonが主催したESCI Challenge for Improving Product Searchでは、オンラインショッピングにおける検索クエリと、検索結果としてユーザーに提示される商品の関係性(ユーザーの意図通りか、意図通りではないが類似した機能を持つかなど)を分類するタスクです。ここでは私たちのチームで取り組んだTask2とTask3を詳しく説明します。
提供されたデータ
このタスクでは、Amazonで商品を検索するクエリといくつかの商品が紐づいたデータが提供されました。実際のデータはこんな感じです。推定する対象はesci_labelのカラム(ラベルの詳細は次のセクション)で、それを各レコードのqueryと商品に関する情報(product_titleなど)から推定します。
Task2
Task2では、検索クエリと商品の関係性をExact (E), Substitute (S), Complement (C), Irrelevant (I)という4種類のラベルに分類し、この分類精度を競います。タスクの名称のESCIはこの4種類のラベルの頭文字からきています。各ラベルの詳細です(公式ページを日本語に訳したものです)。
- Exact (E): 検索クエリに対して仕様を全て満たす商品(例:"plastic water bottle 24oz" というクエリに対して、素材やサイズなどが一致するwater bottle)
- Substitute (S): 検索クエリに対して全ての要望を満たすものではないが機能的な代用ができる商品(例:sweaterという検索クエリに対するfleece)
- Complement (C): 検索クエリに対して全ての要望を満たすものではないが組み合わせて利用できる商品(例:"running shoe"という検索クエリに対するtrack pants)
- Irrelevant (I): 検索クエリに対して関連がない商品(例:"pant"という検索クエリに対するsocks)
対象データは、英語、日本語、スペイン語の3言語で、検索クエリー商品のペアが約260万件提供されました。言語の比率は、英語が69.4%、日本語が17.0%、スペイン語が13.6%で、ラベルの比率は Exact 65.2%、Substitute 21.9%、Complement 2.9%、Irrelevant 10.0%と不均衡なデータになっています。
Task3
Task3はTask2の4値の分類をSubstituteかそうでないかという2値分類にしたタスクです。それ以外はデータセットも含めTask2と共有です。
スケジュール
スケジュールとしては、こんな感じでした。
- 2022/3/15 コンペ開始
- 2022/3/28 データセット提供
- 2022/4/5 ベースライン公開
- 2022/6/30まで prediction submission
- 2022/7/1 code submission
- 2022/7/15 コンペ終了(後日7/20までに延長)
チームメンバーに自然言語処理に詳しい人がいなくて、コンペ開始当初はなかなか精度が上がらず苦労しました。また、最初は予測結果のCSVを投稿して精度評価されていたものが、7/1に急にcode submission roundになり推論コード全体をgit経由で投稿しないと評価されなくなったり、コンペ終了の日程が締め切りギリギリで延長されたりして、モデル精度以外の面でも苦労しました。
9位になった解法
私たちのチームの処理の流れは以下の通りです。
このタスクでは検索クエリと商品のsemantic matching(意味的なマッチング)を行うことが目的です。そのため、基本的な方針として、検索クエリと商品の情報をベクトル化し、そのベクトルをもとにクエリと商品の類似度を計算したり分類を行ったりするという処理が考えられます。自然言語処理で広く使われているTransformerというモデルを使って単語や文章のベクトルを生成します。最近では事前学習済みの様々なTransformerモデルが公開されていて、それらを使うことで検索クエリと商品の説明文などをベクトル化(embeddingを生成)していきます。図では③に該当します。
①不均衡データ対策
タスクの説明でも述べた通り、ラベルごとにデータ数が大きく異なります。一般的にラベルの偏りがある場合に、モデルの学習にそのままデータを使うと多数派のクラスに予測結果が偏ってしまいます。 そこで、不均衡データでも少数派のクラスの予測精度を上げるために、文献2を参考に学習時のデータのサンプリングを工夫しました。Two-phase learningと呼ばれる方法で、最初は多数派のデータをランダムにアンダーサンプリングしてクラス間でサンプル数を揃えて学習した後に、すべてのデータでFine-tuningするという方法です。
②ラベル誤り検出
タスクの説明で紹介した実際のデータを見てみると、例えば4行目のデータでは「針なしほっちきす」に対して商品コードB09F3B413Jの商品がExactと判定されています。しかし、この商品はproduct_bullet_pointに「使い針タイプ」という説明があり、針があるホッチキスのようです。このようにラベルに誤りが含まれていることがあります。
そこで、データセットでラベルが誤っているデータを検出するConfident learning3という手法を使って、提供されたデータのラベルが誤っていそうなレコードを抽出しました。ラベルが誤っていると推定されたレコードを除いて分類モデルの学習を行います。Confident learningの論文の著者がcleanlabというライブラリを作っており、それを利用しました。インストールは簡単で pip install cleanlab
でできます。
ラベル誤りを検出するのに必要なのは、正解ラベルと各クラスの所属確率のデータです。 一度、分類モデルを学習し各クラスの所属確率を出した上で、以下のようにすればラベル誤りを検出できます。
from cleanlab.filter import find_label_issues ordered_label_issues = find_label_issues( labels=labels, pred_probs=pred_probs, return_indices_ranked_by='self_confidence', )
実際はCross-validationを行ってモデルの学習に使っていないデータに対して正解ラベルと各クラスの所属確率を用意して上のコードを実行します。
③分類モデル
今回のタスクでは検索クエリと商品説明文の2つの文の関係性を分類するため、Cross-Encoderという分類モデルを利用します。
Cross-Encoderを利用するにはSentenceTransformersというライブラリを使います。 pip install sentence-transformers
でインストールできます。
図の中のBERTの部分も様々なモデルが考案されており、HuggingFaceで事前学習済みモデルが多数公開されています。BERTのモデルでは多言語に対応したモデルや、各言語に特化したモデルなどいろいろなモデルがあります。
model = CrossEncoder('モデル名', num_labels=ラベル数)
とすることで、Cross-Encoderが利用でき、モデル名を変えることで事前学習済みモデルを利用できます。
今回は多言語向けモデルとしてMicrosoftのmDeBERTaを利用しました。 言語別のモデルには、英語はMicrosoftのMPNet、日本語には東北大学乾研究室で公開している日本語BERT、スペイン語にはHuggingFaceでダウンロード数が最も多かったスペイン語BERTを利用しました。
多言語モデルだけでなく言語別モデルも利用したのは、多言語モデルでのトークン分割(語の区切り)が英語では良さそうですが日本語ではうまくいっていないように見えたためです。日本語モデルを使った場合は内部でmecabという日本語のトークナイザーを利用していて語の区切りがうまく処理できています。
④アンサンブル
アンサンブルは独立に学習した複数の分類モデルの結果を統合し1つの予測結果を出力する方法です。各モデルを統合する方法は多数決にしたり、各モデルの予測確率の平均を計算したりさまざまな方法があります。今回は、コンペの環境で実際にsubmitしてみて、多言語モデル:言語別モデル=2:1で重み付けする方法が精度がよかったので重み付け平均を採用しました。
⑤後処理
文字列での検索で最も単純な方法は、検索クエリと検索対象の文字列がどの程度一致しているか?を考えることだと思います。 そこで、検索クエリと商品タイトルの最長共通部分列長を計算し、検索クエリに対して共通文字列が何%一致しているかとそのときのラベルの分布を見てみました。すると、0%(=検索クエリと商品タイトルで共通する文字がない)場合はIrrelevantのラベルが多く、逆に100%(=検索クエリが商品タイトルに全て含まれる)場合はExactのラベルが多いことがわかります。
もう一つ、予測結果がどういう場合に間違ったのか深堀してみました。 そのために、各クラスの所属確率のTop1とTop2の差を計算し、予測が正解だった場合と不正解だった場合でヒストグラムを作ってみます。すると下の図のような感じになりました。正解している場合は、Top1とTop2の差が大きく、不正解の場合はTop1とTop2の差が小さいことがわかります。
これら2つのことから、Top1とTop2の差が小さいときは予測が間違えている可能性があるので、ルールでラベルを変更することにしました。 具体的には「Top1とTop2の差が0.2未満かつ検索クエリの80%以上が商品タイトルに含まれていたらExactにする」というルールを適用しました。Task3の場合は、Substituteかそうでないかの分類なので、同じ条件の場合にSubstituteでないに分類しました。
各処理による精度改善
不均衡データ対策は手元のデータで精度が改善したので全てに適用することにしたので、Public Testでの改善幅がわからないのですが、それ以外に工夫した点について、どの処理がどの程度効果があったのか1つずつ要素を追加していったときの精度をまとめました(精度はTask3の精度)。アンサンブルによる改善が一番効果が大きかったです。
今回実装したコードはGithubで公開しています。
最後に
本記事ではKDD CUP 2022 ESCI Challenge for Improving Product Searchでの解法を紹介しました。私自身は2014年ごろにTwitterの解析をしていて久しぶりに自然言語処理に触れました。当時と比べるといろんなツールが進化していて、いろんな技術が試せて楽しかったです。今後も新しい技術を取り入れて面白いものを作っていきたいと思います。
今後もこのブログではドコモで開発した技術や新しい技術を試してみた体験記などR&Dの様々な取り組みを発信していく予定ですのでお楽しみに!
- Task1にNTT-DOCOMO-LABS-REDという名前で別メンバーのチームも参加し、15位になりました。チーム名のREDとGREENはメンバーのポケモン好きに由来しています。↩
- Johnson, Justin M., and Taghi M. Khoshgoftaar. "Survey on deep learning with class imbalance." Journal of Big Data 6.1 (2019): 1-54.↩
- Northcutt, Curtis, Lu Jiang, and Isaac Chuang. "Confident learning: Estimating uncertainty in dataset labels." Journal of Artificial Intelligence Research 70 (2021): 1373-1411.↩