はじめに:レコメンドは大手だけのものではない

「この商品を買った人は、こちらも買っています」。大手ECサイトで当たり前のように出てくる、あのおすすめ表示です。売上を底上げする仕組みとして強力なのですが、「うちみたいな小さなECには関係ない話だろう」と感じている方も多いと思います。

たしかに、レコメンドエンジンというと専用のSaaSを契約したり、機械学習エンジニアを雇ったりというイメージがあります。月額数万円のツールを入れるほどではないけれど、手作業で「関連商品」を一つずつ設定するのも限界がある。そんな中途半端な悩みを抱えている中小ECは少なくないはずです。

ですが、すでに購買履歴や閲覧ログが BigQuery に入っているなら、話は変わります。BigQuery ML を使えば、SQLを数本書くだけで自前のレコメンドエンジンを作れます。新しいツールの契約も、Pythonの環境構築も要りません。本記事では、レコメンドの仕組みの考え方から、モデルの作成、推薦結果の取り出し方、そして外部への配信までを、中小ECの現場目線で順番に見ていきます。

なお、「誰が次に買ってくれそうか」をお客さんごとに当てたい場合は、BigQuery MLでEC顧客の購買予測モデルを構築する記事が向いています。今回は「ある商品やお客さんに対して、何をおすすめするか」を出す話です。目的が少し違うので、合わせて読むと使い分けがイメージしやすいと思います。

レコメンドの方式を整理する

ひとくちにレコメンドといっても、作り方にはいくつか種類があります。ここではまず、今回採用する方式を理解しておきましょう。

協調フィルタリングという考え方

今回使うのは 協調フィルタリング と呼ばれる方式です。難しそうな名前ですが、考え方はシンプルです。

  • 似た買い方をしているお客さん同士は、好みも似ているはず
  • だから「自分と似た人が買っていて、自分はまだ買っていない商品」をおすすめする

「あなたと趣味の合う友達のおすすめ」を、データから自動で見つけてくるイメージです。商品の説明文やカテゴリといった中身の情報を使わず、あくまで「誰が何を買ったか」という行動の履歴だけから関連性を導き出すのが特徴です。商品名や説明をきれいに整備していなくても動かせるので、中小ECにとっては始めやすい方式といえます。

行列分解(MATRIX_FACTORIZATION)

協調フィルタリングを実際に計算する方法として、BigQuery ML には 行列分解(Matrix Factorization) が用意されています。

考え方は、「お客さん × 商品」の巨大な表(マトリックス)を思い浮かべるところから始まります。マス目の中身は「そのお客さんがその商品をどれくらい好きか」です。ただ、実際にはほとんどのマスが空白(まだ買っていない・見ていない)です。行列分解は、この虫食いだらけの表から隠れたパターンを見つけ出し、空白のマスに「たぶんこのくらい好きだろう」という推定値を埋めていく技術です。

BigQuery ML では MATRIX_FACTORIZATION というモデルタイプ一つで、この計算をまるごと引き受けてくれます。私たちがやるのは、学習用のデータを整える部分だけです。

💡 補足 行列分解のモデルは、計算リソースを多めに使う設定が必要になる場合があります。利用には専用スロットの予約(reservation)が前提となるケースがあるため、課金まわりは必ず後述の公式ドキュメント確認の流れで進めてください。「とりあえず試したら高額になっていた」を避けるのがいちばん大事です。

ステップ1:学習データを用意する

行列分解に渡すデータは、突き詰めると次の3列だけです。

  • ユーザーID:誰が
  • アイテムID:どの商品を
  • 評価値(rating):どれくらい好きか

この「評価値」をどう決めるかが、レコメンドの質を左右します。

明示的フィードバックと暗黙的フィードバック

評価値には大きく2種類あります。一つは、星5つのレビューのように、お客さんが自分で「好き」を表明したデータです。これを 明示的フィードバック といいます。正確ですが、中小ECではそもそもレビューが少なく、データが集まりにくいのが難点です。

もう一つは、「買った」「何回も見た」「カートに入れた」といった行動から好みを推測するデータで、暗黙的フィードバック と呼びます。レビューを書いてもらわなくても、日々のログから大量に集まるのが強みです。中小ECでは、こちらを使うのが現実的です。

今回は、注文テーブル orders と閲覧ログ pageviews から、暗黙的フィードバックとして評価値を組み立てます。「買った商品は評価が高い」「何度も見た商品は少し気になっている」という素朴な発想を、数値に落とし込みます。

