In-depth analysis and improvement of cold start recommendation model DropoutNet
コールドスタートが必要な理由
レコメンデーションシステムでは通常、協調フィルタリング、行列分解、またはディープラーニングモデルを用いてレコメンデーション候補セットを生成します。これらのリコールアルゴリズムは一般的にユーザーとアイテムの行動マトリックスに依存しています。実際のレコメンデーションシステムでは、新規ユーザーと新規アイテムが継続的に追加されます。しかし、これらの新規ユーザーやアイテムは、十分で豊富な過去のインタラクション行動データが不足しているため、正確なレコメンデーションコンテンツを取得できなかったり、適切なユーザーに正確に推薦されたりすることができません。これがいわゆるレコメンデーションのコールドスタート問題です。コールドスタートはレコメンデーションシステムにとって重要な課題です。既存のレコメンデーションアルゴリズムは、リコール、粗ソート、精ソートのいずれのモジュールにおいても、新規ユーザーや新規アイテムに対して十分に機能せず、ユーザー行動データの収集に過度に依存しがちです。一方、新規ユーザーや新規アイテムの行動データは非常に少ないため、新規アイテムが表示される機会は比較的少なく、新規ユーザーの興味を正確にモデル化できません。
一部のビジネスにおいて、プラットフォームのエコシステム構築と長期的な利益の観点から、新規アイテムをタイムリーに推薦して十分な露出を得ることは非常に重要です。たとえば、ニュース記事は適時性が非常に高く、タイムリーに表示される機会を得られなければ、そのニュース価値は大きく低下します。セルフメディア UGC プラットフォームで、新しく公開されたコンテンツがタイムリーに十分なユーザーに届かなければ、コンテンツクリエイターの創作意欲に影響し、将来的にプラットフォームが保有できる高品質コンテンツの量にも影響を及ぼします。デートプラットフォームで新規ユーザーに十分な注目を集められなければ、新規ユーザーの継続的な流入が期待できず、プラットフォームの活力が失われる可能性があります。
要するに、コールドスタート問題はレコメンデーションシステムにおいて非常に重要であり、ではどのようにしてコールドスタート問題を解決すればよいのでしょうか。
コールドスタート問題の解決方法
レコメンデーションシステムのコールドスタート問題を解決するアルゴリズム(または戦略)は、「泛・快・移・少」(パン・カイ・イー・シャオ)の四字方針に集約されます。
泛(パン):すなわち新規アイテムを汎化し、属性やテーマにおいてより広い概念に依存して推薦します。たとえば、新商品がリリースされた場合、過去に同じカテゴリを好んだユーザーに推薦できます。つまり「商品」から「カテゴリ」への汎化です。「ショート動画」は「作成者」へ汎化されます。新しくリリースされたニュース記事は、同じトピックを好むユーザーに推薦できます。たとえば「J-20」を紹介する記事をミリタリーファンに推薦することで、つまり「ニュース」から「トピック」への汎化です。本質的には、これはコンテンツベースレコメンデーション(Content Based Recommendation)です。より良いレコメンデーション効果を得るため、複数の異なる「上位概念」を同時に汎化する必要がある場合があります。たとえば、新商品を「カテゴリ」だけでなく、「ブランド」「店舗」「スタイル」「カラー」などにも汎化できます。汎化の概念は、新規アイテムに既に内在している場合があり、その場合は比較的単純です。たとえば、商品の各種属性は通常、商品公開時にマーチャントによって入力されています。一方、「トピック」——この記事が「軍事」「スポーツ」「メイクアップ」などのどのトピックに属するか——は別のアルゴリズムによって抽出する必要があります。
タグやトピックの汎化に加えて、何らかのアルゴリズムを用いてユーザーとアイテムの埋め込みベクトルを取得し、ベクトルの距離や類似度を用いてユーザーとアイテムの興味をマッチングする方法も非常に一般的です。行列分解や深層ニューラルネットワークモデルなどのアルゴリズムがユーザーとアイテムの埋め込みベクトルを生成できます。ただし、従来のモデルは依然としてユーザーとアイテムのインタラクション行動データに依存してモデリングを行う必要があり、コールドスタートユーザーやアイテムに対して十分に汎化できません。DropoutNet など、コールドスタートユーザーやアイテムに対しても埋め込みベクトルを生成できるモデルも存在します。これについては後述で詳しく説明します。
汎化や押し上げのアプローチは一見単純で理解しやすく聞こえますが、実際にはさらに深掘りできる多くの作業があります。本質的には、これはアイテムのコンテンツ(属性)情報を利用して、この新規アイテムの過去のインタラクション行動データの不足を補っています。たとえば、アイテムの画像や動画などのマルチモーダル情報を利用して関連するレコメンデーションを行うことができます。たとえば、デートプラットフォームでは、新規ユーザーの写真の外見をスコアリングし(ここでは推薦されるアイテムを指す)、関連する外見の好みを持つユーザーに推薦できます(ここではレコメンデーションリストを閲覧しているユーザーを指す)。
快(カイ):天下の武功、唯快不破。いわゆるコールドスタートアイテムとは過去のユーザーインタラクション行動が不足しているアイテムのことです。そこで自然なアイデアは、新規アイテムのインタラクション行動をより迅速に収集し、レコメンデーションシステムで活用することです。従来のレコメンデーションアルゴリズムのモデルとデータは日単位で更新されますが、リアルタイム処理システムに基づけば、データとモデルを分単位、さらには秒単位で更新できます。このような方法は通常、強化学習や文脈付きバンディットアルゴリズムに基づいています。参考記事を 2 つ紹介します。詳細は省略します:「Implementation and Application of Contextual Bandit Algorithm in Recommender System」、「Experience and Pitfalls of Deploying Contextual Bandit Algorithm in Recommender System in Production Environment」。
移(イー):転移学習は、異なるシナリオのデータを呼び出してモデルを構築する方法です。転移学習を通じて、ソースドメインからターゲットドメインへ知識を転移できます。たとえば、新規ビジネスでサンプル数が少ない場合、他のシナリオのデータを使ってモデリングを行う必要があります。この場合、他のシナリオがソースドメインとなり、新規ビジネスシナリオがターゲットドメインとなります。別の例として、一部の越境 EC プラットフォームは異なる国で異なるサイトを運営しており、新しく開設されたサイトではユーザーインタラクション行動データが少量しかありません。この場合、他の国のより成熟したサイトのインタラクション行動データを利用してモデルをトレーニングし、現在の国のサイトの少量のサンプルでファインチューーニングを行えば、良好的なコールドスタート効果を得られます。転移学習技術を使用する際は、ソースドメインとターゲットドメイン間にある程度の関連性が必要であることに注意してください。たとえば、前述の異なる国のサイトで販売される商品のかなりの部分が重複しているような場合です。
少(シャオ):少数ショット学習技術は、その名の通り、少量の教師ありデータのみを使用してモデルをトレーニングする技術です。その中でも代表的な少数ショット学習方法がメタ学習です。本文の目的はこれらの学習技術を紹介することではないため、詳細な説明は省略します。興味のある方は以下を参照してください:「Cold Start Recommendation Model Based on Meta-Learning」。
本稿では主に「泛化」に基づく方法を紹介します。具体的には、完全にコールドスタートなシナリオに適用可能な埋め込み学習モデルである DropoutNet を詳しく紹介します。元の DropoutNet モデルでは、ユーザーとアイテムの埋め込みベクトルを入力教師シグナルとして提供する必要がありました。これらの埋め込みベクトルは通常、行列分解などの他のアルゴリズムモデルから取得されるため、モデルの使用ハードルを上げていました。本稿では、エンドツーエンドのトレーニング方法を提案し、ユーザーのインタラクション行動を直接トレーニング目標として使用することで、モデルの使用ハードルを大幅に下げました。
さらに、モデルの学習をより効率的にするため、本稿では従来の二項分類予測モデルのポイントワイズ損失関数に加えて、2 つの新しい損失関数を追加しました。1 つは AUC 指標の改善に焦点を当てたランキング損失、もう 1 つはリコール効果の改善に使用されるサポートベクトル誘導ソフトマックス損失(Support Vector Guided Softmax Loss)です。後者は革新的に「ネガティブマイニング」(Negative Mining)と呼ばれる負のサンプリング技術を採用しています。トレーニングプロセス中に現在のミニバッチから自動的に負のサンプルをサンプリングすることで、サンプル空間を拡大し、より優れた学習効果を実現します。
したがって、本稿の主な貢献は 2 つあり、以下のようにまとめられます。
1. DropoutNet モデルを改良し、ユーザーとアイテムのインタラクション行動データを直接トレーニング目標としてエンドツーエンドのトレーニングを行うことで、他のモデルを使用してユーザーとアイテムの埋め込みを教師シグナルとして提供する必要性を回避しました。
2. 多様な損失関数を用いたマルチタスク学習フレームワークを革新的に提案し、トレーニングプロセスでネガティブマイニングの負のサンプリング技術を用いて現在のミニバッチから負のサンプルをサンプリングすることで、サンプル空間を拡大して学習をより効率的にし、トレーニングデータ量が比較的少ないシナリオにも適しています。
DropoutNet モデル解析
NIPS 2017 の論文「DropoutNet: Addressing Cold Start in Recommender Systems」は、ヘッドユーザーやアイテムだけでなく、ミドル・ロングテール、さらには完全に新規のユーザーやアイテムにも適したレコメンデーションシステムのコールドスタートに対処するリコールモデルを紹介しました。
DropoutNet は典型的なデュアルタワー構造であり、ユーザー側タワーはユーザーの潜在空間ベクトル表現を学習し、対応するアイテム側タワーはアイテムの潜在空間ベクトル表現を学習します。ユーザーが現在のアイテムに対してクリックや購入などの何らかのインタラクション行動を行った場合、モデルの損失関数はユーザーのベクトル表現とアイテムのベクトル表現間の距離を可能な限り近づけるように設計されています。ユーザーとアイテムの間にインタラクション行動が発生しない場合、対応するユーザーとアイテムのペアは負のサンプルを構成し、モデルは対応するサンプルにおけるユーザーのベクトル表現とアイテムのベクトル表現間の距離を可能な限り遠ざけようとします。
モデルをレコメンデーションシステムのあらゆる段階に適用可能にするため、ヘッドユーザーやアイテムのベクトル表現だけでなく、ミドル・ロングテール、さらには完全に新規のユーザーやアイテムのベクトル表現も学習できるように、DropoutNet はユーザーとアイテムの特徴を 2 つの部分に分けています。コンテンツ特徴と選好統計特徴です。コンテンツ特徴は比較的安定的で頻繁には変化せず、対応する情報は通常、ユーザー登録時やアイテムの公開時に収集されます。一方、選好統計特徴はインタラクションログから統計的に抽出された特徴であり、動的で時間とともに変化します。新規ユーザーやアイテムには対応するインタラクションがないため、選好統計特徴も存在しません。
では、DropoutNet はどのようにしてモデルを完全に新規のアイテムやユーザーのベクトル表現の学習に適したものにしているのでしょうか。実は、そのアイデアは非常にシンプルです。ディープラーニングにおけるドロップアウトの考え方を借りて、一定の確率で入力の一部の特徴を強制的にゼロに設定する、いわゆる入力ドロップアウトを行います。ここでのドロップアウトはニューラルネットワークモデルのニューロンに作用するのではなく、入力ノードに直接作用することに注意してください。具体的には、ユーザーとアイテムの選好統計特徴は学習过程中に一定の確率でゼロに設定されますが、コンテンツ次元の特徴はドロップアウトされません。
論文の紹介によると、DropoutNet はノイズ除去オートエンコーダー(denoising autoencoder)の考え方を借りています。つまり、トレーニングモデルが破損した入力を受け取って元の入力を再構築するように学習します。すなわち、モデルを学習させることで、一部の入力特徴が欠落している場合でも、より正確なベクトル表現を依然として取得できるようにします。具体的には、入力が破損した状態で学習されたユーザーベクトルとアイテムベクトル間の相関スコアを、入力が破損していない場合のユーザーベクトルとアイテムベクトル間の相関スコアに可能な限り近づけることです。
目的関数は以下の通りです。
O = Σ(u,v) (Uu Vv^T - fU(Uu, Φu^U) fV(Vv, Φv^V)^T)^2 = Σ(u,v) (Uu Vv^T - Ûu V̂v^T)^2
ここで、Ûu はモデルが学習したユーザーベクトル表現、V̂v はモデルが学習したアイテムベクトル表現です。**Uu と Vv は教師シグナルとして外部から入力されたユーザーとアイテムのベクトル表現であり、一般的に他のモデルから学習して取得されます**。
モデルをユーザーのコールドスタートシナリオに適したものにするため、トレーニングプロセス中にユーザーの選好統計特徴をドロップアウトします。
ユーザーコールドスタート:Ouv = (Uu Vv^T - fU(0, Φu^U) fV(Vv, Φv^V)^T)^2
モデルをアイテムのコールドスタートシナリオに適したものにするため、トレーニングプロセス中にアイテムの選好統計特徴をドロップアウトします。
アイテムコールドスタート:Ouv = (Uu Vv^T - fU(Uu, Φu^U) fV(0, Φv^V)^T)^2
DropoutNet モデルの学習プロセスは Algorithm 1 に示されています。
エンドツーエンドトレーニングへの変換
DropoutNet モデルの欠点の 1 つは、教師シグナルとしてユーザーとアイテムの埋め込みベクトルを提供する必要があることです。モデルはドロップアウトを通じて入力特徴の一部をマスクし、部分的な入力特徴からユーザーとアイテムの埋め込みベクトル間の類似度を再構築できるベクトル表現を学習しようとします。その原理はノイズ除去オートエンコーダーに似ています。つまり、ユーザーとアイテムの埋め込みベクトルを学習するために別のモデルが必要だということです。プロセス全体から見ると、2 つの段階で学習目標を完了する必要があります。第 1 段階ではモデルをトレーニングしてユーザーとアイテムの埋め込みベクトルを取得し、第 2 段階では DropoutNet モデルをトレーニングしてより頑健なベクトル表現を取得し、完全に新規のコールドスタートユーザーやアイテムに適用できるようにします。
トレーニングプロセスを簡素化するため、エンドツーエンドのトレーニング方法を提案します。新しいトレーニング方法では、教師シグナルとしてユーザーとアイテムの埋め込みベクトルを提供する必要がなくなり、代わりにユーザーとアイテムのインタラクション行動を教師シグナルとして使用します。たとえば、クリック率予測モデルと同様に、ユーザーがアイテムをクリックした場合、そのユーザーとアイテムは正のサンプルを構成します。ユーザーに提示されたがクリックされなかったアイテムは負のサンプルを構成します。損失関数の設計を通じて、モデルは正のサンプルのユーザーとアイテムのベクトル表現間の類似度を可能な限り高く、負のサンプルのユーザーとアイテムのベクトル表現間の類似度を可能な限り低く学習できます。たとえば、以下の損失関数を使用できます。
L = -[y log(Ûu V̂v+^T) + (1-y) log(1 - Ûu V̂v-^T)]
ここで、y ∈ {0,1} はモデルがフィッティングする目標です。v+ はユーザー u とインタラクションしたアイテムを表し、v- はユーザー u とインタラクションしなかったアイテムを表します。
オンライン負のサンプリングと損失関数
レコメンデーションシステムのリコール段階のモデルとして、露出ログのみを使用してトレーニングサンプルを構築するのでは不十分です。通常、ユーザーに提示できるアイテムは少数であり、プラットフォーム上のほとんどのアイテムは現在のユーザーに露出されない可能性があるためです。これらの未露出アイテムを現在のユーザーとのサンプルとして構築しないと、モデルは潜在するサンプル空間のごく一部しか探索できず、モデルの汎化性能が弱くなります。
サンプルの負のサンプリングはリコールモデルで一般的に使用される技術であり、モデルの効果を確保するための鍵でもあります。負のサンプリングには多くの方法があり、Facebook の論文「Embedding-based Retrieval in Facebook Search」を参照できるため、ここでは詳細を省略します。以下では、実装の観点からサンプルの負のサンプリング方法を説明します。
サンプルの負のサンプリングには通常、以下の表に示す 2 つのアプローチがあります。
負のサンプリング方法
メリット
デメリット
オフライン負のサンプリング
実装が容易
サンプル空間が限定的で、トレーニングが遅い
オンライン負のサンプリング
トレーニング中に動的にサンプル空間を拡大でき、トレーニングが速い
実装がより複雑
オンラインサンプル負のサンプリングにも異なる実装方法があります。たとえば、グローバル共有メモリを使用してサンプリング対象のアイテム集合を管理する方法があります。この方法の欠点の 1 つは、実装がより複雑であることです。通常、複数日のユーザー行動ログを収集・集約してサンプルを構築しますが、サンプル総数が非常に大きくメモリに収まりません。同じアイテムが複数日のサンプルに登場する場合、対応する統計特徴も異なり、適切に処理しないと特徴のクロス問題が発生する可能性があります。
もう 1 つのより巧みな実装は、現在のミニバッチからサンプリングすることです。トレーニングデータは各エポックでグローバルにシャッフルされてからモデルのトレーニングに使用されるため、各ミニバッチのサンプル集合はランダムにサンプリングされます。ミニバッチから負のサンプルをサンプリングすることは、理論的にグローバルなサンプルに対する負のサンプリングと等価です。この方法は実装が比較的簡単であり、本稿ではこのオンラインサンプリング方法を使用します。
具体的には、トレーニングプロセス中にユーザー特徴とアイテム特徴がネットワークの順伝播を行った後、ユーザー埋め込みとアイテム埋め込みを取得します。次に、行列(アイテム埋め込みに対応)の行に対して行単位のローリング操作(row-wise roll)を実行し、行列の行を全体的に N 行下へ移動してから、末尾からあふれた N 行を行列の先頭 N 行に再挿入します。これは循環キューで一方向に N ステップ移動することに相当します。これにより、負のサンプルのユーザーとアイテムのペアが得られ、上記の操作を M 回繰り返すことで M 個の負のサンプルペアを取得します。
変更後の DropoutNet ネットワークを上図に示します。まず、ユーザー意味ベクトルと正のサンプルアイテム間のコサイン類似度を計算し、R(u,i+) とします。次に、ユーザー意味ベクトルと N 個の負のサンプルアイテム間のコサイン類似度を計算し、R(u,i1-), ..., R(u,iN-) とします。N+1 個の類似度スコアに対してソフトマックス変換を適用してユーザーのアイテムに対する選好確率を取得します。最終的な損失関数は、正のサンプルアイテムに対するユーザーの選好確率の負の対数であり、以下の通りです。
L = -log(P(i+|u)) = -log(exp(R(u,i+)) / (exp(R(u,i+)) + Σ(j∈Neg) exp(R(u,ij-))))
さらに、「Support Vector Guided Softmax Loss for Face Recognition」の論文のアイデアを参考に、ソフトマックス損失関数の実装過程に最大マージンとサポートベクトルの方法を導入します。「正解を弱め、誤りを拡大する」方法を用いることで、モデルはトレーニング中により困難なタスクに挑戦させられ、モデルがより頑健になり、予測段階で正確な判断をしやすくなります。
サポートベクトル誘導ソフトマックス損失の TensorFlow 実装コード(負のサンプリングベース)は以下の通りです。
def softmax_loss_with_negative_mining(user_emb,
item_emb,
labels,
num_negative_samples=4,
embed_normed=False,
weights=1.0,
gamma=1.0,
margin=0,
t=1):
"""Compute the softmax loss based on the cosine distance explained below.
Given mini batches for `user_emb` and `item_emb`, this function computes for each element in `user_emb`
the cosine distance between it and the corresponding `item_emb`,
and additionally the cosine distance between `user_emb` and some other elements of `item_emb`
(referred to a negative sample).
The negative samples are formed on the fly by shifting the right side (`item_emb`).
Then the softmax loss will be computed based on these cosine distances.
Args:
user_emb: A `Tensor` with shape [batch_size, embedding_size]. The embedding of user.
item_emb: A `Tensor` with shape [batch_size, embedding_size]. The embedding of item.
labels: a `Tensor` with shape [batch_size]. e.g. click or not click in the session. It's values must be 0 or 1.
num_negative_samples: the num of negative samples, should be in range [1, batch_size).
embed_normed: bool, whether input embeddings l2 normalized
weights: `weights` acts as a coefficient for the loss. If a scalar is provided,
then the loss is simply scaled by the given value. If `weights` is a
tensor of shape `[batch_size]`, then the loss weights apply to each corresponding sample.
gamma: smooth coefficient of softmax
margin: the margin between positive pair and negative pair
t: coefficient of support vector guided softmax loss
return:
support vector guided softmax loss of positive labels
"""
batch_size = get_shape_list(item_emb)[0]
assert 0 < num_negative_samples < batch_size, '`num_negative_samples` should be in range [1, batch_size)'
if not embed_normed:
user_emb = tf.nn.l2_normalize(user_emb, axis=-1)
item_emb = tf.nn.l2_normalize(item_emb, axis=-1)
vectors = [item_emb]
for i in range(num_negative_samples):
shift = tf.random_uniform([], 1, batch_size, dtype=tf.int32)
neg_item_emb = tf.roll(item_emb, shift, axis=0)
vectors.append(neg_item_emb)
# all_embeddings's shape: (batch_size, num_negative_samples + 1, vec_dim)
all_embeddings = tf.stack(vectors, axis=1)
mask = tf.greater(labels, 0)
mask_user_emb = tf.boolean_mask(user_emb, mask)
mask_item_emb = tf.boolean_mask(all_embeddings, mask)
if isinstance(weights, tf.Tensor):
weights = tf.boolean_mask(weights, mask)
# sim_scores's shape: (num_of_pos_label_in_batch_size, num_negative_samples + 1)
sim_scores = tf.keras.backend.batch_dot(
mask_user_emb, mask_item_emb, axes=(1, 2))
pos_score = tf.slice(sim_scores, [0, 0], [-1, 1])
neg_scores = tf.slice(sim_scores, [0, 1], [-1, -1])
loss = support_vector_guided_softmax_loss(
pos_score, neg_scores, margin=margin, t=t, smooth=gamma, weights=weights)
return loss
def support_vector_guided_softmax_loss(pos_score,
neg_scores,
margin=0,
t=1,
smooth=1.0,
threshold=0,
weights=1.0):
"""Refer paper: Support Vector Guided Softmax Loss for Face Recognition (https://128.84.21.199/abs/1812.11317)."""
new_pos_score = pos_score - margin
cond = tf.greater_equal(new_pos_score - neg_scores, threshold)
mask = tf.where(cond, tf.zeros_like(cond, tf.float32),tf.ones_like(cond, tf.float32)) # I_k
new_neg_scores = mask * (neg_scores * t + t - 1) + (1 - mask) * neg_scores
logits = tf.concat([new_pos_score, new_neg_scores], axis=1)
if 1.0 。= smooth:
logits *= smooth
loss = tf.losses.sparse_softmax_cross_entropy(
tf.zeros_like(pos_score, dtype=tf.int32), logits, weights=weights)
# set rank loss to zero if a batch has no positive sample.
loss = tf.where(tf.is_nan(loss), tf.zeros_like(loss), loss)
return loss
ソースコード:https://github.com/alibaba/EasyRec/blob/master/easy_rec/python/loss/softmax_loss_with_negative_mining.py
ペアワイズランキング
ポイントワイズ、ペアワイズ、リストワイズは LTR(ランキング学習)分野における 3 つの代表的な最適化目標です。ディープラーニング時代よりずっと以前から、IR の研究者は一連の基礎的方法を開発してきました。より古典的な研究については、「Learning to Rank Using Gradient Descent」や「Learning to Rank - From Pairwise Approach to Listwise Approach」を参照してください。
ペアワイズの意義は、モデルのトレーニング目標を実際のタスクと可能な限り一致させることにあります。ソートタスクの場合、真の目標は正のサンプルの予測スコアを負のサンプルより高くすることで、これは AUC などの指標に対応します。ペアワイズの古典的な論文 RankNet では、ペアワイズ最適化目標は以下のように記述されます。
Cij = -yij log Pij - (1-yij) log(1-Pij), Pij = e^(f(xi)-f(xj)) / (1+e^(f(xi)-f(xj)))
ここで Pij はモデルがサンプル i をサンプル j より「関連性が高い」と予測する確率を表し、f(xi)-f(xj) は 2 つのサンプルのモデルのポイントワイズ出力ロジットの差です。直感的には、Cij の最適化は、任意の正のサンプルのスコアが任意の負のサンプルのスコアより高くなる確率、つまり AUC を向上させることであり、この形式のペアワイズ損失は AUC 損失とも呼ばれます。
同様に、実装を簡素化し、オフラインでのペアサンプル構築のワークロードを削減するため、In-batch Random Pairing 方法を選択してトレーニング中にミニバッチからペアを構築してペアワイズランク損失を計算します。具体的な実装コードは以下の通りです。
def pairwise_loss(labels, logits):
pairwise_logits = tf.expand_dims(logits, -1) - tf.expand_dims(logits, 0)
logging.info('[pairwise_loss] pairwise logits: {}'.format(pairwise_logits))
pairwise_mask = tf.greater(
tf.expand_dims(labels, -1) - tf.expand_dims(labels, 0), 0)
logging.info('[pairwise_loss] mask: {}'.format(pairwise_mask))
pairwise_logits = tf.boolean_mask(pairwise_logits, pairwise_mask)
logging.info('[pairwise_loss] after masking: {}'.format(pairwise_logits))
pairwise_pseudo_labels = tf.ones_like(pairwise_logits)
loss = tf.losses.sigmoid_cross_entropy(pairwise_pseudo_labels,
pairwise_logits)
# set rank loss to zero if a batch has no positive sample.
loss = tf.where(tf.is_nan(loss), tf.zeros_like(loss), loss)
return loss
レコメンデーションシステムでは通常、協調フィルタリング、行列分解、またはディープラーニングモデルを用いてレコメンデーション候補セットを生成します。これらのリコールアルゴリズムは一般的にユーザーとアイテムの行動マトリックスに依存しています。実際のレコメンデーションシステムでは、新規ユーザーと新規アイテムが継続的に追加されます。しかし、これらの新規ユーザーやアイテムは、十分で豊富な過去のインタラクション行動データが不足しているため、正確なレコメンデーションコンテンツを取得できなかったり、適切なユーザーに正確に推薦されたりすることができません。これがいわゆるレコメンデーションのコールドスタート問題です。コールドスタートはレコメンデーションシステムにとって重要な課題です。既存のレコメンデーションアルゴリズムは、リコール、粗ソート、精ソートのいずれのモジュールにおいても、新規ユーザーや新規アイテムに対して十分に機能せず、ユーザー行動データの収集に過度に依存しがちです。一方、新規ユーザーや新規アイテムの行動データは非常に少ないため、新規アイテムが表示される機会は比較的少なく、新規ユーザーの興味を正確にモデル化できません。
一部のビジネスにおいて、プラットフォームのエコシステム構築と長期的な利益の観点から、新規アイテムをタイムリーに推薦して十分な露出を得ることは非常に重要です。たとえば、ニュース記事は適時性が非常に高く、タイムリーに表示される機会を得られなければ、そのニュース価値は大きく低下します。セルフメディア UGC プラットフォームで、新しく公開されたコンテンツがタイムリーに十分なユーザーに届かなければ、コンテンツクリエイターの創作意欲に影響し、将来的にプラットフォームが保有できる高品質コンテンツの量にも影響を及ぼします。デートプラットフォームで新規ユーザーに十分な注目を集められなければ、新規ユーザーの継続的な流入が期待できず、プラットフォームの活力が失われる可能性があります。
要するに、コールドスタート問題はレコメンデーションシステムにおいて非常に重要であり、ではどのようにしてコールドスタート問題を解決すればよいのでしょうか。
コールドスタート問題の解決方法
レコメンデーションシステムのコールドスタート問題を解決するアルゴリズム(または戦略)は、「泛・快・移・少」(パン・カイ・イー・シャオ)の四字方針に集約されます。
泛(パン):すなわち新規アイテムを汎化し、属性やテーマにおいてより広い概念に依存して推薦します。たとえば、新商品がリリースされた場合、過去に同じカテゴリを好んだユーザーに推薦できます。つまり「商品」から「カテゴリ」への汎化です。「ショート動画」は「作成者」へ汎化されます。新しくリリースされたニュース記事は、同じトピックを好むユーザーに推薦できます。たとえば「J-20」を紹介する記事をミリタリーファンに推薦することで、つまり「ニュース」から「トピック」への汎化です。本質的には、これはコンテンツベースレコメンデーション(Content Based Recommendation)です。より良いレコメンデーション効果を得るため、複数の異なる「上位概念」を同時に汎化する必要がある場合があります。たとえば、新商品を「カテゴリ」だけでなく、「ブランド」「店舗」「スタイル」「カラー」などにも汎化できます。汎化の概念は、新規アイテムに既に内在している場合があり、その場合は比較的単純です。たとえば、商品の各種属性は通常、商品公開時にマーチャントによって入力されています。一方、「トピック」——この記事が「軍事」「スポーツ」「メイクアップ」などのどのトピックに属するか——は別のアルゴリズムによって抽出する必要があります。
タグやトピックの汎化に加えて、何らかのアルゴリズムを用いてユーザーとアイテムの埋め込みベクトルを取得し、ベクトルの距離や類似度を用いてユーザーとアイテムの興味をマッチングする方法も非常に一般的です。行列分解や深層ニューラルネットワークモデルなどのアルゴリズムがユーザーとアイテムの埋め込みベクトルを生成できます。ただし、従来のモデルは依然としてユーザーとアイテムのインタラクション行動データに依存してモデリングを行う必要があり、コールドスタートユーザーやアイテムに対して十分に汎化できません。DropoutNet など、コールドスタートユーザーやアイテムに対しても埋め込みベクトルを生成できるモデルも存在します。これについては後述で詳しく説明します。
汎化や押し上げのアプローチは一見単純で理解しやすく聞こえますが、実際にはさらに深掘りできる多くの作業があります。本質的には、これはアイテムのコンテンツ(属性)情報を利用して、この新規アイテムの過去のインタラクション行動データの不足を補っています。たとえば、アイテムの画像や動画などのマルチモーダル情報を利用して関連するレコメンデーションを行うことができます。たとえば、デートプラットフォームでは、新規ユーザーの写真の外見をスコアリングし(ここでは推薦されるアイテムを指す)、関連する外見の好みを持つユーザーに推薦できます(ここではレコメンデーションリストを閲覧しているユーザーを指す)。
快(カイ):天下の武功、唯快不破。いわゆるコールドスタートアイテムとは過去のユーザーインタラクション行動が不足しているアイテムのことです。そこで自然なアイデアは、新規アイテムのインタラクション行動をより迅速に収集し、レコメンデーションシステムで活用することです。従来のレコメンデーションアルゴリズムのモデルとデータは日単位で更新されますが、リアルタイム処理システムに基づけば、データとモデルを分単位、さらには秒単位で更新できます。このような方法は通常、強化学習や文脈付きバンディットアルゴリズムに基づいています。参考記事を 2 つ紹介します。詳細は省略します:「Implementation and Application of Contextual Bandit Algorithm in Recommender System」、「Experience and Pitfalls of Deploying Contextual Bandit Algorithm in Recommender System in Production Environment」。
移(イー):転移学習は、異なるシナリオのデータを呼び出してモデルを構築する方法です。転移学習を通じて、ソースドメインからターゲットドメインへ知識を転移できます。たとえば、新規ビジネスでサンプル数が少ない場合、他のシナリオのデータを使ってモデリングを行う必要があります。この場合、他のシナリオがソースドメインとなり、新規ビジネスシナリオがターゲットドメインとなります。別の例として、一部の越境 EC プラットフォームは異なる国で異なるサイトを運営しており、新しく開設されたサイトではユーザーインタラクション行動データが少量しかありません。この場合、他の国のより成熟したサイトのインタラクション行動データを利用してモデルをトレーニングし、現在の国のサイトの少量のサンプルでファインチューーニングを行えば、良好的なコールドスタート効果を得られます。転移学習技術を使用する際は、ソースドメインとターゲットドメイン間にある程度の関連性が必要であることに注意してください。たとえば、前述の異なる国のサイトで販売される商品のかなりの部分が重複しているような場合です。
少(シャオ):少数ショット学習技術は、その名の通り、少量の教師ありデータのみを使用してモデルをトレーニングする技術です。その中でも代表的な少数ショット学習方法がメタ学習です。本文の目的はこれらの学習技術を紹介することではないため、詳細な説明は省略します。興味のある方は以下を参照してください:「Cold Start Recommendation Model Based on Meta-Learning」。
本稿では主に「泛化」に基づく方法を紹介します。具体的には、完全にコールドスタートなシナリオに適用可能な埋め込み学習モデルである DropoutNet を詳しく紹介します。元の DropoutNet モデルでは、ユーザーとアイテムの埋め込みベクトルを入力教師シグナルとして提供する必要がありました。これらの埋め込みベクトルは通常、行列分解などの他のアルゴリズムモデルから取得されるため、モデルの使用ハードルを上げていました。本稿では、エンドツーエンドのトレーニング方法を提案し、ユーザーのインタラクション行動を直接トレーニング目標として使用することで、モデルの使用ハードルを大幅に下げました。
さらに、モデルの学習をより効率的にするため、本稿では従来の二項分類予測モデルのポイントワイズ損失関数に加えて、2 つの新しい損失関数を追加しました。1 つは AUC 指標の改善に焦点を当てたランキング損失、もう 1 つはリコール効果の改善に使用されるサポートベクトル誘導ソフトマックス損失(Support Vector Guided Softmax Loss)です。後者は革新的に「ネガティブマイニング」(Negative Mining)と呼ばれる負のサンプリング技術を採用しています。トレーニングプロセス中に現在のミニバッチから自動的に負のサンプルをサンプリングすることで、サンプル空間を拡大し、より優れた学習効果を実現します。
したがって、本稿の主な貢献は 2 つあり、以下のようにまとめられます。
1. DropoutNet モデルを改良し、ユーザーとアイテムのインタラクション行動データを直接トレーニング目標としてエンドツーエンドのトレーニングを行うことで、他のモデルを使用してユーザーとアイテムの埋め込みを教師シグナルとして提供する必要性を回避しました。
2. 多様な損失関数を用いたマルチタスク学習フレームワークを革新的に提案し、トレーニングプロセスでネガティブマイニングの負のサンプリング技術を用いて現在のミニバッチから負のサンプルをサンプリングすることで、サンプル空間を拡大して学習をより効率的にし、トレーニングデータ量が比較的少ないシナリオにも適しています。
DropoutNet モデル解析
NIPS 2017 の論文「DropoutNet: Addressing Cold Start in Recommender Systems」は、ヘッドユーザーやアイテムだけでなく、ミドル・ロングテール、さらには完全に新規のユーザーやアイテムにも適したレコメンデーションシステムのコールドスタートに対処するリコールモデルを紹介しました。
DropoutNet は典型的なデュアルタワー構造であり、ユーザー側タワーはユーザーの潜在空間ベクトル表現を学習し、対応するアイテム側タワーはアイテムの潜在空間ベクトル表現を学習します。ユーザーが現在のアイテムに対してクリックや購入などの何らかのインタラクション行動を行った場合、モデルの損失関数はユーザーのベクトル表現とアイテムのベクトル表現間の距離を可能な限り近づけるように設計されています。ユーザーとアイテムの間にインタラクション行動が発生しない場合、対応するユーザーとアイテムのペアは負のサンプルを構成し、モデルは対応するサンプルにおけるユーザーのベクトル表現とアイテムのベクトル表現間の距離を可能な限り遠ざけようとします。
モデルをレコメンデーションシステムのあらゆる段階に適用可能にするため、ヘッドユーザーやアイテムのベクトル表現だけでなく、ミドル・ロングテール、さらには完全に新規のユーザーやアイテムのベクトル表現も学習できるように、DropoutNet はユーザーとアイテムの特徴を 2 つの部分に分けています。コンテンツ特徴と選好統計特徴です。コンテンツ特徴は比較的安定的で頻繁には変化せず、対応する情報は通常、ユーザー登録時やアイテムの公開時に収集されます。一方、選好統計特徴はインタラクションログから統計的に抽出された特徴であり、動的で時間とともに変化します。新規ユーザーやアイテムには対応するインタラクションがないため、選好統計特徴も存在しません。
では、DropoutNet はどのようにしてモデルを完全に新規のアイテムやユーザーのベクトル表現の学習に適したものにしているのでしょうか。実は、そのアイデアは非常にシンプルです。ディープラーニングにおけるドロップアウトの考え方を借りて、一定の確率で入力の一部の特徴を強制的にゼロに設定する、いわゆる入力ドロップアウトを行います。ここでのドロップアウトはニューラルネットワークモデルのニューロンに作用するのではなく、入力ノードに直接作用することに注意してください。具体的には、ユーザーとアイテムの選好統計特徴は学習过程中に一定の確率でゼロに設定されますが、コンテンツ次元の特徴はドロップアウトされません。
論文の紹介によると、DropoutNet はノイズ除去オートエンコーダー(denoising autoencoder)の考え方を借りています。つまり、トレーニングモデルが破損した入力を受け取って元の入力を再構築するように学習します。すなわち、モデルを学習させることで、一部の入力特徴が欠落している場合でも、より正確なベクトル表現を依然として取得できるようにします。具体的には、入力が破損した状態で学習されたユーザーベクトルとアイテムベクトル間の相関スコアを、入力が破損していない場合のユーザーベクトルとアイテムベクトル間の相関スコアに可能な限り近づけることです。
目的関数は以下の通りです。
O = Σ(u,v) (Uu Vv^T - fU(Uu, Φu^U) fV(Vv, Φv^V)^T)^2 = Σ(u,v) (Uu Vv^T - Ûu V̂v^T)^2
ここで、Ûu はモデルが学習したユーザーベクトル表現、V̂v はモデルが学習したアイテムベクトル表現です。**Uu と Vv は教師シグナルとして外部から入力されたユーザーとアイテムのベクトル表現であり、一般的に他のモデルから学習して取得されます**。
モデルをユーザーのコールドスタートシナリオに適したものにするため、トレーニングプロセス中にユーザーの選好統計特徴をドロップアウトします。
ユーザーコールドスタート:Ouv = (Uu Vv^T - fU(0, Φu^U) fV(Vv, Φv^V)^T)^2
モデルをアイテムのコールドスタートシナリオに適したものにするため、トレーニングプロセス中にアイテムの選好統計特徴をドロップアウトします。
アイテムコールドスタート:Ouv = (Uu Vv^T - fU(Uu, Φu^U) fV(0, Φv^V)^T)^2
DropoutNet モデルの学習プロセスは Algorithm 1 に示されています。
エンドツーエンドトレーニングへの変換
DropoutNet モデルの欠点の 1 つは、教師シグナルとしてユーザーとアイテムの埋め込みベクトルを提供する必要があることです。モデルはドロップアウトを通じて入力特徴の一部をマスクし、部分的な入力特徴からユーザーとアイテムの埋め込みベクトル間の類似度を再構築できるベクトル表現を学習しようとします。その原理はノイズ除去オートエンコーダーに似ています。つまり、ユーザーとアイテムの埋め込みベクトルを学習するために別のモデルが必要だということです。プロセス全体から見ると、2 つの段階で学習目標を完了する必要があります。第 1 段階ではモデルをトレーニングしてユーザーとアイテムの埋め込みベクトルを取得し、第 2 段階では DropoutNet モデルをトレーニングしてより頑健なベクトル表現を取得し、完全に新規のコールドスタートユーザーやアイテムに適用できるようにします。
トレーニングプロセスを簡素化するため、エンドツーエンドのトレーニング方法を提案します。新しいトレーニング方法では、教師シグナルとしてユーザーとアイテムの埋め込みベクトルを提供する必要がなくなり、代わりにユーザーとアイテムのインタラクション行動を教師シグナルとして使用します。たとえば、クリック率予測モデルと同様に、ユーザーがアイテムをクリックした場合、そのユーザーとアイテムは正のサンプルを構成します。ユーザーに提示されたがクリックされなかったアイテムは負のサンプルを構成します。損失関数の設計を通じて、モデルは正のサンプルのユーザーとアイテムのベクトル表現間の類似度を可能な限り高く、負のサンプルのユーザーとアイテムのベクトル表現間の類似度を可能な限り低く学習できます。たとえば、以下の損失関数を使用できます。
L = -[y log(Ûu V̂v+^T) + (1-y) log(1 - Ûu V̂v-^T)]
ここで、y ∈ {0,1} はモデルがフィッティングする目標です。v+ はユーザー u とインタラクションしたアイテムを表し、v- はユーザー u とインタラクションしなかったアイテムを表します。
オンライン負のサンプリングと損失関数
レコメンデーションシステムのリコール段階のモデルとして、露出ログのみを使用してトレーニングサンプルを構築するのでは不十分です。通常、ユーザーに提示できるアイテムは少数であり、プラットフォーム上のほとんどのアイテムは現在のユーザーに露出されない可能性があるためです。これらの未露出アイテムを現在のユーザーとのサンプルとして構築しないと、モデルは潜在するサンプル空間のごく一部しか探索できず、モデルの汎化性能が弱くなります。
サンプルの負のサンプリングはリコールモデルで一般的に使用される技術であり、モデルの効果を確保するための鍵でもあります。負のサンプリングには多くの方法があり、Facebook の論文「Embedding-based Retrieval in Facebook Search」を参照できるため、ここでは詳細を省略します。以下では、実装の観点からサンプルの負のサンプリング方法を説明します。
サンプルの負のサンプリングには通常、以下の表に示す 2 つのアプローチがあります。
負のサンプリング方法
メリット
デメリット
オフライン負のサンプリング
実装が容易
サンプル空間が限定的で、トレーニングが遅い
オンライン負のサンプリング
トレーニング中に動的にサンプル空間を拡大でき、トレーニングが速い
実装がより複雑
オンラインサンプル負のサンプリングにも異なる実装方法があります。たとえば、グローバル共有メモリを使用してサンプリング対象のアイテム集合を管理する方法があります。この方法の欠点の 1 つは、実装がより複雑であることです。通常、複数日のユーザー行動ログを収集・集約してサンプルを構築しますが、サンプル総数が非常に大きくメモリに収まりません。同じアイテムが複数日のサンプルに登場する場合、対応する統計特徴も異なり、適切に処理しないと特徴のクロス問題が発生する可能性があります。
もう 1 つのより巧みな実装は、現在のミニバッチからサンプリングすることです。トレーニングデータは各エポックでグローバルにシャッフルされてからモデルのトレーニングに使用されるため、各ミニバッチのサンプル集合はランダムにサンプリングされます。ミニバッチから負のサンプルをサンプリングすることは、理論的にグローバルなサンプルに対する負のサンプリングと等価です。この方法は実装が比較的簡単であり、本稿ではこのオンラインサンプリング方法を使用します。
具体的には、トレーニングプロセス中にユーザー特徴とアイテム特徴がネットワークの順伝播を行った後、ユーザー埋め込みとアイテム埋め込みを取得します。次に、行列(アイテム埋め込みに対応)の行に対して行単位のローリング操作(row-wise roll)を実行し、行列の行を全体的に N 行下へ移動してから、末尾からあふれた N 行を行列の先頭 N 行に再挿入します。これは循環キューで一方向に N ステップ移動することに相当します。これにより、負のサンプルのユーザーとアイテムのペアが得られ、上記の操作を M 回繰り返すことで M 個の負のサンプルペアを取得します。
変更後の DropoutNet ネットワークを上図に示します。まず、ユーザー意味ベクトルと正のサンプルアイテム間のコサイン類似度を計算し、R(u,i+) とします。次に、ユーザー意味ベクトルと N 個の負のサンプルアイテム間のコサイン類似度を計算し、R(u,i1-), ..., R(u,iN-) とします。N+1 個の類似度スコアに対してソフトマックス変換を適用してユーザーのアイテムに対する選好確率を取得します。最終的な損失関数は、正のサンプルアイテムに対するユーザーの選好確率の負の対数であり、以下の通りです。
L = -log(P(i+|u)) = -log(exp(R(u,i+)) / (exp(R(u,i+)) + Σ(j∈Neg) exp(R(u,ij-))))
さらに、「Support Vector Guided Softmax Loss for Face Recognition」の論文のアイデアを参考に、ソフトマックス損失関数の実装過程に最大マージンとサポートベクトルの方法を導入します。「正解を弱め、誤りを拡大する」方法を用いることで、モデルはトレーニング中により困難なタスクに挑戦させられ、モデルがより頑健になり、予測段階で正確な判断をしやすくなります。
サポートベクトル誘導ソフトマックス損失の TensorFlow 実装コード(負のサンプリングベース)は以下の通りです。
def softmax_loss_with_negative_mining(user_emb,
item_emb,
labels,
num_negative_samples=4,
embed_normed=False,
weights=1.0,
gamma=1.0,
margin=0,
t=1):
"""Compute the softmax loss based on the cosine distance explained below.
Given mini batches for `user_emb` and `item_emb`, this function computes for each element in `user_emb`
the cosine distance between it and the corresponding `item_emb`,
and additionally the cosine distance between `user_emb` and some other elements of `item_emb`
(referred to a negative sample).
The negative samples are formed on the fly by shifting the right side (`item_emb`).
Then the softmax loss will be computed based on these cosine distances.
Args:
user_emb: A `Tensor` with shape [batch_size, embedding_size]. The embedding of user.
item_emb: A `Tensor` with shape [batch_size, embedding_size]. The embedding of item.
labels: a `Tensor` with shape [batch_size]. e.g. click or not click in the session. It's values must be 0 or 1.
num_negative_samples: the num of negative samples, should be in range [1, batch_size).
embed_normed: bool, whether input embeddings l2 normalized
weights: `weights` acts as a coefficient for the loss. If a scalar is provided,
then the loss is simply scaled by the given value. If `weights` is a
tensor of shape `[batch_size]`, then the loss weights apply to each corresponding sample.
gamma: smooth coefficient of softmax
margin: the margin between positive pair and negative pair
t: coefficient of support vector guided softmax loss
return:
support vector guided softmax loss of positive labels
"""
batch_size = get_shape_list(item_emb)[0]
assert 0 < num_negative_samples < batch_size, '`num_negative_samples` should be in range [1, batch_size)'
if not embed_normed:
user_emb = tf.nn.l2_normalize(user_emb, axis=-1)
item_emb = tf.nn.l2_normalize(item_emb, axis=-1)
vectors = [item_emb]
for i in range(num_negative_samples):
shift = tf.random_uniform([], 1, batch_size, dtype=tf.int32)
neg_item_emb = tf.roll(item_emb, shift, axis=0)
vectors.append(neg_item_emb)
# all_embeddings's shape: (batch_size, num_negative_samples + 1, vec_dim)
all_embeddings = tf.stack(vectors, axis=1)
mask = tf.greater(labels, 0)
mask_user_emb = tf.boolean_mask(user_emb, mask)
mask_item_emb = tf.boolean_mask(all_embeddings, mask)
if isinstance(weights, tf.Tensor):
weights = tf.boolean_mask(weights, mask)
# sim_scores's shape: (num_of_pos_label_in_batch_size, num_negative_samples + 1)
sim_scores = tf.keras.backend.batch_dot(
mask_user_emb, mask_item_emb, axes=(1, 2))
pos_score = tf.slice(sim_scores, [0, 0], [-1, 1])
neg_scores = tf.slice(sim_scores, [0, 1], [-1, -1])
loss = support_vector_guided_softmax_loss(
pos_score, neg_scores, margin=margin, t=t, smooth=gamma, weights=weights)
return loss
def support_vector_guided_softmax_loss(pos_score,
neg_scores,
margin=0,
t=1,
smooth=1.0,
threshold=0,
weights=1.0):
"""Refer paper: Support Vector Guided Softmax Loss for Face Recognition (https://128.84.21.199/abs/1812.11317)."""
new_pos_score = pos_score - margin
cond = tf.greater_equal(new_pos_score - neg_scores, threshold)
mask = tf.where(cond, tf.zeros_like(cond, tf.float32),tf.ones_like(cond, tf.float32)) # I_k
new_neg_scores = mask * (neg_scores * t + t - 1) + (1 - mask) * neg_scores
logits = tf.concat([new_pos_score, new_neg_scores], axis=1)
if 1.0 。= smooth:
logits *= smooth
loss = tf.losses.sparse_softmax_cross_entropy(
tf.zeros_like(pos_score, dtype=tf.int32), logits, weights=weights)
# set rank loss to zero if a batch has no positive sample.
loss = tf.where(tf.is_nan(loss), tf.zeros_like(loss), loss)
return loss
ソースコード:https://github.com/alibaba/EasyRec/blob/master/easy_rec/python/loss/softmax_loss_with_negative_mining.py
ペアワイズランキング
ポイントワイズ、ペアワイズ、リストワイズは LTR(ランキング学習)分野における 3 つの代表的な最適化目標です。ディープラーニング時代よりずっと以前から、IR の研究者は一連の基礎的方法を開発してきました。より古典的な研究については、「Learning to Rank Using Gradient Descent」や「Learning to Rank - From Pairwise Approach to Listwise Approach」を参照してください。
ペアワイズの意義は、モデルのトレーニング目標を実際のタスクと可能な限り一致させることにあります。ソートタスクの場合、真の目標は正のサンプルの予測スコアを負のサンプルより高くすることで、これは AUC などの指標に対応します。ペアワイズの古典的な論文 RankNet では、ペアワイズ最適化目標は以下のように記述されます。
Cij = -yij log Pij - (1-yij) log(1-Pij), Pij = e^(f(xi)-f(xj)) / (1+e^(f(xi)-f(xj)))
ここで Pij はモデルがサンプル i をサンプル j より「関連性が高い」と予測する確率を表し、f(xi)-f(xj) は 2 つのサンプルのモデルのポイントワイズ出力ロジットの差です。直感的には、Cij の最適化は、任意の正のサンプルのスコアが任意の負のサンプルのスコアより高くなる確率、つまり AUC を向上させることであり、この形式のペアワイズ損失は AUC 損失とも呼ばれます。
同様に、実装を簡素化し、オフラインでのペアサンプル構築のワークロードを削減するため、In-batch Random Pairing 方法を選択してトレーニング中にミニバッチからペアを構築してペアワイズランク損失を計算します。具体的な実装コードは以下の通りです。
def pairwise_loss(labels, logits):
pairwise_logits = tf.expand_dims(logits, -1) - tf.expand_dims(logits, 0)
logging.info('[pairwise_loss] pairwise logits: {}'.format(pairwise_logits))
pairwise_mask = tf.greater(
tf.expand_dims(labels, -1) - tf.expand_dims(labels, 0), 0)
logging.info('[pairwise_loss] mask: {}'.format(pairwise_mask))
pairwise_logits = tf.boolean_mask(pairwise_logits, pairwise_mask)
logging.info('[pairwise_loss] after masking: {}'.format(pairwise_logits))
pairwise_pseudo_labels = tf.ones_like(pairwise_logits)
loss = tf.losses.sigmoid_cross_entropy(pairwise_pseudo_labels,
pairwise_logits)
# set rank loss to zero if a batch has no positive sample.
loss = tf.where(tf.is_nan(loss), tf.zeros_like(loss), loss)
return loss
Related Articles
-
A detailed explanation of Hadoop core architecture HDFS
Knowledge Base Team
-
What Does IOT Mean
Knowledge Base Team
-
6 Optional Technologies for Data Storage
Knowledge Base Team
-
What Is Blockchain Technology
Knowledge Base Team
Explore More Special Offers
-
Short Message Service(SMS) & Mail Service
50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00
