この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんちには。
データアナリティクス事業本部機械学習チームの中村です。
今回はAmazon Forecastの新機能であるwhat-if分析についてご紹介します。
AWS公式ブログでは以下の記事で紹介されています。
Amazon Forecastの概要
まずAmazon Forecastの概要をおさらいします。
Amazon Forecastは時系列データを予測するサービスです。
入力できる情報には以下の3種類があります。
- TARGET_TIME_SERIES(TTS)
- 予測対象(ターゲット)となる時系列データ。(例: 需要予測の場合は需要のデータ)
- 時系列で変化しない情報(例: 店舗ID)を含めることで分析軸を追加可能。
- RELATED_TIME_SERIES(RTS)
- 関連する時系列データ。(例: 需要予測の場合は価格など)
- TTSに付加した分析軸はこちらにも追加が必要。
- ITEM_METADATA
- アイテムのメタデータを追加することが可能。(例: 商品のブランドなど)
TTSは全てのケースでおいて必須のデータですが、what-if分析ではRTSも必要となります。
what-if分析とは
what-if分析はRTSが変化した際に、TTSがどのように変化するかを分析するための機能です。
例えば「需要予測」の場合は、「需要(TTS)」とは別の関連する時系列データである「価格(RTS)」を過去に遡って下げたと仮定した場合に、 予測した「需要(TTS)」がどの程度変化するのかを分析することが可能になります。
また、Amazon Forecastにかかる費用は以下の通りです。
- データのインポート
- Predictorのトレーニング
- 予測したデータポイント数
- 予測の説明
このうち、What-if分析はデータポイントを予測するため、「予測したデータポイント数」の部分にコストが掛かってくるのでご注意ください。
(実際本記事の通りに実行すると、60ドル程度は必要になりますので留意頂ければと思います)
what-if分析のトライ
今回関連するリソースは以下のような階層構造になっています。
What-if分析に相当するのは、オレンジ部分で、一旦Forecastまで作成した上で構築する必要があります。
S3の準備
事前にバケット作成しておきます。(今回は以下)
- バケット名: sample-nakamura-2022-09-09-forecast
以下のGitHubに、公開されているデータセットがあります。
ここから以下の2つのファイルをダウンロードします。
- consumer_electronics_TTS.csv
- consumer_electronics_RTS.csv
これらをS3のそれぞれアップロードしておきます。(今回は以下)
- s3://sample-nakamura-2022-09-09-forecast/target/consumer_electronics_TTS.csv
- s3://sample-nakamura-2022-09-09-forecast/related/consumer_electronics_RTS.csv
Dataset group作成
「View dataset groups」を押下し、データセットグループ一覧を表示します。
「Create dataset group」を押下します。
Dataset groupの情報を以下のように入力し、末尾の「Next」を押下します。
- Dataset group name: sample_nakamura_what_if_dsg
- Forecasting domain: Custom
Dataset(ターゲット側)作成
Datasetの情報を以下のように入力します。
- Dataset name: sample_nakamura_what_if_tts
- Frequency of your data: 1 months
- Data schema: JSON builderをチェック
またJSON schemaには以下を設定し、Timestamp formatにはyyyy-MM-dd
を設定します。
{
"Attributes": [
{
"AttributeName": "item_id",
"AttributeType": "string"
},
{
"AttributeName": "store_id",
"AttributeType": "string"
},
{
"AttributeName": "timestamp",
"AttributeType": "timestamp"
},
{
"AttributeName": "target_value",
"AttributeType": "float"
}
]
}
Dataset importの設定は以下とします。
- Dataset import name: sample_nakamura_what_if_tts_import
- Select time zone: Do not use time zone
- Import file type: CSV
- Data location: s3://sample-nakamura-2022-09-09-forecast/target/consumer_electronics_TTS.csv
IAM roleは、Create a New Roleを選択すると以下のダイアログがでるので、
Specific S3 bucketsを以下のように設定して、「Create role」を押下します。
- sample-nakamura-2022-09-09-forecast
ちなみに作成されるロールにアタッチされるポリシーは以下のようになります。
(書き込み権限もあるので、後述のエクスポート時もこちらを使用していきます。)
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::sample-nakamura-2022-09-09-forecast"
]
},
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::sample-nakamura-2022-09-09-forecast/*"
]
}
]
}
ロールが作成されるので、その後「Start」を押下します。
その後Importが開始されます。
Dataset group一覧から作成したDataset groupを選択すると、
直後は「Create pending」となっているため、以下のようにActiveとなるまで待ちます。
Dataset(関連データ側)作成
what-if分析には、Related time series dataが必要となるため、上記の画面で「Import」を押下します。
Datasetの情報を以下で入力します。
- Dataset name: sample_nakamura_what_if_rts
- Frequency of your data: 1 months
- Data schema: JSON builderをチェック
またJSON schemaには以下を設定し、Timestamp formatにはyyyy-MM-dd
を設定します。
{
"Attributes":[
{
"AttributeName":"item_id",
"AttributeType":"string"
},
{
"AttributeName":"store_id",
"AttributeType":"string"
},
{
"AttributeName":"timestamp",
"AttributeType":"timestamp"
},
{
"AttributeName":"price",
"AttributeType":"float"
},
]
}
Dataset importの設定は以下とします。
- Dataset import name: sample_nakamura_what_if_rts_import
- Select time zone: Do not use time zone
- Import file type: CSV
- Data location: s3://sample-nakamura-2022-09-09-forecast/target/consumer_electronics_RTS.csv
IAM roleは、先ほどと同じロールを指定します。(データ格納先のバケットは同じの場合)
その後「Start」を押下します。
Importが始まるので、先ほどと同様にRelated time series dataが「Active」となるまで待ちます。
Predictor作成
次にPredictorを作成します。先ほどの画面で、Predictor trainingの横にある「Start」を押下します。
Predictor settingsは以下の値で設定します。
- Predictor name: sample_nakamura_what_if_predictor
- Forecast frequency: 1 month(s)
- Forecast horizon: 3
- Forecast dimensions: store_id
- Forecast quantiles:
- Forecast quantile: Forecast quantile 1, Value: 0.10
- Forecast quantile: Forecast quantile 2, Value: 0.50
- Forecast quantile: Forecast quantile 3, Value: 0.90
他はデフォルトのまま、ページ下部の「Create」を押下します。
すると、Trainingが開始され、Predictor一覧で残り時間が表示されます。
(今回は2時間程度必要でした)
Forecast作成(予測の実行)
Predictor一覧から作成したPredictorを選択すると、「Create forecast」ボタンがありますので、
そこで予測を実行します。
Forecast detailsは以下の値で設定します。
- Forecast name: sample_nakamura_what_if_forecast
- Predictor: sample_nakamura_what_if_predictor
- Item for generating forecasts: All Items
作成が開始されるので、結果を待ちます。
(残り時間が表示され、今回は40分程度かかりました)
作成が終わったら、forecastを選択し、以下の「Create forecast export」を押下します。
Export detailsで以下を入力します。
- Export name: sample_nakamura_what_if_forecast_export
- IAM role: インポート時に作成したものと同じロールを指定
- Export file type: CSV
- S3 forecast export location: s3://sample-nakamura-2022-09-09-forecast/export
ページ下部の「Create Export」を押下して完了を待ちます。
what-if分析の作成
ダッシュボード画面からwhat-if分析が作成できます。「Explore what-if analysis」を押下します。
「Create」を押下します。
What-if analysis detailsを以下のように設定します。
- What-if analysis name: sample_nakamura_what_if_analysis
- Select forecast: sample_nakamura_what_if_forecast
- Item selection: Select all items
ページ下部の「Create what-if analysis」を押下します。
しばらく経過すると、What-if analysisのStatusがActiveとなります。
what-if分析のForecast作成(予測の実行)
上記の画面から、What-if forecastの「Create」を押下して進みます。
What-if forecast detailsに以下を入力します。
- What-if forecast name: sample_nakamura_what_if_analysis_forecast
- What-if forecast definition method: Use transformation functions
- Transformation function builder:
- Action
- Operation: MULTIPLY, AttributeName: price, Value: 0.90
- Conditions:
- AttributeName: timestamp, AttributeValue: 2019-09-01, Condition: GREATER_THAN
上記の設定内容は、2019-09-01以降のpriceデータに0.9を乗算した場合に、
Targetがどのように変化するかを、What-if分析するような記述となっています。
なお、数式で表現できないような値を設定したい場合は、
definition methodに「Define the what-if forecast with a replacement dataset」を選択し、
データを置き換えたRelated Time SeriesデータをS3からImportすることで、What-if分析をすることが可能です。
入力をしたらページ下部の「Create」を押下します。
すると以下のように作成中となるので、しばらく待ちます。
StatusがActiveとなったら、ページ下部に移動し、以下のWhat-if forecast exportで
「Create export」を押下します。
インポート時に作成したものと同じロールを指定
Export detailsで以下を入力します。
- Export name: sample_nakamura_what_if_analysis_forecast_export
- What-if forecasts: sample_nakamura_what_if_analysis_forecast
- S3 forecast export location: s3://sample-nakamura-2022-09-09-forecast/export_what_if
- IAM role: インポート時に作成したものと同じロールを指定
ページ下部の「Create Export」を押下して完了を待ちます。
結果の比較
エクスポート結果をダウンロードして比較していきます。
aws s3 cp s3://sample-nakamura-2022-09-09-forecast/export ./export --recursive
aws s3 cp s3://sample-nakamura-2022-09-09-forecast/export_what_if ./export --recursive
可視化のため、Pythonのコードを準備しました。
import pathlib
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
sns.set(style='darkgrid')
from datetime import datetime
# 学習データ読み込み
tts_df = pd.read_csv("./consumer_electronics_TTS.csv")
# 推論結果読み込み
def read_csv_files(src_path: str):
df = pd.DataFrame([])
for p in pathlib.Path(src_path).glob("*.csv"):
# print(p)
_df = pd.read_csv(p)
if len(df)==0:
df = _df
else:
df = pd.concat([df, _df], axis=0)
df = df.sort_values(['item_id', 'store_id', 'date']).reset_index(drop=True)
df['yyyy-mm-dd'] = [i[:10] for i in df['date']]
return df
base_df = read_csv_files("./export")
whatif_df = read_csv_files("./export_what_if")
# 描画
query_str = 'item_id == "item_001" and store_id == "store_001"'
fig, axes = plt.subplots(2, 1, figsize=(10, 6), dpi=100, sharex="col")
fig.suptitle(query_str)
ax = axes[0]
sns.lineplot(data=tts_df.query(query_str), x='timestamp', y='demand', marker="o", ax=ax, label="train(target)", color=colors[0])
sns.lineplot(data=base_df.query(query_str), x='yyyy-mm-dd', y='p50', marker="o", ax=ax, label="forecast(p50)", color=colors[1])
sns.lineplot(data=whatif_df.query(query_str), x='yyyy-mm-dd', y='sample_nakamura_what_if_analysis_forecast_p50', marker="o", ax=ax, label="what-if-forecast(p50)", color=colors[2])
ax.set_ylim([100, 500])
ax = axes[1]
sns.lineplot(data=rts_df.query(query_str), x='timestamp', y='price', marker="o", ax=ax, label="train(related)", color=colors[0])
sns.lineplot(data=rts_df.query(query_str).query('timestamp > "2019-09-01"'), x='timestamp', y='price_whatif', marker="o", ax=ax, label="what-if", color=colors[2])
[i.set_rotation(90) for i in ax.get_xticklabels()]
ax.set_ylim([40, 150])
plt.tight_layout()
plt.tight_layout()
結果は以下のようになります。(item_id: "item_001", store_id: "store_001"の場合)
上のdemandが予測対象となる時系列データで、下のpriceがRelatedな時系列データとなる情報です。
demand, priceそれぞれ青線で描かれている箇所がPredictorの学習に使用されています。
オレンジ線は、通常のPredictorのForecast結果(p50)で、これがベースラインとなります。
グリーン線がwhat-if分析に関するデータで、priceが0.9掛けだったら、
demandにどのような影響がでるかを確認できます。
影響としては、priceが低下すると、demandが上昇するといったような予測をしているようです。
これは、学習に使用したdemandとpriceが逆相関を持っていることをうまく反映しています。
この結果は、item_id、store_idごとにそれぞれ影響度を確認することが可能です。
興味のある方は他のケースも確認してみてください。
まとめ
いかがでしたでしょうか?
what-if分析で、過去を振り返って様々な仮説を検証することができるので、分析の幅が広がりそうですね。
Amazon Forecastをご利用の方は是非お試しください。
こちらの記事がAmazon Forecastを活用する際の参考になれば幸いです。