15.3 Opérationnaliser votre modèle à l'aide d'une Recette

Dans cet exercice, vous prendrez votre modèle et le rendrez opérationnel à Adobe Experience Platform en créant une recette.

Le bloc-notes du créateur de recettes modélise votre modèle pour l'assembler automatiquement et l'opérationnaliser. Le bloc-notes comporte plusieurs cellules modèles dans lesquelles vous pouvez ajuster le code du modèle :

  • Les exigences et les cellules de configuration vous permettent d'ajouter des bibliothèques supplémentaires et de configurer des jeux de données et des paramètres de réglage pour votre modèle.
  • La cellule d’évaluateur vous permet de fractionner vos données et d’évaluer les performances de votre modèle.
  • Les cellules du chargeur de données de formation et de notation vous permettent de charger les données dont vous avez besoin pour la formation et la notation.
  • Enfin, la cellule de pipeline contient la logique requise pour la formation et la notation de votre modèle.

Nous avons rationalisé les étapes nécessaires à la mise en oeuvre d'un modèle en vous permettant de le former, de l'évaluer et de le noter à l'échelle et de le regrouper dans un flux continu sur Adobe Experience Platform. L'empaquetage sur une recette vous permet également d'utiliser le même code avec des jeux de données différents pour gérer différents cas d'utilisation dans vos entreprises. Notre cas d'utilisation spécifique est axé sur l'utilisation du code de modèle de Recommandations pour les utilisateurs qui recherchent des produits à acheter sur le site Web.

Connectez-vous à Adobe Experience Platform en accédant à cette URL : https://experience.adobe.com/platform.

Une fois connecté, vous accédez à la page d'accueil de Adobe Experience Platform.

Ingestion des données

Avant de continuer, vous devez sélectionner un sandbox. Le sandbox à sélectionner est nommé --aepSandboxId--. Pour ce faire, cliquez sur le texte Production Prod dans la ligne bleue située en haut de votre écran.

Ingestion des données

Après avoir sélectionné le sandbox approprié, vous verrez l'écran changer et vous êtes maintenant dans votre sandbox dédié.

Ingestion des données

Dans Adobe Experience Platform, cliquez sur Ordinateurs portables dans le menu à gauche de l'écran, puis allez à JupyterLab.

Ingestion des données

Dans les portables Jupyter, ouvrez la page Launcher en cliquant sur l'icône + dans la barre des tâches.

DSW

Vous verrez alors ceci :

DSW

Ouvrez un bloc-notes Générateur de recettes vierge en cliquant sur le bouton Générateur de recettes sur le lanceur.

DSW

Vous aurez alors un nouveau bloc-notes vide et vide du Générateur de recettes. Avant de continuer, donnez un nom descriptif à votre bloc-notes. Cliquez avec le bouton droit sur le fichier [Python 3] Recipe Builder.ipynb et cliquez sur Renommer.

DSW

Saisissez mutuel365-insurance-sales-propensity.ipynb comme nom pour votre ordinateur portable et appuyez sur Entrée. Vous aurez ensuite ceci :

DSW

Dans ce bloc-notes, vous allez effectuer les opérations suivantes :

  • Former un modèle
  • Score d’un modèle
  • Créer une recette à partir du modèle

Configurez toutes les étapes en détail.

Fichiers de configuration

Faites défiler l'écran vers le bas du bloc-notes Recipe Builder jusqu'à ce que les fichiers de configuration s'affichent.

DSW

Vous devez maintenant mettre à jour les cellules pour la configuration de formation et la configuration de score.

Configuration de la formation

Cliquez dans la cellule pour Configuration de la formation.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

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

DSW

Vous verrez également du code similaire dans cette même cellule :

{
   "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"
}

Remplacez ce code par ce code :

{
    "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--"
}
IMPORTANT

Les variables d'environnement aepCarInsuranceInteractionsDatasetId et aepCarInsuranceInteractionsSchemaRef font référence à un ID de jeu de données du jeu de données créé dans votre instance Adobe Experience Platform et à un ID de référence de schéma d'un schéma créé dans votre instance Adobe Experience Platform.

