Поделиться через


Пример. Создание и развертывание пользовательского навыка с помощью конструктора Машинного обучения 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.yamlconda dependencies file
  8. Нажмите кнопку развертывания, чтобы развернуть новую конечную точку.

Чтобы интегрировать только что созданную конечную точку с Когнитивным поиском, сделайте следующее:

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