BigQuery ML を使用して映画の評価に基づきレコメンデーションを行う


このチュートリアルでは、データ アナリストを対象に BigQuery ML の行列分解モデルを紹介します。BigQuery ML を使用すると、BigQuery で SQL クエリを使用して機械学習モデルを作成して実行できます。このチュートリアルは、SQL のユーザーが簡単に機械学習を利用できるようにすることを目標としています。使い慣れたツールを使用してモデルを構築でき、データを移動する必要もないため、開発スピードを向上させることができます。

このチュートリアルでは、movielens1m データセットを使用して明示的なフィードバックからモデルを作成し、映画 ID とユーザー ID を指定してレコメンデーションを行う方法を学びます。

MovieLens のデータセットには、ユーザーが映画に付けた 1~5 のスケールの評価と、映画のジャンルなどのメタデータが含まれています。

目標

このチュートリアルでは、次のものを使用します。

  • BigQuery ML。CREATE MODEL ステートメントを使用して明示的なレコメンデーション モデルを作成します。
  • ML.EVALUATE 関数。ML モデルを評価します。
  • ML.WEIGHTS 関数。トレーニング中に生成された潜在因子の重みを調査します。
  • ML.RECOMMEND 関数。ユーザー向けにレコメンデーションを生成します。

費用

このチュートリアルでは、Google Cloud の課金対象となる次のコンポーネントを使用します。

  • BigQuery
  • BigQuery ML

BigQuery の費用の詳細については、BigQuery の料金ページをご覧ください。

BigQuery ML の費用の詳細については、BigQuery ML の料金をご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  5. Google Cloud プロジェクトで課金が有効になっていることを確認します

  6. 新しいプロジェクトでは、BigQuery が自動的に有効になります。既存のプロジェクトで BigQuery を有効にするには、

    BigQuery API を有効にします。

    API を有効にする

    にアクセスします。

ステップ 1: データセットを作成する

ML モデルを保存する BigQuery データセットを作成します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] ページに移動

  2. [エクスプローラ] ペインで、プロジェクト名をクリックします。

  3. [アクションを表示] > [データセットを作成] をクリックします。

    データセットを作成する。

  4. [データセットの作成] ページで、次の操作を行います。

    • [データセット ID] に「bqml_tutorial」と入力します。

    • [ロケーション タイプ] で [マルチリージョン] を選択してから、[US(multiple regions in United States)] を選択します。

      一般公開データセットは US マルチリージョンに保存されています。わかりやすくするため、データセットを同じロケーションに保存します。

    • 残りのデフォルトの設定は変更せず、[データセットを作成] をクリックします。

      データセットの作成ページ。

ステップ 2: MovieLens のデータセットを BigQuery に読み込む

BigQuery コマンドライン ツールを使用して、1m MovieLens データセットを BigQuery に読み込む手順は次のとおりです。movielens というデータセットが作成され、関連する movielens テーブルがデータセットに保存されます。

curl -O 'http://files.grouplens.org/datasets/movielens/ml-1m.zip'
unzip ml-1m.zip
bq mk --dataset movielens
sed 's/::/,/g' ml-1m/ratings.dat > ratings.csv
bq load --source_format=CSV movielens.movielens_1m ratings.csv \
  user_id:INT64,item_id:INT64,rating:FLOAT64,timestamp:TIMESTAMP

映画のタイトルにコロン、カンマ、パイプが含まれているため、別の区切り文字を使用する必要があります。映画のタイトルを読み込むには、最後の 2 つのコマンドの少し異なるバリアントを使用する必要があります。

sed 's/::/@/g' ml-1m/movies.dat > movie_titles.csv
bq load --source_format=CSV --field_delimiter=@ \
 movielens.movie_titles movie_titles.csv \
 movie_id:INT64,movie_title:STRING,genre:STRING

ステップ 3: 明示的なレコメンデーション モデルを作成する

次に、前のステップで読み込んだ movielens のサンプル テーブルを使用して、明示的なレコメンデーション モデルを作成します。次の GoogleSQL クエリを使用して、すべてのユーザー - アイテム ペアの評価を予測するためのモデルを作成します。

