15.3レシピを使用したモデルの操作

この練習では、レシピを作成して、モデルを使用し、Adobe Experience Platformで操作します。

レシピビルダーのノートブックは、モデルを自動的にパッケージ化して操作できるようにテンプレート化します。 ノートブックには、モデルコードを次の場所に合わせた複数のテンプレート化されたセルがあります。

  • 要件と設定セルを使用すると、ライブラリを追加したり、モデルのデータセットや調整パラメーターを設定したりできます
  • 評価基準セルを使用すると、データを分割し、モデルのパフォーマンスを評価できます
  • トレーニングとスコアリングのデータローダーセルを使用すると、トレーニングとスコアリングに必要なデータを読み込むことができます
  • 最後に、パイプラインセルには、モデルのトレーニングとスコアリングの両方に必要なロジックが含まれています。

モデルのトレーニング、評価、スコアリングを規模別に行い、Adobe Experience Platformでシームレスに1つのフローにパッケージ化できるので、モデルの運用に必要な手順を合理化しました。 また、レシピにパッケージ化すると、異なるデータセットを持つ同じコードを使用して、組織内の異なる使用例に電力を供給することもできます。 アドビの具体的な使用例は、Webサイトで購入する製品を検索するユーザーに対して、recommendationsモデルコードの使用に関するものです。

次のURLに移動してAdobe Experience Platformにログインします。 https://experience.adobe.com/platform.

ログインした後、Adobe Experience Platformのホームページに移動します。

データ取得

続行する前に、 Sandboxを選択する必要があります。 選択するサンドボックスに名前が付けられ --aepSandboxId--ます。 これを行うには、画面上の青い線で「 実稼働 」というテキストをクリックします。

データ取得

適切なサンドボックスを選択すると、画面の変更が表示され、専用のサンドボックスに移動します。

データ取得

Adobe Experience Platformで、画面の左側のメニューで [ノートブック] ​をクリックし、 JupyterLab​に移動します。

データ取得

「Jupyter Notebooks」で、タスクバーの + アイコンをクリックして「 Launcher 」ページを開きます。

DSW

次の図が表示されます。

DSW

ランチャーの「 レシピビルダー 」ボタンをクリックして、空のレシピビルダーノートブックを開きます。

DSW

その後、空の空の新しいRecipe Builderノートブックが作成されます。 続行する前に、ノートブックにわかりやすい名前を付けてください。 [Python 3] Recipe Builder.ipynb ファイルを右クリックし、「 名前の変更」をクリックします。

DSW

ノートブックの名前として mutual365-insurance-sales-propentity.ipynb を入力し、 Enterを押します。 その後、次の手順を実行します。

DSW

このノートブックでは、次の操作を行います。

  • モデルのトレーニング
  • モデルにスコアを付ける
  • モデルからレシピを作成する

すべての手順を詳細に設定します。

設定ファイル

設定ファイル」が表示されるまで、Recipe Builderノートブック内を下にスクロールします。

DSW

次に、トレー ニング設定 および スコア設定のセルを更新する必要があります

トレーニングの設定

トレーニング設定」のセル内をクリックします。

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

%%writefile ~/my-workspace/.recipes/recipe-tFgHWnuH5/training.conf

DSW

同じセルにも同様のコードが表示されます。

{
   "trainingDataSetId": "<replace with training dataset id>",
   "ACP_DSW_TRAINING_XDM_SCHEMA": "<replace with training xdm schema id>",
   "tenantId": "_<tenant_id>",
   "learning_rate": "0.1",
   "n_estimators": "100",
   "max_depth": "3"
}

そのコードを次のコードで置き換えます。

{
    "trainingDataSetId": "--aepCarInsuranceInteractionsDatasetId--",
    "ACP_DSW_TRAINING_XDM_SCHEMA": "https://ns.adobe.com/--aepTenantIdSchema--/schemas/--aepCarInsuranceInteractionsSchemaRef--",
    "train_records_limit":1000000,
    "n_estimators": "80",
    "max_depth": "5",
    "ten_id": "--aepTenantId--"
}
重要

環境変数 aepCarInsuranceInteractionsDatasetId とaepCarInsuranceInteractionsSchemaRef ​は、Adobe Experience Platformインスタンスで作成されたデータセットのデータセットIDと、Adobe Experience Platformインスタンスで作成されたスキーマのスキーマ参照IDを参照します。

aepCarInsuranceInteractionsDatasetId は、Webサイトのデータセット デモシステム —イベントデータセット(グローバルv1.1)​のデータセットIDを参照します。 aepCarInsuranceInteractionsSchemaRef は、スキーマ デモイベントスキーマ用のスキーマ参照IDを参照します。Webサイト(グローバルv1.1)。 ノートブックの「 トレーニング設定 」セルにコードを貼り付けるときは、環境変数をデータセットIDとスキーマ参照IDで置き換えます。

これで、「 Training Configuration 」セルに似たような内容になります。

DSW

スコア設定

スコアリング設定」のセル内をクリックします。

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

