管理实时机器学习笔记本(Alpha)

重要

尚未向所有用户提供实时机器学习。 此功能位于alpha中,仍在测试中。 此文档可能会更改。

以下指南概述了构建实时机器学习应用程序所需的步骤。 使用提供的​Real-time ML Python笔记本模板Adobe,本指南涵盖培训模型、创建DSL、将DSL发布到Edge并对请求打分。 在您实施实时机器学习模型的过程中,您需要修改模板以满足数据集的需求。

创建实时机器学习笔记本

在Adobe Experience Platform UI中,从​数据科学​中选择​Notebooks。 接下来,选择​JupyterLab,并为加载环境留出一些时间。

打开JupyterLab

出现JupyterLab启动器。 向下滚动至​Real-Time Machine Learning​并选择​Real-time ML​笔记本。 此时会打开一个模板,其中包含带有示例数据集的示例笔记本单元格。

blank python

导入和发现节点

开始,方法是为模型导入所有所需的包。 确保您计划用于节点创作的任何包都已导入。

注意

您对导入的列表可能因您希望创建的模型而有所不同。 随着新节点的添加,此列表将随时间而改变。 有关可用节点的完整列表,请参阅节点参考指南

from pprint import pprint
import pandas as pd
import numpy as np
import json
import uuid
from shutil import copyfile
from pathlib import Path
from datetime import date, datetime, timedelta
from platform_sdk.dataset_reader import DatasetReader

from rtml_nodelibs.nodes.standard.preprocessing.json_to_df import JsonToDataframe
from rtml_sdk.edge.utils import EdgeUtils
from rtml_sdk.graph.utils import GraphBuilder
from rtml_nodelibs.nodes.standard.ml.onnx import ONNXNode
from rtml_nodelibs.core.nodefactory import NodeFactory as nf
from rtml_nodelibs.nodes.standard.preprocessing.pandasnode import Pandas
from rtml_nodelibs.nodes.standard.preprocessing.one_hot_encoder import OneHotEncoder
from rtml_nodelibs.nodes.standard.ml.artifact_utils import ModelUpload
from rtml_nodelibs.core.nodefactory import NodeFactory as nf
from rtml_nodelibs.core.datamsg import DataMsg

以下代码单元格打印可用节点的列表。

# Discover Nodes
pprint(nf.discover_nodes())

列表备注

实时机器学习模型的训练

使用以下选项之一,您即将编写Python代码以读取、预处理和分析数据。 接下来,您需要培训自己的ML模型,将其序列化为ONNX格式,然后将其上传到Real-time Machine Learning模型存储。

培训您自己的型号

开始。

注意

在​实时ML​模板中,从Github中捕获汽车保险CSV数据集

加载培训数据

如果您希望从Adobe Experience Platform中使用数据集,请取消以下单元格的注释。 接下来,您需要用相应的值替换DATASET_ID

rtml数据集

要访问JupyterLab笔记本中的数据集,请在JupyterLab的左侧导航中选择​数据​选项卡。 将显示​Datasets​和​Schemas​目录。 选择​Datasets​并右键单击,然后从您要使用的数据集的下拉菜单中选择​Explore Data in Notebook​选项。 可执行代码条目显示在笔记本的底部。 此单元格包含您的dataset_id

数据集访问

完成后,右键单击并删除您在笔记本底部生成的单元格。

培训属性

使用提供的模板,修改config_properties中的任何培训属性。

config_properties = {
    "train_records_limit":1000000,
    "n_estimators": "80",
    "max_depth": "5",
    "ten_id": "_experienceplatform"  
}

准备模型

使用​Real-time ML​模板,您需要分析、预处理、培训和评估ML模型。 通过应用数据转换和构建培训管道来完成此操作。

数据转换

需要修改​Real-time ML​模板​数据转换​单元格,才能使用您自己的数据集。 通常,这涉及重命名列、数据汇总以及数据准备/功能工程。

注意

以下示例已使用[ ... ]进行压缩以用于可读性。 请视图并展开完整代码单元格的​实时ML​模板数据转换部分。

df1.rename(columns = {config_properties['ten_id']+'.identification.ecid' : 'ecid',
                     [ ... ]}, inplace=True)
df1 = df1[['ecid', 'km', 'cartype', 'age', 'gender', 'carbrand', 'leasing', 'city', 
       'country', 'nationality', 'primaryuser', 'purchase', 'pricequote', 'timestamp']]
print("df1 shape 1", df1.shape)
#########################################
# 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'] == 'yes'), 'purchase'] = 1
df1.purchase.fillna(0, inplace=True)
df1['purchase'] = df1['purchase'].astype(int)

