Amazon Web Services ブログ

Amazon Redshift Serverless と Amazon SageMaker によるスケーラブルな大規模データ活用基盤のコストベンチマーク

AI/ML(機械学習)の技術を実ビジネスに活用できるか検証するPoC(Proof of Concept:概念実証)フェーズにおいては、対象範囲を絞った小さなデータセットでMLモデルの構築・評価を行うことがあります。例えば小売業において、特定の店舗や商品カテゴリに絞り、需要予測モデルを構築してみるケースなどです。

PoCでよい結果が得られれば、全店展開や全商品展開など実ビジネスへの導入にむけてプロジェクトが動きますが、ここで課題が発生します。大規模データが対象になったことによる処理時間やコストの増大です。大規模データ処理基盤をいちから検討すると工数がかかり、本番導入への障壁になる可能性もあります。

このような課題解決に向けて、私たちは小売業で売り上げ数量の予測を実現するサンプルソリューションを公開しました。この記事では、Amazon Redshift Serverless と Amazon SageMaker を使用した大規模データ活用ソリューションで、実際にさまざまなサイズのデータで検証を行い、本ソリューション利用にかかるコストや時間を示すとともに、検証から得られたソリューション利用のポイントを解説します。

ソリューション

大規模データ処理を高速かつ低コストに実現するためのソリューションをGitHubで公開しています。このソリューションは、小売業を想定したサンプルデータセットを併せて用意しており、店舗別、商品別の売上個数の予測値を算出します。アーキテクチャの詳細はこちらを参照してください。

主な処理は、Amazon Redshift Serverless によるデータの前処理や特徴量生成、Amazon SageMaker によるMLモデルのトレーニング、SageMaker による推論(店別・商品別の売り上げ数量予測)の3つです。

Amazon Redshift Serverless は、大規模なデータに対する分析や加工をコスト効率よく高速に実行できるデータウェアハウスのサービスです。機械学習に必要な前処理をSQLで手軽に実行することができます。また、Serverless であることからインフラストラクチャーの管理が不要であるため、運用にあたってインフラストラクチャーの専門家を配置する必要はありません。

Amazon SageMaker は、高性能かつ低コストの機械学習をあらゆるユースケースで実現するための、包括的なツールセットを提供するフルマネージドサービスです。SageMakerを使用することで、ノートブック、デバッガー、プロファイラー、パイプライン、MLOpsなどのツールを使って、スケール可能なMLモデルの構築、トレーニング、デプロイができます。また、データサイエンティストやMLエンジニアが機械学習モデルのトレーニングとデプロイを迅速に開始できるようにする組み込みアルゴリズムスイートを提供しています。

本ソリューションでは SageMaker ビルトインアルゴリズムの LightGBM を利用しています。売り上げ数量予測は夜間にバッチ処理にて計算する運用を想定し、SageMaker バッチ変換ジョブを用いています。データ規模に対する処理時間とコストのベンチマークのため、MLモデルの予測精度は評価対象外としています。

サンプルデータセット

ソリューションには、下の表に示すような商品マスタ、店舗マスタ、イベントカレンダ情報、天気情報、トランザクション(会計)データなどが用意されています。これらのデータは人工的に作成しています。データのさらなる詳細についてはこちらをご参照ください。

ファイル名 データ名 概要
categories.csv 商品カテゴリマスタ 商品の大分類、中分類、小分類などのカテゴリに関する情報
event_calendar.csv イベントカレンダ 祝日や、全社的なイベントに関する情報。店舗からの入力が必要な「店舗別イベント情報」は用いない。
products.csv 商品マスタ 商品名、カテゴリ、価格などの商品に関する情報
stores.csv 店舗マスタ 店舗タイプや所在地などの店舗に関する情報
transactions.csv 会計記録 1会計処理(トランザクション)を1レコードで記録。購買商品詳細はtransaction_details.csvに記録
transaction_details.csv 会計明細 会計内容の詳細、購買商品の種類ごとにレコードを持つ
weather.csv 天気情報 外部システムから取得した日別、都道府県別の天気に関する情報

GitHubにあるサンプルデータは、10MB程度の小さなものです。今回の検証ではより大きなデータセットを作成し、4つのデータセットに対して検証を行います。データセット名と特徴は以下の通りです。

  • retail_small : GitHubにある小規模データセット。20商品、3店舗、トランザクション5分に1回。
  • retail_medium : 中規模データセット。3500商品、200店舗、トランザクション1分に1回。
  • retail_large : 大規模データセット。3500商品、2000店舗、トランザクション1分に1回。
  • retail_extra_large : 特大規模データセット。3500商品、20000店舗、トランザクション1分に1回。

各データセットにおける各ファイルの詳細を以下に示します。ファイル名をクリックするとダウンロードすることができます。

 