#standardSQL
CREATE OR REPLACE MODEL `bqml_tutorial.my_explicit_mf_model`
OPTIONS
  (model_type='matrix_factorization',
   user_col='user_id',
   item_col='item_id',
   l2_reg=9.83,
   num_factors=34) AS
SELECT
  user_id,
  item_id,
  rating
FROM `movielens.movielens_1m`

CREATE MODEL コマンドはモデルを作成するとともに、作成したモデルのトレーニングも行います。

クエリの詳細

CREATE MODEL 句は、bqml_tutorial.my_explicit_mf_model という名前のモデルを作成し、トレーニングするために使用されます。

OPTIONS(model_type='matrix_factorization', user_col='user_id', ...) 句は、行列分解モデルを作成していることを示します。デフォルトでは、feedback_type='IMPLICIT' が指定されていない限り、明示的な行列分解モデルが作成されます。暗黙的な行列分解モデルの作成方法の例については、BigQuery ML を使用した暗黙的なフィードバックの推奨事項をご覧ください。

このクエリの SELECT ステートメントは、次の列を使用してレコメンデーションを生成します。

  • user_id - ユーザー ID(INT64)。
  • item_id - 映画 ID(INT64)。
  • rating - user_iditem_id に与えた 1~5 の明示的な評価。(FLOAT64)。

FROM 句(movielens.movielens_1m)は、movielens データセットの movielens_1m テーブルにクエリを実行していることを示しています。ステップ 2 の手順を行っている場合は、このデータセットは BigQuery プロジェクトにあります。

CREATE MODEL クエリを実行する

モデルを作成してトレーニングする CREATE MODEL クエリを実行するには:

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、次の GoogleSQL クエリを入力します。

#standardSQL
CREATE OR REPLACE MODEL `bqml_tutorial.my_explicit_mf_model`
OPTIONS
  (model_type='matrix_factorization',
   user_col='user_id',
   item_col='item_id',
   l2_reg=9.83,
   num_factors=34) AS
SELECT
  user_id,
  item_id,
  rating
FROM `movielens.movielens_1m`
  1. [実行] をクリックします。

    クエリが完了するまでに約 10 分かかります。完了後、モデル(my_explicit_mf_model)が Google Cloud コンソールのナビゲーション パネルに表示されます。クエリは CREATE MODEL ステートメントを使用してモデルを作成するため、クエリの結果は表示されません。

ステップ 4(省略可): トレーニングの統計情報を取得する

モデルのトレーニング結果を確認するには、ML.TRAINING_INFO 関数を使用するか、Google Cloud コンソールで統計情報を表示します。このチュートリアルでは、Google Cloud コンソールを使用します。

機械学習アルゴリズムは、多くのサンプルを検査し、損失を最小限に抑えるモデルを見つけることでモデルを構築します。このプロセスを経験損失最小化と呼びます。

CREATE MODEL クエリで生成したモデルのトレーニング統計を確認するには:

  1. Google Cloud コンソールのナビゲーション パネルの [リソース] セクションで、[PROJECT_ID] > [bqml_tutorial] を開き、[my_explicit_mf_model] をクリックします。

  2. [トレーニング] タブをクリックしてから、[テーブル] をクリックします。結果は次のようになります。

    ML.TRAINING_INFO の出力。

    [トレーニング データの損失] 列は、トレーニング データセットでモデルのトレーニングを行った後に計算された損失指標を表します。行列分解を実行したため、この列は平均二乗誤差になります。データを分割するとユーザーやアイテムの評価をすべて失う可能性があるため、デフォルトでは、行列分解モデルはデータ分割を行いません。そのため、ホールドアウト データセットを指定しない限り [評価データの損失] 列は存在しません。その結果、欠落しているユーザーやアイテムに関する潜在因子の情報はモデルに含まれなくなります。

    ML.TRAINING_INFO 関数の詳細については、BigQuery ML 構文リファレンスをご覧ください。

ステップ 5: モデルを評価する

モデルを作成したら、ML.EVALUATE 関数を使用して評価者のパフォーマンスを評価します。ML.EVALUATE 関数は、実際の評価に対する予測評価を評価します。

モデルの評価に使用するクエリは次のとおりです。

#standardSQL
SELECT
  *
