Exemple : Générer et déployer une compétence personnalisée avec le concepteur Azure Machine Learning (archivé)

Cet exemple est archivé et hors support. Il a expliqué comment utiliser le concepteur Azure Machine Learning est un canevas interactif facile à utiliser pour créer des modèles Machine Learning pour des tâches telles que la régression et la classification. L’appel du modèle créé par le concepteur dans un pipeline d'enrichissement de la Recherche cognitive nécessite quelques étapes supplémentaires. Dans cet exemple, vous allez créer un modèle de régression simple pour prédire le prix d’une automobile et appeler le point de terminaison d’inférence en tant que compétence AML.

Suivez le didacticiel Régression - Prédiction de prix automobile (avancé) dans la page de documentation exemples pipelines &jeux de données pour créer un modèle qui prédit le prix d’une voiture en fonction des différentes fonctionnalités.

Important

Le déploiement du modèle suivant le processus d’inférence en temps réel entraîne un point de terminaison valide, mais pas un point de terminaison que vous pouvez utiliser avec la compétence AML dans la Recherche cognitive.

Inscrire un modèle et télécharger des ressources

Une fois que vous avez entraîné un modèle, enregistrez le modèle entraîné et suivez les étapes pour télécharger tous les fichiers du trained_model_outputs dossier ou télécharger uniquement les fichiers score.py et conda_env.yml à partir de la page des artefacts du modèle. Vous allez modifier le script de scoring avant le déploiement du modèle en tant que point de terminaison d’inférence en temps réel.

Les pipelines d’enrichissement de recherche cognitive fonctionnent sur un document unique et génèrent une requête qui contient les entrées pour une prédiction unique. Le score.py téléchargé accepte une liste d’enregistrements et retourne une liste de prédictions sous forme de chaîne JSON sérialisée. Vous apporterez deux modifications au score.py

  • Modifier le script pour qu’il fonctionne avec un enregistrement d’entrée unique, et non avec une liste
  • Modifiez le script pour retourner un objet JSON avec une propriété unique, le prix prédit.

Ouvrez le score.py téléchargé et modifiez la fonction run(data). La fonction est actuellement configurée pour s’attendre à recevoir l’entrée suivante, comme décrit dans le fichier _samples.json du modèle.

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

Vos modifications garantissent que le modèle peut accepter l’entrée générée par recherche cognitive lors de l’indexation, qui est un enregistrement unique.

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

Remplacer les lignes 27 à 30 par


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

Vous devez également modifier la sortie générée par le script à partir d’une chaîne vers un objet JSON. Modifiez l’instruction return (ligne 37) dans le fichier d’origine pour :

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

Voici la fonction run mise à jour avec les modifications apportées au format d’entrée et la sortie prédite qui accepte un enregistrement unique comme entrée et retourne un objet JSON avec le prix prédit.

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]
    }

Inscrire et déployer le modèle

Avec vos modifications enregistrées, vous pouvez maintenant inscrire le modèle dans le portail. Sélectionnez le modèle de registre et fournissez-lui un nom valide. Choisissez Other for Model Framework, Custom for Framework Name et 1.0 for Framework Version. Sélectionnez l’option Upload folder, puis sélectionnez le dossier avec le score.py mis à jour et conda_env.yaml.

Sélectionnez le modèle, puis choisissez l’action Deploy. L’étape de déploiement suppose que vous disposez d’un cluster d’inférence AKS provisionné. Les instances de conteneur ne sont actuellement pas prises en charge dans la Recherche cognitive.

  1. Fournir un nom de point de terminaison valide
  2. Sélectionnez le type de calcul de Azure Kubernetes Service
  3. Sélectionnez le nom de calcul de votre cluster d’inférence
  4. Basculez enable authentication en position activée
  5. Sélectionnez Key-based authentication pour le type
  6. Sélectionnez le score.py mis à jour pour entry script file
  7. Sélectionnez le conda_env.yaml pour conda dependencies file
  8. Sélectionnez le bouton Déployer pour déployer votre nouveau point de terminaison.

Pour intégrer le point de terminaison nouvellement créé à la Recherche cognitive

  1. Ajouter un fichier JSON contenant un enregistrement automobile seul à un conteneur blob
  2. Configurez un pipeline d’enrichissement par IA à l’aide de l’Assistant Importation de données. Veillez à sélectionner JSON comme parsing mode
  3. Sous l’onglet Add Enrichments, sélectionnez une seule compétence Extract people names en tant qu’espace réservé.
  4. Ajoutez un nouveau champ à l’index appelé predicted_price de type Edm.Double, définissez la propriété Récupérable sur true.
  5. Terminer le processus d’importation de données

Ajouter la compétence AML à l’ensemble de compétences

Dans la liste des ensembles de compétences, sélectionnez l’ensemble de compétences que vous avez créé. Vous allez maintenant modifier l’ensemble de compétences pour remplacer la compétence d’identification des personnes par la compétence AML pour prédire les prix. Sous l’onglet Définition d’ensemble de compétences (JSON), sélectionnez Azure Machine Learning (AML) dans la liste déroulante des compétences. Sélectionnez l’espace de travail, pour que la compétence AML découvre votre point de terminaison, l’espace de travail et le service de recherche doivent se trouver dans le même abonnement Azure. Sélectionnez le point de terminaison que vous avez créé précédemment dans le didacticiel. Vérifiez que la compétence contient bien les informations d’URI et d’authentification telles que configurées lorsque vous avez déployé le point de terminaison. Copiez le modèle de compétence et remplacez la compétence dans l’ensemble de compétences. Modifiez la compétence pour :

  1. Attribuer un nom valide
  2. Ajouter une description
  3. Définir degreesOfParallelism à 1
  4. Attribuez le contexte à /document
  5. Réglez toutes les entrées aux valeurs requises, consultez l'exemple de définition d'aptitude ci-dessous
  6. Définissez les sorties pour capturer le prix prédit retourné.
{
      "@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"
        }
      ]
    }

Mettre à jour les mappages de champs de sortie de l’indexeur

Les mappages de champs de sortie de l’indexeur déterminent les enrichissements enregistrés dans l’index. Remplacez la section mappages de champs de sortie de l’indexeur par l’extrait de code ci-dessous :

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

Vous pouvez maintenant exécuter votre indexeur et vérifier que la propriété predicted_price est renseignée dans l’index avec le résultat de votre sortie de compétence AML.