DataRobot AIアクセラレーター：マルチラベルモデリングを使った商品レコメンデーション

DataRobotで小売・流通業を担当しているデータサイエンティストの井原です。
「顧客一人ひとりに最適な商品を提案したいけど、商品数が多すぎて困っている…」なんてことはありませんか？ ECサイト運営やサービス提供において、顧客満足度向上と売上アップに直結するレコメンド機能は重要です。
しかし、顧客ごとに購入商品数が異なったり、商品の特徴量を個別に用意するとデータ量が膨大になったりするので、レコメンドは後回しになっている方もいるのではないでしょうか？
今回は、そんな悩みを解決するマルチラベルモデリングを活用した、DataRobot AIアクセラレータの[「マルチラベルを使ったレコメンデーション」](https://github.com/datarobot-community/ai-accelerators/blob/main/use_cases_and_horizontal_approaches/Ecommerce_recommendation_engine/Recommendation%20Engine.ipynb)テンプレートをご紹介します。 このテンプレートを使うと、わずかな改変でご自身のデータに対しても簡単に高精度な複数商品レコメンドを実現できます。

### マルチラベルモデリングとは？
マルチラベルモデリングとは、一つのデータに対して複数のラベルを同時に予測する手法です。 例えば、ある顧客の購買履歴から「この顧客は次にどの商品を購入する可能性が高いか？」を予測する場合、従来の分類モデルでは「商品A」や「商品B」など、一つの商品（ラベル）しか予測できませんでした。
しかし、マルチラベルモデリングでは、「商品A」「商品C」「商品D」など、複数の商品を同時に予測できます。 これにより、顧客のニーズに合致した、より多様な商品をレコメンドすることが可能になります。
以下の例では、通常の分類とマルチラベル分類を使ったときのブログのカテゴリ分類結果の違いを比較しています。通常の分類の場合の結果がひとつなのに対し、マルチラベルを使った分類では複数の結果が得られています。

　　　　　![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/daaafe3f-dc35-49a5-8bc1-e24ef67c2ac4.png)

### DataRobotのマルチラベルモデリング
DataRobotにはマルチラベルモデリングの機能が用意されています。
アプローチについては、LightGBMのアルゴリズムのみ「二値予測の組み合わせ」を使用しており、他はアルゴリズム側でマルチラベルに対応しているもの（kNNやKerasなど）を使用しています。

### マルチクラス分類との違い
マルチラベルモデリングと混同されがちなのが「マルチクラス分類」です。 マルチクラス分類も複数のクラスを扱う点は同じですが、出力は常に一つのクラスに限定されます。
例えば、犬の種類を予測する場合、マルチクラス分類では「柴犬」「プードル」「チワワ」の中からどれか一つを予測します。 一方、マルチラベルモデリングでは、「柴犬」と「プードル」の両方など、複数のラベルを同時に予測できます。

### DataRobot AIアクセラレータで実現するレコメンデーション
それでは、実際にDataRobot AIアクセラレータを使って、マルチラベルモデリングによるレコメンドを実装してみましょう。
今回は、オンラインスーパーの注文データを例に、顧客ごとに次に購入する可能性の高い商品を3つ予測するモデルを構築します。

#### 使用データ
このAIアクセラレータのテンプレートでは、以下の3種類のファイルを使用しています。
- [orders.csv](https://s3.amazonaws.com/datarobot_public_datasets/ai_accelerators/instacart/orders.csv)：オンラインスーパーの各注文データ
- [order_products.csv](https://s3.amazonaws.com/datarobot_public_datasets/ai_accelerators/instacart/order_products.csv)：各注文に含まれる商品の情報
- [test.csv](https://s3.amazonaws.com/datarobot_public_datasets/ai_accelerators/instacart/test.csv)：予測対象となる注文のリスト（顧客ID, 注文日）

ordersとorder_productsは注文ID (order_id) をキーとして結合できます。

　　　　　　　![img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/ae793b5e-7a79-4682-9471-73d5e68e1fa0.png)

このテンプレートをご自身のデータに適用されたい場合は、ご自身の注文データと商品データに置き換えてください。


#### データ整形＆モデリング手順
**1. データの読み込み**
AWS S3上の3つのファイルを読み込みます。

```python
orders = pd.read_csv(    "https://s3.amazonaws.com/datarobot_public_datasets/ai_accelerators/instacart/orders.csv",
    parse_dates=["order_time"],
    infer_datetime_format=True,
)
order_products = pd.read_csv(  "https://s3.amazonaws.com/datarobot_public_datasets/ai_accelerators/instacart/order_products.csv"
)
test = pd.read_csv(
"https://s3.amazonaws.com/datarobot_public_datasets/ai_accelerators/instacart/test.csv"
)
```

**2. 対象商品の絞り込み**
今回は、購入頻度の高い上位500商品に絞って分析を行います。なお、DataRobotのマルチラベルモデリングは最大1000クラスまで対応しています。
```python
order_counts = (
    pd.DataFrame(order_products.groupby("product_name").size(), columns=["count"])
    .reset_index()
    .sort_values("count", ascending=False)
    .reset_index() )

max_number_of_items = 500
frequent_orders = order_counts.product_name.head(max_number_of_items).to_list()
```

**3. 顧客/注文ごとのデータ作成**
各顧客の過去の購買履歴に基づいて、対象商品を購入したかどうかを表すデータを作成します。これを muti_label_product_training_dr として保存します。
```python
multi_label_product_training = orders.copy()
multi_label_product_training["items"] = "[]"
for row in multi_label_product_training.itertuples():
    order_id = row.order_id
    order_data = order_products.loc[order_products.order_id == order_id]
    items = order_data.loc[order_data.product_name.isin(frequent_orders)][
        "product_name"
    ].to_list()
    multi_label_product_training.loc[row.Index, "items"] = json.dumps(items)
multi_label_product_training = multi_label_product_training.drop("order_id", axis=1)
multi_label_product_training.order_time = ( multi_label_product_training.order_time.dt.date )
multi_label_product_training.user_id = multi_label_product_training.user_id.astype(int)
```

**4. 特徴量探索**
DataRobotの[自動特徴量探索機能](https://docs.datarobot.com/ja/docs/data/transform-data/feature-discovery/enrich-data-using-feature-discovery.html)を使用して、既存データから新たな特徴量を自動生成します。これにより、モデルの精度向上を目指します。
このケースでは、顧客IDであるuser_idをキーとしてmulti_label_product_trainingとorders_drを、オーダーIDであるorder_idをキーとしてorders_drとorder_products_drをつなげ、予測対象日から過去30日間 (-31日から-1日まで) の特徴量を作成しています。

```python
relationships = [
    {
        "dataset2Identifier": "orders_dr",
        "dataset1Keys": ["user_id"],
        "dataset2Keys": ["user_id"],
        "feature_derivation_window_start": -31,
        "feature_derivation_window_end": -1,
        "feature_derivation_window_time_unit": "DAY",
        "prediction_point_rounding": 1,
        "prediction_point_rounding_time_unit": "MINUTE",
    },
    {
        "dataset1Identifier": "orders_dr",
        "dataset2Identifier": "order_products_dr",
        "dataset1Keys": ["order_id"],
        "dataset2Keys": ["order_id"],
    },
]


relationship_config = dr.RelationshipsConfiguration.create(
    dataset_definitions=dataset_definitions, relationships=relationships
)
```

**5. オートパイロットによるモデリング**
DataRobotの自動で複数モデルを作成・評価するオートパイロットの機能で、マルチラベル分類モデルを自動構築します。
ここではプロジェクト名、予測ターゲット、データパーティショニングの方法、特徴量探索に使う時間の情報なども指定しています。

```python
project = dr.Project.create_from_dataset(
    multi_label_product_training_dr.id,
    project_name="AI Accelerator - Recommendation Engine",
)

project.analyze_and_model(
    target="items",
    relationships_configuration_id=relationship_config.id,
    partitioning_method=dr.GroupCV(
        holdout_pct=20, reps=5, partition_key_cols=["user_id"]
    ),
    feature_engineering_prediction_point="order_time",
    mode=dr.enums.AUTOPILOT_MODE.QUICK,
    max_wait=36000,
    worker_count=-1,
)
project.wait_for_autopilot()
```

**6. 顧客別の商品購入確率予測**
過去の購買商品を元に、各顧客が各商品を購入する確率を予測します。

```python
model = dr.ModelRecommendation.get(
    project.id, dr.enums.RECOMMENDED_MODEL_TYPE.RECOMMENDED_FOR_DEPLOYMENT
).get_model()


dataset = project.upload_dataset(predict_dataset)

pred_job = model.request_predictions(dataset.id)
preds = pred_job.get_result_when_complete()
```
予測結果 pred は以下のように、ユーザーごとに各商品を購入する確率の行列になります。

![img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/eb1583c7-ced1-4809-bc42-b2355c521090.png)

**7. レコメンド商品の抽出**
予測結果から、各商品に対して高いクラス確率を持つ上位3商品を抽出します。これが、顧客へのレコメンド商品となります。

```python
preds = preds[[c for c in preds.columns if "class" in c]]
preds.columns = [c.replace("class_", "") for c in preds.columns]

top_recommendations = pd.DataFrame(
    preds.apply(
        lambda x: list(preds.columns[np.array(x).argsort()[::-1][:3]]), axis=1
    ).to_list(),
    columns=["recommendation 1", "recommendation 2", "recommendation 3"],
)

output = pd.concat(
    [
        predict_dataset[["user_id", "order_time"]].reset_index(drop="True"),
        top_recommendations,
    ],
    axis=1,
)
output
```
出力結果 output を見てみると、ユーザーID14315の顧客にはクリームチーズ、バナナ、サワークリーム、4892の顧客にはヨーグルト、アボカド、マリナラソースといったようにユーザーごと、日付ごとに別の商品がおすすめされています。

![img04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/2a0da15e-25f4-4e39-ac5b-7e18e2f0f437.png)

### 特徴量探索とは？
DataRobotの特徴量探索は、データ同士を結合したり演算処理を加えることで、自動的に新しい特徴量を生成する機能です。 例えば、「注文金額」と「注文商品数」から「平均商品単価」を算出するなど、個別で作ると手間のかかる特徴量を一度に生成できます。また、さまざまな演算処理によって新しく作成した特徴量群から、予測のために有用な特徴量だけを選択して予測モデルに組み込むところまで自動化されています。

用意されている演算処理の一覧は以下のとおりです。
![img05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/22c5ec3e-3fc3-4550-b83b-f3159053b387.png)

### マルチラベルモデリングの活用例
マルチラベルモデリングは、レコメンド以外にもさまざまな場面で活用できます。ぜひこのブログでご紹介したAIアクセラレータとDataRobotを利用して、皆様の業務課題の解決にマルチラベルモデリングを試してみてください。

![img06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/26763ec2-1eb9-433f-9d30-c810e6b18154.png)

### まとめ
今回は、DataRobot AIアクセラレータの「マルチラベルを使ったレコメンデーション」テンプレートを活用し、マルチラベルモデリングによる高精度なレコメンドシステムの実装方法をご紹介しました。
DataRobotを使えば、コードを書かずに、簡単に高精度なマルチラベルモデルを構築できます。 顧客満足度向上と売上アップを実現するために、ぜひDataRobot AIアクセラレータを活用してみてください！

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