データセット ファイル名 レコード数 サイズ(.csv) サイズ(.csv.gz) 説明
retail_small categories.csv 14 864 B
event_calendar.csv 19 1.6 KB
products.csv 20 1.4 KB 20商品
store.csv 3 200 B 3店舗
weather.csv 90 6.4 KB
transactions.csv 25059 2.1 MB 各店舗5分に1回発生
transaction_details.csv 137559 8.2 MB
TOTAL 約 16 万 10.3 MB
retail_medium categories.csv 250 15.9 KB
event_calendar.csv 19 1.9 KB
products.csv 3500 267.1 KB 3500商品
store.csv 200 16 KB 200店舗
weather.csv 1410 99.8 KB
transactions.csv.gz 8352200 726 MB 100 MB 各店舗1分に1回発生
transaction_details.csv.gz 45999200 2.9 GB 310 MB
TOTAL 約 0.46 億 3.7 GB 0.4 GB
retail_large categories.csv 250 15.9 KB
event_calendar.csv 19 1.9 KB
products.csv 3500 267.1 KB 3500商品
store.csv 2000 157 KB 2000店舗
weather.csv 1410 99.8 KB
transactions.csv.gz 83522000 7.2 GB 992 MB 各店舗1分に1回発生
transaction_details.csv.gz 459992000 30 GB 3.1GB
TOTAL 約 4.6 億 37 GB 4 GB
retail_extra_large categories.csv 250 15.9 KB
event_calendar.csv 19 1.9 KB
products.csv 3500 267.1 KB 3500商品
store.csv 20000 1.6 MB 20000店舗
weather.csv 1410 99.8 KB
transactions.csv.gz 835220000 74 GB 9.7 GB 各店舗1分に1回発生
transaction_details_storeid_1_2000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_2001_4000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_4001_6000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_6001_8000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_8001_10000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_10001_12000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_12001_14000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_14001_16000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_16001_18000.csv.gz 459992000 30 GB 3.1 GB
transaction_details_storeid_18001_20000.csv.gz 459992000 30 GB 3.1 GB
TOTAL 約 46 億 374 GB 40 GB

retail_extra_largeデータセットのtransaction_details.csvについては、2000店舗ごとにファイルを分けています。データ内容はstore_id以外は各店舗で同一です。

実験:処理時間とコストの計測

4つのデータセットに対して、Redshift Serverless による前処理、SageMaker による学習、SageMaker による推論の処理時間とコストを計測しました。

実施手順

GitHub上に準備されているretail_smallデータセットに対しては、クイックスタートガイドに従って実施することができます。その他3つのデータセットに対しては、データセットをダウンロードして実施する必要があります。以下にretail_extra_largeのケースについてガイドします。

retail_extra_largeデータセットの検証ガイド

クイックスタートガイド:デプロイの準備「4. 実行環境の準備」において、AWS Cloud9 のリサイズは 500GB とします。データセットのダウンロードで必要なためです。(retail_medium、retail_largeは 100GB で十分)

クイックスタートガイド:How to deploy「1. cdk.jsonを編集」において、パラメータの編集を行います。

  • “trainingInstanceType”の、”ml.m5.xlarge”を”ml.m5.4xlarge”に変更します。(SageMaker学習ジョブでのメモリ枯渇に対応。retail_medium、retail_largeは変更不要)

クイックスタートガイド:Operation「3. テストデータをアップロード」において、データセットのダウンロード、.gzファイルの解凍、S3へのアップロードを行います。

まず、Cloud9 のターミナルで以下のコマンドを実行し、ファイルのダウンロードを行います。(retail_medium、retail_largeの場合は、-Pオプションの格納先ディレクトリと、ダウンロードURLを変更してください。)

<Cloud9 ターミナルで実行>

cd /home/ec2-user/environment/retail-large-data-ml-e2e/test

wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/categories.csv
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/event_calendar.csv
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/products.csv
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/store.csv
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/weather.csv
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transactions.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_1_2000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_2001_4000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_4001_6000.csv.gz 
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_6001_8000.csv.gz 
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_8001_10000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_10001_12000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_12001_14000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_14001_16000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_16001_18000.csv.gz
wget -P ./extralargedata/ https://d3rhanl4x81lsu.cloudfront.net/retail_extra_large/transaction_details_storeid_18001_20000.csv.gz

ダウンロードファイルに含まれる.gzファイルを解凍します。

<Cloud9 ターミナルで実行>