-- ユーザー × 商品 ごとに「好みの強さ」を評価値として組み立てる
CREATE OR REPLACE TABLE `your_project.ec.reco_training` AS
WITH purchases AS (
  -- 購入は強いシグナル。買った数量を重みにする
  SELECT
    user_id,
    item_id,
    SUM(quantity) * 5 AS purchase_score
  FROM `your_project.ec.orders`
  WHERE order_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 365 DAY)
  GROUP BY user_id, item_id
),
views AS (
  -- 閲覧は弱いシグナル。見た回数を控えめに加点する
  SELECT
    user_id,
    item_id,
    COUNT(*) * 1 AS view_score
  FROM `your_project.ec.pageviews`
  WHERE view_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 365 DAY)
  GROUP BY user_id, item_id
)
SELECT
  COALESCE(p.user_id, v.user_id) AS user_id,
  COALESCE(p.item_id, v.item_id) AS item_id,
  -- 購入スコアと閲覧スコアを合算して評価値にする
  COALESCE(p.purchase_score, 0) + COALESCE(v.view_score, 0) AS rating
FROM purchases AS p
FULL OUTER JOIN views AS v
  USING (user_id, item_id)
WHERE COALESCE(p.user_id, v.user_id) IS NOT NULL;

ここでの重み付け(購入を5倍、閲覧を1倍)は、あくまで出発点の一例です。扱う商材によって、閲覧がどれだけ購買につながるかは大きく変わります。最初はシンプルに始めて、結果を見ながら調整していくのがおすすめです。

ステップ2:モデルを作成する

学習データができたら、いよいよモデルを作ります。CREATE MODEL 文でモデルタイプに MATRIX_FACTORIZATION を指定し、どの列がユーザー・アイテム・評価値なのかを伝えるだけです。

-- 行列分解でレコメンドモデルを学習する
CREATE OR REPLACE MODEL `your_project.ec.reco_model`
OPTIONS (
  model_type = 'MATRIX_FACTORIZATION',
  user_col = 'user_id',
  item_col = 'item_id',
  rating_col = 'rating',
  -- 暗黙的フィードバックを使う場合は 'IMPLICIT' を指定する
  feedback_type = 'IMPLICIT'
) AS
SELECT
  user_id,
  item_id,
  rating
FROM `your_project.ec.reco_training`;

ポイントは feedback_type です。今回のように「買った・見た」という行動から評価値を作った場合は IMPLICIT(暗黙的)を指定します。星評価のような明示的なデータなら EXPLICIT を使います。ここを取り違えると、モデルの解釈がずれてしまうので注意してください。

学習にかかる時間とコストは、ユーザー数と商品数、そして組み合わせの数に応じて増えていきます。最初から全期間・全商品で回すのではなく、直近1年・主力商品など範囲を絞って試し、感触をつかんでから広げるのが安全です。

ステップ3:ML.RECOMMENDで推薦を取り出す

モデルができたら、ML.RECOMMEND を使って「誰に・何を・どれくらいの強さでおすすめするか」を取り出します。出力は、ユーザーと商品の組み合わせごとに、好みの強さの予測値が並んだ表です。予測値の列名は rating_col に指定した列名から決まり、今回のように rating 列を使った場合は predicted_rating_confidence という列名になります(出力列名や構文はバージョンで変わることがあるため、最新の仕様は公式ドキュメントで確認してください)。

特定のお客さんに対するおすすめ上位を出すなら、こう書きます。

-- 指定したユーザーへのおすすめ商品 上位10件を取り出す
SELECT
  user_id,
  item_id,
  predicted_rating_confidence
FROM ML.RECOMMEND(
  MODEL `your_project.ec.reco_model`,
  (SELECT 'user_12345' AS user_id)
)
ORDER BY predicted_rating_confidence DESC
LIMIT 10;

全ユーザー分をまとめて出して、各ユーザーの上位N件だけを残したい場合は、ウィンドウ関数で順位を付けて絞り込みます。

-- 全ユーザーについて、おすすめ上位5件ずつをテーブルに保存する
CREATE OR REPLACE TABLE `your_project.ec.reco_results` AS
WITH ranked AS (
  SELECT
    user_id,
    item_id,
    predicted_rating_confidence,
    ROW_NUMBER() OVER (
      PARTITION BY user_id
      ORDER BY predicted_rating_confidence DESC
    ) AS rank
  FROM ML.RECOMMEND(MODEL `your_project.ec.reco_model`)
)
SELECT
  user_id,
  item_id,
  predicted_rating_confidence,
  rank
