- 1 1. 応用ML(マネージドML)の本番課題とAmazon Personalizeの全体像
- 2 2. Amazon Personalize 基礎 — レシピ・データセットグループ・キャンペーン
- 3 3. 実装・運用 — リアルタイム推薦API・再学習・A-Bテスト
- 4 4. 精度評価・チューニング
- 5 5. 統合・MLOps連携
- 6 6. コスト・スケール運用
- 7 7. 実戦統合パターン — 既存ML/AIとの使い分け・組合せ
- 8 8. つまずきポイント・アンチパターン・まとめ
1. 応用ML(マネージドML)の本番課題とAmazon Personalizeの全体像

推薦エンジンは、現代のデジタルビジネスにおいて売上と継続率を直接左右する基盤技術です。Amazonの自社データでは、推薦機能がサイト全体の売上の35%以上を占めるとされており、NetflixではコンテンツのWatch時間のうち80%以上が推薦エンジン経由といわれています。ECサイト・メディアプラットフォーム・動画配信・音楽ストリーミングのいずれにおいても、「あなたへのおすすめ」の精度が滞在時間・購入率・継続率を左右するため、推薦エンジンは今やデジタルプロダクトの根幹インフラと位置づけられています。
推薦エンジンを自前で構築するコスト
推薦システムを自前で構築するには、複数のフェーズにわたる開発・運用コストが生じます。
データ基盤の整備
ユーザーの行動ログ(クリック・購入・閲覧・評価)を収集・蓄積するパイプラインを設計し、リアルタイムストリーム処理とバッチETLの両方を整備する必要があります。データ品質管理(重複・欠損・ノイズ除去)やスキーマ変更への対応も継続的な運用負荷となります。
モデル構築と学習インフラ
協調フィルタリング・行列分解・深層学習ベースの推薦モデルを選定し、学習コードを実装します。ハイパーパラメータチューニング・モデルのバージョン管理・A-Bテスト基盤の整備など、MLエンジニアリングの専門知識が不可欠です。GPUを含む学習インフラのコストも無視できません。
本番デプロイと継続的運用
学習済みモデルを低レイテンシで推論できるエンドポイントにデプロイし、トラフィック増加への自動スケーリング・モデルのドリフト監視・定期的な再学習パイプラインを整備します。これらをゼロから自前構築すると、MLエンジニアが数ヶ月かけて基盤を作り込む必要があり、コアビジネスへの投資機会を逃しやすくなります。
推薦エンジンの構築・運用に必要な一連の工程を、Amazonのマネージドサービスとしてパッケージ化したのがAmazon Personalizeです。
Amazon Personalizeとは — ターンキーML推薦エンジン
Amazon Personalizeは、Amazonが自社のショッピングサービスで長年培った推薦技術を、マネージドサービスとして一般公開したターンキーML(Turnkey Machine Learning)です。
「ターンキー」とは「鍵を回すだけで動く」という意味で、機械学習モデルの自前構築・トレーニングインフラの管理・アルゴリズムの実装が不要なことを指します。利用者が行う作業は次の3つだけです。
- データを準備してS3に置く — Users(ユーザー属性)・Items(アイテム属性)・Interactions(行動ログ)の3種のCSVを用意します
- レシピ(推薦アルゴリズム)を選択する — 用途に合わせたプリセットアルゴリズムを選択します
- 推薦APIを呼び出す — GetRecommendations APIでリアルタイム推薦結果を取得します
この3ステップで、数日以内に本番品質の推薦エンジンを稼働させられます。SageMakerで自前モデルを構築する場合と比較して、数週間〜数ヶ月のデプロイまでの期間を大幅に短縮できます。
Personalizeが向いているユースケースは明確です。「ユーザーへのアイテム推薦・ランキング・類似アイテム提示」という推薦タスクであれば、まずPersonalizeを検討するのが合理的です。推薦アルゴリズムのカスタマイズ要件が少なく、短期間でMVPを立ち上げたいチームにとって、最も速く安全な選択肢です。
Amazon PersonalizeとSageMaker・Bedrock・タスク特化AIの使い分け
AWSのML/AIサービスは役割が明確に異なります。どのサービスを選ぶかは「何の課題を解くか」によって決まります。
SageMaker — 自前MLモデルの構築・トレーニング・MLOps
SageMakerは、MLエンジニアによる独自アルゴリズムの実装から、トレーニング・評価・デプロイの全ライフサイクルを管理するプラットフォームです。特徴量エンジニアリングの自由度が高く、推薦以外のあらゆるMLタスク(不正検知・需要予測・画像分類等)に対応できます。ただし、データパイプラインからモデル実装・MLOpsインフラの構築まで、利用者自身で設計・実装する必要があります。柔軟性は高い反面、構築コストも相応にかかる点がSageMakerの特徴です。
SageMakerが向いているケースは、Personalizeの提供するレシピでは対応できない複雑な推薦ロジックが必要な場合、独自の特徴量エンジニアリングが不可欠な場合、または大規模グラフデータ(ソーシャルグラフ等)を用いた推薦が必要な場合です。一般的な成長パスとして、PersonalizeでターンキーのMVP推薦を本番化し、ビジネスの成長に伴い精度要件が高まった段階でSageMakerへ移行する段階的アプローチが推奨されています。
Amazon Bedrock — 基盤モデルによる生成AI
Bedrockは、Claude・Llama・Titanなどの基盤モデル(Foundation Model)をAPIで利用できる生成AIプラットフォームです。テキスト生成・要約・翻訳・対話・コード生成など、自然言語生成に特化しています。ファインチューニングやRAG構成でのカスタマイズも可能ですが、「推薦」という特定の課題に対しては、Personalizeの方が推薦精度・開発速度ともに優位です。
なお、Amazon PersonalizeとBedrockは組み合わせて活用できます。Personalizeが「何を推薦するか」を担い、Bedrockが「なぜこの商品をお勧めするか」という推薦理由の自然言語生成を補完するハイブリッドパターンが有効です(§7参照)。
タスク特化AI — 抽出・分類・認識・文字起こし
Amazon Textract(文書テキスト抽出)・Amazon Comprehend(自然言語処理・分類・感情分析)・Amazon Rekognition(画像・動画の物体認識)・Amazon Transcribe(音声文字起こし)などのタスク特化AIは、特定の入力(文書・画像・音声)から情報を抽出・分類・認識するサービスです。推薦エンジンとは役割が異なりますが、Comprehendで商品説明文を分類してPersonalizeのItems属性として充当するなど、Personalizeと組み合わせることでコールドスタート対応力を強化できます(§7参照)。
Amazon Personalize — 推薦のターンキーML(本記事)
PersonalizeはML/AIサービスの中で「推薦という特定タスクをモデル構築なしで解く」ターンキーMLとして位置づけられます。
| サービス | 課題の種類 | 主な特徴 |
|---|---|---|
| Amazon Personalize | 推薦・パーソナライゼーション | ターンキーML・モデル構築不要(本記事) |
| SageMaker | 自前MLモデル構築・MLOps | 柔軟だが構築コスト高 |
| Amazon Bedrock | 生成・要約・対話・説明文 | 基盤モデルAPIで即時利用 |
| タスク特化AI | 抽出・分類・認識・文字起こし | Textract/Comprehend/Rekognition等 |
| SageMaker Canvas | 需要予測・時系列予測 | Forecast新規受付停止のため代替として推奨 |
★Amazon Forecastは新規受付を停止しています。需要予測が必要な場合は、SageMaker Canvasの時系列予測機能を代替としてご検討ください。本記事では需要予測に関してはSageMaker Canvasを1文で案内するにとどめ、主題はPersonalizeに集中します。
Amazon Personalizeの全体フロー
Amazon Personalizeは「データセットグループ→ソリューション→キャンペーン→推薦API」という一貫したパイプラインで構成されています。fig01に示すアーキテクチャを参照しながら各ステップを確認してください。
ステップ1: データセットグループの作成とデータ取込
まず、ユースケース単位でデータセットグループを作成します。1つのデータセットグループには以下の3種のデータセットを格納します。
- Interactionsデータセット — ユーザーがアイテムに対して行った行動ログ。クリック・購入・視聴・評価などのイベントを格納します。このデータが推薦精度の核心です
- Itemsデータセット — 推薦対象のアイテムのメタデータ。商品カテゴリ・価格帯・公開日などを格納します
- Usersデータセット — ユーザーのメタデータ。年齢層・会員ランクなどを格納します(任意)
データはS3に配置したCSVをデータセットインポートジョブで取り込みます。データセットグループはユースケース単位で作成するため、ECの商品推薦と動画推薦を並行する場合はデータセットグループを分けて設計します。
ステップ2: ソリューションの作成と学習
レシピ(推薦アルゴリズムのテンプレート)を選択してソリューションを作成し、ソリューションバージョン(学習済みモデル)を生成します。学習完了後、NDCG@K・precision@K・MRR・coverageなどのオフライン評価メトリクスが自動算出されます。主要レシピの詳細は§2で解説します。
User-Personalization-v2を選ぶ場合、データ投入後に2時間ごとの自動更新(automatic updates)が有効化され、新規アイテムや直近の行動変化がモデルに反映されます。定期的な全再学習は別途スケジュール設定します。
ステップ3: キャンペーンまたはバッチ推論ジョブの作成
リアルタイム推薦が必要な場合はキャンペーン(APIエンドポイント)を作成します。キャンペーンはプロビジョンドTPS(Transactions Per Second)で課金されます。メール配信や日次バッチなど非同期の大量推薦が必要な場合はバッチ推論ジョブを使用します。両者のコスト比較は§6で詳述します。
ステップ4: 推薦APIの呼び出し
GetRecommendations API(個人化推薦)またはGetPersonalizedRanking API(候補リストの個人化並べ替え)をアプリケーションから呼び出して推薦結果を取得します。Event Trackerを使えばユーザーの行動ログをリアルタイムに取り込み、新規ユーザーのコールドスタート対応も実現できます。
本シリーズVol1の範囲と想定読者
想定読者
- AWSを使って推薦エンジンの本番導入を検討しているエンジニア・MLエンジニア
- SageMakerでの自前モデル構築よりも短期間でPersonalizeを使った推薦システムを立ち上げたいチーム
- 既存の推薦エンジンをPersonalizeに移行・置き換えを検討しているアーキテクト
- 機械学習は専門外だが、推薦エンジンをサービスに組み込む必要があるエンジニア
前提知識
- AWSの基本操作(S3へのファイル配置・IAMロールの設定)
- Pythonの基礎的なコーディング(boto3でのAPI呼び出しレベル)
- 機械学習の基本用語(モデル・学習・評価指標)の概念的な理解
SageMaker・Lambda・Step Functionsなどの詳細な操作方法は既存の関連記事を参照し、本記事ではPersonalize固有の構成・運用に集中します。S3の基本操作やIAMロール設定の詳細は対象外とします。
Vol1の全体構成
本Vol1はPersonalizeのコアコンポーネントから精度評価・MLOps・コスト・他サービスとの連携まで、本番運用に必要な知識を一冊にまとめています。各セクションは独立して参照できるように設計しており、導入済みの方は目的のセクションから読むことができます。
- Personalize基礎 — レシピ/データセットグループ/ソリューション/キャンペーン(§2)
- 実装・運用 — リアルタイム推薦API/再学習/A-Bテスト(§3)
- 精度評価・チューニング — NDCG/precision@K/レシピ選定(§4)
- 統合・MLOps連携 — S3/Lambda/Event Tracker/パイプライン(§5)
- コスト・スケール運用と既存ML/AIとの使い分け(§6・§7)
- Amazon Personalize — 推薦という特定タスクをモデル構築不要で解くターンキーML(本記事)
- SageMaker — 自前MLモデルの構築・トレーニング・MLOps(柔軟だが構築コスト高)
- Bedrock — 基盤モデルによる生成AI(生成/要約/対話)
- タスク特化AI — Textract/Comprehend/Rekognition/Transcribe(抽出・分類・認識)
抽出・認識のタスク特化AIはこちら(タスク特化AIサービス実践 Vol1)
2. Amazon Personalize 基礎 — レシピ・データセットグループ・キャンペーン

