BASEにおける類似画像検索を利用した関連商品表示の裏側

氏原淳志氏:今日は「『BASE』の類似商品APIの裏側」という内容でお話しします。

まず自己紹介します。私は氏原淳志と言いまして、BASE株式会社でData Strategyチームのエンジニアをやっております。Data Strategyチームというのは、データの分析であったりとか機械学習であったりとかを担当するチームです。

私はもともとサービスのバックエンド回りを主に担当していたんですけど、TensorFlowが出たあたりからDeepLearningを中心に機械学習を始めまして、現在ではBASEでモデルの作成をしたりとか、チームのみなさんが作成してくれたモデルを実運用でどうやって使っていこうかなということについて、インフラや仕組みを考える担当をしています。

ちなみに私はビールが大好きでして、とくにクラフトビールですね。会社でビール部を主催しているんですけど、最近はコロナのせいで部活ができてないので。

(会場笑)

本当にムカついております。

(会場笑)

簡単にですけど、BASEというサービスをもしかしたら知らない方が……いなければいいなぁと思っているんですけど(笑)。

(会場笑)

BASEの事業について少し説明します。BASEはネットショップの作成サービスです。ネットで何か売りたいなという方が無料でネットショップを作れるというサービスですね。商品が売れた際に手数料をいただくビジネスモデルですが、基本的には無料で運営できるものになっています。

すべてのショップを横断して、類似商品を表示する

ここから本題に入ります。今回のテーマは類似画像・テキスト検索ですが、BASEでもそれを行っている場所があります。BASEはネットショップを開くと、個々のお店のWebページができるんですけど、実はBASEではスマホ向けのショッピングアプリも提供していて、そちらでは、BASEを利用して開設されたネットショップを横断的に商品検索できて、購入できます。

アプリの商品ページを見たときに、関連する商品を表示しています。こちらでは、類似画像やテキストの検索を行っています。今アプリの画面をお見せしていますが、こちらに表示されている商品が、今取得している商品に類似した商品で、ここに関連する商品として出しています。ここはData Strategyチームが提供している類似商品APIで、候補を選んでいます。

今回のLT(ライトニングトーク)では、この類似商品APIが、実際にはどういう仕組みで動いているのかと、そのAPIのインフラ・運用はどうなっているのかについてお話しします。

類似商品APIの仕組み

まずは類似商品APIの仕組みですね。商品に似た商品を探すのに何を使って検索をしているかというと、画像やテキストの特徴量の近さを商品の類似度として使っています。画像は商品の画像、テキストは商品のタイトルや説明文を使っています。それらから特徴量を抽出して、BASEのショップ内で似た特徴量をもっている商品を探すというかたちになっています。

画像の特徴量としては、MobileNet、テキストの特徴量としては以前はfastTextのdoc vectorを使っていたんですけど、今はfastTextとSCDVという仕組みに移行しています。近傍探索に関しては、以前はNGTを使っていたんですけど、現在はfaissを使っています。

では解説していきます。MobileNetは、たぶんほとんどの方が知っていると思うんですけど、ディープラーニングの中で、CNNを使って画像の特徴量を抽出していくネットワークの一種です。Googleが2、3年ぐらい前に発表したものです。

たいていのディープラーニングのフレームワークを使ったら、MobileNetの事前学習のモデルが用意されていると思うんですけど、我々も事前学習されたモデルをそのまま使っています。Kerasをinclude_top=Falseとやると、特徴量を抽出してきた層のその下に、全結合層でそのカテゴリで分類しています。この全結合層は、なしにして使うこともできます。MobileNetだと、1,024次元の特徴量抽出モデルとして使えます。

テキストに関しては、fastTextを使っています。fastTextは、FacebookがOSSで開発している単語の分散表現学習などができるツールでして、doc vectorも計算できます。ただdoc vectorは、単純にword vectorの平均なので、あまり精度がよくないので、現在ではそれにfastTextで計算した単語を、さらに分散表現を使って、SCDVで計算しています。

この辺りの詳しい仕組みは、ここで解説すると時間が掛かるので、Qiitaに公式のページがあるので、そちらを見てください。

近傍探索で以前使っていたツールはNGTですね。これも、先ほどベンチマークがすごく速いという話がありましたが、私もすごく速いと思います。数百万個の1,024次元ベクトルを登録して、そこからこのベクトルに近い期待値をもってくるのに、数10ミリセックで返ってくる。すごく速いです。ただ、すごくメモリを食いますね(笑)。