FROM
  ML.EVALUATE(MODEL `bqml_tutorial.my_explicit_mf_model`,
    (
    SELECT
      user_id,
      item_id,
      rating
     FROM
      `movielens.movielens_1m`))

クエリの詳細

先頭の SELECT ステートメントで、モデルから列を取得します。

FROM 句で、モデル bqml_tutorial.my_explicit_mf_model に対して ML.EVALUATE 関数を使用します。

このクエリでネストしている SELECT ステートメントと FROM 句は CREATE MODEL クエリと同じです。

また、入力データを指定せずに ML.EVALUATE を呼び出すこともできます。これはトレーニングで計算された評価指標を使用します。

#standardSQL
SELECT
  *
FROM
  ML.EVALUATE(MODEL `bqml_tutorial.my_explicit_mf_model`)

ML.EVALUATE クエリを実行する

モデルを評価する ML.EVALUATE クエリを実行するには:

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. クエリエディタのテキスト領域に、次の GoogleSQL クエリを入力します。

    #standardSQL
    SELECT
    *
    FROM
    ML.EVALUATE(MODEL `bqml_tutorial.my_explicit_mf_model`,
      (
      SELECT
    user_id,
    item_id,
    rating
       FROM
    `movielens.movielens_1m`))
    
  3. (省略可)処理を行うロケーションを設定するには、[展開] > [クエリ設定] をクリックします。[処理を行うロケーション] には US を選択します。処理を行うロケーションはデータセットのロケーションに基づいて自動的に検出されるため、この手順は省略できます。

    クエリの設定

  4. [実行] をクリックします。

  5. クエリが完了したら、クエリテキスト領域の下にある [結果] タブをクリックします。結果は次のようになります。

    ML.EVALUATE の出力。

    明示的な行列分解を実行したため、結果には次の列が含まれます。

    • mean_absolute_error
    • mean_squared_error
    • mean_squared_log_error
    • median_absolute_error
    • r2_score
    • explained_variance

評価結果における重要な測定指標は、R2 スコアです。R2 スコアは、線形回帰予測が実際のデータに近似するかどうかを決定する統計的尺度です。0 は、平均値周辺のレスポンス データにばらつきがないことを示しています。1 は、平均値周辺のレスポンス データにばらつきがあることを示しています。

ステップ 6: モデルを使用して評価を予測し、レコメンデーションを行う

一連のユーザーのアイテム評価をすべて確認する

ML.RECOMMEND は、モデル以外に引数を追加で受け取る必要はありませんが、オプションのテーブルを受け取ることができます。入力テーブルに入力 user 列または入力 item 列の名前と一致する列が 1 つしかない場合、各 user の予測アイテム評価がすべて出力されます。逆もまた同様です。すべての users またはすべての items が入力テーブルにある場合、オプションの引数を ML.RECOMMEND に渡さない場合と同じ結果が出力されます。

次の例は、5 人のユーザーのすべての映画評価を取得するクエリの例です。

#standardSQL
SELECT
  *
FROM
  ML.RECOMMEND(MODEL `bqml_tutorial.my_explicit_mf_model`,
    (
    SELECT
      user_id
    FROM
      `movielens.movielens_1m`
    LIMIT 5))

クエリの詳細

一番上の SELECT ステートメントは、useritempredicted_rating 列を取得します。この最後の列は ML.RECOMMEND 関数によって生成されます。ML.RECOMMEND 関数を使用した場合は、モデルの出力列名は predicted_<rating_column_name> です。明示的な行列分解モデルの場合、predicted_ratingrating の推定値です。

ML.RECOMMEND 関数は、モデル bqml_tutorial.my_explicit_mf_model を使用して評価を予測するために使用されます。

このクエリでネストしている SELECT ステートメントは、トレーニングに使用される元のテーブルから user_id 列のみを選択します。

LIMIT 句(LIMIT 5)は、ML.RECOMMEND に送信する 5 つの user_id をランダムに除外します。

すべてのユーザー - アイテム ペアの評価を確認する

モデルを評価したら、次のステップではモデルを使用して評価を予測します。モデルを使用して、すべてのユーザーとアイテムの組み合わせの評価を次のクエリで予測します。

#standardSQL
SELECT
  *