Amazon Personalizeは、AWSが提供するターンキーML推薦エンジンです。機械学習モデルを自前で構築・管理することなく、Amazonの推薦技術をマネージドサービスとして利用できます。本セクションでは、Personalizeを構成する主要コンポーネントを詳しく解説します。
データセットグループとデータセット
Amazon Personalizeのデータ管理の基本単位がデータセットグループ(Dataset Group)です。1つのユースケース(例: EC推薦エンジン、動画推薦システム)に対して1つのデータセットグループを作成し、その中に最大3種類のデータセットを格納します。データセットグループ単位でレシピ・ソリューション・キャンペーンを管理するため、ユースケースが複数ある場合はデータセットグループを分けて設計します。
1. Usersデータセット
ユーザーのメタデータを格納します。USER_IDは必須フィールドです。年齢、性別、会員種別、居住地域などのカスタム属性をスキーマで定義できます。Usersデータセットは任意ですが、新規ユーザーへのコールドスタート対応や特定セグメントのパーソナライゼーション品質向上のために準備することを推奨します。
- フォーマット: CSV(スキーマ定義必須)
- 必須フィールド: USER_ID(string型)
- 任意フィールド: 年齢、性別、会員ランク等のカスタム属性
- 推奨: ユーザーの特性を示す属性を追加すると、コールドスタート時の推薦精度が向上します
2. Itemsデータセット
推薦対象のアイテムのメタデータを格納します。ITEM_IDは必須フィールドです。商品カテゴリ、ジャンル、価格帯、公開日時などのメタデータが推薦精度に影響します。特にCREATION_TIMESTAMPフィールドを含めると、新着アイテムを推薦に含める動作が改善します。アイテムの鮮度を考慮した推薦を実現したい場合は必ず追加してください。
- フォーマット: CSV(スキーマ定義必須)
- 必須フィールド: ITEM_ID(string型)
- 任意フィールド: カテゴリ、価格帯、公開日、ジャンル等
- 注意: item metadataはUser-Personalization-v2でコールドスタート対応に活用されます
3. Interactionsデータセット — 推薦精度の核心
ユーザーがアイテムに対して行った行動ログを格納します。3種のデータセットの中で最も重要であり、Interactionsデータの質と量が推薦精度を直接左右します。どれだけ優れたレシピを選んでもInteractionsデータが不足していては精度が出ません。
- フォーマット: CSV(スキーマ定義必須)
- 必須フィールド: USER_ID / ITEM_ID / TIMESTAMP(Unix秒)
- 推奨フィールド: EVENT_TYPE(購入/閲覧/クリック等)、EVENT_VALUE(重み付け)
- 最小要件: ユニークユーザー25人以上・ユニークアイテム2個以上・合計インタラクション1,000件以上(不足すると学習が失敗します)
- 推奨規模: 本番運用では1万件以上を目安に収集します
Interactionsは複数のEVENT_TYPEをまとめて収集するのが現実的です。購入(purchase)・詳細ページ閲覧(view)・クリック(click)・カート追加(addToCart)等を区別し、各イベントに重み(EVENT_VALUE)を付与することでモデルに行動の重要度を伝えます。
レシピ — 用途別の推薦アルゴリズム
レシピ(Recipe)は、推薦の目的に応じて選択する学習アルゴリズムのテンプレートです。2026年時点の主要レシピを用途別に整理します。
ユーザーへの個人化推薦
| レシピ名 | 用途 | 特徴 |
|---|---|---|
| User-Personalization-v2 | 個人化推薦(推奨) | 最大500万アイテム・2時間ごとの自動更新・item metadata対応・低レイテンシ。新規ユーザー(コールドスタート)にも対応 |
| Personalized-Ranking-v2 | 候補リストの個人化並べ替え | 既存の候補リストをユーザー好みで再ランク付け。コンテンツ一覧をパーソナライズする用途 |
トレンド・次の行動予測
| レシピ名 | 用途 | 特徴 |
|---|---|---|
| Trending-Now | トレンドアイテム推薦 | 直近の行動データからトレンドを検出し急上昇アイテムを推薦 |
| Next-Best-Action | 次の行動予測 | ユーザーが次に取りそうな行動を予測しコンバージョン促進 |
アイテム間・汎用
| レシピ名 | 用途 | 特徴 |
|---|---|---|
| Item-to-Item (SIMS) | 類似アイテム推薦 | アイテムIDを入力として類似アイテムを返す。「このアイテムを見た人はこちらも見ています」 |
| Popularity-Count | 人気度ベース推薦 | Interactions件数が多いアイテムを推薦。コールドスタート補完やベースライン比較に有用 |
レシピ選定の基本方針: ほとんどのユースケースではUser-Personalization-v2から始めることを推奨します。追加要件(トレンド対応・類似アイテム・候補絞り込み)がある場合に他レシピを追加・併用します。Personalized-Ranking-v2は個人化推薦ではなく再ランク付け専用です。誤ってUser-Personalizationの代わりに使わないよう注意してください。
ソリューションとソリューションバージョン
ソリューション(Solution)は、データセットグループとレシピを組み合わせた学習設定の定義です。ソリューション自体は設定のみで、実際に学習されたモデルはソリューションバージョン(Solution Version)として管理されます。
ソリューション作成時の主な設定:
- レシピ選択: 上記のレシピ一覧から用途に合わせて選択します
- ハイパーパラメータ最適化(HPO): 有効化すると複数のハイパーパラメータ組み合わせを試して最良のモデルを選択します(学習時間・コスト増)
- アイテム探索(exploration): User-Personalization-v2ではexploration weightで新規アイテムを推薦に含める割合を調整できます
ソリューションバージョンの作成には数分〜数十分かかります(データ量による)。作成完了後にオフラインメトリクス(NDCG@K / precision@K / MRR / coverage)が自動算出されます。
# Boto3でのソリューションバージョン作成例
import boto3
personalize = boto3.client('personalize', region_name='ap-northeast-1')
response = personalize.create_solution_version(
solutionArn='arn:aws:personalize:ap-northeast-1:123456789012:solution/my-solution',
trainingMode='FULL'
)
solution_version_arn = response['solutionVersionArn']
print(f"ソリューションバージョン作成開始: {solution_version_arn}")
キャンペーン — リアルタイム推薦エンドポイント
キャンペーン(Campaign)は、ソリューションバージョンを元にしたリアルタイム推薦のAPIエンドポイントです。アプリケーションからGetRecommendations / GetPersonalizedRanking APIを呼び出す際のターゲットになります。
プロビジョンドTPS(Transactions Per Second)がキャンペーンの重要な設定です。
- minProvisionedTPS: 最小保証TPS。この値を下回っても常時課金されます(コスト管理の最重要ポイント)
- 高負荷時の自動スケール: 実際のTPSがminProvisionedTPSを超えると自動スケールします(最大: minProvisionedTPS × 10程度まで)
- 推奨: 本番環境では負荷テストを実施してから適切な最小TPSを設定します。過大設定は継続的なコスト増に直結します
# Boto3でのキャンペーン作成例
response = personalize.create_campaign(
name='my-recommendation-campaign',
solutionVersionArn=solution_version_arn,
minProvisionedTPS=1
)
campaign_arn = response['campaignArn']
print(f"キャンペーン作成完了: {campaign_arn}")
キャンペーン作成後、GetRecommendations APIでリアルタイム推薦を取得できます。
# GetRecommendations API呼び出し例
runtime = boto3.client('personalize-runtime', region_name='ap-northeast-1')
response = runtime.get_recommendations(
campaignArn=campaign_arn,
userId='user-12345',
numResults=10
)
for item in response['itemList']:
print(f"推薦アイテム: {item['itemId']} (スコア: {item.get('score', 'N/A')})")
バッチ推論ジョブ — 大量ユーザーへのオフライン推薦
バッチ推論ジョブ(Batch Inference Job)は、大量のユーザーやアイテムに対して推薦を一括生成する機能です。リアルタイムAPIを使わずにコストを抑えながら大規模な推薦を実現できます。
| 比較項目 | リアルタイム推薦(キャンペーン) | バッチ推論ジョブ |
|---|---|---|
| レイテンシ | 低レイテンシ(100ms以下) | 非同期(数分〜数時間) |
| 課金形態 | TPS常時課金 | 処理件数ベース |
| 向いている用途 | Webアプリ・モバイル等のリアルタイム推薦 | メール配信・プッシュ通知・日次バッチ処理 |
| スケール | リクエスト単位 | 数百万件の一括処理可 |
バッチ推論の処理フロー:
- S3にUserIDリスト(JSON形式:
{"userId": "user-001"})を1行1レコードで配置します - バッチ推論ジョブを作成し、入力S3パス・出力S3パス・ソリューションバージョンを指定します
- ジョブ完了後、出力S3パスに推薦結果(JSON)が保存されます
- Lambda/Glue等でDynamoDB書き込み・メール配信等の後処理を自動化します
# バッチ推論ジョブの作成例
response = personalize.create_batch_inference_job(
jobName='daily-recommendation-batch',
solutionVersionArn=solution_version_arn,
jobInput={'s3DataSource': {'path': 's3://my-bucket/input/users.json'}},
jobOutput={'s3DataDestination': {'path': 's3://my-bucket/output/'}},
roleArn='arn:aws:iam::123456789012:role/PersonalizeS3Role',
numResults=25
)
データ形式 — CSVとスキーマ定義
Personalizeへのデータ取り込みはすべてCSV形式です。取り込み前にスキーマ(Schema)を定義し、CSVヘッダーと一致させる必要があります。スキーマはAvro JSON形式で定義します。
Interactionsスキーマの定義例:
{
"type": "record",
"name": "Interactions",
"namespace": "com.amazonaws.personalize.schema",
"fields": [
{ "name": "USER_ID", "type": "string" },
{ "name": "ITEM_ID", "type": "string" },
{ "name": "TIMESTAMP", "type": "long" },
{ "name": "EVENT_TYPE", "type": "string" },
{ "name": "EVENT_VALUE", "type": ["null", "float"], "default": null }
],
"version": "1.0"
}
データ取り込み時の注意点:
- USER_ID・ITEM_IDは文字列型(string)を使用します。数値のみのIDを使うと本番システムのユーザーIDとのマッピングで問題が発生しやすいため、文字列型で管理することを推奨します
- TIMESTAMPはUnixエポック秒(整数型)で格納します。ISO 8601形式は使用できません
- Interactions CSVの1行目はヘッダー行(スキーマフィールド名と完全一致が必要です)
- S3へのCSVアップロード後、データセットインポートジョブを実行してPersonalizeに取り込みます
- データセットグループ — Users / Items / Interactions(行動ログが最重要)
- レシピ — User-Personalization-v2(推奨・最大500万items・2時間自動更新)/Personalized-Ranking-v2/Trending-Now/SIMS類似/Popularity-Count
- ソリューション→ソリューションバージョン(学習済みモデル)→キャンペーン(リアルタイム推薦エンドポイント)
- バッチ推論ジョブ=大量オフライン推薦。データ形式=CSV(スキーマ定義)
3. 実装・運用 — リアルタイム推薦API・再学習・A-Bテスト

