Пример: Создайте и разверните навык на заказ с помощью конструктора машинного обучения в Azure (архивировано)

Этот пример архивируется и не поддерживается. В нем объясняется, как использовать конструктор машинного обучения Azure — это простой интерактивный холст для создания моделей машинного обучения для таких задач, как регрессия и классификация. Вызов модели, созданной конструктором в конвейере обогащения Когнитивного поиска, требует нескольких дополнительных действий. В этом примере вы создадите простую модель регрессии для прогнозирования цены автомобиля и вызовете конечную точку инференса в качестве навыка AML.

Следуйте руководству Регрессия — прогнозирование цен на автомобили (расширенное) на странице документации примеры конвейеров и наборов данных, чтобы создать модель, которая прогнозирует цену автомобиля на основе различных характеристик.

Важный

Развертывание модели после процесса вывода в режиме реального времени приведет к допустимой конечной точке, но не к той, которую можно использовать с навыком AML в Когнитивном поиске.

Регистрация модели и скачивание ресурсов

После обучения модели зарегистрируйте обученную модель и выполните действия, чтобы скачать все файлы в trained_model_outputs папке или скачать только score.pyconda_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. Измените инструкцию возврата (строка 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 для Model Framework, 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. Нажмите кнопку развертывания, чтобы развернуть новую конечную точку.

Интеграция только что созданной конечной точки с Cognitive Search

  1. Добавьте JSON-файл, содержащий одну автомобильную запись, в контейнер блоб-объектов
  2. Настройте конвейер обогащения ИИ с помощью мастера импорта данных. Не забудьте выбрать 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.