Implementación de un modelo en una ASP.NET Core Web API

Aprenda cómo publicar un modelo de Machine Learning de ML.NET entrenado previamente en la Web a través de una ASP.NET Core Web API. Publicar un modelo a través de una API web permite predicciones mediante métodos HTTP estándar.

Requisitos previos

Creación de un proyecto de ASP.NET Core Web API

  1. Inicie Visual Studio 2022 y seleccione Crear un proyecto.

  2. En el cuadro de diálogo Crear un proyecto:

    • Escriba Web API en el cuadro de búsqueda.
    • Seleccione la plantilla API web de ASP.NET Core y seleccione Siguiente.
  3. En el cuadro de diálogo Configure el proyecto:

    • Asigne al proyecto el nombre SentimentAnalysisWebAPI.
    • Seleccione Next (Siguiente).
  4. En el cuadro de diálogo Información adicional:

    • Anule la sección de No usar instrucciones de nivel superior.
    • Seleccione Crear.
  5. Instale los siguientes paquetes NuGet:

    Para obtener más información sobre cómo instalar paquetes de en Visual Studio, consulte la guía Instalación y uso de un paquete NuGet en Visual Studio.

Incorporación del modelo a un proyecto de ASP.NET Core Web API

  1. Copie el modelo pregenerado en el directorio del proyecto SentimentAnalysisWebAPI.

  2. Configure el proyecto para copiar el archivo de modelo en el directorio de salida. En el Explorador de soluciones:

    • Haga clic con el botón derecho en el archivo ZIP del modelo y seleccione Propiedades.
    • En Avanzadas, cambie el valor de Copiar en el directorio de salida por Copiar si es posterior.

Creación de modelos de datos

Debe crear algunas clases para definir el esquema de la entrada y salida del modelo.

Nota

Las propiedades de las clases de esquema de entrada y salida dependen de las columnas del conjunto de datos usadas para entrenar el modelo, así como de la tarea de aprendizaje automático (regresión, clasificación, etc.).

En el archivo Program.cs:

  1. Agregue las siguientes instrucciones using:

    using Microsoft.ML.Data;
    using Microsoft.Extensions.ML;
    
  2. En la parte inferior del archivo, agregue las siguientes clases:

    Entrada del modelo

    Para este modelo, la entrada contiene una sola propiedad SentimentText, que es una cadena que representa un comentario de usuario.

    public class ModelInput
    {
        public string SentimentText;
    }
    

    Salida del modelo

    Una vez que el modelo evalúa la entrada, genera una predicción con tres propiedades: Sentiment, Probability y Score. En este caso, Sentiment es la opinión prevista del comentario del usuario y Probability y Score son medidas de confianza para la predicción.

    public class ModelOutput
    {
        [ColumnName("PredictedLabel")]
        public bool Sentiment { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

Registro de PredictionEngine para usarlo en la aplicación

Para realizar una sola predicción, tendrá que crear un objeto PredictionEngine. PredictionEngine no es seguro para subprocesos. Además, tiene que crear una instancia de ella en cualquier lugar en que se necesite dentro de la aplicación. A medida que crece la aplicación, este proceso puede volverse difícil de administrar. Para mejorar el rendimiento y la seguridad para subprocesos, use una combinación de inserción de dependencias y el servicio PredictionEnginePool, que crea un elemento ObjectPool de objetos PredictionEngine para usarlo en toda la aplicación.

En el vínculo siguiente se proporciona más información si quiere aprender sobre la inserción de dependencias en ASP.NET Core.

Agregue el código siguiente al archivo Program.cs:

builder.Services.AddPredictionEnginePool<ModelInput, ModelOutput>()
    .FromFile(modelName: "SentimentAnalysisModel", filePath: "sentiment_model.zip", watchForChanges: true);

En un nivel alto, este código inicializa los objetos y servicios de manera automática para su uso más adelante cuando lo solicite la aplicación en lugar de tener que hacerlo manualmente.

Los modelos de Machine Learning no son estáticos. A medida que haya nuevos datos de entrenamiento disponibles, el modelo se vuelve a entrenar y a implementar. Una manera de obtener la versión más reciente del modelo en la aplicación es volver a empezar o volver a implementar la aplicación. Sin embargo, esto implica un tiempo de inactividad de la aplicación. El servicio PredictionEnginePool proporciona un mecanismo para volver a cargar un modelo actualizado sin necesidad de volver a empezar o volver a implementar la aplicación.

Establezca el parámetro watchForChanges en true y el PredictionEnginePool inicia un FileSystemWatcher que escucha las notificaciones de cambios en el sistema de archivos y genera eventos cuando se produce un cambio en el archivo. Este solicita al PredictionEnginePool que vuelva a cargar automáticamente el modelo.

El modelo se identifica mediante el parámetro modelName, por lo que se puede volver a cargar más de un modelo por aplicación tras el cambio.

Sugerencia

Como alternativa, puede usar el método FromUri al trabajar con modelos almacenados de manera remota. En lugar de ver si hay eventos modificados de archivo, FromUri sondea la ubicación remota en busca de cambios. El intervalo de sondeo predeterminado es de 5 minutos. Puede aumentar o disminuir el intervalo de sondeo en función de los requisitos de la aplicación. En el ejemplo de código siguiente, PredictionEnginePool sondea el modelo almacenado en el URI especificado cada minuto.

services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
  .FromUri(
      modelName: "SentimentAnalysisModel",
      uri:"https://github.com/dotnet/samples/raw/main/machine-learning/models/sentimentanalysis/sentiment_model.zip",
      period: TimeSpan.FromMinutes(1));

Asignación de punto de conexión de predicción

Para procesar las solicitudes HTTP entrantes, cree un punto de conexión.

Reemplace el punto de conexión / por lo siguiente:

var predictionHandler =
    async (PredictionEnginePool<ModelInput, ModelOutput> predictionEnginePool, ModelInput input) =>
        await Task.FromResult(predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", input));

app.MapPost("/predict", predictionHandler);

El punto de conexión /predict acepta solicitudes HTTP POST y usa el grupo del motor de predicción para devolver una predicción mediante la entrada proporcionada.

Cuando haya terminado, program.cs debe tener un aspecto similar al siguiente:

using Microsoft.ML.Data;
using Microsoft.Extensions.ML;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddPredictionEnginePool<ModelInput, ModelOutput>()
    .FromFile(modelName: "SentimentAnalysisModel", filePath: "sentiment_model.zip", watchForChanges: true);

var app = builder.Build();

var predictionHandler =
    async (PredictionEnginePool<ModelInput, ModelOutput> predictionEnginePool, ModelInput input) =>
        await Task.FromResult(predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", input));

app.MapPost("/predict", predictionHandler);

app.Run();

public class ModelInput
{
    public string SentimentText;
}

public class ModelOutput
{
    [ColumnName("PredictedLabel")]
    public bool Sentiment { get; set; }

    public float Probability { get; set; }

    public float Score { get; set; }
}

Prueba local de Web API

Una vez que todo está configurado, es momento de probar la aplicación.

  1. Ejecute la aplicación.

  2. Abra PowerShell y escriba el código siguiente, donde PORT es el puerto donde escuchar la aplicación.

    Invoke-RestMethod "https://localhost:<PORT>/predict" -Method Post -Body (@{SentimentText="This was a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
    

    Si se realiza correctamente, la salida debería ser similar al texto siguiente:

    sentiment probability score
    --------- ----------- -----
    False         0.5     0
    

¡Enhorabuena! Publicó correctamente el modelo para realizar predicciones en Internet mediante una ASP.NET Core Web API.

Pasos siguientes