Amazon Web Services ブログ

Amazon SageMaker の因数分解機を使った、ムービーレコメンダーを構築する

レコメンドは機械学習 (ML) の中でも最も一般的なアプリケーションのひとつです。このブログ記事では、因数分解機に基づいた動画レコメンドモデルを構築する方法を紹介します。これは組み込みアルゴリズムのひとつで、Amazon SageMaker の中でもよく使われている MovieLens データセットです。

因数分解機について

因数分解機 (Factorization Machines, FM) は、2010 年に導入された教師あり機械学習技術です ( 研究論文、PDF ) 。FM は、行列因数分解を使うと問題次元数の削減が可能なことから名付けられました。。

FM は分類や回帰に使用でき、線形回帰などの従来のアルゴリズムよりも大規模な疎データセットにおいて、計算効率がより大幅に向上できます。そのため、FM がレコメンドに広く使用されているのです。実際のレコメンドの数は非常に少ないものの ( ユーザーは利用可能なアイテム全てを評価しません )、ユーザー数とアイテム数はとても多いのが普通です。

以下に簡単な例を示します。密なユーザー行列 ( 次元 4×2 ) と密なアイテム行列 (2×4) に、疎な評価行列 ( 次元 4×4) を組み込む場合です。ご覧のように、因数の数 (2) が評価行列 (4) の列数よりも小さいです。さらに、この乗算によって、評価行列の全てのブランク値を埋めることができます。これを利用して、新しいアイテムをどのユーザーにもレコメンドすることができるのです。

出典 : data-artisans.com

この記事では、FM を使用して、ムービーレコメンダーを構築します。Companion Jupyter ノートブックは Amazon S3 または Github からダウンロードできます。

MovieLens データセット

このデータセットは、レコメンド構築のはじめの一歩としてはよいでしょう。いろんなサイズがあります。このブログ記事では、1682 本の映画で 943 人のユーザーから、ml100k : 100,000 の評価を使用します。ご覧のように、ml100kの評価行列は、考えうる 1,586,126 (943*1682) のうち 100,000 の評価しかないので、非常にまばらです ( 正確に言うと、93.6%) 。

データセットの最初の 10 行は次のとおりです。 : ユーザー 754 は映画 595 に 2 つ星の評価を与えました。

ユーザー ID 数、ムービー ID、評価、タイムスタンプ
754         595         2             879452073
932         157         4             891250667
751         100         4             889132252
101         820         3             877136954
606         1277      3             878148493
581         475         4             879641850
13           50           5             882140001
457         59           5             882397575
111         321         3             891680076
123         657         4             879872066

データセットの準備

前で説明したように、FM は高次元のデータセットで最もよく機能します。結果として、ユーザー ID とムービー ID ( タイムスタンプは無視します ) を one-hot エンコードすることになります。したがって、データセットの各サンプルは、ユーザー ID とムービー ID に対して 2 つの値のみを 1 に設定すると、2,625 ブーリアンベクトル (943+1682) になります。

バイナリ ( つまり、好きか好きでないか ) のレコメンダーを構築します。4 つ星と 5 つ星の評価は 1 に設定します。それより低い評価は 0 に設定します。

最後にもうひとつ、Amazon SageMaker の FM 実装では、トレーニングとテストデータを float32 テンソルで、protobuf 形式で保存する必要があります。( 複雑そうですよね。でも Amazon SageMaker SDK にはこうしたことをやってくれる便利なユーティリティ関数があるので、そんなに心配しなくて大丈夫です。 )

ハイレベルビュー

実装するための手順は次のとおりです。

  1. MovieLens トレーニングセットとテストセットをディスクからロードする。
  2. 各セットについて、one-hot エンコードしたデータサンプルがある疎行列を構築する。
  3. 各セットについて、評価があるラベルベクトルを構築する。
  4. 両セットを protobuf でエンコードしたファイルにセットする。
  5. これらのファイルを Amazon S3 バケットにコピーする。
  6. Amazon SageMaker で FM のトレーニングジョブを設定して実行する。
  7. 対応するモデルをエンドポイントにデプロイする。
  8. いくつかの予測を実行する。