gunzip extralargedata/*.gz

解凍したデータセットをCloud9からS3にアップロードします。まず、以下の upload_s3.sh ファイルを作成します。

<Cloud9 ターミナルで実行>

cd /home/ec2-user/environment/retail-large-data-ml-e2e/test

touch upload_s3.sh

upload_s3.shを開き、以下の内容を記載します。

<upload_s3.shの中身>


#!/bin/bash

echo "create prefix in ${INPUTBUCKET}"
echo "data size is ${DIR_SIZE}"

aws s3 cp ${DIR_SIZE}/categories.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/categories/categories.csv
aws s3 cp ${DIR_SIZE}/event_calendar.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/event_calendar/event_calendar.csv
aws s3 cp ${DIR_SIZE}/products.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/products/products.csv
aws s3 cp ${DIR_SIZE}/store.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/stores/store.csv
aws s3 cp ${DIR_SIZE}/weather.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/weather/weather.csv
aws s3 cp ${DIR_SIZE}/transactions.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transactions/transactions.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_1_2000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_1_2000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_2001_4000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_2001_4000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_4001_6000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_4001_6000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_6001_8000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_6001_8000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_8001_10000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_8001_10000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_10001_12000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_10001_12000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_12001_14000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_12001_14000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_14001_16000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_14001_16000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_16001_18000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_16001_18000.csv
aws s3 cp ${DIR_SIZE}/transaction_details_storeid_18001_20000.csv s3://${INPUTBUCKET}/${PROCESSINGDATE}/transaction_details/transaction_details_storeid_18001_20000.csv

この、upload_s3.shをターミナルから以下のコマンドで使用します。INPUTBUCKET変数にはS3バケット名(retaildatasolutionstack-inputbucketXXXの正しい名称)を記載してください。

<Cloud9 ターミナルで実行>


### バケット名置き換える
export INPUTBUCKET=retaildatasolutionstack-inputbucketXXXXXXXX-XXXXXXXXXXXXX

### Cloud9のデータセットディレクトリ
export DIR_SIZE=extralargedata

for GENDATE in 2023-04-01 2023-04-15 2023-04-16 2023-04-17
do
export PROCESSINGDATE=${GENDATE}
bash upload_s3.sh
done

この後は、クイックスタートガイド:Operation「4. ワークフローキック」から手順通りに実行します。

計測方法

  • Redshift Serverlessについては、AWS Step Functionsの”WakeUpRedshift”から”TrainingKicker”までを処理時間とします。この中で”WaitForWakeUp”は600秒待つ設定となっているので、処理時間から600秒を引いて算出します。
  • Redshift Serverlessのコストについては、4回ジョブを実行するので、合計コストを4で割った値とします。
  • SageMaker学習については、SageMakerトレーニングジョブの詳細画面から「請求可能な時間(秒)」を取得し、インスタンスの単価から算出します。
  • SageMaker推論はバッチ変換ジョブの詳細画面から「およそのバッチ変換所要時間」を取得し、インスタンスの単価と数から算出します。

その他条件

  • リージョン:東京リージョン(ap-northeast-1)
  • 学習インスタンスタイプ: ml.m5.xlarge (retail_extra_largeのみ検証ガイドで述べた通りml.m5.4xlarge)
  • 推論インスタンスタイプ: ml.m5.xlarge
  • cdk.jsonのパラメータ”inferenceInstanceCount”は1とし、負荷分散しない場合の推論処理時間を計測する。

計測結果

計測は2023年12月〜2024年1月のものであり、最新の状況では異なる可能性があることにご留意ください。

東京リージョンにおけるml.m5.xlargeの時間あたり料金は0.298USD、ml.m5.4xlargeは1.19USDになります。(トレーニング、バッチ変換ともに)

データセット データサイズ Redshift Serverless 処理時間 [秒] Redshift Serverless コスト [ドル] SageMaker学習 処理時間 [秒] SageMaker学習 コスト [ドル] SageMaker推論 処理時間 [秒] SageMaker推論 コスト [ドル] TOTAL 処理時間 [秒] TOTAL コスト [ドル]
retail_small 10.3 MB 259 4.48 77 0.00637 120 0.00993 456 4.4963
retail_medium 3.7 GB 558 7.755 167 0.01382 240 0.01987 965 7.78869
retail_large 37 GB 2159 28.295 924 0.07649 1320 0.10927 4403 28.48076
retail_extra_large 374 GB 4136 70.58 2584 0.85416 12420 1.0281 19140 72.46226

処理時間を [秒] から [時分秒] へ、コストを [ドル] から[円] へ変換して以下に示します。(1ドル = 150円換算)

コストは少数第2位以下切り捨てで表示しています。

データセット データサイズ Redshift Serverless 処理時間 [時分秒] Redshift Serverless コスト [円] SageMaker学習 処理時間 [時分秒] SageMaker学習 コスト [円] SageMaker推論 処理時間 [時分秒] SageMaker推論 コスト [円] TOTAL 処理時間 [時分秒] TOTAL コスト [円]
retail_small 10.3 MB 4分19秒 672.0 1分17秒 0.9 2分0秒 1.4 7分36秒 674.4
retail_medium 3.7 GB 9分18秒 1163.2 2分47秒 2.0 4分0秒 2.9 16分5秒 1168.3
retail_large 37 GB 35分59秒 4244.2 15分24秒 11.4 22分0秒 16.3 1時間13分23秒 4272.1
retail_extra_large 374 GB 1時間8分56秒 10587.0 43分4秒 128.1 3時間27分0秒 154.2 5時間19分0秒 10869.3

さらに処理時間を短縮するために

  • 前処理に関しては、データの規模がさらに大きくなり、処理時間が問題になってきた場合は、Amazon Redshift Serverlessの処理能力をスケールさせることで対応することができます。Amazon Redshift Serverlessではベースの処理能力をRPU (Redshift Processing Unit) という単位で設定することができます。この値を大きくすることで処理能力を増大させ、処理の実行時間を短縮することができます。Amazon Redshift Serverlessの料金体系はRPUとクエリ実行時間を掛け合わせたものであるため、例えばRPUを2倍にすることで実行時間を半分にできたとすると、合計の料金が変わることなく実行時間を短縮することができます。
  • SageMaker学習に関しては、今回は1インスタンスで実施しましたが、長時間になることはありませんでした。しかし特徴量の数やハイパーパラメータによっては長時間化する可能性があります。その場合の選択肢として、SageMakerビルトインアルゴリズムのLightGBMは分散学習機能を実装しています。
  • SageMaker推論に関しては、retail_extra_largeの場合でも3時間27分、TOTALでも5時間19分であったことは、夜間のバッチ処理を想定しても実用に耐えうる値と思われます。また、今回は推論インスタンスを1で実施しましたが、”inferenceInstanceCount”パラメータを1より大きくすることで分散して推論処理を得られることができます。参考に、”inferenceInstanceCount”を4にした場合、3時間27分が55分となりました。単純に1/4の時間にはなりませんが、処理時間をパラメータ変更のみで大きく短縮することができます。

まとめ

本稿では、「小売業で売り上げ数量の予測を実現するサンプルソリューション」を活用することで、コストを抑えつつ、大規模データを短時間で処理できることを示すために検証を行いました。POCのデータサイズでは問題にならなくても、大規模データを利用する本番環境ではコストや時間が課題になることがあります。

今回の検証では、370GB、47億レコードのデータに対して5時間強、10000円強程度で処理が可能という結果を得ました。これは本ソリューションが大規模データにおいて高いコストパフォーマンスを提供することを示しています。また、推論を4インスタンスに分散することで、推論処理時間が3時間27分から55分に短縮され、全体としても5時間19分から2時間47分までさらに短縮できることが確認できました。

一方で、あくまで今回のデータセットに対しての結果であり、別データでも同じ性能が出るとは限らない点に注意が必要です。データや前処理ロジック、モデルパラメータで異なりますので、本稿を参考に自社のデータでも試していただければと思います。


著者について

dcoccia 伊藤 芳幸(Ito Yoshiyuki), シニア機械学習ソリューションアーキテクト
生成AIを含むAI/ML技術の支援を担当しています。事業会社での経験を生かし、ビジネス上の課題を解決するためのAI/MLソリューションの提案や導入支援に努めています。新しい技術に触れることは楽しみの一つで、積極的に手を動かしています。
プライベートでは育児に忙しい日々を送っていますが、フットサルやジム通いを通じてストレスを発散しています。

dcoccia 秋田 仁雅(Akita Yoshinori), プロトタイピングエンジニア
普段は AWS を用いてプロトタイプを開発することでお客様の課題を解決するプロトタイピングエンジニアという業務を担当。

dcoccia 平間 大輔(Hirama Daisuke), Redshift スペシャリストソリューションアーキテクト
AWSでは主にデータウェアハウスサービスのAmazon Redshiftに関する技術支援を担当。パフォーマンスチューニングが大好物。プライベートでは最近レトロPCいじりにハマっています。

dcoccia 下佐粉 昭(Shimosako Akira, @simosako), シニアソリューションアーキテクト (アナリティクス)
AWS ではデータレイク、データウェアハウス、BI 等アナリティクス領域専門のエンジニアとして活動。分析システムを AWS 上で稼働させるための技術支援を行いつつ、オンラインセミナーやイベントを通じて、新しい考え方や技術を広くを伝える活動をしている。
最近は「週刊 AWS」で、AWS の最新情報を伝える活動も行っている。プライベートは完全なインドア派でスポーツ観戦・観劇・絵画や映画の鑑賞と体を動かさないことに時間を費やしているが、そろそろ運動する習慣を作らないとヤバいのではと焦る日々。