FROM ranked
WHERE rank <= 5;

この結果テーブルが、レコメンドエンジンの「成果物」です。あとはこれをサイトやメールに反映していけば、おすすめ表示が動き出します。

なお、おすすめの中に「すでに買った商品」や「在庫切れの商品」が混ざることがあります。実運用では、注文済みの商品を除外したり、在庫テーブルと突き合わせて表示可能なものだけに絞ったりする後処理を入れておくと、お客さんの体験が一段良くなります。在庫の動きと絡めた分析については、GA4とBigQueryでEC在庫回転率と死蔵在庫を可視化する記事も参考になります。

結果をどう活かすか:Vertex AIや外部配信への展開

レコメンド結果のテーブルができたら、それを実際の接客につなげていきます。やり方はいくつか段階があります。

いちばん手軽なのは、結果テーブルを定期的に更新し、サイト側やメール配信ツールから参照する形です。スケジュールクエリで毎晩 reco_results を作り直しておけば、最新の行動を反映したおすすめを各ページやメルマガに差し込めます。中小ECなら、まずはここから始めるだけで十分に効果を体感できるはずです。

もう一歩進めて、リアルタイムに近い形でおすすめを返したくなったら、Vertex AI へ展開する道があります。BigQuery ML で作ったモデルは Vertex AI 側に登録(エクスポート)して、オンラインで推論を返すエンドポイントとして使える仕組みが用意されています。「お客さんがページを開いた瞬間に、その場でおすすめを計算して返す」といった使い方に向きますが、その分だけ運用の手間とコストは増えます。

最初からリアルタイム配信を狙う必要はありません。まずはバッチで結果テーブルを作り、効果が確認できてからリアルタイム化やVertex AIへの展開を検討する、という順序が現実的です。

⚠️ 進める前の注意点

実際に手を動かす前に、いくつか気をつけておきたい点があります。

構文や課金の最新情報は、必ず公式で確認してください。 BigQuery ML の MATRIX_FACTORIZATION は、オプション名や料金体系、スロット予約の要否などが更新されることがあります。とくに行列分解は計算リソースの扱いが他のモデルと異なる場合があるため、本記事のSQLはあくまで考え方を示すサンプルとして扱い、実行前に Google Cloud の公式ドキュメント で現在の仕様と料金を確かめてください。

暗黙的フィードバックには独特の注意点があります。 「見た・買った」という行動は「好き」を意味するとは限りません。たとえば、間違ってクリックしただけ、比較のために何度も見ただけ、ということもあります。また「買わなかった=嫌い」とも言い切れません(単に知らなかっただけかもしれません)。暗黙的フィードバックは、こうした曖昧さを含んだまま学習する点を理解しておくことが大切です。重み付けやノイズの除き方を一度で決めようとせず、結果を見ながら少しずつ調整していくのが、遠回りに見えて確実です。

精度の数字は、実データで測ってください。 本記事では具体的な精度や売上改善率の数値は挙げていません。レコメンドの効き目は、商材・客層・商品点数によって大きく変わるからです。もし他の記事や資料で「導入で売上◯◯%アップ」といった数字を見かけても、それはその環境での一例にすぎません。自分のECで効いているかどうかは、おすすめ経由のクリック率や購入率を計測して判断するのが唯一の確実な方法です。

まとめ

レコメンドエンジンは、もはや大手だけの専有物ではありません。購買・閲覧データが BigQuery に入っていれば、中小ECでも自前で組める時代になりました。

本記事の流れを振り返ると、次のようになります。

  • レコメンドの方式として、行動履歴だけで動く 協調フィルタリング(行列分解) を選んだ
  • 注文と閲覧のログから、暗黙的フィードバックとして評価値を組み立てた
  • CREATE MODELMATRIX_FACTORIZATION モデルを学習した
  • ML.RECOMMEND でお客さんごとのおすすめを取り出し、結果テーブルに保存した
  • まずはバッチ配信から始め、必要に応じて Vertex AI でのリアルタイム化を検討する

大切なのは、最初から完璧を目指さないことです。直近1年・主力商品という小さな範囲で一度回してみて、「自分でもおすすめが作れた」という手応えを得るところから始めてみてください。重み付けの調整や除外処理、効果測定は、動くものができてからゆっくり育てていけば十分です。SQLが書ける環境さえあれば、レコメンドは思っているよりずっと身近なところにあります。