1,024次元のベクトルを数百万個詰め込むと、だいたい数十ギガバイトくらいを一気に使うことになるので、これはかなり運用がツライため、現在はfaissを使っています。

こちら(faiss)は、Facebookが作っているOSSの高次元近傍探索ツールです。NGTに比べると、圧縮とかの仕組みが用意されていて便利です。ただ圧縮方法によっては、事前の学習が必要になります。圧縮をフル活用したら、NGTに比べてメモリを1/100くらいまで減らせて、とても便利です。

加えて、これはとても大事だと思うんですけど、ドキュメントが充実しています。GitHubのリポジトリのwikiにいろいろ書いてあるので、すごいありがたく使っています。

類似商品APIの運用

こうしたツールを使って類似商品APIを作っています。その上で実際にどう運用されているかを説明しますと、まず画像の特徴量は事前に計算し、テキストはオンデマンドで計算しています。モデルの更新はデイリー(日次)でやっていて、ECSを利用したマイクロサービスと組み合わせて、APIを提供しています。

もう少し詳しく見ていくと、こちら(スライド)が画像の特徴量を事前計算している動きです。BASEでは、画像を登録したときにS3に保存されます。S3で新しいファイルが保存されたよというイベントをSNSで投げることができますので、SNSで受け取って、SQSで流して、このSQSをECSがポーリングコーディングしています。

ECSは、それを受け取るとS3から画像をダウンロードして、それをSageMakerに対して特徴量を計算してくれと投げます。それで計算された特徴量をS3に保存する、というかたちになっています。これでほぼリアルタイムで画像の特徴量が計算されて、S3に保存されているというかたちになります。

こちらはモデルの更新です。これは先ほどデイリーと言いましたけど、Cloud Watch Rulesのルールで、1日一回イベントが発火しています。Step Functionsが起動されて、Step FunctionsはまずECS Taskを動かします。これはfaissのインデックスを作成取得するのが目的です。

ECS Taskでは、まずRDSからどういう商品をインデックスに入れるのかを選びます。先ほどリアルタイムで計算されてS3に入っているので、その商品の特徴量をここから引っ張ってきます。

テキストに関してはS3ではなくて、ここでオンデマンドで計算しています。これはちょっと、裏にいろいろ事情があります(笑)。

ECSで計算された結果を、またS3に保存します。それが終わったら、Step Functionsは次にLambdaを呼びます。これが、ECSを再起動します。何のECSかと言いますと、faissのインデックスを検索するサービスをECSに立てていまして、この再起動をかけています。

ECSで冗長性を確保していますので、全部が一気に落ちることはありません。そのため、少しずつ変更されていくので、ダウンタイムはないかたちになっています。

faissのインデックスをどうやってAPIで提供しているのか説明します。Data Strategyチームで作った機能は、基本的にAPIで提供しています。このAPIは、まずALBがエンドポイントになって、外から受けています。次にAPIプロキシがいて、そこからまたルーティングされて、それぞれの類似画像の商品APIだったり、類似テキストの商品APIだったりが呼ばれています。

ここは画像とテキストの両方あるんですが、なぜこんなことになっているかは、歴史的経緯があります。

画像とテキスト、類似商品APIの使い分け

実はもともとは類似商品APIは、画像だけでやっていました。ところが画像だけでやっていると、問題が起こったのです。ファッション系では精度がすごくいいんですけど、ファッション以外の食品とかだと、精度が悪くなるんです。例えば日本酒の商品の画像で、その類似商品を出せとやってみたら瓶が似てるので醤油が出てくるんです。

(一同笑)

これは類似を探すのに画像を使っている以上、どうにもならないことなので、なんとかするためにテキストでの類似商品APIというのも作りました。

実はここに書いていないんですけど、商品のカテゴリ推定APIというのがあって、API Proxyでは最初にその商品のカテゴリを推定しています。そして、カテゴリがファッションだったら、画像を優先する処理をしています。カテゴリがファッションでなかったら、テキストを優先するということを、このAPI Proxyでいろいろと小細工して提供しています。

今はファッションとそれ以外で、画像とテキストを使い分けているんですけど、実は画像とテキストを同時に扱う汎用的商品特徴量モデルを作成中です。これを使って、類似商品以外にも、自動カテゴリ分類など、いろいろとやっていきたいと思っています。

ご清聴ありがとうございました。

(会場拍手)