[ ... ]

print("df1 shape 2", df1.shape)

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

df1['carbrand'] = df1['carbrand'].str.lower()
df1['country'] = df1['country'].str.lower()
df1.loc[(df1['carbrand'] == 'vw'), 'carbrand'] = 'volkswagen'

[ ... ]

df1['age'].fillna(df1['age'].median(), inplace=True)
df1['gender'].fillna('notgiven', inplace=True)

[ ... ]

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

#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:
    [ ... ]
    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']]
print("df final", df_final.shape)

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

运行提供的单元格以查看示例结果。 从carinsurancedataset.csv数据集返回的输出表返回您定义的修改。

数据转换示例

培训渠道

然后,您需要创建培训管道。 除了需要转换和生成ONNX文件外,这看起来与任何其他培训管道文件相似。

使用在上一个单元格中定义的数据转换,修改模板。 下面突出显示的代码用于在功能管道中生成ONNX文件。 请视图​实时ML​模板,以获取完整的管道代码单元格。

#for generating onnx
def generate_onnx_resources(self):        
    install_dir = os.path.expanduser('~/my-workspace')
    print("Generating Onnx")
        
    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.onnx", "wb") as f:
        f.write(onx.SerializeToString())
            
    print("Model onnx created")

完成培训管道并通过数据转换修改数据后,请使用以下单元格运行培训。

model = train(config_properties, df_final)

生成并上传ONNX模型

完成成功的培训运行后,您需要生成一个ONNX模型并将培训的模型上传到Real-time Machine Learning模型存储。 运行以下单元格后,您的ONNX型号将与所有其他笔记本一起显示在左边栏中。

import os
import skl2onnx, subprocess

model.generate_onnx_resources()
注意

更改model_path字符串值(model.onnx)以更改模型的名称。

model_path = "model.onnx"
注意

以下单元格不可编辑或删除,并且需要该单元格才能使用实时机器学习应用程序。

model = ModelUpload(params={'model_path': model_path})
msg_model = model.process(None, 1)
model_id = msg_model.model['model_id']
 
print("Model ID : ", model_id)

ONNX模型

上传您自己预先培训的ONNX模型

使用位于JupyterLab笔记本中的上载按钮,将您预先培训的ONNX型号上载到Data Science Workspace笔记本环境。

上载图标

接下来,更改​实时ML​笔记本中的model_path字符串值以匹配您的ONNX型号名称。 完成后,运行​设置模型路径​单元格,然后运行​将模型上传到RTML模型存储​单元格。 成功时,您的模型位置和模型ID都会在响应中返回。

上传自己的模型

域特定语言(DSL)创建

本节概述创建DSL。 您即将创作包含任何数据预处理的节点,以及ONNX节点。 接下来,使用节点和边创建DSL图。 边缘使用基于元组的格式(node_1、node_2)连接节点。 图形不应具有循环。

重要

必须使用ONNX节点。 如果没有ONNX节点,应用程序将失败。

节点创作

注意

您可能会根据所使用的数据类型有多个节点。 下面的示例仅概述​实时ML​模板中的单个节点。 请视图完整代码单元格的​实时ML​模板​节点创作​部分。

下面的Pacnots节点使用"import": "map"将方法名称作为字符串导入参数中,然后输入参数作为映射函数。 以下示例使用{'arg': {'dataLayerNull': 'notgiven', 'no': 'no', 'yes': 'yes', 'notgiven': 'notgiven'}}执行此操作。 映射到位后,您可以选择将inplace设置为TrueFalse。 根据是否要应用转换,将inplace设置为TrueFalse。 默认情况下,"inplace": False会创建新列。 为提供新列名称提供支持的设置将添加到后续发行版中。 最后一行cols可以是单列名称或列列表。 指定要应用转换的列。 在此示例中,指定了leasing。 有关可用节点以及如何使用这些节点的详细信息,请访问节点参考指南

# Renaming leasing column using Pandas Node
leasing_mapper_node = Pandas(params={'import': 'map',
                                'kwargs': {'arg': {
                                    'dataLayerNull': 'notgiven', 
                                    'no': 'no', 
                                    'yes': 'yes', 
                                    'notgiven': 'notgiven'}},
                                'inplace': True,
                                'cols': 'leasing'})

构建DSL图

创建节点后,下一步是将节点链在一起以创建图形。

开始,通过构建数组来列出图形的所有节点。