やってみましょう。

MovieLens データセットの読み込み

ml-100k には複数のテキストファイルが含まれていますが、ここでは 2 つのファイルを使用してモデルを構築します。

  • ua.base (90,570 個のサンプル ) がトレーニングセットになります。
  • ua.test (9,430 個のサンプル ) がテストセットになります。

どちらのファイルも同じタブ区切り形式です。

  • ユーザー ID (1 〜 943 の整数 )
  • ムービー ID( 1 〜 1682 の整数 )
  • 評価 (1 と 5 の間の整数 )
  • タイムスタンプ ( エポックベースの整数 )

結果として、次のデータ構造を構築することになります。

  • トレーニング疎行列 : 90,570 行と 2,625 列 ( ユーザー ID に 943 の one-hot エンコード機能と、ムービー ID に 1682 の one-hot エンコード機能)
  • トレーニングラベル配列 : 90,570 件の評価
  • テスト疎行列 : 9,430 行と 2,625 列
  • テストラベル配列 : 9,430 件の評価

確認 : 各サンプルは、単一の one-hot エンコード機能ベクトルでなければなりません。ユーザー ID、ムービー ID、および追加する可能性のある機能には、one-hot エンコードした値を連結する必要があります。異なるベクトルのリストを作成するのは (1 つはユーザー ID 用、もう 1 つはムービー ID 用など )正しいやり方ではありません。

このトレーニング行列は今のところ、よりまばらです : 237,746,250 の値 (90,570*2,625) 全てのうち、181,140 だけがゼロではありません (90,570*2) 。言い換えれば、この行列は 99.92% の疎行列です。これを密度が高い行列として保存すると、ストレージとコンピューティング能力を大量に浪費することになります。

これを避けるには、サンプルには scipy.lil_matrix 疎行列、ラベルには Numpy 配列を使います。

クラスあたりのサンプル数がほぼ同じであることを確認しましょう。不均衡なデータセットは、分類子にとって深刻な問題となります。

print(np.count_nonzero(Y_train)/nbRatingsTrain)
0.55
print(np.count_nonzero(Y_test)/nbRatingsTest)
0.58

やや不均衡ですが、まあいいでしょう。次へ進みましょう。

protobuf ファイルへの書き込み

次に、トレーニングセットとテストセットを Amazon S3 に保存してある 2 つの protobuf ファイルに書き出します。幸いにも、write_spmatrix_to_sparse_tensor() ユーティリティ関数に任せることができます。サンプルとラベルを、インメモリ protobuf でエンコードした疎な多次元配列 (AKA テンソル ) に書き込みます。

その後、バッファを Amazon S3 にコミットします。このステップが完了したら、データ準備は完了です。今からトレーニングジョブに取り組みます。

トレーニングのためのトラブルシューティングのヒント

  • サンプルとラベルはどちらも float32 値ですか ?
  • サンプルは疎行列 (Numpy 配列やその他でない ) に保存していますか ?
  • ラベルはベクトル ( どんな種類の行列でもなく ) に保存していますか ?
  • write_spmatrix_to_sparse_tensor() は未定義ですか ?SDK 1.0.2 に追加しているので、Amazon SageMaker SDK をアップグレードする必要があるかもしれません。記事末尾の付録を参照してください。

注 : 最新の Amazon SageMaker SDK へのアップグレード

  1. ノートブックインスタンスを開きます。
  2. インスタンスで、Jupyter ターミナルを開きます。
  3. Conda 環境を有効にし、SDK をアップグレードします。例えば、
source activate python2
pip install -U sagemaker

Amazon S3 でのトレーニングセットは以下の通りです。: 5.5MB 疎行列だけなんて、最高 !

$ aws s3 ls s3://jsimon-sagemaker-us/sagemaker/fm-movielens/train/train.protobuf2018-01-28 16:50:29    5796480 train.protobuf

トレーニングジョブの実行