Amazon Personalizeのリアルタイム推薦は、アプリケーションからキャンペーンエンドポイントへAPIを呼び出すシンプルな構成で実現できます。本節では、GetRecommendations / GetPersonalizedRanking APIの使い方、Event Trackerによるリアルタイム行動取込、フィルタによるビジネスルール適用、A-Bテストの設計、再学習サイクルの管理を順に解説します。
GetRecommendations API — ユーザー別リアルタイム推薦
GetRecommendations APIは、指定したuserId(匿名ユーザーにはsessionIdを利用)に対して推薦itemIdリストとスコアを返します。呼び出し先はキャンペーンARNで、レスポンスはitemListとして最大500件のitemId+scoreが返却されます。
import boto3
personalize_runtime = boto3.client("personalize-runtime", region_name="ap-northeast-1")
response = personalize_runtime.get_recommendations(
campaignArn="arn:aws:personalize:ap-northeast-1:123456789012:campaign/my-campaign",
userId="user_001",
numResults=20,# 取得件数(デフォルト25)
filterArn="arn:aws:personalize:ap-northeast-1:123456789012:filter/purchased-filter",
context={
"DEVICE_TYPE": "mobile" # コンテキスト変数(セッションごとの条件)
}
)
for item in response["itemList"]:
print(item["itemId"], item["score"])
レスポンス構造はシンプルです。itemIdはItems CSVのitemIdに対応しており、scoreは0〜1の相対値です(同一呼び出し内でのソート比較に使用し、絶対的な確率ではありません)。numResultsは最大500件まで指定可能ですが、実際のUI要件(トップ10表示など)に合わせて絞り込みます。
Personalizeは推薦結果を内部でキャッシュするため、P50レイテンシは通常50〜100ms程度に収まります。SLAが厳しいケースでは、キャンペーンのminProvisionedTPSを適切に設定して低レイテンシを維持します。
GetPersonalizedRanking API — 候補リストの個人化スコア並べ替え
GetPersonalizedRankingは、あらかじめ候補として絞り込まれたitemIdリストをPersonalizeが個人化スコアで並べ替えて返すAPIです。ルールベースで事前絞り込みした結果をPersonalizeで個人化する「ハイブリッド推薦」に適しています。
response = personalize_runtime.get_personalized_ranking(
campaignArn="arn:aws:personalize:ap-northeast-1:123456789012:campaign/ranking-campaign",
userId="user_001",
inputList=["item_101", "item_205", "item_318", "item_412", "item_530"],
filterArn="arn:aws:personalize:ap-northeast-1:123456789012:filter/in-stock-filter",
)
ranked = response["personalizedRanking"]
# ranked[0] が最もスコアが高いアイテム
典型的なユースケースは「カテゴリページの表示順最適化」です。カテゴリ内の商品(100〜1000件)をルールで絞り込んだ後、Personalizeで上位20件のみを個人化スコアで並べ替えて表示することで、クリック率の向上が期待できます。GetPersonalizedRankingにはPersonalized-Ranking-v2レシピを使ったキャンペーンが必要です。
Event Tracker — リアルタイム行動ログ投入
Event Trackerは、ユーザーの行動(クリック・購入・視聴など)をリアルタイムでPersonalizeに送信し、推薦モデルを即時に更新する仕組みです。初期学習時にInteractions CSVを取り込んだ後、本番稼働中の行動ログはEvent Trackerで継続的に蓄積します。
Event Trackerはコンソールまたは以下のAPIで作成します。
personalize = boto3.client("personalize", region_name="ap-northeast-1")
response = personalize.create_event_tracker(
name="my-event-tracker",
datasetGroupArn="arn:aws:personalize:ap-northeast-1:123456789012:dataset-group/my-dataset-group",
)
tracking_id = response["trackingId"]# アプリ側で保持する
行動発生時にはPutEvents APIで送信します。
personalize_events = boto3.client("personalize-events", region_name="ap-northeast-1")
personalize_events.put_events(
trackingId=tracking_id,
userId="user_001",
sessionId="session_abc",
eventList=[
{
"eventId": "evt_001",
"eventType": "click",
"sentAt": 1717600000.0, # UNIXタイムスタンプ
"itemId": "item_205",
"properties": '{"discount": "false"}'
}
]
)
Event Trackerで送られたイベントはリアルタイムにモデルへ反映され、新規ユーザー(コールドスタート)でも数回の行動ログを蓄積すると推薦精度が向上します。User-Personalization-v2はitem metadataも活用するため、行動ログが少ない新規ユーザーへのコールドスタート対応が改善されています。
コールドスタート対策のベストプラクティス
行動ログがゼロの新規ユーザーには、Personalize内部のExploration機能(User-Personalization-v2のexplorationWeight設定)が機能します。explorationWeightを0.3程度に設定しておくと、モデルが蓄積データに基づく活用(Exploitation)と新規ユーザー向けの探索(Exploration)を自動的にバランスさせます。アイテム側のコールドスタートは、新商品のメタデータ(カテゴリ・タグ・価格帯)をItems CSVに登録することで、PutItemsを通じて即時に推薦候補へ追加できます。
フィルタ — ビジネスルールをAPIレイヤーで適用
フィルタは推薦結果にビジネスルールを適用するPersonalize固有の機能です。購入済みアイテムの除外、在庫切れ商品の除外、特定カテゴリへの絞り込みなど、推薦アルゴリズムが学習した内容をそのままUIへ出力せず、ビジネスニーズを加味できます。
フィルタはFilter Expression言語(SQL-like)で定義します。
# 購入済みアイテム除外
EXCLUDE itemId WHERE INTERACTIONS.event_type IN ("purchase")
# カテゴリ絞り込み(動的変数を使用)
INCLUDE itemId WHERE ITEMS.category IN ($CATEGORY)
# 在庫切れ除外(Items CSVのin_stockカラムを参照)
EXCLUDE itemId WHERE ITEMS.in_stock IN ("false")
フィルタはコンソールまたはAPIで事前に作成し、GetRecommendations / GetPersonalizedRanking呼び出し時にfilterArnで指定します。1つのキャンペーンに対して複数のフィルタを状況に応じて切り替えることも可能です。
$CATEGORYのような変数は、API呼び出し時にfilterValuesとして動的に渡せます。
response = personalize_runtime.get_recommendations(
campaignArn=campaign_arn,
userId="user_001",
filterArn=filter_arn,
filterValues={"CATEGORY": '"sports"'} # JSON文字列形式で渡す
)
在庫テーブルとの連動パターンとしては、アプリ側でリアルタイム在庫データを取得しフィルタ変数として渡す方法と、PutItems APIでPersonalizeのItems CSVを在庫変更のたびに更新してITEMS.in_stock IN ("false")で除外する方法があります。前者は在庫変動に即時対応できる反面、呼び出し側で在庫データを取得するAPIコストが生じます。後者はPersonalize側でデータを管理できる反面、在庫変更からItems CSV更新までのラグが生じます。
A-Bテスト — 複数キャンペーン・ソリューションバージョンで効果測定
A-BテストはPersonalize推薦の精度を実際のビジネス指標(CTR・CVR・購入額)で検証するために不可欠です。オフラインメトリクス(NDCG等)はデータ品質に依存するため、本番での実測でビジネスへの貢献を確認します。
パターン1: 複数キャンペーン比較
既存キャンペーン(レシピAまたは旧ソリューションバージョン)と新キャンペーン(レシピBまたは新ソリューションバージョン)を並行稼働させ、アプリ側でユーザーを振り分けます。トラフィック分割はアプリ層で行います。
import hashlib
def get_campaign_arn(user_id: str) -> str:
"""ユーザーIDのハッシュでA/B群を決定する"""
hash_value = int(hashlib.md5(user_id.encode()).hexdigest(), 16)
# 50/50でA/B割り振り
if hash_value % 2 == 0:
return campaign_arn_a
return campaign_arn_b
パターン2: 自動探索(Exploration)によるシングルキャンペーンA-B相当
User-Personalization-v2は内部で探索(Exploration)と活用(Exploitation)のバランスを自動調整します。explorationWeightを設定することで、新規アイテムへの露出を増やし、推薦の多様性を確保できます。これはシングルキャンペーンでの自動A-B相当の仕組みです。
効果計測にはPersonalize Eventsのイベントデータを活用します。Campaign AへのアクセスとCampaign Bへのアクセスを明示的に記録し、CTRはクリックイベント数÷推薦表示数、CVRは購入イベント数÷クリック数で算出します。統計的有意差はカイ二乗検定または2標本比率検定で確認します。一般的には1週間〜2週間以上の観測期間が必要です。
再学習サイクル — automatic updatesと全再学習の使い分け
User-Personalization-v2はautomatic updates機能を持ち、2時間ごとに自動でモデルを更新します。新規アイテムのメタデータが追加された場合や、直近の行動パターンの変化を反映するために有効です。このautomatic updatesは新たなソリューションバージョンを作成しないため、キャンペーン更新作業は不要です。
全再学習(createSolutionVersion)が必要なタイミングは以下の通りです。
- データセットの大幅な変更(スキーマ変更・大量データ追加)
- レシピのハイパーパラメータ変更
- 精度が低下し、履歴データを含む全再学習で改善が見込まれる場合
- 定期的なモデルバージョン作成(コンプライアンス/監査要件)
全再学習はトレーニング費用が発生し、完了まで数時間かかることがあります。そのため、automatic updatesで日常的な鮮度を維持しつつ、週次または月次で全再学習するサイクルが多くの本番環境で採用されています。
新しいソリューションバージョンが完成したら、updateCampaignでキャンペーンに適用します。更新中もリクエストは旧バージョンで継続処理されるため、ダウンタイムは発生しません。
personalize.update_campaign(
campaignArn=campaign_arn,
solutionVersionArn=new_solution_version_arn,
minProvisionedTPS=1,
)
キャンペーン設定 — minProvisionedTPSとauto-scaling
キャンペーンのminProvisionedTPSは「最小スループット」であり、この値以上のリクエストが来るとPersonalizeがauto-scalingで対応します。minProvisionedTPSは常時課金(リクエストがなくても課金)となるため、負荷パターンに合わせた適正値の設定がコスト管理の要です。
本番環境では1(最小値)から始め、P95/P99レイテンシをCloudWatchで監視しながら段階的に引き上げる運用が安全です。auto-scalingが発動すると追加コストが発生するため、定常的に高負荷が予測される場合は最初からminProvisionedTPSを高めに設定することでauto-scalingのコストを抑えられます。
レイテンシ確認は以下のCloudWatchメトリクスで行います。
- GetRecommendations Latency: 推薦API呼び出しのレイテンシ(P50/P90/P99)
- PutEvents Latency: Event Tracker書き込みのレイテンシ
- GetPersonalizedRanking Latency: ランキングAPIのレイテンシ
本番リリース前にはロードテスト(Locust・k6等)でキャンペーンの最大TPSを確認し、想定ピーク時のP99レイテンシが許容範囲内であることを検証します。
- リアルタイム推薦 — GetRecommendations / GetPersonalizedRanking APIでキャンペーンから低レイテンシ取得
- Event Tracker — ユーザー行動をリアルタイム取込しコールドスタート/新規ユーザーに即対応
- フィルタ — 購入済み除外/在庫切れ除外/カテゴリ絞り込み等のビジネスルール適用
- 再学習 — 全再学習とautomatic updates(2時間ごと)の使い分け。A-Bテストは複数キャンペーンで比較
4. 精度評価・チューニング