aepCarInsuranceInteractionsDatasetId fait référence à l'ID de jeu de données du système de démonstration de jeu de données - jeu de données de Événement pour le site Web (Global v1.1), aepCarInsuranceInteractionsSchemaRef fait référence à l'ID de référence de Schéma du système de démonstration de schéma - Schéma de Événement pour le site Web (Global v1.1.1.1). Remplacez les variables d’environnement par l’ID de jeu de données et l’ID de référence du Schéma lorsque vous collez le code dans la cellule Configuration de la formation de votre bloc-notes.

Vous devez maintenant disposer d’un élément similaire dans la cellule Configuration de la formation :

DSW

Configuration du score

Cliquez dans la cellule pour Scoring Configuration.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

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

DSW

Vous verrez également du code similaire dans cette même cellule :

{
   "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>"
}

Remplacez ce code par ce code :

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

Les variables d'environnement aepCarInsuranceInteractionsDatasetId, aepMlPredictionsDatasetId et aepMlPredictionsSchemaRef se rapportent aux ID de jeu de données des jeux de données et à l'ID de référence de Schéma des schémas créés dans votre instance Adobe Experience Platform.

aepCarInsuranceInteractionsDatasetId fait référence à l'ID de jeu de données du système de démonstration de jeu de données - jeu de données de Événement pour le site Web (Global v1.1), aepMlPredictionsDatasetId fait référence à l'ID de jeu de données du système de démonstration de jeux de données - jeu de données pour les prédictions ML (Global v 1), aepMlPredictionsSchemaRef fait référence à l'ID de référence du Schéma du Schéma de données de Profil du système de démonstration de l'schéma, le Schéma de Profil pour les prédictions ML (Global v1.1). ​**​** Remplacez les variables d’environnement par l’ID de jeu de données et l’ID de référence du Schéma lorsque vous collez le code dans la cellule Configuration de score de votre bloc-notes.

Vous devez maintenant disposer de quelque chose de similaire dans la cellule Configuration ​de score :

DSW

Fichier de chargement de données de formation

Faites défiler l'écran vers le bas du bloc-notes du Générateur de recettes jusqu'à ce que le fichier de chargement de données de formation s'affiche.

DSW

Vous devez maintenant mettre à jour le code du fichier de chargement de données de formation.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

DSW

Dans cette cellule, vous trouverez un code similaire à celui-ci :

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

Remplacez ce code (sans remplacer la ligne %%writefile ) par ce code :

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

Vous devez maintenant disposer d’un élément similaire dans la cellule Fichier de chargeur de données d’ entraînement:

DSW

Score du fichier de chargeur de données

Faites défiler l'écran vers le bas du bloc-notes du Générateur de recettes jusqu'à ce que le fichier ​Scoring Data Loader s'affiche.

DSW

Vous devez maintenant mettre à jour le code du fichier de chargement de données de score.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

DSW

Dans cette cellule, vous trouverez un code similaire à celui-ci :

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

Remplacez ce code (sans remplacer la ligne %%writefile ) par ce code :

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

Vous devez maintenant disposer d’un élément similaire dans la cellule Fichier de chargement de données de score :

DSW

Fichier de tuyau

Faites défiler l'écran vers le bas du bloc-notes Recipe Builder jusqu'à ce que le fichier ​Pipeline s'affiche.

DSW

Vous devez maintenant mettre à jour le code du fichier ​pipelines.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

DSW

Dans cette cellule, vous trouverez un code similaire à celui-ci :

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

Remplacez ce code (sans remplacer la ligne %%writefile ) par ce code :

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

Vous devez maintenant disposer de quelque chose de similaire dans la cellule Fichier de tuyau :

DSW

Fichier d’évaluation

Faites défiler l'écran vers le bas du bloc-notes du Générateur de recettes jusqu'à ce que le fichier ​Evaluator s'affiche.

DSW

Vous devez maintenant mettre à jour le code du fichier ​d’évaluation.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

DSW

Dans cette cellule, vous trouverez un code similaire à celui-ci :

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

Remplacez ce code (sans remplacer la ligne %%writefile ) par ce code :

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

Vous devez maintenant disposer de quelque chose de similaire dans la cellule Fichier ​évaluateur :

DSW

Fichier d'enregistrement de données

Faites défiler l'écran vers le bas du bloc-notes du Générateur de recettes jusqu'à ce que le fichier ​Data Saver s'affiche.

DSW

Vous devez maintenant mettre à jour le code du fichier ​d’enregistrement de données.