AWS リージョンで利用可能な FM コンテナを基にしたエスティメーターをまず作成します。それから、FM 特有のハイパーパラメータ ( 全リストはドキュメントの中にあります。 ) をいくつか設定する必要があります。 :

  • feature_dim : 各サンプルの機能数 ( 今回のケースでは 2,625 個) 。
  • predictor_type : ‘ binary_classifier‘ をこれから使用します。
  • num_factors : ユーザーおよびアイテム行列によくある次元 ( 記事の最初にある例で説明しています。 ) 。

ここで使用している他のものは、オプションです ( 説明も必要ないでしょう ) 。

最後に、トレーニングジョブを実行しましょう。fit() API の呼び出しに必要なことは、Amazon S3 でホストするトレーニングとテストセットの両方を通過するだけです。シンプルかつレガントですね。

数分で、トレーニングは完了です。トレーニングログは Jupyter ノートブックか Amazon CloudWatch Logs のどちらかにあるのでチェックしてください。(/ aws / sagemaker / trainingjobs ロググループの中です ) 。

50 エポック後の検査精度は 71.5% で、F1 値 ( バイナリ分類子の典型的なメトリック ) は 0.75 (1 は完全な分類子を示します) となります。すごい値ではありませんが、疎行列と protobuf で興奮したので、ハイパーパラメータをそれほど調整することはしませんでした。もちろん、今回の例より優れた方法で行うことは可能です。

[01/29/2018 13:42:41 INFO 140015814588224] #test_score (algo-1) : binary_classification_accuracy
[01/29/2018 13:42:41 INFO 140015814588224] #test_score (algo-1) : 0.7159
[01/29/2018 13:42:41 INFO 140015814588224] #test_score (algo-1) : binary_classification_cross_entropy
[01/29/2018 13:42:41 INFO 140015814588224] #test_score (algo-1) : 0.581087609863
[01/29/2018 13:42:41 INFO 140015814588224] #test_score (algo-1) : binary_f_1.000
[01/29/2018 13:42:41 INFO 140015814588224] #test_score (algo-1) : 0.74558968389

最後に、モデルのデプロイをカバーします。

モデルのデプロイ

モデルのデプロイに必要なのは、単純な API コールのみです。その昔 (6 か月ほど前 ) には、AWS でもかなりの作業が必要でした。ここでは deploy() を呼び出すだけです。

モデルの HTTP エンドポイントを、predict() API のおかげで、呼び出す準備が整いました。リクエストとレスポンスデータの両方のフォーマットは JSON です。このため、単純なシリアライザを用意して、疎行列サンプルを JSON に変換する必要があります。

これで、どのユーザーのどんな映画でも分類できます。新しいデータセットを作成して、トレーニングおよびテストセットと同じ方法でそれを処理し、predict() 使用して結果を得ます。また、さまざまな予測閾値 ( あるスコアより上の 1 に予測を設定し、その下に 0 を設定する ) を試して、最も効果的なレコメンドをもたらす値を確認してください。MovieLens のデータセットには映画のタイトルも含まれているため、もっといろいろと試してみることができます。

まとめ

組み込みアルゴリズムは、トレーニングコードを書く必要がなく、すばやく作業を完了するのに優れた方法です。かなりのデータ準備が必要ですが、このブログの記事で見たように、非常に大規模なトレーニングジョブを迅速かつスケーラブルにできるところがポイントです。

Amazon SageMaker の組み込みアルゴリズムに関して他にも興味があれば、こちらが過去の関連記事です。:

レコメンドシステムについて、もっと詳しく知りたい方のために、下記にいくつかおもしろいリソースを載せておきます。

いつも、読んでいただきありがとうございます。Twitter で、喜んで質問にお答えします。

AWS の同僚たちが素晴らしいアドバイスとデバッグのヒントをくれました。Sireesha Muppala、Yuri Astashanok、David Arpin、そして Guy Ernest、どうもありがとう。


今回のブログの投稿者について

Julien は EMEA の人工知能およびMachine Learning のエバンジェリストです。彼は、開発者や企業のアイデアを実現させるための支援を中心として活動しています。彼は余暇時間に、JRR Tolkien の作品を何度も読んでいます。