Amazon Personalizeの推薦品質を本番で維持・改善するには、オフライン評価メトリクスの正確な読み方とチューニング手法を体系的に理解することが不可欠です。ソリューションバージョン(学習済みモデル)を作成すると、コンソールやAPIで自動算出されたメトリクスを確認できます。まずこれらのメトリクスの意味を把握し、次にハイパーパラメータ最適化(HPO)やレシピ選定の反復サイクルを設計します。最終的な精度判断はオンラインA-Bテスト(§3参照)で行いますが、その前提となるオフライン評価を適切に活用することで、A-Bテストのコストと期間を大幅に削減できます。
4-1. オフライン評価メトリクスの読み方
ソリューションバージョン作成時、Personalizeはインタラクションデータを「学習用」と「テスト用」に自動分割し、テスト用データで以下のメトリクスを算出します。カットオフK(5/10/25)ごとの値が出力されるため、推薦枠のUI設計に合わせてどのKを重視するかを事前に決めておくことが重要です。
NDCG@K(Normalized Discounted Cumulative Gain)
NDCGは推薦リストのランキング品質を測る代表的な指標です。正解アイテムが推薦リストの上位に来るほど高いスコアを与え、順位が下がるにつれて割引(Discount)をかけます。スコアは0〜1の範囲で、1.0に近いほど正解アイテムが上位に集中していることを示します。
- NDCG@5: 推薦リストの上位5件の品質。ファーストビューに推薦枠が5件表示される場合に最重要視する指標です
- NDCG@10: 推薦リストの上位10件の品質。スクロール無しで見える推薦全体の評価に適しています
- NDCG@25: 推薦リストの上位25件の品質。カルーセル全体や一覧ページの評価に使用します
NDCGが低い場合は、Interactionsデータの量・品質不足、レシピの選択ミス、またはハイパーパラメータの調整不足が主な原因です。NDCGの改善には、まずデータ品質の改善(4-5節参照)を優先します。
precision@K(Precision at K)
precision@Kは上位K件の推薦リスト中に正解アイテムが何件含まれるかの割合です。NDCGとは異なり、順位の重み付けは行いません。
precision@K = 上位K件中の正解アイテム数 / K
例えばprecision@10=0.3であれば、上位10件中3件が実際にユーザーが関与したアイテムを正しく推薦できていることを意味します。ECサイトの「あなたへのおすすめ」枠など、推薦枠内のヒット率を重視する用途ではprecision@Kを主要KPIとして設定します。
MRR(Mean Reciprocal Rank)
MRRは最初の正解アイテムが推薦リストの何位に出るかを測ります。
MRR = 1 / (最初の正解アイテムの順位)
例えば最初の正解アイテムが1位なら1.0、2位なら0.5、5位なら0.2です。検索エンジンのように「とにかく最初のヒットが重要」な用途、あるいは推薦枠の最上位1件のみが重視されるシナリオでMRRを活用します。ECサイトのトップ推薦1件、ヘッダーバナー枠などに適しています。
coverage(カバレッジ)
カバレッジは全アイテム数のうち推薦に登場したアイテムの割合を示します。
coverage = 推薦に1回以上登場したアイテム数 / 全アイテム数
カバレッジが低い(例: 0.05以下)場合は、人気アイテムへ過度に集中した状態となり、ロングテールのアイテムは推薦されにくくなります。ECやメディアでは、人気アイテムへの偏重は短期CTRを高める一方で探索体験を損ない、長期エンゲージメント低下のリスクをはらんでいます。カバレッジとNDCGのトレードオフを意識しながらチューニングします。
4-2. ハイパーパラメータ最適化(HPO)
Amazon Personalizeのソリューション作成時にHPO(Hyperparameter Optimization)を有効化すると、指定した探索範囲内でハイパーパラメータの最良の組み合わせを自動探索します。
HPO有効化の方法
コンソールではソリューション作成画面の「ハイパーパラメータ設定」でHPOをオンにします。APIではCreateSolutionリクエストのsolutionConfig.hpoConfigにmax_runtime_in_seconds(探索時間上限)とmax_parallel_training_jobs(並列探索数)を設定します。
import boto3
personalize = boto3.client('personalize')
response = personalize.create_solution(
name='my-solution-hpo',
datasetGroupArn='arn:aws:personalize:ap-northeast-1:123456789012:dataset-group/my-group',
recipeArn='arn:aws:personalize:::recipe/aws-user-personalization-v2',
solutionConfig={
'hpoConfig': {
'hpoObjective': {
'type': 'Maximize',
'metricName': 'validation/coverage',
'metricRegex': r'.*'
},
'hpoResourceConfig': {
'maxNumberOfTrainingJobs': '6',
'maxParallelTrainingJobs': '2'
}
}
}
)
HPO最適化の目標設定
hpoObjective.metricNameにはNDCG@K・precision@K・MRRのいずれかを指定します。業務要件に合ったメトリクスを目標に設定することで、そのメトリクスを最大化するハイパーパラメータを探索します。探索ジョブ数を増やすと精度が上がりますが、学習コスト($/トレーニング時間)も増加するため、最初は4〜6ジョブ程度で試すことを推奨します。
4-3. レシピ比較実験
ユースケースに応じたレシピ選定は精度に直結します。同一のデータセットグループで複数レシピのソリューションバージョンを作成し、オフラインメトリクスを比較することで最適なレシピを選定できます。
| レシピ | 適したユースケース | NDCG傾向 | coverage傾向 |
|---|---|---|---|
| User-Personalization-v2 | ユーザー個人への推薦全般 | 高い | 中〜高 |
| Trending-Now | 急上昇コンテンツの推薦 | 中 | 低め(人気偏重) |
| Popularity-Count | 人気ランキング表示 | 低め | 最低(人気偏重) |
| Personalized-Ranking-v2 | 既存候補リストの並べ替え | 文脈依存 | 文脈依存 |
| SIMS | アイテム類似の「関連商品」 | 文脈依存 | 中 |
User-Personalization-v2を軸にする理由
User-Personalization-v2はAmazonの主力レシピで、最大500万アイテムのスケールと2時間ごとの自動更新(新アイテムの自動取込)を備えます。item metadataを活用したコールドスタート対応も組み込まれており、大多数の個人化推薦ユースケースで最高の精度を発揮します。まずUser-Personalization-v2でベースラインを作り、ビジネス要件(急上昇コンテンツの推薦など)に応じてTrending-Nowを補助的に使う構成が推奨です。
Popularity-Countの役割
Popularity-CountはNDCGが低い一方で、コールドスタートユーザー(行動ログが少ない新規ユーザー)への初期推薦に活用できます。新規ユーザーのInteractionsが蓄積されるまでの期間は、Popularity-Count推薦→Event Trackerで行動を継続取込→User-Personalization-v2推薦へ段階的に移行する設計が実践的です。
4-4. コールドスタート対応
コールドスタートはPersonalizeの精度評価で最も頻繁に議論されるトピックです。新規ユーザーと新規アイテムの2種類に分けて対策します。
新規ユーザーのコールドスタート
行動ログ(Interactions)が0〜数件の新規ユーザーには、個人化推薦の根拠となるデータが不足しています。対策として以下の段階的アプローチを取ります。
- 初期段階(Interactions 0〜5件): Popularity-Count + Trending-Nowで人気・急上昇アイテムを推薦
- 移行段階(Interactions 5〜20件): User-Personalization-v2を試しつつ、Event Trackerで行動を即時投入してモデルを更新
- 個人化段階(Interactions 20件以上): User-Personalization-v2が個人の嗜好を学習し、精度が安定
Event TrackerのPutEvents APIで行動イベントをリアルタイム投入することで、コールドスタートの解消を加速できます。セッション内でのクリック・購入・評価などのイベントをその場でPersonalizeに送り込むと、次回の推薦API呼び出し時から反映されます。
新規アイテムのコールドスタート
新しく登録されたアイテムはInteractionsがゼロのため、類似ベースの推薦(SIMS)や人気ベースでは推薦されにくい状態です。対策はitem metadataの充実です。
- Itemsデータセットに
category・genre・price_range・brand・release_dateなどのメタデータを付与する - User-Personalization-v2はitem metadataを自動的に活用し、類似カテゴリ・属性のアイテムをコールドスタート期間中も推薦候補に組み込む
CREATION_TIMESTAMPフィールドを設定すると、新着アイテムへの探索的推薦を強化できる
4-5. A-Bテスト設計
オフライン評価で有望なソリューションバージョン・レシピを絞り込んだ後は、オンラインA-Bテストで最終評価します。Personalizeでは複数のキャンペーンを並行稼働させることでA-Bテストを実装できます。
A-Bテストの設計指針
- キャンペーンA: 既存のソリューションバージョン(ベースライン・対照群)
- キャンペーンB: HPO後・新レシピのソリューションバージョン(チャレンジャー)
- 割り振り: アプリ側でユーザーIDのハッシュ値等でA群・B群を分け、それぞれのキャンペーンARNを呼び分ける
- 主要KPI: CTR(クリック率)・購入率・セッション継続時間・一人当たり推薦クリック数
- 評価期間: 統計的有意差を確認できるだけのサンプルサイズ(最低1週間・トラフィック量に依存)を確保
import hashlib
def get_campaign_arn(user_id: str) -> str:
"""ユーザーIDのハッシュでA/B群を決定する"""
CAMPAIGN_A = 'arn:aws:personalize:ap-northeast-1:123456789012:campaign/baseline'
CAMPAIGN_B = 'arn:aws:personalize:ap-northeast-1:123456789012:campaign/challenger'
hash_value = int(hashlib.md5(user_id.encode()).hexdigest(), 16)
# 50/50でA/B割り振り
return CAMPAIGN_A if hash_value % 2 == 0 else CAMPAIGN_B
オフライン評価とオンライン評価の乖離に注意
オフラインメトリクス(NDCG等)で高評価のソリューションバージョンが、必ずしもオンラインCTRを向上させるとは限りません。coverageを重視したモデルはオフラインNDCGが低くなりやすいですが、ユーザーの発見体験向上を通じて長期エンゲージメントの上昇につながることもあります。オフライン評価は絞り込みの道具として使い、最終判断は常にオンラインA-Bテストで行うことが重要です。
4-6. データ品質向上による精度改善
メトリクスが低い場合、モデルやハイパーパラメータより先にデータ品質を疑うことが精度改善の近道です。
Interactionsデータの量と多様性
- Personalizeは最低1,000件以上のInteractionsを推奨。理想は10万件以上
- 1ユーザーあたり最低2件のインタラクションが必要。行動ログの薄いユーザーが多い場合は
eventValueThresholdで低品質インタラクションを除外する - イベントタイプ(click/purchase/like)が混在する場合は
eventTypeWeightsで購入に高い重みを付与し、推薦の精度を業務目標に合わせる
ノイズ除去と重複排除
- ボット・テストユーザーのInteractionsは事前に除去する
- 同一ユーザー×同一アイテムの重複インタラクションは、最新のタイムスタンプを残して重複排除する
TIMESTAMPの精度は秒単位で記録する(ミリ秒単位は不要だが秒以下では機能しない)
精度改善の反復サイクル
データ追加・クリーニング
↓
ソリューションバージョン再作成(HPO有効)
↓
オフラインメトリクス比較(NDCG/precision/MRR/coverage)
↓
有望モデルでオンラインA-Bテスト(CTR/購入率比較)
↓
勝者キャンペーンを本番へ → 次のサイクルへ
このサイクルを定期的に回すことで、ユーザー行動の変化やアイテムカタログの更新に追従した推薦品質を維持できます。
- オフラインメトリクス(自動算出) — NDCG@K(K=5/10/25)/precision@K/MRR/coverage
- レシピ選定 — 用途別に最適なレシピを選ぶ(個人化/並べ替え/類似)
- ハイパーパラメータ最適化(HPO)で精度を引き上げ
- オフライン評価は目安。最終判断はオンラインA-Bテスト(§3)で実測。データ品質(行動ログ量/期間)が精度を左右
5. 統合・MLOps連携