FROM
  ML.RECOMMEND(MODEL `bqml_tutorial.my_explicit_mf_model`)

クエリの詳細

一番上の SELECT ステートメントは、useritempredicted_rating 列を取得します。この最後の列は ML.RECOMMEND 関数によって生成されます。ML.RECOMMEND 関数を使用した場合は、モデルの出力列名は predicted_<rating_column_name> です。明示的な行列分解モデルの場合、predicted_ratingrating の推定値です。

ML.RECOMMEND 関数は、モデル bqml_tutorial.my_explicit_mf_model を使用して評価を予測するために使用されます。

結果をテーブルに保存する方法の 1 つは次のとおりです。

#standardSQL
CREATE OR REPLACE TABLE `bqml_tutorial.recommend_1m`
OPTIONS() AS
SELECT
  *
FROM
  ML.RECOMMEND(MODEL `bqml_tutorial.my_explicit_mf_model`)

ML.RECOMMENDQuery Exceeded Resource Limits エラーが発生した場合は、上位の課金階層で再試行してください。BigQuery コマンドライン ツールでは、フラグ --maximum_billing_tier を使用して設定できます。

レコメンデーションを生成する

前のレコメンデーション クエリを使用して、予測された評価で並べ替えを行い、ユーザーごとの上位予測アイテムを出力できます。次のクエリでは、item_ids を先ほどアップロードした movielens.movie_titles テーブルにある movie_ids と結合し、ユーザーごとに上位 5 つのおすすめ映画を出力します。

#standardSQL
SELECT
  user_id,
  ARRAY_AGG(STRUCT(movie_title, genre, predicted_rating)
ORDER BY predicted_rating DESC LIMIT 5)
FROM (
SELECT
  user_id,
  item_id,
  predicted_rating,
  movie_title,
  genre
FROM
  `bqml_tutorial.recommend_1m`
JOIN
  `movielens.movie_titles`
ON
  item_id = movie_id)
GROUP BY
  user_id

クエリの詳細

内部 SELECT ステートメントは、レコメンデーション結果テーブルの item_idmovielens.movie_titles テーブルの movie_id に対して内部結合を行います。movielens.movie_titles は、movie_id を映画のタイトルにマッピングするだけでなく、IMDB がリストする映画のジャンルも含みます。

最上位の SELECT ステートメントは、GROUPS BY user_id を使用してネストされた SELECT ステートメントの結果を集計し、movie_title, genre,predicted_rating を降順で集計して上位 5 つの映画のみ保持します。

ML.RECOMMEND クエリを実行する

ML.RECOMMEND クエリを実行して、ユーザーごとにおすすめの映画上位 5 つを出力するには:

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、次の GoogleSQL クエリを入力します。

    #standardSQL
    CREATE OR REPLACE TABLE `bqml_tutorial.recommend_1m`
    OPTIONS() AS
    SELECT
    *
    FROM
    ML.RECOMMEND(MODEL `bqml_tutorial.my_explicit_mf_model`)
    
  3. [実行] をクリックします。

    クエリが完了すると、bqml_tutorial.recommend_1m がナビゲーション パネルに表示されます。クエリは CREATE TABLE ステートメントを使用してテーブルを作成するため、クエリ結果は表示されません。

  4. 新しいクエリをもう 1 つ作成します。前のクエリの実行が完了したら、[クエリエディタ] のテキスト領域に次の GoogleSQL クエリを入力します。

    #standardSQL
    SELECT
     user_id,
     ARRAY_AGG(STRUCT(movie_title, genre, predicted_rating)
    ORDER BY predicted_rating DESC LIMIT 5)
    FROM (
    SELECT
     user_id,
     item_id,
     predicted_rating,
     movie_title,
     genre
    FROM
     `bqml_tutorial.recommend_1m`
    JOIN
     `movielens.movie_titles`
    ON
     item_id = movie_id)
    GROUP BY
     user_id
    
  5. (省略可)処理を行うロケーションを設定するには、[展開] > [クエリ設定] をクリックします。[処理を行うロケーション] には US を選択します。処理を行うロケーションはデータセットのロケーションに基づいて自動的に検出されるため、この手順は省略できます。

    クエリの設定

  6. [実行] をクリックします。

  7. クエリが完了したら、クエリテキスト領域の下にある [結果] タブをクリックします。結果は次のようになります。

    ML.RECOMMEND の出力

