データサイエンティストの中村です。 ファッションアイテムの画像から抽出した特徴量は検索以外にも利用することができます。 今回はレコメンドにおける画像特徴量の活用について、以下の3トピックを考えてみたいと思います。
- 画像特徴量を利用したコンテンツベースレコメンド
- モデルベース協調フィルタリングにおけるコールドスタート問題の軽減
- 画像特徴量を利用したモデルベース協調フィルタリングの高度化
画像特徴量を利用したコンテンツベースレコメンド
あるアイテムを好きなユーザーはとよく似たアイテムも好きであると仮定します。このユーザーへの推薦は、と似ているアイテムを推薦すれば良いわけですが、このとき、アイテムの類似度を評価する尺度として画像特徴量が使えます。 アイテムの画像特徴量をとしたとき、アイテムとアイテムの類似度はとの間の距離を用いて表現できます。類似度(距離)にはコサイン類似度やユークリッド距離がよく使われます。
実際にAutoencoderで抽出した特徴量を使ってアイテムを推薦すると、以下のようになります。
コンテンツベースのレコメンドでは、画像特徴量に基づくアイテム類似度を予め計算しておき、直近の履歴に応じて推薦アイテムを決定します。 類似度計算にはトランザクションデータを必要としない為、コールドスタートに強い手法と言えます。
一方で、結果を見て分かる通り、推薦されるアイテムはどれも似通ってしまいます。同じデザインで価格やブランドが違う服を提案したいときには使えますが、新しい発見を得る機会は少なくなります。
モデルベース協調フィルタリングにおけるコールドスタート問題の軽減
モデルベース協調フィルタリングの例として行列分解(Matrix Factorization)があります。 行列分解のインプットはレーティング行列であるため、レーティングが存在しないアイテムは推薦対象に含めることができません。 この問題は画像特徴量を利用することで軽減することが可能です。
行列分解
行列分解を用いてレーティング行列を との積に分解できたとします。このときユーザーとアイテムの相性は中の対応する要素の内積で表現できます。
(バイアス項は省略しています)
はベクトルで、アイテムの特徴量とみなすことができます。はファクターの数です。
画像特徴量の利用
ファッションECサイトには毎日新しいアイテムが追加されています。レコメンドにもなるべく早い段階で新着アイテムを反映したいという思いがあります。 上の式を参照すると、新着アイテムの特徴量さえ計算できれば、ユーザーベクトルと内積をとることですべてのユーザーとの相性を計算できそうです。 行列分解の計算後に画像特徴量を利用して新着アイテムの特徴量を無理矢理与えてしまおうというのがここで紹介する方法です。
レーティングが存在するアイテムの集合を、新着アイテムをで表記します。画像特徴量はレーティングの有無に関係なくすべてのアイテムについて計算可能です。新着アイテムの画像特徴量をクエリに近傍探索を実行すれば、新着アイテムの近傍を得ることができます。
このとき、新着アイテムの特徴量を以下のように定義します。
新着アイテムの特徴量は、近傍のアイテムの特徴量の重み付き線形和とし、重みは新着アイテムとの類似度に依存する形で定義します。
これにより新着アイテムの特徴量が計算できました。実際に計算された特徴量を可視化すると以下のようになります。 左はクエリ画像、中央は画像が似ているアイテム、右は行列分解で計算した特徴量が似ているアイテムです。クエリ画像はレーティングの付いていない新着アイテムですが、行列分解で計算した特徴量を使って比較しても違和感のないアイテムが並んでいます。
今回は重みを近傍法を利用して定義しましたが、この重みは学習によって求めることも可能です。詳しくはGantner2010*1をご覧ください。
画像特徴量を利用したモデルベース協調フィルタリングの高度化
ここでは行列分解のモデル自体を高度化する方法を考えます。 あるユーザーのファッションアイテムに対する好みには、アイテムの見た目も影響を与えていそうです。 この直感を定式化するため、一般的な行列分解の式に画像に依存する項を加えます。
ここで、はユーザーのアイテムの見た目に対する重み、はアイテムの特徴量をと同じ次元にマッピングするための行列、はアイテムの画像自体に対するバイアスです。 右辺第1項だけだと通常の行列分解となります。第2項および第3項が画像に関する項で、第2項はユーザーと画像の相互作用、第3項は画像自体の魅力を表現しています。
これをBayesian Personalized Ranking(BPR)という手法で解いたのがHe2015*2です。彼らはこの手法をVisual Bayesian Personalized Ranking(VBPR)と呼んでいます。
実装
VBPRをchainerで実装しました。VBPRのアルゴリズムはシンプルなのでフレームワークを使うまでもありませんが、深層学習フレームワークを利用して実装すれば実績のある最適化アルゴリズムなどの恩恵を受けることができます。
VBPRのモデルの定義は以下のようになります。
import numpy as np import chainer from chainer import functions as F from chainer import links as L from chainer import Variable class VBPR(chainer.Chain): def __init__(self, n_user, n_item, n_latent, n_visual, d_image, reg=0.0): self.n_user = n_user self.n_item = n_item self.n_latent = n_latent self.n_visual = n_visual self.d_image = d_image self.reg = reg self._layers = { 'latent_u': L.EmbedID(self.n_user, self.n_latent), 'latent_i': L.EmbedID(self.n_item, self.n_latent), 'visual_u': L.EmbedID(self.n_user, self.n_visual), 'visual_i': L.Linear(self.d_image, self.n_visual, nobias=True), 'bias_v': L.Linear(self.d_image, 1, nobias=True), } super(VBPR, self).__init__(**self._layers) for param in self.params(): param.data[...] = np.random.uniform(-0.1, 0.1, param.data.shape) def __call__(self, u, i, j, xi, xj): gamma_u = self.latent_u(u) gamma_i = self.latent_i(i) gamma_j = self.latent_i(j) theta_u = self.visual_u(u) theta_i = self.visual_i(xi) theta_j = self.visual_i(xj) bias_i = self.bias_v(xi) bias_j = self.bias_v(xj) x_uij = F.sum(gamma_u * (gamma_i - gamma_j), axis=1) x_uij += F.sum(theta_u * (theta_i - theta_j), axis=1) x_uij += F.reshape(bias_i - bias_j, (u.shape[0], )) loss = F.log1p(F.exp(-x_uij)) if self.reg > 0: loss += self.reg * F.sum(gamma_u*gamma_u, axis=1) loss += self.reg * F.sum(gamma_i*gamma_i, axis=1) loss += self.reg * F.sum(gamma_j*gamma_j, axis=1) loss += self.reg * F.sum(theta_u*theta_u, axis=1) loss += self.reg * F.sum(theta_i*theta_i, axis=1) loss += self.reg * F.sum(theta_j*theta_j, axis=1) loss += self.reg * F.sum(bias_i *bias_i , axis=1) loss += self.reg * F.sum(bias_j *bias_j , axis=1) loss = F.sum(loss) / u.shape[0] chainer.report({'loss': loss,}, self)
行列の各行はユーザー/アイテムの分散表現とみなせるので、EmbedID
で定義します。画像特徴量を任意の次元数にマッピングする場合はLinear
が使えます。d_image
という変数は画像特徴量の次元数です。
forwardはユーザーID、アイテムIDおよび対応する画像の画像特徴量(ベクトル)を引数に取ります。
実験
参考程度に実験を行いました。実験用に加工したIQONのデータセットを使います。ユーザー数は21382、アイテム数は99337、レーティングの数は547880です。レーティングの値は{0,1}のバイナリになっています。BPR、VBPR、VBPRの第2項と第3項(画像に関する項)(ここではVLRと呼ぶことにします)の3手法をRecall@100とnDCG@100で比べた結果、以下のようになりました。
残念ながら大勝というわけにはいきませんでした。ただし良い感触がまったくないわけではなく、オリジナルのVBPRを再現してパラメータを丁寧に決めればそれなりに差はつくのではないかと考えています。
まとめ
レコメンドに画像の情報を反映する方法を紹介しました。 とくに2つ目のコールドスタート対策は簡単に拡張できて使い勝手が良いのでおすすめです。IQONデータセットの場合、この手法を適用することで10万以上のアイテムを推薦候補に加えることができます。
最後に
VASILYでは、最新の研究にアンテナを張りながら、同時にユーザーの課題解決を積極的に行うメンバーを募集しています。 興味のある方はこちらからご応募ください。