Amazon Personalizeを本番環境で継続的に運用するには、データ準備から再学習・デプロイまでを自動化するMLOpsパイプラインの構築が欠かせません。本節では、S3へのデータ投入方法、Glue/Lambdaによる前処理自動化、Step FunctionsとEventBridgeを組み合わせた再学習パイプライン、Event Trackerによるリアルタイム行動ログ収集、IAM設計、CloudWatch監視の構成を体系的に解説します。
5.1 データ準備パイプライン
S3へのデータ投入形式
Amazon Personalizeは3種類のデータセット(Users・Items・Interactions)をS3から取り込みます。各データセットの形式はCSV・JSON Lines・Avroに対応しており、本番運用ではCSVが最もシンプルで扱いやすいです。
Interactionsデータセット(行動履歴)は以下の必須フィールドを含むCSVを用意します。
USER_ID,ITEM_ID,TIMESTAMP,EVENT_TYPE
user_001,item_abc,1700000001,click
user_002,item_xyz,1700000050,purchase
TIMESTAMPはUnix秒形式で指定します。EVENT_TYPEはPersonalizeのレシピが認識できる値(click・purchaseなど)を統一して使用してください。
Itemsデータセットには商品IDと属性(カテゴリ・価格帯・タグなど)を含めます。
ITEM_ID,CATEGORY,PRICE_RANGE,CREATION_TIMESTAMP
item_abc,electronics,high,1690000000
item_xyz,books,low,1695000000
UsersデータセットにはユーザーIDと属性(年齢層・会員ランクなど)を含めます。
USER_ID,AGE_GROUP,MEMBERSHIP
user_001,30s,premium
user_002,20s,standard
Glue/Lambdaによるデータ変換・前処理自動化
生ログ(アプリサーバーのアクセスログ・DWHのトランザクションテーブルなど)をPersonalize入力形式に変換するには、AWS Glue ETLジョブが有効です。GlueジョブはPySpark/Python Shellで記述でき、S3上のRaw領域からClean領域へデータを変換した後、Personalizeのデータセットグループへ取り込みます。
Lambdaはリアルタイム取込に向いています。たとえばDynamoDB Streamsの変更イベントをトリガーにしてLambdaが新しいアイテム情報をPersonalizeのItems DatasetにCreateDatasetImportJobで追加するパターンが一般的です。
データ品質チェック
Personalizeへの取込失敗を防ぐため、ETL段階で以下の品質チェックを実施します。
- 重複除去:
USER_ID + ITEM_ID + TIMESTAMPの組み合わせを主キーとして重複行を除去します。同一ユーザーが同一時刻に同一アイテムを操作した重複行はInteractionsの精度に影響します。 - タイムスタンプ正規化: タイムゾーン混在(JST/UTC)による誤差を防ぐため、全タイムスタンプをUTC Unix秒に統一します。
- 不正ラベル除去:
EVENT_TYPEに未定義の文字列が混入すると、レシピの重み付けを崩します。許可リスト(click・purchase・streamなど)以外の値は除去またはリマップします。 - スパースアイテムの除外: インタラクション数が極端に少ないアイテム(たとえば2件未満)はPersonalizeの精度向上に寄与しないため、取り込み前にフィルタリングします。
5.2 自動化パイプライン
Step Functionsによる再学習ワークフロー
データ取込からソリューションバージョン作成・キャンペーン更新までを一貫して自動化するには、AWS Step Functionsのステートマシンが最適です。以下は標準的なフローです。
[DatasetImportJob作成] → [ジョブ完了待機] → [CreateSolutionVersion]
→ [SolutionVersion完了待機] → [GetSolutionMetrics]
→ [Choice: NDCG@25 >= 閾値?] → [Yes: UpdateCampaign] / [No: SNS通知]
PersonalizeのCreateDatasetImportJob・CreateSolutionVersion・UpdateCampaignはすべて非同期APIです。Step FunctionsのWaitステートでポーリングし、ジョブIDをキーにして完了を確認します。.sync:2統合パターンを使うと、Lambdaを別途用意せずStep Functionsから直接Personalizeのジョブ完了を待機できます。
メトリクス評価ステップでは、GetSolutionMetricsのレスポンスからNDCG@25・precision@25を取得し、Choice状態でしきい値(例: NDCG@25 >= 0.05)を下回る場合はSNS通知を発行してキャンペーン更新をスキップします。自動的に悪化したモデルが本番に適用されないためのガードとして機能します。
EventBridge + Lambdaによる定期再学習スケジューリング
再学習は週次・日次など業種に合わせた周期で実行します。EventBridgeのスケジュールルールでLambdaをトリガーし、LambdaがStep Functionsステートマシンを起動する構成がシンプルです。
import boto3
import os
sf = boto3.client('stepfunctions')
def handler(event, context):
response = sf.start_execution(
stateMachineArn=os.environ['STATE_MACHINE_ARN'],
input='{"datasetGroupArn": "' + os.environ['DATASET_GROUP_ARN'] + '"}'
)
return response['executionArn']
再学習頻度はビジネス要件に依存します。ECサイトのように商品・ユーザーの変化が速い場合は日次、B2BのSaaSで変化が緩やかな場合は週次が目安です。再学習にはトレーニング費用が発生するため、過剰な頻度にしないよう注意してください。
CodePipeline連携によるモデル評価・自動デプロイゲート
スキーマ変更やPersonalizeの設定変更をIaC(CloudFormation/CDK)で管理する場合、CodePipelineに組み込むと変更の追跡・ロールバックが容易になります。典型的な構成は次のとおりです。
- Source: GitHubにスキーマ定義JSONやCDKコードをプッシュします。
- Build: CodeBuildでスキーマの差分チェック・ユニットテストを実行します。
- Test: Lambdaを呼び出してPersonalizeのデータセットグループに新スキーマを適用し、インポートジョブを実行します。
- Approval:
GetSolutionMetricsでNDCGを取得し、閾値未満なら手動承認ゲートで停止します。 - Deploy: 承認後にUpdateCampaignでキャンペーンを新ソリューションバージョンへ切り替えます。
5.3 Event Tracker統合
PutEvents APIによるリアルタイム行動ログ投入
Event TrackerはPersonalizeへリアルタイムでユーザー行動を送信する仕組みです。Webアプリ・モバイルアプリのフロントエンドまたはバックエンドからPutEvents APIを呼び出すことで、インタラクションデータセットをバッチ取込なしにリアルタイムで更新できます。
Event Trackerを作成するとtrackingIdが払い出されます。このIDを使ってPutEventsを呼び出します。
Python(バックエンド)からの送信例:
import boto3
import time
client = boto3.client('personalize-events')
client.put_events(
trackingId='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
userId='user_001',
sessionId='session_abc',
eventList=[
{
'eventType': 'click',
'itemId': 'item_xyz',
'sentAt': time.time(),
'properties': '{"numRatings": 0}'
}
]
)
JavaScript(フロントエンド)からの送信例:
フロントエンドから直接PutEventsを呼ぶ場合は、AWS SDK for JavaScript v3のPersonalizeEventsClientを使用します。Amplifyと組み合わせる場合は認証済みCognitoユーザーの一時認証情報でAPIを呼び出すため、アクセスキーをフロントエンドに埋め込む必要はありません。
import {
PersonalizeEventsClient,
PutEventsCommand
} from "@aws-sdk/client-personalize-events";
const client = new PersonalizeEventsClient({ region: "ap-northeast-1" });
await client.send(new PutEventsCommand({
trackingId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
userId: "user_001",
sessionId: "session_abc",
eventList: [{
eventType: "click",
itemId: "item_xyz",
sentAt: Date.now() / 1000
}]
}));
フロントエンド→Event Tracker→Personalize連携でコールドスタート改善
新規ユーザーはインタラクション履歴がなく(コールドスタート)、精度が低下しやすいです。Event Trackerを使うと、ページ訪問直後から行動ログをリアルタイムに蓄積し、同一セッション内でパーソナライズ精度を段階的に向上させられます。User-Personalization-v2レシピはセッション中のリアルタイムイベントを考慮して推薦を更新するため、コールドスタートの影響を大幅に軽減できます。
5.4 IAM設計
Personalizeサービスロール(S3アクセス用)
PersonalizeがS3バケットからデータを読み込むには、Personalizeサービスプリンシパルを信頼したIAMロールが必要です。信頼ポリシーは以下のように設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "personalize.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
このロールにはS3バケットへのs3:GetObject・s3:ListBucket権限を付与します。エクスポート(バッチ推論の出力書き込み)が必要な場合はs3:PutObjectも追加します。
PutEvents/GetRecommendations用最小権限ロール
バックエンドLambdaからPutEventsを呼び出す場合のLambda実行ロールポリシー例です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["personalize:PutEvents"],
"Resource": "*"
}
]
}
GetRecommendations・GetPersonalizedRankingの呼び出し元(アプリサーバー)にも必要なAPIのみを許可する最小権限ポリシーを適用します。管理権限(CreateSolution・DeleteCampaignなど)は運用自動化用のLambda/Step Functions実行ロールにのみ付与し、推薦API呼び出し元とは明確に分離してください。
5.5 CloudWatch監視
主要メトリクス
PersonalizeはCloudWatchに以下のメトリクスを自動でエクスポートします。
| メトリクス | 説明 | 推奨アラート設定 |
|---|---|---|
| GetRecommendations Latency | 推薦API応答時間 | p99 > 100ms でアラート |
| GetRecommendations TPS | 毎秒リクエスト数 | プロビジョンドTPSの80%超過で通知 |
| ThrottledRequests | スロットリング発生回数 | 1件以上でアラート |
| CoverageRate | 推薦対象アイテムの網羅率 | 20%未満でアラート |
| solutionTrainingJobStatus | 再学習ジョブの状態 | FAILED時にSNS通知 |
アラームはCloudWatch Alarmで設定し、SNS経由でSlack/PagerDutyに通知するパターンが一般的です。CoverageRateの低下はインタラクションデータが特定アイテムに偏っている(ポピュラリティバイアス)サインです。この場合は探索的推薦(Exploration weightパラメータ)を調整するか、コールドアイテム補完ロジックを追加します。
ログ管理
CloudTrailはPersonalizeのAPI操作(CreateSolution・DeleteCampaignなど)をすべて記録します。誰がいつキャンペーンを変更したかを追跡するため、CloudTrailを有効化して3〜12ヶ月間S3に保持する設定を推奨します。
データセットが格納されたS3バケットにはサーバーアクセスログを有効化します。誰がデータを読み書きしたかのアクセス証跡となります。再学習パイプラインの各ステップのログはCloudWatch Logsに集約し、ロググループの保持期間を30日以上に設定します。エラー発生時の原因追跡に不可欠です。
- パイプライン自動化 — EventBridge/Step Functions/Lambdaで「取込→再学習→評価→キャンペーン更新」を自動化
- Event Trackerでリアルタイム行動を継続取込しモデルを鮮度維持
- IAMサービスロール+S3アクセス権限。スキーマ/データセットをCI/CDで管理
- 監視 — CloudWatchで推薦APIレイテンシ/エラー率。定期再学習でデータドリフトに対応
6. コスト・スケール運用
Amazon Personalizeのコストは、サービスの利用形態に応じて複数の課金要素で構成されています。本セクションでは、コスト体系の全体像と各要素の詳細を解説し、実際の運用での最適化手法・スケール上限・マルチリージョン/マルチアカウント設計・CloudWatch監視の運用実践をまとめます。
★ コスト数値・制限値は変動します。実際の料金と上限はAmazon Personalizeの公式料金ページおよび公式ドキュメントで最新情報をご確認ください。
Personalizeのコスト体系 — 4つの課金要素
Amazon Personalizeのコストは以下の4つの要素で構成されます。
① データ処理費用(Data Ingestion)
Personalizeにデータを取り込む際の費用です。データセットグループにインポートするデータ量(GB)に対して課金されます。
- 課金対象: Users / Items / Interactions 各データセットのインポートデータ量
- 課金単位: GB あたり(参考値: 約$0.05/GB — 最新値は公式ページ確認)
- 無料枠: Personalizeには一定量の無料枠が設定されています(AWSの月間無料枠ページを参照)
データインポートは初回取込時と増分更新時の両方で発生します。初期データ量が数GBを超えるケースでも数百ドル以内に収まることが多く、Personalizeの全コストの中では比較的小さな要素です。
② トレーニング費用(Training)
ソリューションバージョン(学習済みモデル)の作成にかかる費用です。
- 課金対象: ソリューションバージョンのトレーニング時間
- 課金単位: トレーニング時間あたり(参考値: 約$0.24/トレーニング時間 — 最新値は公式ページ確認)
- 発生タイミング:
CreateSolutionVersionを実行した際
データ量やレシピによりトレーニングに要する時間は数分〜数時間変動します。ハイパーパラメータ最適化(HPO)を有効化すると複数の組み合わせを並列トレーニングするため、ジョブ数倍の費用が発生します。月次の全再学習を実施する場合、トレーニング費用は月間で数十ドル〜数百ドル程度になることが多いです。
③ リアルタイム推薦費用(Real-Time Recommendations)
キャンペーン(リアルタイム推薦エンドポイント)の稼働費用です。Personalizeの運用コストの主要因であり、最も注意が必要なコスト要素です。
- 課金対象: キャンペーンのプロビジョンドTPS(Transactions Per Second)
- 課金単位: TPS × 時間(参考値: 最小1TPS で約$0.20/時間 — 最新値は公式ページ確認)
- 常時課金: リクエストが0件でも
minProvisionedTPS分は常時課金されます
★ プロビジョンドTPSの常時課金が最大のコスト落とし穴です。
minProvisionedTPS=1でキャンペーンを24時間稼働させると、月間のリアルタイム推薦費用は以下の計算になります(参考値のため最新料金は公式ページでご確認ください)。
1 TPS × 24時間 × 30日 ≒ 720時間/月
720時間 × $0.20/時間 ≒ 月額 $144
minProvisionedTPS=5に設定すると月額は5倍の約$720になります。不要なキャンペーンを削除せずに放置したり、トラフィック量に対して過大なTPS設定をすることが、Personalizeコスト超過の最大の原因です。
④ バッチ推論費用(Batch Recommendations)
バッチ推論ジョブによる大量オフライン推薦の費用です。
- 課金対象: バッチ推論で処理したユーザー件数
- 特徴: リアルタイム推薦と比較してコストが大幅に安価
- 向いている用途: メール配信・プッシュ通知・日次バッチ処理など非同期推薦
リアルタイム推薦が不要なユースケースでは、バッチ推論ジョブに切り替えることでコストを大幅に削減できます。1日1回バッチ処理すれば良いメール配信用の推薦であれば、キャンペーンを廃止してバッチ推論ジョブのみで運用することを検討してください。
コスト最適化 — 6つの実践手法
手法1: minProvisionedTPSを適切に設定する
最も効果的なコスト削減策です。キャンペーン作成時のminProvisionedTPSは最小値(1)から開始し、CloudWatchで実際のTPSを監視しながら段階的に調整します。
コスト最適化の流れ:
① minProvisionedTPS=1でキャンペーン作成
② 本番稼働後、CloudWatchの推薦APIレイテンシ/スロットリングを監視
③ スロットリング(ThroughputExceededException)が発生したらTPSを引き上げ
④ 負荷テスト結果をもとに適切なminProvisionedTPSを確定
ピークトラフィックに対してオートスケーリングが発動することを前提に、minProvisionedTPSは「ベーストラフィック」を賄う最小値に設定し、ピーク対応はオートスケーリングに任せる設計が推奨です。負荷テストはLocust・k6等のツールを使い、ピーク時に想定されるTPSを実測してから設定値を決定します。
手法2: 不要なキャンペーンを速やかに削除する
テスト・実験・A-Bテスト目的で作成したキャンペーンは、役目を終えたら速やかに削除します。キャンペーンはminProvisionedTPS × 24時間で課金が継続するため、1TPS設定のキャンペーンでも月額約$144相当の費用が発生し続けます(参考値)。
キャンペーン削除の手順:
- コンソールまたはBoto3で
delete_campaignを実行します - DeleteCampaign完了を確認したら課金が停止します
- A-Bテスト終了後は敗者側キャンペーンを速やかに削除する運用ルールを整備します
キャンペーン管理台帳(Excelやスプレッドシート)を整備し、キャンペーン名・目的・作成日・担当者・削除予定日を記録するプロセスを確立することを推奨します。
手法3: バッチ推論とリアルタイム推薦を用途に応じて使い分ける
推薦のユースケースを「リアルタイム必須」と「バッチで十分」に分類し、後者はバッチ推論ジョブに移行します。
| ユースケース | 推奨方式 | 理由 |
|---|---|---|
| EC商品ページのリアルタイム推薦 | キャンペーン(リアルタイム) | ユーザーの即時アクションに応じた推薦が必要 |
| メール配信用の推薦リスト(日次) | バッチ推論ジョブ | 非同期・大量処理で十分。コスト大幅削減 |
| プッシュ通知用の推薦(夜間バッチ) | バッチ推論ジョブ | 処理タイミングが固定。バッチが最適 |
| 週次レコメンドメール用 | バッチ推論ジョブ | 週1回の処理。常時稼働キャンペーンは不要 |
バッチ推論への移行によるコスト削減効果は大きく、メール配信専用のキャンペーンをバッチ推論ジョブに置き換えるだけで月額コストを大幅に削減できる事例が多くあります。
手法4: Interactionsデータの間引きでインポートコストを抑える
Personalizeへのデータインポートはデータ量(GB)に比例してコストが発生します。本番運用では行動ログが大量に蓄積するため、インポート前の間引き処理を検討します。
- 低品質インタラクション(ボット・テストユーザー・重複)を除去してデータ量を削減します
eventValueThresholdを使い、重要度の低いイベント(短時間の閲覧等)を除外します- 増分インポートを設計し、全件再インポートを避けます
なお、Personalizeが学習に使用するInteractionsは最大2年分です。2年以上前のデータはPersonalizeが自動で除外するため、長期間蓄積した行動ログを全件送り込む必要はありません。直近2年分に絞ったインポートで、データ量とコストを最適化できます。
手法5: ソリューションバージョンのバージョン管理とコスト管理
ソリューションバージョンは作成するたびにトレーニング費用が発生します。不要になった古いバージョンは削除してコストを管理します。また、HPOを有効化するとジョブ数倍のトレーニングが走るため、最初の実験フェーズではHPO無効で複数レシピを試してから、有望なレシピのみでHPOを実行する順序が費用対効果の高いアプローチです。
ソリューションバージョンの作成前に、データ量・レシピ・HPO有無からトレーニング時間を見積もり、コストを事前に把握することを推奨します。HPO有効時は探索ジョブ数(maxNumberOfTrainingJobs)を抑えてコストを制御できます。
手法6: ElastiCacheでキャンペーンへのリクエストをキャッシュする
アプリケーションとキャンペーンの間にElastiCache(Redis)を配置し、推薦結果をキャッシュすることで、実際にキャンペーンに到達するTPSを削減できます。推薦結果のTTL(有効期限)を30〜300秒程度に設定し、ヒット率を高めてキャンペーンのTPSを抑制します。ElastiCacheによるキャッシュは低レイテンシ維持にも貢献するため、コストとパフォーマンスの両面で効果があります。
ただし、TTLが長すぎるとEvent Tracker経由で更新されたリアルタイム推薦が反映されなくなります。ユーザーの行動が活発なセッション中は短いTTL(30〜60秒)、長時間アクティビティがないユーザーには長めのTTL(300秒〜)を動的に切り替える設計を検討してください。
スケール上限と設計
Amazon Personalizeのスケール上限を把握した上で、本番システムを設計することが重要です。★ 以下は参考値です。最新の制限値は公式ドキュメントでご確認ください。
User-Personalization-v2のスケール仕様
| 項目 | 参考上限 | 補足 |
|---|---|---|
| 最大アイテム数 | 500万アイテム | データセットグループ単位 |
| Interactions最大期間 | 2年分 | 2年以上前のデータは自動で除外 |
| TPSのオートスケーリング | minProvisionedTPS × 10程度まで | 瞬間的なバースト対応 |
| バッチ推論の最大規模 | 数百万ユーザー | ジョブ単位で大量処理可能 |
500万アイテムの上限は多くのECサイト・メディアプラットフォームのユースケースで十分ですが、大規模な商品カタログ(ファッション・マルチブランドモール等)では上限に近づく可能性があります。その場合は、カテゴリ別にデータセットグループを分割する「カテゴリ別推薦エンジン」設計を検討します。
TPSオートスケーリングの動作
キャンペーンのTPSは以下のように動作します。
minProvisionedTPS: 常時保証されるTPS。この値以上は常時課金- オートスケーリング範囲: 実際のTPSが
minProvisionedTPSを超えると自動拡張 - スケールアップ速度: 需要の急増に対してPersonalizeが段階的にキャパシティを拡大
- スケールダウン: トラフィックが落ち着くと
minProvisionedTPSまで縮小
大規模キャンペーンやフラッシュセールなど急激なトラフィック増加が予想される場合は、事前にminProvisionedTPSを引き上げておくことでスロットリングを防止できます。updateCampaignでTPSを変更しても反映までに数分かかる場合があるため、セールイベント前には余裕をもって設定変更を完了させてください。
オートスケーリング時は追加コストが発生します。定常的に高負荷が予測される場合は、最初からminProvisionedTPSを高めに設定することでオートスケーリング発動を抑制し、コストを予測可能な範囲に収める設計も有効です。
マルチリージョン/マルチアカウント構成
データセットグループは単一リージョン
Amazon Personalizeのデータセットグループは単一リージョン内で完結します。マルチリージョン展開が必要な場合は、各リージョンでデータセットグループを独立して作成し、データを複製する必要があります。リージョン間でのPersonalizeリソースの共有はサポートされていません。
マルチリージョン推薦の設計パターン
[ユーザーのリクエスト]
↓
[CloudFront + Route 53 (レイテンシルーティング)]
↓
ap-northeast-1のPersonalizeキャンペーン (日本ユーザー)
us-east-1のPersonalizeキャンペーン(北米ユーザー)
eu-west-1のPersonalizeキャンペーン(欧州ユーザー)
各リージョンのPersonalizeには、対応するリージョンのS3バケットからデータを取り込みます。リージョン間のデータ複製にはS3 Cross-Region Replicationを使用します。Interactionsデータのリアルタイム同期は、Event Trackerを各リージョンのPersonalizeへ並行送信する設計とします。
マルチリージョン構成では、キャンペーンをリージョン数分稼働させるためコストが倍増します。必要なリージョンのみデプロイし、グローバルトラフィックが少ないリージョンはバッチ推論で対応するなどのコスト最適化が重要です。
マルチアカウント構成
本番・開発・テスト環境をAWSアカウントで分離する場合、Personalizeは各アカウント内で独立して構成します。アカウント間のPersonalizeリソース共有はサポートされていないため、マスターアカウントで管理するデータを各アカウントにコピーする設計が必要です。
共通の推薦データ(商品マスタ等)をS3バケットのクロスアカウントアクセス経由で各アカウントのPersonalizeに取り込むパターンが現実解です。クロスアカウントアクセスはIAMロールの信頼ポリシーとS3バケットポリシーで構成します。本番アカウントのInteractionsを開発アカウントに同期する際は、個人識別情報(PII)の匿名化をETL処理で実施するセキュリティ設計が必要です。
CloudWatchメトリクスによる運用監視
Personalizeは主要な運用メトリクスをCloudWatchに自動でエクスポートします。これらを監視することで、コスト超過・パフォーマンス劣化・推薦品質の低下を早期に検知できます。
主要監視メトリクス
GetRecommendations Latency(推薦APIレイテンシ)
GetRecommendations APIの応答時間をP50・P90・P99で監視します。通常、P99は100ms以内に収まります。レイテンシが上昇した場合は以下を確認します。
minProvisionedTPSがトラフィックに対して低すぎてオートスケーリングが追いつかない- フィルタ式が複雑すぎて処理負荷が高い
- データセットのアイテム数が上限に近づいている
推奨アラート設定: P99 > 200ms で警告、P99 > 500ms で緊急アラート。
GetRecommendations TPS(実際のTPS)
キャンペーンに到達している実際のTPSを監視します。
minProvisionedTPSの80%を超えてきたら、スロットリング発生前にTPSを引き上げる準備をします- 深夜帯のTPSが非常に低い場合は、
minProvisionedTPSの設定を見直してコスト最適化の余地を検討します
ThrottledRequests(スロットリング回数)
スロットリングが発生するとThroughputExceededExceptionエラーが返され、ユーザーへの推薦が失敗します。スロットリングはユーザー体験を直接損なうため、即時のアラートを設定します。
推奨アラート設定: 5分間のスロットリング回数 > 1件で警告アラート。
CoverageRate(推薦カバレッジ率)
全アイテムのうち推薦に登場しているアイテムの割合です。この値が極端に低い場合(10%以下)は、人気アイテムへの偏重(ポピュラリティバイアス)が強い状態です。
- ExplorationWeight(Exploration設定)を調整して多様性を確保します
- 推薦に全く登場しないアイテムが増えている場合は、Itemsデータセットのメタデータを充実させます
DatasetImportJobStatus / SolutionVersionStatus
データインポートジョブと再学習ジョブのステータスをモニタリングします。ジョブがFAILEDになった場合はSNS経由でアラートを送信します。
[CloudWatch Alarm]
↓
[SNS Topic]
↓
[Lambda or Slack Webhook] / [PagerDuty (緊急度高)]
ダッシュボード構成例
Personalizeの運用ダッシュボードには以下のウィジェットを配置することを推奨します。
- GetRecommendations Latency (P50/P90/P99) — 折れ線グラフ
- 実際のTPS vs minProvisionedTPS — 比較グラフ
- ThrottledRequests — バーグラフ(0以上でアラート色)
- CoverageRate — 折れ線グラフ(低下傾向を視覚化)
- 月間コスト推移 — Personalizeの各課金要素ごとに可視化
これらのメトリクスを組み合わせることで、コスト・パフォーマンス・推薦品質を一元的に可視化し、問題の早期検知と迅速な対応が可能になります。
★ PersonalizeのCloudWatchメトリクス一覧と詳細は公式ドキュメント「Monitoring Amazon Personalize」をご参照ください。メトリクス名やディメンションは変更される場合があります。
- コスト構成=データ取込($/GB)+トレーニング($/時間)+リアルタイム推薦(プロビジョンドTPS常時課金)+バッチ
- ★キャンペーンの最小プロビジョンドTPSは常時課金。過大プロビジョン/不要キャンペーン放置がコスト増の主因
- リアルタイム不要な用途はバッチ推論でコスト削減。再学習頻度も最適化
- スケール=User-Personalization-v2は最大500万items。TPSオートスケーリングを設計
7. 実戦統合パターン — 既存ML/AIとの使い分け・組合せ

