DataRobot AI アクセラレーター：時系列モデルでタイムリーにKPIを予測しよう

### はじめに
シニアデータサイエンティストの菅原崇です。金融業界のお客様向けに、与信モデルや人材育成や生成AIプロジェクト等を担当しています。

今回は、AIアクセラレーターの[『財務計画と分析ワークフロー』](https://docs.datarobot.com/ja/docs/api/accelerators/use-cases-accel/fin-plan.html)を取り上げます。このユースケースでは、DataRobotの時系列モデルでタイムリーにKPI（ここでは月次の売上）を予測する方法を、データの前処理からデプロイで予測するところまで紹介しています。皆さんの部門のKPI（顧客数、個別製品やサービスの売上件数等）に置き換えれば、このテーマはほぼ全てのビジネスパーソンに関連します。

KPIのタイムリーな予測はビジネスの成功に不可欠ですが、精度、解釈性、迅速な開発、そして分かりやすい情報共有など、多くの課題を伴います。スプレッドシートやExcelなどの手運用に依存したKPI管理から脱却し、DataRobotの時系列モデルとコードベースの自動化を活用することで、これらの課題を克服し、KPI予測を効率化できます。

### 全体の流れ
このノートブックは時系列プロジェクトをエンドツーエンドでカバーしているため、.pyに変換すると1,000行近くあります。全体像を把握しやすくするために、一般的な機械学習プロジェクトの流れに従って、下記のようにステップを整理します。

1. データ準備
1. モデル構築と評価
1. 予測と結果の可視化
1. モデルのデプロイと予測

#### 1.データ準備
このステップでは、元の日次データsales.csvを学習データts_monthly_training
に加工しています。ここでは下記のような入出力関係にあります。同等の前処理はpandasやSQLでも可能です。

![sugawara01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/c0734399-fd73-4f4f-abbc-ae346687aa49.png)

時系列のテーマでは、例えば下記のように、可視化することが重要です。スパイクや最近のトレンドなど、直感的に理解できることが多いからです。ここでデータオーナーや社内関係者と確認の機会を設けましょう。もし何かしらのミスやエラーがあれば、この時点で気がつくことも重要だからです。

![sugawara02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/03e8e81d-ed0f-4ca0-87da-71f98a64631e.png)

#### 2.モデル構築と評価
時系列モデルの設定は特徴量とパーティションに時間軸を考慮するため、複雑です。GUIで繰り返し作業や第三者の再現をしようとすると、ミスが発生しやすくなるので、Pythonでの再現性の価値が見出せます。

設定編として、まずは『Monthly_Sales_Forecast』というプロジェクト名としています。次に、時系列モデル固有の設定をしていきます。GUIと照らし合わせながら、必要な設定を確認します。特徴量の派生ウィンドウ（FDW）で、ここでは例えば、過去6ヶ月の特徴量を生成する期間を指定します。この設定で、例えば6ヶ月間の最大値や平均値のような特徴量が自動生成され、モデルの精度が高まります。予測ウィンドウ（FW）は、将来12ヶ月分の予測をすると設定しています。また、この系列は、SegmentA〜Cまで3つあることを認識させています。ここでは、事前に既知の特徴量（KA_VARS）はありません。アメリカの祝日カレンダー（CALENDAR）を自動生成しています。手動でカレンダーを作り込むことも可能ですが、まずは自動生成で時間を掛けずに試すことも有意義です。

![sugawara03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/6f4268d7-c2c5-42a4-ba85-64cf802bc9c4.png)

```python
# Create a new DataRobot project
project = dr.Project.create_from_dataset(
    project_name="Monthly_Sales_Forecast", dataset_id=training_dataset.id)

# Set Time Series Parameters
# Feature Derivation Window
# What rolling window should DataRobot use to derive features?
FDW = [(-6, 0)]

# Forecast Window
# Which future values do you want to forecast? (i.e. Forecast Distances)
FW = [(1, 12)]

# Known In Advance features
# Features that will be known at prediction time - all other features will go through an iterative feature engineering and selection process to create time-series features.
FEATURE_SETTINGS = []
KA_VARS = []
for column in KA_VARS:
    FEATURE_SETTINGS.append(
        dr.FeatureSettings(column, known_in_advance=True, do_not_derive=False)
    )

# Calendar
# Create a calendar file from a dataset to see how specific events by date contribute to better model performance
CALENDAR = dr.CalendarFile.create_calendar_from_country_code(
    country_code="US",
    start_date=min(training_df["Order Date"]),  # Earliest date in calendar
    end_date=max(training_df["Order Date"]),
)  # Last date in calendar

# Create DatetimePartitioningSpecification
# The DatetimePartitioningSpecification object is how we pass our settings to the project
time_partition = dr.DatetimePartitioningSpecification(
    # General TS settings
    use_time_series=True,
    datetime_partition_column="Order Date",  # Date column
    multiseries_id_columns=["Segment"],  # Multi-series ID column
    # FDW and FD
    forecast_window_start=FW[0][0],
    forecast_window_end=FW[0][1],
    feature_derivation_window_start=FDW[0][0],
    feature_derivation_window_end=FDW[0][1],
    # Advanced settings
    feature_settings=FEATURE_SETTINGS,
    calendar_id=CALENDAR.id,
)
```

モデル構築編として、予測ターゲットを Sales として、使えるだけワーカーを(worker_count = -1)使う設定としています。project.wait_for_autopilot(verbosity=0)は、オートパイロットが終了するまで待ち、ログを出力しないという設定を示しています。

```python
# Start Autopilot
project.analyze_and_model(
    # General parameters
    target="Sales",  # Target to predict
    worker_count=-1,  # Use all available modeling workers for faster processing
    # TS options
    partitioning_method=time_partition,  # Feature settings
)

# If you want to wait for Autopilot to finish, run this code
# You can set verbosity to 1 if you want to print progress updates as Autopilot runs
project.wait_for_autopilot(verbosity=0)
```

これでモデル構築パートが終わりましたので、モデルを様々な指標で評価します。
定量的な評価例として、[時系列の精度](https://docs.datarobot.com/ja/docs/modeling/analyze-models/evaluate/aot.html)をPythonで可視化しています。この機能はセグメント別や予測距離やバックテストの種類別に精度評価ができるのですが、このデモデータだけでも、全240パターン（4セグメント * 12予測距離 * 5バックテスト）あります。このようなケースでは、Pythonで網羅的に可視化する方が便利だと考えられます。

![sugawara04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/e2090923-9c1e-4b25-8c5e-ece44558382d.png)

定性的な評価例として、『Retrieve Feature Impact』のパートで、特徴量のインパクト（モデルの精度にどの特徴量が寄与しているか）もPythonで算出しています。

```python
# get model
top_model = dr.Model.get(project=project.id, model_id=scores["Model_ID"][2])

# Request and retrieve feature impact
feature_impacts = (
    top_model.get_or_request_feature_impact()
)  # Will trigger Feature Impact calculations if not done
FI_df = pd.DataFrame(feature_impacts)  # Convert to dataframe

# Sort features by Normalized Feature Impact
FI_df = FI_df.sort_values(by="impactNormalized", ascending=False)

# Take top 10
FI_df = FI_df[0:5]

# Plotly Graph
fig = go.Figure()

# Add bar trace
fig.add_trace(
    go.Bar(y=FI_df["featureName"], x=FI_df["impactNormalized"], orientation="h")
)

# Update layout for better visualization
fig.update_layout(
    title="Feature Impact",
    xaxis=dict(title="Normalized Feature Impact", range=[0, 1.1]),
    yaxis=dict(title="Feature", autorange="reversed"),
    margin=dict(
        l=200
    ),  # this is to ensure the y-labels (feature names) are not cut off
    template="plotly_dark",
)

# Display the plot
fig.show()
```
![sugawara05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/9ad4d098-ed62-466a-bcf0-29bcc841ddca.png)

#### 3.予測と結果の可視化
ここまでで、モデルの評価が完了したので、このモデルで予測していくパートになります。

ここではデモの都合で、学習データ(ts_monthly_training)をそのまま予測データ（test_dataset）にしています。最も精度の高いモデルをfrozen_modelとして、85％の信頼区間(prediction_intervals_size)で予測値を求めています。

サンプルとして予測値の最初の5行を出力しています。後段の処理で、可視化しています。時系列プロジェクトにおいては、このような可視化の重要性は強調しすぎても強調しすぎることはありません。

```python
# Upload data to modeling project
df = training_dataset.get_as_dataframe()
test_dataset = project.upload_dataset(df)

# Get frozen model
frozen_model = all_models[0]

# Request Predictions
pred_job = frozen_model.request_predictions(
    dataset_id=test_dataset.id,
    include_prediction_intervals=True,
    prediction_intervals_size=85,
)

preds = pred_job.get_result_when_complete()

preds.head(5)
```

![sugawara06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/cc69abfb-59fc-4878-9fb2-fc440f6299d8.png)

#### 4.モデルのデプロイと予測
このセクションは、基本的に前セクションと同等であり、デプロイ版になります。
デフォルトの予測環境に、先程のfrozen_modelをデプロイし、『FP&A - Segment Forecasting Model』という名称と概要を指定しています。
そして、このデプロイに予測ジョブを投げています。GUIの方でも、このバッチジョブの実行結果が確認できます。

```python
# Set the prediction server to deploy to
prediction_server_id = dr.PredictionServer.list()[
    0
].id  # EDIT THIS BASED ON THE PREDICTION SERVERS AVAILABLE TO YOU

# Set deployment details
deployment = dr.Deployment.create_from_learning_model(
    model_id=frozen_model.id,
    label="FP&A - Segment Forecasting Model",
    description="FP&A - Segment Forecasting Model",
    default_prediction_server_id=prediction_server_id,
)

# Score the dataset using the given deployment ID
job, predictions = dr.BatchPredictionJob.score_pandas(
    deployment.id, df
)  # Deployment ID and Scoring dataset

# Print a message to indicate that scoring has started
print("Started scoring...", job)

# Wait for the job to complete
job.wait_for_completion()
```

![sugawara07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/44e4c9aa-7cd0-467c-b649-f266799bd750.png)

![sugawara08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/1501116c-d774-4977-a14b-c5956fa160c6.png)

![sugawara09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/6ec7d7c9-1e19-4f51-90bd-7c3f8498f1ae.png)

### まとめと今後に
本記事では、AIアクセラレーターの[『財務計画と分析ワークフロー』](https://docs.datarobot.com/ja/docs/api/accelerators/use-cases-accel/fin-plan.html)を取り上げ、時系列プロジェクトをデータの前処理からデプロイで予測するところまで、網羅的にカバーしました。このようなユースケースを活用することで、KPI予測のような業務も、大幅に効率化し、スケールすることも期待されます。

次のステップとして、時系列予測には、しばしばダッシュボードやレポーティングも求められます。そのようなニーズに対応して、DataRobotは[予測アシスタント](https://github.com/datarobot-community/forecast-assistant)も公開しています。これは、生成AI機能も組み合わせることで、なぜそのような予測になったのかレポーティングするものになります。皆様の業務のさらなる効率化や高付加価値につながりますので、ぜひご活用ください。

![sugawara10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/599c005b-345d-4ba4-a589-5a1cad9ea163.png)

### DataRobotトライアルのご案内
DataRobotでは、トライアル環境を提供しています。以下のURLからアカウントを作成し、DataRobotの主要な機能をお試しいただけます。

[DataRobotトライアルに申し込む](https://page.datarobot.com/trial-jp.html?utm_source=qiita&utm_medium=3rdPartyPromoter&utm_campaign=FTJP-qiita)

### 関連動画（DataRobot University）のご案内
こちらの記事で紹介している内容の講義動画を、オンライン学習コンテンツ[「DataRobot University」](https://jp.learn.datarobot.com/learn/learning-path/ai-accelerator)でご覧いただくことができます。なお、こちらの動画はDataRobotのお客様限定のコードが必要となります。コードが分からない方は代理店窓口の方にお問い合わせ下さい。