示例:使用 Azure 机器学习设计器生成和部署自定义技能(存档)

此示例已存档且不受支持。 其中介绍了如何使用 Azure 机器学习设计器 是一种易于使用的交互式画布,用于为回归和分类等任务创建机器学习模型。 调用设计器在认知搜索扩充管道中创建的模型需要执行一些额外的步骤。 在此示例中,你将创建一个简单的回归模型来预测汽车的价格,并将推理终结点调用为 AML 技能。

按照 回归 - 汽车价格预测(高级) 教程中的 示例管道 & 数据集 文档页创建一个模型来预测给定不同特征的汽车价格。

重要

按照实时推理过程部署模型将导致有效的终结点,但不能将模型用于认知搜索中的 AML 技能。

注册模型并下载资产

训练模型后,注册训练的模型,并按照步骤下载 trained_model_outputs 文件夹中的所有文件,或仅下载模型项目页中的 score.py 和 conda_env.yml 文件。 在将模型部署为实时推理终结点之前,将编辑评分脚本。

认知搜索增强流程作用于单个文档,并生成包含单个预测输入的请求。 下载的 score.py 接受记录列表,并将预测列表作为序列化的 JSON 字符串返回。 你将对 score.py 进行两项更改

  • 编辑脚本以处理单个输入记录,而不是列表
  • 编辑脚本以返回具有单个属性(预测价格)的 JSON 对象。

打开下载的 score.py 并编辑 run(data) 函数。 该函数目前设置为接受如模型 _samples.json 文件中所述的以下输入。

[
  {
    "symboling": 2,
    "make": "mitsubishi",
    "fuel-type": "gas",
    "aspiration": "std",
    "num-of-doors": "two",
    "body-style": "hatchback",
    "drive-wheels": "fwd",
    "engine-location": "front",
    "wheel-base": 93.7,
    "length": 157.3,
    "width": 64.4,
    "height": 50.8,
    "curb-weight": 1944,
    "engine-type": "ohc",
    "num-of-cylinders": "four",
    "engine-size": 92,
    "fuel-system": "2bbl",
    "bore": 2.97,
    "stroke": 3.23,
    "compression-ratio": 9.4,
    "horsepower": 68.0,
    "peak-rpm": 5500.0,
    "city-mpg": 31,
    "highway-mpg": 38,
    "price": 6189.0
  },
  {
    "symboling": 0,
    "make": "toyota",
    "fuel-type": "gas",
    "aspiration": "std",
    "num-of-doors": "four",
    "body-style": "wagon",
    "drive-wheels": "fwd",
    "engine-location": "front",
    "wheel-base": 95.7,
    "length": 169.7,
    "width": 63.6,
    "height": 59.1,
    "curb-weight": 2280,
    "engine-type": "ohc",
    "num-of-cylinders": "four",
    "engine-size": 92,
    "fuel-system": "2bbl",
    "bore": 3.05,
    "stroke": 3.03,
    "compression-ratio": 9.0,
    "horsepower": 62.0,
    "peak-rpm": 4800.0,
    "city-mpg": 31,
    "highway-mpg": 37,
    "price": 6918.0
  },
  {
    "symboling": 1,
    "make": "honda",
    "fuel-type": "gas",
    "aspiration": "std",
    "num-of-doors": "two",
    "body-style": "sedan",
    "drive-wheels": "fwd",
    "engine-location": "front",
    "wheel-base": 96.5,
    "length": 169.1,
    "width": 66.0,
    "height": 51.0,
    "curb-weight": 2293,
    "engine-type": "ohc",
    "num-of-cylinders": "four",
    "engine-size": 110,
    "fuel-system": "2bbl",
    "bore": 3.15,
    "stroke": 3.58,
    "compression-ratio": 9.1,
    "horsepower": 100.0,
    "peak-rpm": 5500.0,
    "city-mpg": 25,
    "highway-mpg": 31,
    "price": 10345.0
  }
]

更改将确保模型可以接受认知搜索在编制索引期间生成的输入,这是一条记录。

{
    "symboling": 2,
    "make": "mitsubishi",
    "fuel-type": "gas",
    "aspiration": "std",
    "num-of-doors": "two",
    "body-style": "hatchback",
    "drive-wheels": "fwd",
    "engine-location": "front",
    "wheel-base": 93.7,
    "length": 157.3,
    "width": 64.4,
    "height": 50.8,
    "curb-weight": 1944,
    "engine-type": "ohc",
    "num-of-cylinders": "four",
    "engine-size": 92,
    "fuel-system": "2bbl",
    "bore": 2.97,
    "stroke": 3.23,
    "compression-ratio": 9.4,
    "horsepower": 68.0,
    "peak-rpm": 5500.0,
    "city-mpg": 31,
    "highway-mpg": 38,
    "price": 6189.0
}

将第 27 行至 30 行替换为


    for key, val in data.items():
        input_entry[key].append(decode_nan(val))

还需要编辑脚本从字符串生成的输出到 JSON 对象。 编辑原始文件中的 return 语句(第 37 行),更改为:

    output = result.data_frame.values.tolist()
    return {
        "predicted_price": output[0][-1]
    }

下面是更新的 run 函数,其中包含输入格式的更改以及将接受单个记录作为输入的预测输出,并返回具有预测价格的 JSON 对象。