AWS Machine Learning/AIサービスは役割分担が明確で、適切に組み合わせることで開発速度と柔軟性の両立が可能です。本節では、Amazon PersonalizeとSageMaker・Bedrock・タスク特化AIの使い分け基準と、代表的な統合パターンを解説します。
サービス選定の基本フレームワーク
まず、解こうとしている課題を以下の4軸で分類します。
| 課題の種類 | 推奨サービス | 特徴 |
|---|---|---|
| 推薦・パーソナライゼーション | Amazon Personalize | モデル構築不要のターンキーML |
| 自前MLモデルの構築・再現性 | SageMaker | 柔軟だが構築・運用コストが高い |
| 生成・要約・対話・説明文 | Amazon Bedrock | 基盤モデルAPIで即時利用 |
| 抽出・分類・認識・書き起こし | タスク特化AI | Textract/Comprehend/Rekognition/Transcribeが担当 |
| 需要予測・時系列予測 | SageMaker Canvas | Forecast新規受付停止のため代替として推奨 |
選定の出発点は「推薦という特定タスクか否か」です。ユーザーへのアイテム推薦・ランキング・類似アイテム提示のいずれかであれば、まずPersonalizeを検討します。Personalizeで対応できない場合にSageMakerへ移行するアプローチを取ることで、初期開発速度を最大化できます。
SageMaker自前MLとの境界 — どちらを選ぶか
Personalizeを選ぶ条件
- 推薦という課題を解く(アイテム推薦/ランキング/類似)
- ユーザー行動ログ(購入・クリック・視聴)が存在または収集できる
- モデルのアルゴリズム詳細をコントロールする必要がない
- 短期間(数日〜数週間)でMVPを立ち上げたい
- Users/Items/Interactionsの3テーブルで表現できる推薦課題
SageMakerを選ぶ条件
- Personalizeの提供するレシピでは対応できない複雑な推薦ロジックが必要
- 独自の特徴量エンジニアリング(複数データソースの結合・変換)が不可欠
- リアルタイムの在庫・文脈情報を推薦スコア計算に直接組み込みたい
- モデルの再現性・バージョン管理・AB試験設計を細かくコントロールする必要がある
- 大規模グラフデータ(ソーシャルグラフなど)を使った推薦が必要
典型的な成長パス
PersonalizeでターンキーのMVP推薦を本番化し、CTR/CVRを確認します。ビジネスの成長に伴い精度要件が高まった段階で、SageMaker Feature StoreとSageMaker Pipelinesを使った自前特徴量エンジニアリングに移行します。最終的にはSageMakerでのカスタムモデルA-Bテストへと発展させる段階的アプローチが、リスクとコストの観点から推奨です。
Bedrock生成AIとのハイブリッド推薦
Personalizeの推薦リストとBedrockの生成能力を組み合わせることで、単純な「アイテムリスト」を超えた体験を提供できます。
パターン1: Personalize推薦 + Bedrock推薦理由生成
Personalizeが推薦したアイテムに対して、Bedrockが自然言語での「なぜこれをお勧めするか」を生成します。
import boto3, json
personalize_runtime = boto3.client("personalize-runtime")
bedrock_runtime = boto3.client("bedrock-runtime")
# Step1: Personalizeで推薦アイテムを取得
recs = personalize_runtime.get_recommendations(
campaignArn=campaign_arn,
userId=user_id,
numResults=5,
)
item_ids = [r["itemId"] for r in recs["itemList"]]
# Step2: DynamoDBなどからアイテムメタデータを取得
items_info = fetch_items_metadata(item_ids)
# Step3: Bedrockで推薦理由を生成
prompt = f"推薦アイテム: {items_info}
各アイテムの推薦理由を1文で生成してください。"
response = bedrock_runtime.invoke_model(
modelId="anthropic.claude-haiku-4-5-20251001",
body=json.dumps({
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 300,
"anthropic_version": "bedrock-2023-05-31"
}),
)
result = json.loads(response["body"].read())
このパターンはECサイトの「あなたへのおすすめ理由」機能やメールマガジンのパーソナライズ説明文生成に有効です。Personalizeが「何を推薦するか」を担い、Bedrockが「なぜ推薦するか」を補完する役割分担が明確です。
パターン2: Comprehendテキスト分類 → Personalizeアイテムメタデータ強化
タスク特化AIのAmazon Comprehendで商品説明文を分析し、カテゴリ・属性を自動タグ付けしてPersonalizeのItems CSVに充当します。これにより商品マスタのメタデータが薄い場合でも、Personalizeのコールドスタート対応力が向上します。
商品説明文
→ Comprehend分類(スポーツ/アウトドア/軽量 等)
→ Personalizeアイテムカラムに追加
→ コールドスタート精度向上
パターン3: Rekognition画像ラベル → アイテムメタデータ
Amazon Rekognitionで商品画像からラベル(「白いスニーカー」「ランニングシューズ」等)を自動抽出し、Personalizeのアイテムメタデータとして活用します。商品ページ画像がある場合に、テキスト属性が少ないアイテムのメタデータを補完できます。
rekognition = boto3.client("rekognition")
response = rekognition.detect_labels(
Image={"S3Object": {"Bucket": "my-bucket", "Name": "products/item_205.jpg"}},
MaxLabels=10,
MinConfidence=80,
)
labels = [label["Name"] for label in response["Labels"]]
# これをPersonalize Items CSVの属性カラムに追加する
需要予測の現状 — SageMaker Canvas時系列予測
Amazon Forecastは新規受付を停止しており、需要予測・時系列予測が必要な場合はSageMaker Canvasの時系列予測機能が現在の推奨代替です。SageMaker Canvasはコードなしで時系列予測モデルを構築・デプロイできるノーコードMLサービスです。
PersonalizeとSageMaker Canvasの組み合わせ例: ECサイトで「どの商品を何個在庫するか」の需要予測にSageMaker Canvasを活用し、在庫切れ商品をPersonalizeフィルタで自動除外する構成が現実解です。こうすることで「推薦の個人化」と「在庫整合性」を分離して管理できます。
E-Commerce統合パターン
ECサイトでの典型的なPersonalize活用マッピングです。各ページ/シーンに最適なレシピが異なる点は、Personalize設計の核心です。
| ページ/シーン | 活用レシピ | 推薦内容 |
|---|---|---|
| トップページ | User-Personalization-v2 | ユーザー個別の推薦商品 |
| 商品ページ「この商品を見た人は」 | SIMS(Item-to-Item類似) | 類似商品リスト |
| カート画面「次のアクション」 | Next-Best-Action | 次に取りやすい行動(購入促進) |
| カテゴリ一覧 | Personalized-Ranking-v2 | カテゴリ内商品の個人化ランキング |
| 急上昇トレンド枠 | Trending-Now | 最近急増している商品 |
| メール/プッシュ通知 | User-Personalization-v2(バッチ) | オフライン推薦リスト |
Event TrackerでカートアクションをeventType=”add-to-cart”として記録することで、Next-Best-Actionレシピが購入完了に向けたアクションを推薦できます。購入済みアイテムはフィルタ(EXCLUDE itemId WHERE INTERACTIONS.event_type IN ("purchase"))で自動除外し、推薦の質を維持します。
各シーンのA-Bテストは独立して設計することが重要です。トップページのPersonalize推薦導入効果は「クリック率向上」、SIMS類似商品はカート追加率、Next-Best-Actionは購入率をそれぞれ主要KPIとして設定します。
メディア/動画配信統合パターン
動画・音楽・コンテンツ配信サービスでのPersonalize活用例です。
データ設計のポイント
- Interactions: 再生開始・再生完了・スキップ・評価イベントをeventTypeに応じて重み付けします。再生完了=高スコア、スキップ=負のシグナルとして設定します
- Items: コンテンツID・ジャンル・公開日・出演者・言語をItems CSVに格納します。コンテンツメタデータの充実がコールドスタート対応力を決めます
- Users: 年齢層・選好ジャンル・プラットフォーム(モバイル/TV)をUsers CSVに格納します
User-Personalization-v2でホーム画面の「あなたへのおすすめ」を個人化し、Event TrackerでリアルタイムにViewEventを送信することで、セッション内での次コンテンツ推薦精度が向上します。再生完了率(Completion Rate)をA-BテストのKPIとして設定し、Personalize推薦ありvs.なしで比較するのが一般的なアプローチです。Trending-Nowレシピをホーム画面の「今話題」枠に補完的に使うことで、個人化推薦と話題性の組み合わせによるエンゲージメント向上が期待できます。
Lambda + API Gatewayによるサーバーレス推薦API構築
Personalizeのリアルタイム推薦をアプリに組み込む際、Lambda + API GatewayによるサーバーレスAPIレイヤーが最も採用される構成です。
App
→ API Gateway
→ Lambda
→ ElastiCache(キャッシュ確認)
→ ヒット: キャッシュを返す
→ ミス: Personalize GetRecommendations を呼び出す
→ filterArn/filterValuesで動的フィルタ適用
→ DynamoDB からアイテムメタデータを一括取得
→ ElastiCache にキャッシュして返却
Lambdaでの処理フロー:
- API GatewayからuserIdを受け取る
- ElastiCacheで推薦結果のキャッシュヒットを確認(TTL: 60〜300秒)
- キャッシュミス時はPersonalize GetRecommendationsを呼び出す
- filterArnで動的フィルタを適用(在庫状況をfilterValuesで渡す)
- DynamoDBからアイテムメタデータを一括取得してレスポンスを構築
- ElastiCacheに結果をキャッシュして返却
ElastiCacheによるキャッシュはPersonalizeのminProvisionedTPS課金を抑えるうえでも有効です。ただし、TTLが長すぎるとEvent Tracker経由で更新されたリアルタイム推薦が反映されなくなるため、ユーザー行動が活発なセッション中は短いTTL(30〜60秒)、長時間アクティビティがないユーザーには長めのTTL(300秒〜)を動的に切り替える設計が有効です。
Lambda関数のコールドスタート対策として、Provisioned Concurrencyを設定するか、CloudWatch EventsでのWarm-up呼び出しを設定します。推薦APIはユーザー操作のクリティカルパスに入るため、P99レイテンシ200ms以内を目標に設計します。DynamoDBからのアイテムメタデータ取得はBatchGetItemを使って並列化し、ボトルネックにならないよう注意します。
PersonalizeはAWS ML/AIサービスのエコシステムの中で「推薦という特定タスクのターンキー解」として位置づけられます。生成AIはBedrock(推薦理由生成・対話式推薦への発展)、抽出・分類はタスク特化AI(メタデータ自動付与)、自前モデルはSageMaker(精度要件が高まった際の移行先)、需要予測はSageMaker Canvasと役割を分担します。Personalizeはこれらのサービスと組み合わせることで、単体では実現できないリッチな推薦体験を構築できます。
- 推薦/パーソナライゼーション → Amazon Personalize(ターンキー・本記事)
- 抽出・分類・認識・文字起こし → タスク特化AI / 生成・要約・対話 → Bedrock
- 自前MLモデルの構築・MLOps → SageMaker / 需要予測 → SageMaker Canvas時系列予測(ForecastはSUNSET)
- 組合せ — Personalize推薦+Bedrockで推薦理由生成、ターンキーで開始し複雑化でSageMakerへ移行
自前MLモデル開発はこちら(SageMaker Unified Studio Vol1)
生成AIはこちら(Amazon Bedrock本番運用 Vol1)
8. つまずきポイント・アンチパターン・まとめ
Amazon Personalizeを本番で使い始めると、データ品質・設定ミス・コスト・運用の各フェーズで多くの落とし穴に遭遇します。本セクションでは現場で頻出するつまずきポイントとその対処法を解説し、アンチパターンと正解をまとめます。
つまずきポイント 7選
1. Interactionsデータ不足で精度が出ない
症状: ソリューションバージョンを作成してもNDCG@Kが極端に低い。または学習ジョブ自体が失敗してエラーになる。
原因: Personalizeはユニーク1,000件以上のインタラクション・25人以上のユーザー・2種類以上のアイテムを要求します。この最小要件を満たしていない、あるいはInteractionsが存在してもEVENT_TYPEが統一されておらず有効データが薄い場合に発生します。
対処法:
– 本番データが不足している初期段階では、まずコールドスタート戦略としてPopularity-Countを使いながらInteractionsを蓄積します
– EVENT_TYPEをview・click・purchase等で統一し、eventValueThresholdで低品質イベントを除外します
– 目安: User-Personalization-v2で実用的な精度を得るには最低でも1万件以上のInteractionsを確保します
2. USER_IDが数値型のみで本番ユーザーIDと不一致
症状: 推薦APIを呼び出してもユーザーが存在しないエラー、または常に新規ユーザー扱いになる。
原因: データベースのオートインクリメントIDをそのままCSVに投入すると、本番アプリの文字列型ユーザーID(UUID、ハッシュID等)と一致しません。
対処法:
– USER_IDは必ず文字列型(string)で投入します
– 本番アプリが内部的に数値IDを使う場合は、Personalizeへ投入する前に文字列型へキャストし、マッピングテーブルで変換関係を管理します
3. キャンペーンのminProvisionedTPS未調整でスロットリングまたはコスト超過
症状A: 本番トラフィックがキャンペーン設定のTPS上限を超えてスロットリングエラー(ThroughputExceededException)が発生する。
症状B: 逆に過大なminProvisionedTPSを設定して月額コストが予想外に高くなる。
原因: minProvisionedTPSはリクエストがなくても常時課金される最小TPS値です。多くの場合、初期設定のまま本番に投入し、後から気づくパターンです。
対処法:
– 本番前に負荷テストを実施し、ピークTPSを測定してからminProvisionedTPSを設定します
– オートスケーリングを有効化し、maxProvisionedTPSを上限として設定します
– 低トラフィックのユースケースはバッチ推論ジョブへの切り替えを検討します
4. A-Bテスト未実施でレシピ変更・再学習の効果が不明
症状: レシピ変更や再学習後に「精度が上がった」とオフラインメトリクスで判断したが、実際のCTR・購入率に変化がない。
原因: NDCG等のオフラインメトリクスとオンラインのビジネス指標は必ずしも相関しません。オフライン評価のみで判断すると、ユーザーに悪影響を与える変更を見逃すリスクがあります。
対処法:
– レシピ変更やHPOで有望なソリューションバージョンを特定した後は、必ず複数キャンペーン並行稼働でA-Bテストを実施します
– キャンペーン割り振りはユーザーIDのハッシュ値を使い、同一ユーザーが常に同じ群へ入るようにします
– 評価指標はCTR・購入率・セッション時間など業務目標に直結するKPIを使用します
5. フィルタ式が複雑すぎてGetRecommendations APIのレスポンスが遅い
症状: GetRecommendations APIの応答時間がSLAを超える。または推薦数が指定より大幅に少ない。
原因: 複数条件のフィルタ(在庫切れ除外AND購入済み除外AND特定カテゴリ限定等)を組み合わせると、フィルタリング後の候補が極端に少なくなったり、処理負荷が増加します。
対処法:
– フィルタは必要最小限に絞ります。複雑なビジネスロジックはアプリ側で実装します
– フィルタ対象の除外リストが大きい場合は、Personalizeフィルタよりアプリ側後処理の方が高速です
– numResultsより多めに推薦を取得しておいてアプリ側でフィルタするアプローチも有効です
6. 再学習スケジュール未設定でモデルが陳腐化
症状: サービス開始当初は推薦が適切だったのに、数週間後から「古い商品」「在庫切れ商品」が推薦される。新規アイテムが推薦に出てこない。
原因: User-Personalization-v2は自動更新(2時間ごと)でInteractionsの変化に追従しますが、ソリューションバージョン自体の全学習(FULL)を省くとItemsデータセットの変化(新商品追加、廃盤商品削除)が反映されません。
対処法:
– 定期的な全学習(週次・月次等)をEventBridge + Step Functionsで自動化します
– 商品カタログ更新タイミングでデータセットインポートジョブを自動実行します
– フィルタで在庫切れアイテムを除外し、Itemsデータセットから廃盤アイテムを削除するパイプラインを整備します
7. バッチジョブ出力がS3に散乱して後処理が未実装
症状: バッチ推論ジョブは成功するが、S3出力が整理されておらず後段のメール配信・DynamoDB書き込みと連携できていない。
原因: バッチ推論ジョブはS3パスに出力をそのまま置くだけで、後処理は利用者側で実装する必要があります。このアーキテクチャが理解されていないと、出力が使われずS3へ溜まり続ける状態になります。
対処法:
– S3パス設計をs3://bucket/personalize-output/{date}/{job-name}/のように日付・ジョブ名で整理します
– S3イベント通知またはEventBridgeルールでジョブ完了を検知し、Lambda経由でDynamoDB書き込み・SQS・メール配信等の後処理を自動実行します
– バッチ出力はJSON形式(1行1ユーザーの推薦リスト)であることを前提にパーサーを実装します
8. CSVスキーマ不整合でデータ取込ジョブが失敗する
症状: データセットインポートジョブを実行すると途中でエラー終了し、Personalizeにデータが取り込まれない。コンソールで確認するとスキーマ検証エラーが表示される。
原因: Personalizeへのデータ取り込みはAvro JSONで定義したスキーマとCSVヘッダー・カラム型が完全一致している必要があります。よくある不整合として以下が挙げられます。
- USER_IDをCSVでは
user_idと小文字で書いているがスキーマではUSER_IDと大文字で定義している - TIMESTAMPカラムがISO形式(
2024-01-01T00:00:00)で入力されているが、Personalizeが要求するのはUnixエポック秒(整数型) - EVENT_VALUEをCSVにNULL/空文字で入力しているが、スキーマで
["null", "float"]ではなくfloat(non-nullable)で定義している - CSVにスキーマ未定義の余分なカラムが含まれている
対処法:
- まずS3に配置するCSVをサンプル100件程度に絞って小規模でインポートジョブを試し、スキーマ検証エラーを早期発見します
- TIMESTAMPはETLで必ず
int(datetime.timestamp())形式に変換してから出力します - スキーマでnullableなフィールドは
["null", "型"]形式で定義し、CSVの空値を許容します - 本番規模データ投入前にスキーマ検証スクリプトを作成し、ヘッダー名・型・行数を自動チェックするCI/CDステップを追加します
スキーマ定義とCSVの整合性確認は一度正しく設定すれば繰り返し問題になりにくいですが、データソースの変更やETLリファクタリング時に意図せず壊れることがあります。データパイプラインへの自動検証組み込みを推奨します。
アンチパターン → 正解対応表
| # | アンチパターン | 何が起きるか | 正解 |
|---|---|---|---|
| AP1 | Personalized-Ranking-v2を個人化推薦に使う | GetRecommendationsが使えない。並べ替え専用レシピのため候補リストなしでは推薦結果が返らない | 個人化推薦にはUser-Personalization-v2を使う |
| AP2 | minProvisionedTPSを10など大きい値で設定して放置 | 推薦リクエストが月に数件でも24時間×10TPSで課金が継続し月額コストが数万円規模になる | 負荷測定後に適切な最小値(1〜3程度から開始)を設定し、オートスケーリングで上限をカバー |
| AP3 | Event Trackerを設置せず静的データのみで運用 | 新規ユーザーはInteractionsゼロのため常にコールドスタート推薦(人気順)になり、パーソナライゼーションが働かない | Event Tracker + PutEvents APIでセッション中の行動をリアルタイム投入し、コールドスタートを段階的に解消 |
| AP4 | オフラインNDCGだけで「精度改善確認済み」と判断しA-Bテストを省略 | 実際のCTR・購入率が改善しないどころか悪化する変更を本番適用するリスクがある | オフラインメトリクスは絞り込みに使い、最終判断は必ずオンラインA-Bテスト(複数キャンペーン並行)で実施 |
| AP5 | CSVのUSER_IDを数値型で投入 | 本番アプリのユーザーIDと型不一致になり、APIで「未知のユーザー」扱いになりコールドスタート推薦が継続 | USER_ID・ITEM_IDは文字列型で統一し、本番アプリのIDと完全一致させる |
| AP6 | 購入済み商品フィルタを設定せず運用 | ユーザーが既に購入した商品が繰り返し推薦され、推薦体験が著しく低下しCTRが下がる | Personalizeフィルタで購入済み(PURCHASED)イベントのあるアイテムを除外する式を設定する |
本番導入前チェックリスト
Amazon Personalizeを本番環境へリリースする前に、以下のチェックリストを確認することを推奨します。
データ品質チェック
- [ ] Interactionsデータが1,000件以上(推奨: 1万件以上)あるか
- [ ] USER_ID・ITEM_IDが文字列型で統一されているか
- [ ] TIMESTAMPがUnixエポック秒(整数型)で格納されているか
- [ ] EVENT_TYPEが統一されており、購入イベントに高いEVENT_VALUEを付与しているか
- [ ] ボット・テストユーザーのインタラクションが除去されているか
設定チェック
- [ ] レシピが用途に合致しているか(個人化推薦にはUser-Personalization-v2を使用)
- [ ] minProvisionedTPSが負荷テスト結果をもとに適切な値へ設定されているか
- [ ] 購入済み商品除外フィルタが設定されているか
- [ ] Event Trackerが設定されており、リアルタイム行動投入が可能か
- [ ] 定期再学習スケジュール(週次または月次)が設定されているか
監視・運用チェック
- [ ] CloudWatchでGetRecommendationsのレイテンシ・エラー率アラームを設定しているか
- [ ] バッチ推論ジョブの後処理(DynamoDB書き込み等)が実装されているか
- [ ] A-Bテストの実施計画と成功基準(KPI・評価期間)を策定しているか
- [ ] 不要になったキャンペーンを即座に削除するオペレーション手順があるか
このチェックリストを本番リリースのgatingとして活用することで、上述のアンチパターンを事前に回避できます。
まとめ — Amazon Personalizeで実現するターンキーML推薦の全体像
Amazon Personalizeは、AWSが長年Amazonショッピングで培った推薦技術をマネージドサービスとして提供するターンキーMLです。機械学習エンジニアがモデルを自前構築することなく、データを用意してレシピを選択するだけで本番品質の推薦エンジンを稼働できます。
本記事で学んだ主要ポイントの再確認
- データセットグループの3テーブル構成: Users / Items / Interactionsの3データセットが基本です。Interactionsが推薦精度の核心であり、1,000件以上(実用は1万件以上)を確保することが精度の前提条件です
- レシピ選定が設計の肝: User-Personalization-v2を軸に、用途に応じてTrending-Now・SIMS・Personalized-Ranking-v2を組み合わせます。Personalized-Ranking-v2は再ランク付け専用で個人化推薦には使用できません
- ソリューション → ソリューションバージョン → キャンペーン: このパイプラインを理解することで、学習・デプロイ・更新のサイクルを設計できます
- minProvisionedTPSは常時課金: キャンペーン設定の最重要コストパラメータです。適切な値を負荷テスト後に設定し、不要なキャンペーンは速やかに削除します
- バッチ推論ジョブ: メール配信や日次バッチなどリアルタイム不要な用途はバッチ推論でコストを大幅削減できます
- A-Bテストは必須: オフラインNDCGとオンラインCTRは必ずしも相関しません。レシピ・モデル変更の効果は複数キャンペーン並行稼働のA-Bテストで最終確認します
ML/AIサービスとの使い分けの再確認
推薦・パーソナライゼーション用途にはPersonalize(本記事)を選択します。テキスト抽出・画像認識・音声認識はタスク特化AI、生成・要約・対話はBedrock、自前MLモデルの構築・チューニングはSageMakerが最適です。要件の複雑化に伴い、Personalizeのターンキー推薦から始めてSageMaker自前MLへ段階移行する成長パスも有力です。
Personalizeを選ぶ判断基準
自前MLモデルの構築(SageMaker)とPersonalizeのどちらを選ぶか迷った場合は、以下の基準を参考にします。
- 推薦アルゴリズムのカスタマイズ要件が少ない → Personalize(ターンキー)
- 固有のビジネスロジックやカスタム特徴量が推薦の核心 → SageMaker自前ML
- 数週間以内のプロトタイプ検証が必要 → Personalize(セットアップ速度優位)
- 数百万アイテム・数千万ユーザーのスケールで独自最適化が必要 → SageMaker自前ML
初期フェーズはPersonalizeで速く始め、要件の複雑化に応じてSageMakerへ段階移行する成長パスが多くのプロジェクトで現実解です。
Vol2予告 — Personalize本番運用の深化
本記事Vol1では、Amazon Personalizeのコアコンポーネント(データセットグループ・レシピ・ソリューション・キャンペーン・バッチ推論)と実運用で頻出するつまずきポイント・アンチパターンを解説しました。続くVol2では以下のトピックを取り上げる予定です。
- マルチテナント推薦設計: データセットグループ分離戦略とテナント間推薦精度の最適化
- フィルタ設計の応用: 動的フィルタ(ユーザー属性・リアルタイム在庫との連携)と静的フィルタの使い分け
- Event Trackerの高度な活用: セッションベースのリアルタイム更新とコンバージョンファネル最適化
- コスト最適化の高度手法: キャンペーンのTPS自動調整・バッチ/リアルタイムのハイブリッド設計
- 本番トラブルシューティング: CloudWatchアラーム設計・推薦品質の継続的モニタリング体制
Vol2公開までは、SageMaker MLOpsパイプラインやBedrockとの組み合わせによる推薦システム強化についても関連記事でご確認いただけます。
- Amazon Personalizeはモデル構築不要で推薦エンジンを実装するターンキーML
- データセットグループ(Users/Items/Interactions)+レシピ選択が設計の肝。Interactions行動ログが精度を左右
- リアルタイム推薦API+Event Tracker+フィルタで運用。精度はオフラインメトリクス+A-Bテストで評価
- 推薦はPersonalize、生成はBedrock、自前MLはSageMaker、需要予測はSageMaker Canvasと使い分ける
関連: SageMaker MLOps(ML/AI本番運用 Vol3)