movie_id のメタデータ情報は INT64 以外もあるため、ユーザーごとのおすすめの映画上位 5 つに関する情報などを確認できます。movietitles と同等なトレーニング データのテーブルがない場合、結果は数値 ID またはハッシュだけで表示されるため、人による解釈が困難なものになることがあります。

因子別上位ジャンル

各潜在因子が関連していると思われるジャンルを知るには、次のクエリを実行できます。

#standardSQL
SELECT
  factor,
  ARRAY_AGG(STRUCT(feature, genre,
      weight)
  ORDER BY
    weight DESC
  LIMIT
    10) AS weights
FROM (
  SELECT
    * EXCEPT(factor_weights)
  FROM (
    SELECT
      *
    FROM (
      SELECT
        factor_weights,
        CAST(feature AS INT64) as feature
      FROM
        ML.WEIGHTS(model `bqml_tutorial.my_explicit_mf_model`)
      WHERE
        processed_input= 'item_id')
    JOIN
      `movielens.movie_titles`
    ON
      feature = movie_id) weights
  CROSS JOIN
    UNNEST(weights.factor_weights)
  ORDER BY
    feature,
    weight DESC)
GROUP BY
  factor

クエリの詳細

最も内部にある SELECT ステートメントは、item_id または映画の因子重み配列を取得し、movielens.movie_titles テーブルと結合して各アイテム ID のジャンルを取得します。

結果は各 factor_weights 配列と CROSS JOIN され、次に ORDER BY feature, weight DESC されます。

最後に、最上位の SELECT ステートメントは、factor 別に内部ステートメントの結果を集計し、各ジャンルの重み別に並べ替えた各因子の配列を作成します。

クエリの実行

上記のクエリを実行して、因子ごとに上位 10 の映画ジャンルを出力するには:

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. クエリエディタのテキスト領域に、次の GoogleSQL クエリを入力します。

#standardSQL
SELECT
  factor,
  ARRAY_AGG(STRUCT(feature, genre,
      weight)
  ORDER BY
    weight DESC
  LIMIT
    10) AS weights
FROM (
  SELECT
    * EXCEPT(factor_weights)
  FROM (
    SELECT
      *
    FROM (
      SELECT
        factor_weights,
        CAST(feature AS INT64) as feature
      FROM
        ML.WEIGHTS(model `bqml_tutorial.my_explicit_mf_model`)
      WHERE
        processed_input= 'item_id')
    JOIN
      `movielens.movie_titles`
    ON
      feature = movie_id) weights
  CROSS JOIN
    UNNEST(weights.factor_weights)
  ORDER BY
    feature,
    weight DESC)
GROUP BY
  factor
  1. (省略可)処理を行うロケーションを設定するには、[展開] > [クエリ設定] をクリックします。[処理を行うロケーション] には US を選択します。処理を行うロケーションはデータセットのロケーションに基づいて自動的に検出されるため、この手順は省略できます。

    クエリの設定

  2. [実行] をクリックします。

  3. クエリが完了したら、クエリテキスト領域の下にある [結果] タブをクリックします。結果は次のようになります。

    重み分析

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

  • 作成したプロジェクトを削除する。
  • または、プロジェクトを保存して、データセットを削除する。

データセットを削除する

プロジェクトを削除すると、プロジェクト内のデータセットとテーブルがすべて削除されます。プロジェクトを再利用する場合は、このチュートリアルで作成したデータセットを削除できます。

  1. 必要に応じて、Google Cloud コンソールで [BigQuery] ページを開きます。

    [BigQuery] ページに移動

  2. ナビゲーションで、作成した bqml_tutorial データセットをクリックします。

  3. ウィンドウの右側にある [データセットを削除] をクリックします。この操作を行うと、データセット、テーブル、すべてのデータが削除されます。

  4. [データセットの削除] ダイアログ ボックスでデータセットの名前(bqml_tutorial)を入力して、[削除] をクリックします。

プロジェクトを削除する

プロジェクトを削除するには:

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