nodes = [json_df_node, 
        to_datetime_node,
        hour_node,
        dayofweek_node,
        age_fillna_node,
        carbrand_fillna_node,
        country_fillna_node,
        cartype_primary_nationality_km_fillna_node,
        carbrand_mapper_node,
        cartype_mapper_node,
        country_mapper_node,
        gender_mapper_node,
        leasing_mapper_node,
        age_to_int_node,
        age_bins_node,
        dummies_node, 
        onnx_node]

接下来,将节点与边连接。 每个元组都是Edge连接。

小贴士

由于节点之间是线性相关的(每个节点都取决于前一个节点的输出),您可以使用简单的Python列表理解创建链接。 如果节点依赖多个输入,请添加您自己的连接。

edges = [(nodes[i], nodes[i+1]) for i in range(len(nodes)-1)]

连接节点后,构建图。 以下单元格为必填项,无法编辑或删除。

dsl = GraphBuilder.generate_dsl(nodes=nodes, edges=edges)
pprint(json.loads(dsl))

完成后,将返回一个edge对象,其中包含每个节点以及映射到这些节点的参数。

edge retur

发布到边缘(集线器)

注意

实时机器学习临时部署到Adobe Experience Platform Hub并由其管理。 有关其他详细信息,请访问实时机器学习架构的概述部分。

现在您已创建了DSL图形,可以将图形部署到Edge。

重要

不要经常发布到Edge,这会使Edge节点过载。 建议不要多次发布同一模型。

edge_utils = EdgeUtils()
(edge_location, service_id) = edge_utils.publish_to_edge(dsl=dsl)
print(f'Edge Location: {edge_location}')
print(f'Service ID: {service_id}')

更新DSL并重新发布到Edge(可选)

如果不需要更新DSL,可跳至评分

注意

仅当您希望更新已发布到Edge的现有DSL时,才需要以下单元格。

您的模型可能会不断发展。 与其创建全新服务,不如使用新模型更新现有服务。 您可以定义要更新的节点,为其分配新ID,然后将新DSL重新上传到Edge。

在以下示例中,节点0会使用新ID进行更新。

# Update the id of Node 0 with a random uuid.

dsl_dict = json.loads(dsl)
print(f"ID of Node 0 in current DSL: {dsl_dict['edge']['applicationDsl']['nodes'][0]['id']}")

new_node_id = str(uuid.uuid4())
print(f'Updated Node ID: {new_node_id}')

dsl_dict['edge']['applicationDsl']['nodes'][0]['id'] = new_node_id

更新的节点

更新节点ID后,您可以将更新的DSL重新发布到Edge。

# Republish the updated DSL to Edge
(edge_location_ret, service_id, updated_dsl) = edge_utils.update_deployment(dsl=json.dumps(dsl_dict), service_id=service_id)
print(f'Updated dsl: {updated_dsl}')

您将返回更新的DSL。

更新的DSL

评分

发布到Edge后,评分由客户端的POST请求完成。 通常,这可以从需要ML分数的客户端应用程序中完成。 您也可以从邮递员那里做。 Real-time ML​模板使用EdgeUtils演示此过程。

注意

在对开始评分之前,需要少量处理时间。

# Wait for the app to come up
import time
time.sleep(20)

使用与培训中使用的模式相同的内容,生成样本评分数据。 此数据用于构建一个评分数据帧,然后转换为评分词典。 请视图完整代码单元格的​实时ML​模板。

评分数据

对Edge端点进行分数

使用​实时ML​模板中的以下单元格对Edge服务进行评分。

对边缘得分

评分完成后,将返回Edge中的Edge URL、Payload和计分输出。

从Edge列表已部署的应用程序

要在Edge上生成当前部署的应用程序的列表,请运行以下代码单元格。 无法编辑或删除此单元格。

services = edge_utils.list_deployed_services()
print(services)

返回的响应是已部署服务的数组。

[
    {
        "created": "2020-05-25T19:18:52.731Z",
        "deprecated": false,
        "id": "40eq76c0-1c6f-427a-8f8f-54y9cdf041b7",
        "type": "edge",
        "updated": "2020-05-25T19:18:52.731Z"
    }
]

从Edge中删除已部署的应用程序或服务ID(可选)

注意

此单元格用于删除已部署的Edge应用程序。 除非需要删除已部署的Edge应用程序,否则不要使用以下单元格。

if edge_utils.delete_from_edge(service_id=service_id):
    print(f"Deleted service id {service_id} successfully")
else:
    print(f"Failed to delete service id {service_id}")

后续步骤

通过上面的教程,您成功地培训了ONNX模型并将其上传到实时机器学习模型存储。 此外,您还对实时机器学习模型进行了评分和部署。 如果您想了解有关可用于模型创作的节点的更多信息,请访问节点参考指南

在此页面上