%%writefile ~/my-workspace/.recipes/recipe-tFgHWnuH5/scoring.conf

DSW

同じセルにも同様のコードが表示されます。

{
   "scoringDataSetId": "<replace with scoring input dataset id>",
   "scoringResultsDataSetId": "<replace with scoring results dataset id>",
   "ACP_DSW_SCORING_RESULTS_XDM_SCHEMA": "<replace with scoring results xdm schema id>",
   "tenantId": "_<tenant_id>"
}

そのコードを次のコードで置き換えます。

{
   "scoringDataSetId": "--aepCarInsuranceInteractionsDatasetId--",
   "scoringResultsDataSetId": "--aepMlPredictionsDatasetId--",
   "ACP_DSW_SCORING_RESULTS_XDM_SCHEMA": "https://ns.adobe.com/--aepTenantIdSchema--/schemas/--aepMlPredictionsSchemaRef--",
   "ten_id": "--aepTenantId--"
}
重要

環境変数 aepCarInsuranceInteractionsDatasetId、aepMlPredictionsDatasetId aepMlPredictionsSchemaRef ​は、Adobe Experience Platformインスタンスで作成されたスキーマのデータセットIDとスキーマ参照IDを参照します。

aepCarInsuranceInteractionsDatasetId は、Webサイト(グローバルv1.1)のデータセット デモシステム —イベントデータセット(Global v1.1)のデータセットIDを参照します。 aepMlPredictionDatasetId は、MLのデ ータセットデモシステム —プロファイルデータセット予測(グローバルv1.1​**​**​**​**, ML予測MlPredicationsep SchemaRefRefSystemスキーマスキーマRef ID IDの参照プロファイルML予測(グローバルv1)スキーマスキーマの ノートブックの「 スコアリング設定 」セルにコードを貼り付けるときは、環境変数をデータセットIDとスキーマ参照IDで置き換えます。

これで、「 スコアリング設定 」セルに似たような内容になります。

DSW

トレーニングデータローダーファイル

Recipe Builderノートブックを下にスクロールして、 トレーニングデータローダーファイルが表示されます

DSW

次に、ト レーニングデータローダーファイルのコードを更新する必要があります

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

DSW

このセルには、次のようなコードが表示されます。

import pandas as pd
from datetime import datetime, timedelta
from platform_sdk.dataset_reader import DatasetReader
from .utils import get_client_context

def load(config_properties):
    print("Training Data Load Start")

    #########################################
    # Load Data
    #########################################
    client_context = get_client_context(config_properties)

    dataset_reader = DatasetReader(client_context, config_properties['trainingDataSetId'])

    timeframe = config_properties.get("timeframe")
    tenant_id = config_properties.get("tenant_id")

    if (timeframe is not None):
        date_before = datetime.utcnow().date()
        date_after = date_before - timedelta(minutes=int(timeframe))
        dataframe = dataset_reader.where(dataset_reader[tenant_id + '.date'].gt(str(date_after)).And(dataset_reader[tenant_id + '.date'].lt(str(date_before)))).read()
    else:
        dataframe = dataset_reader.read()

    if '_id' in dataframe.columns:
        #Rename columns to strip tenantId
        dataframe = dataframe.rename(columns = lambda x : str(x)[str(x).find('.')+1:])
        #Drop id and timestamp
        dataframe.drop(['_id', 'timestamp'], axis=1, inplace=True)

    #########################################
    # Data Preparation/Feature Engineering
    #########################################
    dataframe.date = pd.to_datetime(dataframe.date)
    dataframe['week'] = dataframe.date.dt.week
    dataframe['year'] = dataframe.date.dt.year

    dataframe = pd.concat([dataframe, pd.get_dummies(dataframe['storeType'])], axis=1)
    dataframe.drop('storeType', axis=1, inplace=True)
    dataframe['isHoliday'] = dataframe['isHoliday'].astype(int)

    dataframe['weeklySalesAhead'] = dataframe.shift(-45)['weeklySales']
    dataframe['weeklySalesLag'] = dataframe.shift(45)['weeklySales']
    dataframe['weeklySalesDiff'] = (dataframe['weeklySales'] - dataframe['weeklySalesLag']) / dataframe['weeklySalesLag']
    dataframe.dropna(0, inplace=True)

    dataframe = dataframe.set_index(dataframe.date)
    dataframe.drop('date', axis=1, inplace=True)

    print("Training Data Load Finish")
    return dataframe

このコードを( %%writefile 行を上書きせずに)次のコードで置き換えます。

import numpy as np
import pandas as pd
from datetime import datetime, timedelta
from platform_sdk.dataset_reader import DatasetReader
from .utils import get_client_context

def load(config_properties):
    print("Training Data Load Start")

    #########################################
    # Load Data
    #########################################
    client_context = get_client_context(config_properties)
    train_records_limit = config_properties['train_records_limit']

    dataset_reader = DatasetReader(client_context, config_properties['trainingDataSetId'])

    #timeframe = config_properties.get("timeframe")
    #tenant_id = config_properties.get("tenant_id")
    print('Reading Training Data')
    df1 = dataset_reader.limit(train_records_limit).read()
    df1.rename(columns = {config_properties['ten_id']+'.identification.core.ecid' : 'ecid',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.numberKm': 'km',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.type': 'cartype',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerAge': 'age',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerGender' : 'gender',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.brand' : 'carbrand',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.leasing' : 'leasing',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerCity' : 'city',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerCountry' : 'country',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerNationality' : 'nationality',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.isCustomerPrimaryDriver' : 'primaryuser',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.hasCustomerPurchased' : 'purchase',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.priceBasic' : 'pricequote'}, inplace=True)
    df1 = df1[['ecid', 'km', 'cartype', 'age', 'gender', 'carbrand', 'leasing', 'city',
           'country', 'nationality', 'primaryuser', 'purchase', 'pricequote', 'timestamp']]
    df1 = df1.loc[df1['age'] != 0]

    #########################################
    # Data Rollup
    #########################################
    df1['timestamp'] = pd.to_datetime(df1.timestamp)
    df1['hour'] = df1['timestamp'].dt.hour.astype(int)
    df1['dayofweek'] = df1['timestamp'].dt.dayofweek
    df1.loc[(df1['purchase'] == 'true'), 'purchase'] = 1
    df1.loc[(df1['purchase'] == 'false'), 'purchase'] = 0
    df1.loc[(df1['purchase'] == ''), 'purchase'] = 0
    df1.purchase.fillna(0, inplace=True)
    df1['purchase'] = df1['purchase'].astype(int)

    df1.dropna(subset = ['ecid'], inplace=True)
    df1['ecid'] = df1['ecid'].astype(str)
    df_conv_dict = df1.groupby('ecid').max()[['purchase']]
    df_conv_dict = df_conv_dict.to_dict()

    idx = df1.groupby('ecid')['timestamp'].transform(max) == df1['timestamp']
    df1 = df1[idx]
    df1 = df1.drop_duplicates(subset = 'ecid', keep = 'last', inplace = False)
    #df1['purchase'] = df1['ecid'].map(df_conv_dict['purchase'])

    #########################################
    # Data Preparation/Feature Engineering
    #########################################

    df1['carbrand'] = df1['carbrand'].str.lower()
    df1['country'] = df1['country'].str.lower()
    df1.loc[(df1['carbrand'] == 'vw'), 'carbrand'] = 'volkswagen'
    df1.loc[(df1['carbrand'] == 'citroen'), 'carbrand'] = 'cadillac'
    df1.loc[(df1['carbrand'] == 'opel'), 'carbrand'] = 'bmw'
    df1.loc[(df1['carbrand'] == 'mini'), 'carbrand'] = 'volkswagen'

    df1.loc[(df1['cartype'] == 'SUV / Geländewagen') | (df1['cartype'] == 'SUV / Tout terrain'), 'cartype'] = 'suv'
    df1.loc[(df1['cartype'] == 'Kleinwagen') | (df1['cartype'] == 'Untere Mittelklasse') | (df1['cartype'] == 'Mikroklasse'), 'cartype'] = 'hatchback'
    df1.loc[(df1['cartype'] == 'Mittelklasse') | (df1['cartype'] == 'Obere Mittelklasse'), 'cartype'] = 'sedan'
    df1.loc[(df1['cartype'] == 'Kompaktvan / Minivan'), 'cartype'] = 'minivan'
    df1.loc[(df1['cartype'] == 'Cabriolet / Roadster'), 'cartype'] = 'convertible'
    df1.loc[(df1['cartype'] == 'Coupé / Sportwagen'), 'cartype'] = 'coupe'
    df1.loc[(df1['cartype'] == 'dataLayerNull'), 'cartype'] = pd.np.nan
    df1.loc[(df1['cartype'] == 'Luxusklasse'), 'cartype'] = 'luxury'
    df1.loc[(df1['cartype'] == 'Strasse'), 'cartype'] = 'mpv'

    df1.loc[(df1['leasing'] == 'false'), 'leasing'] = 'no'
    df1.loc[df1['country'] == 'at', 'country'] = 'austria'
    df1.loc[(df1['leasing'] == 'dataLayerNull'), 'leasing'] = pd.np.nan
    df1.loc[(df1['gender'] == 'dataLayerNull'), 'gender'] = pd.np.nan
    df1.loc[(df1['carbrand'] == 'dataLayerNull'), 'carbrand'] = pd.np.nan

    df1['age'].fillna(df1['age'].median(), inplace=True)
    df1['gender'].fillna('notgiven', inplace=True)
    df1['leasing'].fillna('notgiven', inplace=True)
    df1['carbrand'].fillna('bmw', inplace=True)
    df1['country'].fillna('germany', inplace=True)
    df1['cartype'].fillna('na', inplace=True)
    df1['primaryuser'].fillna('na', inplace=True)
    df1['nationality'].fillna('na', inplace=True)
    df1['km'].fillna('na', inplace=True)

    df1['city'] = df1.groupby('country')['city'].transform(lambda x : x.fillna(x.mode()))
    #df1.dropna(subset = ['pricequote'], inplace=True)

    #grouping
    grouping_cols = ['carbrand', 'cartype', 'city', 'country']

    for col in grouping_cols:
        df_idx = pd.DataFrame(df1[col].value_counts().head(6))

        def grouping(x):
            if x in df_idx.index:
                return x
            else:
                return "Others"
        df1[col] = df1[col].apply(lambda x: grouping(x))

    def age(x):
        if x < 20:
            return "u20"
        elif x > 19 and x < 29:
            return "20-28"
        elif x > 28 and x < 43:
            return "29-42"
        elif x > 42 and x < 55:
            return "43-54"
        elif x > 54 and x < 65:
            return "55-64"
        elif x >= 65:
            return "65+"
        else:
            return "Others"

    df1['age'] = df1['age'].astype(int)
    df1['age_bucket'] = df1['age'].apply(lambda x: age(x))

    df_final = df1[['hour', 'dayofweek','age_bucket', 'gender', 'city',
       'country', 'carbrand', 'cartype', 'leasing', 'pricequote', 'purchase']]

    cat_cols = ['age_bucket', 'gender', 'city', 'dayofweek', 'country', 'carbrand', 'cartype', 'leasing']
    df_final = pd.get_dummies(df_final, columns = cat_cols)

    dataframe = df_final.copy()

    df_final.head(20)

    print("Training Data Load Finish")
    return dataframe

これで、「 Training Data Loader File 」セルに似たような内容になりました。

DSW

スコアリングデータローダーファイル

スコアリングデータローダーファイル」が表示されるまで、Recipe Builderノートブック内を下にスクロールします。

DSW

次に、 スコアリングデータローダーファイルのコードを更新する必要があります

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

DSW

このセルには、次のようなコードが表示されます。

import pandas as pd
from datetime import datetime, timedelta
from .utils import get_client_context
from platform_sdk.dataset_reader import DatasetReader

def load(config_properties):

    print("Scoring Data Load Start")

    #########################################
    # Load Data
    #########################################
    client_context = get_client_context(config_properties)

    dataset_reader = DatasetReader(client_context, config_properties['scoringDataSetId'])
    timeframe = config_properties.get("timeframe")
    tenant_id = config_properties.get("tenant_id")

    if (timeframe is not None):
        date_before = datetime.utcnow().date()
        date_after = date_before - timedelta(minutes=int(timeframe))
        dataframe = dataset_reader.where(dataset_reader[tenant_id + '.date'].gt(str(date_after)).And(dataset_reader[tenant_id + '.date'].lt(str(date_before)))).read()
    else:
        dataframe = dataset_reader.read()
        print(dataframe)

    #########################################
    # Data Preparation/Feature Engineering
    #########################################
    if '_id' in dataframe.columns:
        #Rename columns to strip tenantId
        dataframe = dataframe.rename(columns = lambda x : str(x)[str(x).find('.')+1:])
        #Drop id and timestamp
        dataframe.drop(['_id', 'timestamp'], axis=1, inplace=True)

    dataframe.date = pd.to_datetime(dataframe.date)
    dataframe['week'] = dataframe.date.dt.week
    dataframe['year'] = dataframe.date.dt.year

    dataframe = pd.concat([dataframe, pd.get_dummies(dataframe['storeType'])], axis=1)
    dataframe.drop('storeType', axis=1, inplace=True)
    dataframe['isHoliday'] = dataframe['isHoliday'].astype(int)

    dataframe['weeklySalesAhead'] = dataframe.shift(-45)['weeklySales']
    dataframe['weeklySalesLag'] = dataframe.shift(45)['weeklySales']
    dataframe['weeklySalesDiff'] = (dataframe['weeklySales'] - dataframe['weeklySalesLag']) / dataframe['weeklySalesLag']
    dataframe.dropna(0, inplace=True)

    dataframe = dataframe.set_index(dataframe.date)
    dataframe.drop('date', axis=1, inplace=True)

    print("Scoring Data Load Finish")

    return dataframe

このコードを( %%writefile 行を上書きせずに)次のコードで置き換えます。

import pandas as pd
from datetime import datetime, timedelta
from .utils import get_client_context
from platform_sdk.dataset_reader import DatasetReader

def load(config_properties):

    print("Scoring Data Load Start")

    #########################################
    # Load Data
    #########################################
    client_context = get_client_context(config_properties)

    dataset_reader = DatasetReader(client_context, config_properties['scoringDataSetId'])

    #timeframe = config_properties.get("timeframe")
    #tenant_id = config_properties.get("tenant_id")
    df1 = dataset_reader.read()
    df1.rename(columns = {config_properties['ten_id']+'.identification.core.ecid' : 'ecid',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.numberKm': 'km',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.type': 'cartype',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerAge': 'age',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerGender' : 'gender',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.brand' : 'carbrand',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.leasing' : 'leasing',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerCity' : 'city',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerCountry' : 'country',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.customerNationality' : 'nationality',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.isCustomerPrimaryDriver' : 'primaryuser',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.hasCustomerPurchased' : 'purchase',
                     config_properties['ten_id']+'.interactionDetails.insurance.car.priceBasic' : 'pricequote'}, inplace=True)
    df1 = df1[['ecid', 'km', 'cartype', 'age', 'gender', 'carbrand', 'leasing', 'city',
           'country', 'nationality', 'primaryuser', 'purchase', 'pricequote', 'timestamp']]
    df1 = df1.loc[df1['age'] != 0]

    #########################################
    # Data Rollup
    #########################################
    df1['timestamp'] = pd.to_datetime(df1.timestamp)
    df1['hour'] = df1['timestamp'].dt.hour.astype(int)
    df1['dayofweek'] = df1['timestamp'].dt.dayofweek

    df1.loc[(df1['purchase'] == 'true'), 'purchase'] = 1
    df1.loc[(df1['purchase'] == 'false'), 'purchase'] = 0
    df1.loc[(df1['purchase'] == ''), 'purchase'] = 0
    df1.purchase.fillna(0, inplace=True)
    df1['purchase'] = df1['purchase'].astype(int)

    df1.dropna(subset = ['ecid'], inplace=True)
    df1['ecid'] = df1['ecid'].astype(str)
    df_conv_dict = df1.groupby('ecid').max()[['purchase']]
    df_conv_dict = df_conv_dict.to_dict()

    idx = df1.groupby('ecid')['timestamp'].transform(max) == df1['timestamp']
    df1 = df1[idx]
    df1 = df1.drop_duplicates(subset = 'ecid', keep = 'last', inplace = False)
    df1['purchase'] = df1['ecid'].map(df_conv_dict['purchase'])

    #########################################
    # Data Preparation/Feature Engineering
    #########################################

    df1['carbrand'] = df1['carbrand'].str.lower()
    df1['country'] = df1['country'].str.lower()
    df1.loc[(df1['carbrand'] == 'vw'), 'carbrand'] = 'volkswagen'
    df1.loc[(df1['carbrand'] == 'citroen'), 'carbrand'] = 'cadillac'
    df1.loc[(df1['carbrand'] == 'opel'), 'carbrand'] = 'bmw'
    df1.loc[(df1['carbrand'] == 'mini'), 'carbrand'] = 'volkswagen'

    df1.loc[(df1['cartype'] == 'SUV / Geländewagen') | (df1['cartype'] == 'SUV / Tout terrain'), 'cartype'] = 'suv'
    df1.loc[(df1['cartype'] == 'Kleinwagen') | (df1['cartype'] == 'Untere Mittelklasse') | (df1['cartype'] == 'Mikroklasse'), 'cartype'] = 'hatchback'
    df1.loc[(df1['cartype'] == 'Mittelklasse') | (df1['cartype'] == 'Obere Mittelklasse'), 'cartype'] = 'sedan'
    df1.loc[(df1['cartype'] == 'Kompaktvan / Minivan'), 'cartype'] = 'minivan'
    df1.loc[(df1['cartype'] == 'Cabriolet / Roadster'), 'cartype'] = 'convertible'
    df1.loc[(df1['cartype'] == 'Coupé / Sportwagen'), 'cartype'] = 'coupe'
    df1.loc[(df1['cartype'] == 'dataLayerNull'), 'cartype'] = pd.np.nan
    df1.loc[(df1['cartype'] == 'Luxusklasse'), 'cartype'] = 'luxury'
    df1.loc[(df1['cartype'] == 'Strasse'), 'cartype'] = 'mpv'

    df1.loc[(df1['leasing'] == 'false'), 'leasing'] = 'no'
    df1.loc[df1['country'] == 'at', 'country'] = 'austria'
    df1.loc[(df1['leasing'] == 'dataLayerNull'), 'leasing'] = pd.np.nan
    df1.loc[(df1['gender'] == 'dataLayerNull'), 'gender'] = pd.np.nan
    df1.loc[(df1['carbrand'] == 'dataLayerNull'), 'carbrand'] = pd.np.nan

    df1['age'].fillna(df1['age'].median(), inplace=True)
    df1['gender'].fillna('notgiven', inplace=True)
    df1['leasing'].fillna('notgiven', inplace=True)
    df1['carbrand'].fillna('bmw', inplace=True)
    df1['country'].fillna('germany', inplace=True)
    df1['cartype'].fillna('na', inplace=True)
    df1['primaryuser'].fillna('na', inplace=True)
    df1['nationality'].fillna('na', inplace=True)
    df1['km'].fillna('na', inplace=True)

    df1['city'] = df1.groupby('country')['city'].transform(lambda x : x.fillna(x.mode()))
    df1.dropna(subset = ['pricequote'], inplace=True)

    #grouping
    grouping_cols = ['carbrand', 'cartype', 'city', 'country']

    for col in grouping_cols:
        df_idx = pd.DataFrame(df1[col].value_counts().head(6))

        def grouping(x):
            if x in df_idx.index:
                return x
            else:
                return "Others"
        df1[col] = df1[col].apply(lambda x: grouping(x))

    def age(x):
        if x < 20:
            return "u20"
        elif x > 19 and x < 29:
            return "20-28"
        elif x > 28 and x < 43:
            return "29-42"
        elif x > 42 and x < 55:
            return "43-54"
        elif x > 54 and x < 65:
            return "55-64"
        elif x >= 65:
            return "65+"
        else:
            return "Others"

    df1['age'] = df1['age'].astype(int)
    df1['age_bucket'] = df1['age'].apply(lambda x: age(x))

    df_final = df1[['ecid', 'hour', 'dayofweek','age_bucket', 'gender', 'city',
       'country', 'carbrand', 'cartype', 'leasing', 'pricequote']]

    #cat_cols = ['age_bucket', 'gender', 'city', 'dayofweek', 'country', 'carbrand', 'cartype', 'leasing']
    #df_final = pd.get_dummies(df_final, columns = cat_cols)

    dataframe = df_final.copy()

    print("Scoring Data Load Finish")

    return dataframe

これで、 スコアリングデータローダーファイル 」セルに似たような内容になります。

DSW

パイプラインファイル

Pipeline File (パイプラインファイル)が表示されるまでRecipe Builderノートブック内を下にスクロールします。

DSW

次に、 パイプラインファイルのコードを更新する必要があります

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

DSW

このセルには、次のようなコードが表示されます。

from sklearn.ensemble import GradientBoostingRegressor

def train(config_properties, data):

    print("Train Start")

    #########################################
    # Extract fields from configProperties
    #########################################
    learning_rate = float(config_properties['learning_rate'])
    n_estimators = int(config_properties['n_estimators'])
    max_depth = int(config_properties['max_depth'])


    #########################################
    # Fit model
    #########################################
    X_train = data.drop('weeklySalesAhead', axis=1).values
    y_train = data['weeklySalesAhead'].values

    seed = 1234
    model = GradientBoostingRegressor(learning_rate=learning_rate,
                                      n_estimators=n_estimators,
                                      max_depth=max_depth,
                                      random_state=seed)

    model.fit(X_train, y_train)
    print("Train Complete")
    return model

def score(config_properties, data, model):

    print("Score Start")

    X_test = data.drop('weeklySalesAhead', axis=1).values
    y_test = data['weeklySalesAhead'].values
    y_pred = model.predict(X_test)

    data['prediction'] = y_pred
    data = data[['store', 'prediction']].reset_index()
    data['date'] = data['date'].astype(str)

    print("Score Complete")
    return data

このコードを( %%writefile 行を上書きせずに)次のコードで置き換えます。

import pandas as pd
import numpy as np
from sklearn import metrics
from sklearn.metrics import roc_curve, auc, mean_squared_error
from sklearn.ensemble import RandomForestClassifier
import os

def underSample(data):
    conv = data[data['purchase'] > 0]
    non_conv = data[data['purchase'] == 0]
    sample_size = len(conv)
    non_sample = non_conv.sample(n = sample_size)
    frames = [conv, non_sample]
    result = pd.concat(frames)
    return result

class RandomForest():
    def __init__(self, config_properties, X, y):
        print("initiating model")
        self.n_estimators = int(config_properties['n_estimators'])
        self.max_depth = int(config_properties['max_depth'])
        self.X = X
        self.y = y
        self.features = X.columns.values.tolist()
        self.model = RandomForestClassifier(n_estimators=self.n_estimators, max_depth=self.max_depth, random_state=32)
        self.trained_model = self.model.fit(self.X,self.y)
    def train_model(self):
        print('fitting model')
        return self.model.fit(self.X,self.y)

    def make_tarfile(self, output_filename, source_dir):
        with tarfile.open(output_filename, "w:gz") as tar:
            tar.add(source_dir, arcname=os.path.basename(source_dir))

    #for generating onnx
    def generate_onnx_resources(self):
        install_dir = os.path.expanduser('~/my-workspace')
        print("Generating Onnx")
        try:
            subprocess.check_call(["conda", "uninstall", "-y", "protobuf"])
        except:
            print("protobuf not installed via conda")

        subprocess.check_call(["python", '-m', 'pip', 'install', 'skl2onnx'])

        from skl2onnx import convert_sklearn
        from skl2onnx.common.data_types import FloatTensorType

        # ONNX-ification
        initial_type = [('float_input', FloatTensorType([None, self.feature_len]))]

        print("Converting Model to Onnx")
        onx = convert_sklearn(self.model, initial_types=initial_type)

        with open("model_new.onnx", "wb") as f:
            f.write(onx.SerializeToString())

        self.make_tarfile('model_new.tar.gz', 'model.onnx')
        print("Model onnx created")

def train(config_properties, data):

    print("Train Start")
    y_train = data['purchase']
    X_train = data.drop('purchase', axis=1)
    # Fit model
    lead_score = RandomForest(config_properties, X_train, y_train)
    lead_score.train_model()

    print("Train Complete")

    return lead_score

def score(config_properties, data, model):

    print("Score Start")
    cat_cols = ['age_bucket', 'gender', 'city', 'dayofweek', 'country', 'carbrand', 'cartype', 'leasing']
    data = pd.get_dummies(data, columns = cat_cols)

    X_score = data.drop('ecid', axis=1)
    train_feats = model.features
    print(train_feats)

    trained_model = model.trained_model
    score_feats = X_score.columns.values.tolist()
    missing_feats = list(set(train_feats) - set(score_feats))
    extra_feats = list(set(score_feats) - set(train_feats))
    for c in extra_feats:
        X_score.drop(c, axis=1, inplace=True)
    for c in missing_feats:
        X_score[c] = 0
    X_score = X_score[train_feats]
    print(X_score.columns.values.tolist())
    y_preds = trained_model.predict_proba(X_score)[:,1]

    data.rename(columns = {'ecid' : config_properties['ten_id']+'.identification.core.ecid'}, inplace=True)

    data[config_properties['ten_id']+'.individualScoring.insurance.carInsuranceSalesPrediction'] = y_preds
    data = data[[config_properties['ten_id']+'.identification.core.ecid', config_properties['ten_id']+'.individualScoring.insurance.carInsuranceSalesPrediction']]

    print("Score Complete")
    return data

これで、「 パイプラインファイル 」(Pipeline File)セルに似たようなものが存在するはずです。

DSW

エバリュエーターファイル

Recipe Builderノートブックを下にスクロールして、 評価元ファイルが表示されます

DSW

ここで、 エバリュエーターファイルのコードを更新する必要があります

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

DSW

このセルには、次のようなコードが表示されます。

from ml.runtime.python.core.regressionEvaluator import RegressionEvaluator
import numpy as np

class Evaluator(RegressionEvaluator):
    def __init__(self):
        print ("Initiate")

    def split(self, config={}, dataframe=None):
        train_start = '2010-02-12'
        train_end = '2012-01-27'
        val_start = '2012-02-03'
        train = dataframe[train_start:train_end]
        val = dataframe[val_start:]

        return train, val

    def evaluate(self, data=[], model={}, config={}):
        print ("Evaluation evaluate triggered")
        val = data.drop('weeklySalesAhead', axis=1)
        y_pred = model.predict(val)
        y_actual = data['weeklySalesAhead'].values
        mape = np.mean(np.abs((y_actual - y_pred) / y_actual))
        mae = np.mean(np.abs(y_actual - y_pred))
        rmse = np.sqrt(np.mean((y_actual - y_pred) ** 2))

        metric = [{"name": "MAPE", "value": mape, "valueType": "double"},
                  {"name": "MAE", "value": mae, "valueType": "double"},
                  {"name": "RMSE", "value": rmse, "valueType": "double"}]

        print(metric)
        return metric

このコードを( %%writefile 行を上書きせずに)次のコードで置き換えます。

from ml.runtime.python.core.regressionEvaluator import RegressionEvaluator
import numpy as np
from sklearn import metrics
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split

class Evaluator(RegressionEvaluator):
    def __init__(self):
        print ("Initiate")

    def split(self, config={}, dataframe=None):

        train, val = train_test_split(dataframe, test_size = 0.2, random_state = 32)

        return train, val

    def evaluate(self, data=[], model={}, config={}):
        model = model.trained_model
        print ("Evaluation evaluate triggered")
        val = data.drop('purchase', axis=1)
        y_pred = model.predict(val)
        y_actual = data['purchase']

        y_pred_proba = model.predict_proba(val)[:,1]

        accuracy = metrics.accuracy_score(y_actual, y_pred, normalize=True, sample_weight=None)
        recall = metrics.recall_score(y_actual, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None)
        precision = metrics.precision_score(y_actual, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None)

        val_fpr, val_tpr, _ = roc_curve(y_actual, y_pred_proba)
        roc_auc = auc(val_fpr, val_tpr)

        metric = [{"name": "Accuracy", "value": accuracy, "valueType": "double"},
                  {"name": "Recall", "value": recall, "valueType": "double"},
                  {"name": "Precision", "value": precision, "valueType": "double"}]

        print(metric)
        return metric

これで、 評価基準ファイル セルに似たような要素が表示されます。

DSW

データセーバーファイル

Recipe Builderノートブックを下にスクロールして、[ Data Saver File]が表示されるまで下にスクロールします。

DSW

次に、 データセーバーファイルのコードを更新する必要があります

何をする前に気をつけて!! 何を行っても、 %%writefileを使って開始を削除したり、上書きしたりしないでください。 この行は、Recipe Builderノートブックで必要です。

DSW

このセルには、次のようなコードが表示されます。

import pandas as pd
from .utils import get_client_context
from platform_sdk.models import Dataset
from platform_sdk.dataset_writer import DatasetWriter

def save(config_properties, prediction):
  print("Datasaver Start")

  client_context = get_client_context(config_properties)
  tenant_id = config_properties.get("tenantId")
  prediction = prediction.add_prefix(tenant_id+".")

  prediction = prediction.join(pd.DataFrame(
      {
          '_id': "",
          'timestamp': '2019-01-01T00:00:00',
          'eventType': ""
      }, index=prediction.index))

  dataset = Dataset(client_context).get_by_id(config_properties['scoringResultsDataSetId'])
  dataset_writer = DatasetWriter(client_context, dataset)
  dataset_writer.write(prediction, file_format='json')

  print("Datasaver Finish")
  print(prediction)

このコードを( %%writefile 行を上書きせずに)次のコードで置き換えます。

from .utils import get_client_context
from platform_sdk.models import Dataset
from platform_sdk.dataset_writer import DatasetWriter

def save(config_properties, prediction):
  print("Datasaver Start")

  client_context = get_client_context(config_properties)
  dataset = Dataset(client_context).get_by_id(config_properties['scoringResultsDataSetId'])
  dataset_writer = DatasetWriter(client_context, dataset)
  dataset_writer.write(prediction, file_format='json')

  print("Datasaver Finish")
  print(prediction)

これで、[ Data Saver File ]セルに似たような内容が表示されます。

DSW

これで、ノートブックの実行に必要なすべてのコードが構成されました。

モデルのトレーニング

モデルのトレーニングは、[トレ イン ]ボタンをクリックして行います。

DSW

上部のツールバーにある[ トレーニング ]をクリックして、ノートブックにトレーニングを作成します。 これにより、トレーニングデータローダー、パイプラインセル、評価基準セルが実行され、モデルのパフォーマンスを測定する評価指標が生成されます。 トレーニングスクリプトのコマンドと出力のログがノートブック(エバリュエーター — セルの下)に表示されます。

Train」をクリックすると、トレーニングランが開始し、完了するまでに数分かかります。

DSWDSWDSW

「トレ イン」をクリックすると、次のセルが実行されます。

  • 要件ファイル
  • 設定ファイル — トレーニング
  • トレーニングデータローダーファイル
  • パイプラインファイル
  • エバリュエーターファイル

モデルにスコアを付ける

モデルのスコアは、「 スコア 」ボタンをクリックして実行します。

DSW

上部のツールバーにある スコア (Score)をクリックして、セルにトレーニングの実行を作成します。 これにより、スコアリングデータローダー、パイプラインセルおよび評価基準セルが実行され、モデルのパフォーマンスを測定する評価指標が生成されます。 A log of commands and outputs from the training script will appear in the notebook (under the pipeline.py cell).

スコア」をクリックすると、トレーニングの実行が開始し、完了するまでに数分かかります。

DSWDSWDSW

スコア」をクリックすると、次のセルが実行されます。

  • 要件ファイル
  • 設定ファイル — スコアリング
  • スコアリングデータローダーファイル
  • パイプラインファイル
  • エバリュエーターファイル

さらに、スコアリング実行の最後に、傾向スコアの出力がAdobe Experience PlatformのML予測(グローバルv1.1)データセットの デモシステム —プロファイルデータセットに保存されます

これは ここで確認できます

DSW

モデルからレシピを作成する

レシピの作成は、「レシピを 作成 」ボタンをクリックして行います。

DSW

トレーニングとスコアの出力結果に満足したら、レシピを作成できます。 「 レシピを作成 」ボタンをクリックして、プロセスを開始します。

レシピを作成すると、モデルを尺度でテストできます。

レシピを作成 」ボタンをクリックした後に、レシピの名前を入力する必要があります。

DSW

命名規則として、次を使用してください。

  • ​ldapCarInsurancePropentity

ldap をldapに置き換えます

例:ldap vangeluwの場合、レシピの名前は次のようになります。 vangeluwCarInsurancePropentity

DSW

「レシピ名」を入力した後、「 OK」をクリックします。

2つ目のポップアップが表示され、レシピが作成中であることを示します。 この処理には最大5分かかる場合があります。処理が終了するまでお待ちください。

DSW

レシピ作成プロセスの進行状況は、ジュピター・ノートブックの右上隅に表示できます。

DSW

他に何もしないでください。レシピ作成処理を続行する場合は、このブラウザウィンドウをノートブックで開いたままにしておく必要があります。

数分後に、レシピの作成が完了します。

ポップアップ・ウィンドウで[ 表示レシピ ]をクリックします。

DSW

次に、使用可能なすべてのレシピが表示されます。この中には、レシピも含まれています。

DSW

レシピの作成が完了したら、次の練習に進みましょう。ここでは、開始の拡張性に優れたトレーニングと実験を行います。

次の手順: 15.4レシピのトレーニングとスコアリング

モジュール15に戻る

すべてのモジュールに戻る

このページ