def run(data):
    data = json.loads(data)
    input_entry = defaultdict(list)
    # data is now a JSON object not a list of JSON objects
    for key, val in data.items():
        input_entry[key].append(decode_nan(val))

    data_frame_directory = create_dfd_from_dict(input_entry, schema_data)
    score_module = ScoreModelModule()
    result, = score_module.run(
        learner=model,
        test_data=DataTable.from_dfd(data_frame_directory),
        append_or_result_only=True)
    #return json.dumps({"result": result.data_frame.values.tolist()})
    output = result.data_frame.values.tolist()
    # return the last column of the the first row of the dataframe
    return  {
        "predicted_price": output[0][-1]
    }

注册并部署模型

保存更改后,现在可以在门户中注册模型。 选择注册模型,并提供有效的名称。 选择 Other 作为模型框架,Custom 作为框架名称,1.0 作为框架版本。 选择 Upload folder 选项,然后选择具有更新 score.py 和 conda_env.yaml的文件夹。

选择模型,然后选择 Deploy 操作。 部署步骤假定已预配 AKS 推理群集。 认知搜索当前不支持容器实例。

  1. 提供有效的终结点名称
  2. 选择 Azure Kubernetes Service 的计算类型
  3. 选择推理群集的计算名称
  4. 将 enable authentication 切换到“开启”
  5. 为类型选择 Key-based authentication
  6. 选择更新的 score.py 用于 entry script file
  7. 选择 conda_env.yaml 的 conda dependencies file
  8. 选择“部署”按钮以部署新终结点。

将新创建的终结点与认知搜索集成

  1. 将包含单个汽车记录的 JSON 文件添加到 Blob 容器
  2. 使用导入数据向导配置 AI 扩充管道。 请务必选择 JSON 作为 parsing mode
  3. 在“Add Enrichments”选项卡上,选择单个技能 Extract people names 作为占位符。
  4. 将名为 predicted_price类型的 Edm.Double 的新字段添加到索引中,将“可检索”属性设置为 true。
  5. 完成导入数据过程

将 AML 技能添加到技能集

从技能集列表中,选择创建的技能集。 现在,你将编辑技能集,将人员识别技能替换为 AML 技能来预测价格。 在“技能集定义”(JSON)选项卡上,从技能下拉列表中选择 Azure Machine Learning (AML)。 选择工作区,以便 AML 技能发现您的终结点。工作区和搜索服务需要位于同一 Azure 订阅中。 选择在本教程前面创建的终结点。 验证技能是否已使用部署终结点时配置的 URI 和身份验证信息进行填充。 复制技能模板并替换技能组中的技能。 将技能编辑为:

  1. 将名称设置为有效名称
  2. 添加说明
  3. 将 degreesOfParallelism 设置为 1
  4. 将上下文设置为 /document
  5. 将输入设置为所有必需的输入,请参阅下面的示例技能定义
  6. 设置输出以捕捉返回的预测价格。
{
      "@odata.type": "#Microsoft.Skills.Custom.AmlSkill",
      "name": "AMLdemo",
      "description": "AML Designer demo",
      "context": "/document",
      "uri": "Your AML endpoint",
      "key": "Your AML endpoint key",
      "resourceId": null,
      "region": null,
      "timeout": "PT30S",
      "degreeOfParallelism": 1,
      "inputs": [
        {
          "name": "symboling",
          "source": "/document/symboling"
        },
        {
          "name": "make",
          "source": "/document/make"
        },
        {
          "name": "fuel-type",
          "source": "/document/fuel-type"
        },
        {
          "name": "aspiration",
          "source": "/document/aspiration"
        },
        {
          "name": "num-of-doors",
          "source": "/document/num-of-doors"
        },
        {
          "name": "body-style",
          "source": "/document/body-style"
        },
        {
          "name": "drive-wheels",
          "source": "/document/drive-wheels"
        },
        {
          "name": "engine-location",
          "source": "/document/engine-location"
        },
        {
          "name": "wheel-base",
          "source": "/document/wheel-base"
        },
        {
          "name": "length",
          "source": "/document/length"
        },
        {
          "name": "width",
          "source": "/document/width"
        },
        {
          "name": "height",
          "source": "/document/height"
        },
        {
          "name": "curb-weight",
          "source": "/document/curb-weight"
        },
        {
          "name": "engine-type",
          "source": "/document/engine-type"
        },
        {
          "name": "num-of-cylinders",
          "source": "/document/num-of-cylinders"
        },
        {
          "name": "engine-size",
          "source": "/document/engine-size"
        },
        {
          "name": "fuel-system",
          "source": "/document/fuel-system"
        },
        {
          "name": "bore",
          "source": "/document/bore"
        },
        {
          "name": "stroke",
          "source": "/document/stroke"
        },
        {
          "name": "compression-ratio",
          "source": "/document/compression-ratio"
        },
        {
          "name": "horsepower",
          "source": "/document/horsepower"
        },
        {
          "name": "peak-rpm",
          "source": "/document/peak-rpm"
        },
        {
          "name": "city-mpg",
          "source": "/document/city-mpg"
        },
        {
          "name": "highway-mpg",
          "source": "/document/highway-mpg"
        },
        {
          "name": "price",
          "source": "/document/price"
        }
      ],
      "outputs": [
        {
          "name": "predicted_price",
          "targetName": "predicted_price"
        }
      ]
    }

更新索引器输出字段映射

索引器输出字段的映射确定了哪些增强功能会被保存到索引中。 将索引器的输出字段映射部分替换为以下代码片段:

"outputFieldMappings": [
    {
      "sourceFieldName": "/document/predicted_price",
      "targetFieldName": "predicted_price"
    }
  ]

现在,您可以运行索引器,并验证 predicted_price 属性在索引中是否已被填入来自 AML 技能输出的结果。