Avant de faire quoi que ce soit, veuillez faire attention ! ! Quoi que vous fassiez, ne supprimez ou n'écrasez pas la ligne qui début avec %%write. Cette ligne est requise par le bloc-notes Recipe Builder.

DSW

Dans cette cellule, vous trouverez un code similaire à celui-ci :

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)

Remplacez ce code (sans remplacer la ligne %%writefile ) par ce code :

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)

La cellule Fichier de l’ économiseur de données doit maintenant contenir un élément similaire :

DSW

Vous avez maintenant configuré tout le code dont vous avez besoin pour exécuter votre bloc-notes.

Former un modèle

Pour former un modèle, cliquez sur le bouton Train .

DSW

Cliquez sur Train sur la barre d'outils supérieure pour créer une session de formation dans le bloc-notes. Cette opération exécute les cellules du chargeur de données de formation, du pipeline et de l’évaluateur et génère des mesures d’évaluation afin d’évaluer les performances du modèle. Un journal des commandes et des sorties du script de formation s'affiche dans le bloc-notes (sous la cellule Évaluateur - ).

Après avoir cliqué sur Train, la session de formation début et dure quelques minutes.

DSW
DSW
DSW

Lorsque vous cliquez sur Train, les cellules suivantes sont exécutées :

  • Fichier requis
  • Fichiers de configuration - Formation
  • Fichier de chargement de données de formation
  • Fichier de tuyau
  • Fichier d’évaluation

Score d’un modèle

Le score d’un modèle est effectué en cliquant sur le bouton Note .

DSW

Cliquez sur Score sur la barre d’outils supérieure pour créer une exécution de formation dans la cellule. Cette opération exécute les cellules du chargeur de données de score, du pipeline et de l’évaluateur et génère des mesures d’évaluation afin d’évaluer les performances du modèle. A log of commands and outputs from the training script will appear in the notebook (under the pipeline.py cell).

Après avoir cliqué sur Score, la session de formation début et dure quelques minutes.

DSW
DSW
DSW

Lorsque vous cliquez sur Score, les cellules suivantes sont exécutées :

  • Fichier requis
  • Fichiers de configuration - Score
  • Score du fichier de chargeur de données
  • Fichier de tuyau
  • Fichier d’évaluation

De plus, à la fin de la série de score, la sortie avec des scores de propension est stockée dans Adobe Experience Platform, dans le jeu de données Demo System - Profil Dataset for ML Predictions (Global v1.1) .

Vous pouvez vérifier ceci ici.

DSW

Créer une recette à partir du modèle

Pour créer une recette, cliquez sur le bouton Créer une recette .

DSW

Lorsque vous êtes satisfait des résultats de la formation et de la notation, vous pouvez créer une recette. Cliquez sur le bouton Créer une recette pour début du processus.

La création d'une recette vous permet de tester votre modèle à l'échelle.

Après avoir cliqué sur le bouton Créer une recette , vous devez saisir un nom pour votre recette.

DSW

À titre de convention d’affectation de nom, veuillez utiliser :

  • ​ldapCarInsurancePropensity

Remplacez ldap par ldap.

Exemple : pour ldap vangeluw, le nom de votre recette doit être : vangeluwCarInsurancePropensity.

DSW

Après avoir saisi un nom de recette, cliquez sur OK.

Une seconde fenêtre contextuelle s'affiche, vous indiquant que votre Recette est en cours de création. Cette opération peut prendre jusqu'à 5 minutes, veuillez patienter jusqu'à ce que le processus se termine.

DSW

Vous pouvez vue la progression du processus de création de recettes dans le coin supérieur droit des blocs-notes Jupyter.

DSW

Ne faites rien d'autre, vous devez garder cette fenêtre de navigateur ouverte sur le bloc-notes avec le processus de création de recettes en cours.

Au bout de quelques minutes, la création de la recette est terminée.

Cliquez sur Recettes de Vue dans la fenêtre contextuelle.

DSW

Vous verrez alors toutes les recettes disponibles, qui incluent maintenant votre recette également.

DSW

Maintenant que vous avez créé votre recette, poursuivons l'exercice suivant dans lequel vous allez début une formation et une expérimentation évolutives.

Étape suivante : 15.4 Formation et score de votre recette

Revenir au module 15

Revenir à tous les modules

Sur cette page