Compartir a través de


Tutorial: Análisis de la opinión de reseñas de películas con un modelo de TensorFlow entrenado previamente en ML.NET

En este tutorial se muestra cómo usar un modelo de TensorFlow previamente entrenado para clasificar la opinión en comentarios de sitios Web. El clasificador binario de opiniones es una aplicación de consola de C# desarrollada con Visual Studio.

El modelo de TensorFlow que se usa en este tutorial se entrenó con reseñas de películas procedentes de la base de datos de IMDB. Cuando haya terminado de desarrollar la aplicación, podrá proporcionar el texto de la reseña de la película y la aplicación le indicará si la reseña tiene una opinión positiva o negativa.

En este tutorial aprenderá a:

  • Carga de un modelo de TensorFlow entrenado previamente
  • Transformación del texto de comentario del sitio web en características adecuadas para el modelo
  • Uso del modelo para realizar una predicción

Puede encontrar el código fuente para este tutorial en el repositorio dotnet/samples.

Requisitos previos

Programa de instalación

Crear la aplicación

  1. Cree una aplicación de consola en C# llamada "TextClassificationTF". Haga clic en el botón Next (Siguiente).

  2. Seleccione .NET 6 como marco de trabajo que va a usarse. Haga clic en el botón Crear.

  3. Cree un directorio denominado Datos en el proyecto para guardar los archivos del conjunto de datos.

  4. Instale el paquete NuGet Microsoft.ML:

    Nota

    En este ejemplo se usa la versión estable más reciente de los paquetes NuGet mencionados, a menos que se indique lo contrario.

    En el Explorador de soluciones, haga clic con el botón derecho en Administrar paquetes NuGet. Elija "nuget.org" como origen del paquete y luego seleccione la pestaña Examinar. Busque Microsoft.ML, seleccione el paquete que desee y luego, el botón Instalar. Acepte los términos de licencia del paquete que elija para continuar con la instalación. Repita estos pasos para Microsoft.ML.TensorFlow, Microsoft.ML.SampleUtils y SciSharp.TensorFlow.Redist.

Adición del modelo TensorFlow al proyecto

Nota:

El modelo de este tutorial procede del repositorio de GitHub, dotnet/machinelearning-testdata. El modelo tiene el formato TensorFlow SavedModel.

  1. Descargue el archivo zip sentiment_model y descomprímalo.

    El archivo zip contiene:

    • saved_model.pb: el propio modelo de TensorFlow. El modelo toma una matriz de enteros de longitud fija (tamaño 600) de características que representan el texto de una cadena de reseña de IMDB y genera dos probabilidades que suman 1: la probabilidad de que la reseña de entrada tenga una opinión positiva y la probabilidad de que la reseña de entrada tenga una opinión negativa.
    • imdb_word_index.csv: una asignación de palabras individuales a un valor entero. La asignación se usa para generar las características de entrada para el modelo de TensorFlow.
  2. Copie el contenido del directorio sentiment_model más interno en el directorio sentiment_model del proyecto TextClassificationTF. En este directorio está el modelo y los archivos auxiliares adicionales que se necesitan en este tutorial, tal como se muestra en la imagen siguiente:

    contenido del directorio sentiment_model

  3. En el Explorador de soluciones, haga clic con el botón derecho en cada uno de los archivos del directorio sentiment_model y los subdirectorios y seleccione Propiedades. En Avanzadas, cambie el valor de Copiar en el directorio de salida por Copiar si es posterior.

Adición de instrucciones Using y variables globales

  1. Agregue las siguientes instrucciones using adicionales a la parte superior del archivo Program.cs:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms;
    
  2. Cree una variable global justo después de las instrucciones using que contenga la ruta de acceso del archivo de modelo guardado.

    string _modelPath = Path.Combine(Environment.CurrentDirectory, "sentiment_model");
    
    • _modelPath es la ruta de acceso del archivo del modelo entrenado.

Modelado de los datos

Las reseñas de películas son texto de forma libre. La aplicación convierte el texto en el formato de entrada que el modelo espera en varias fases discretas.

La primera consiste en dividir el texto en palabras independientes y usar el archivo de asignación proporcionado para asignar cada palabra a una codificación de enteros. El resultado de esta transformación es una matriz de enteros de longitud variable cuya longitud corresponde al número de palabras de la oración.

Propiedad. Value Tipo
ReviewText Esta película es realmente buena cadena
VariableLengthFeatures 14,22,9,66,78,... int[]

El tamaño de la matriz de características de longitud variable se cambia a una longitud fija de 600. Esta es la longitud que espera el modelo de TensorFlow.

Propiedad. Value Tipo
ReviewText Esta película es realmente buena cadena
VariableLengthFeatures 14,22,9,66,78,... int[]
Características 14,22,9,66,78,... int[600]
  1. Cree una clase para los datos de entrada en la parte inferior del archivo Program.cs:

    /// <summary>
    /// Class to hold original sentiment data.
    /// </summary>
    public class MovieReview
    {
        public string? ReviewText { get; set; }
    }
    

    La clase de datos de entrada, MovieReview, tiene un objeto string para comentarios de usuario (ReviewText).

  2. Cree una clase para las características de longitud variable, después de la clase MovieReview:

    /// <summary>
    /// Class to hold the variable length feature vector. Used to define the
    /// column names used as input to the custom mapping action.
    /// </summary>
    public class VariableLength
    {
        /// <summary>
        /// This is a variable length vector designated by VectorType attribute.
        /// Variable length vectors are produced by applying operations such as 'TokenizeWords' on strings
        /// resulting in vectors of tokens of variable lengths.
        /// </summary>
        [VectorType]
        public int[]? VariableLengthFeatures { get; set; }
    }
    

    La propiedad VariableLengthFeatures tiene un atributo VectorType para designarla como vector. Todos los elementos de vector deben ser del mismo tipo. En conjuntos de datos con un gran número de columnas, la carga de varias columnas como un único vector reduce el número de pasadas de datos cuando se aplican transformaciones de datos.

    Esta clase se usa en la acción ResizeFeatures. Los nombres de sus propiedades (en este caso, solo una) se usan para indicar las columnas de DataView que se pueden usar como entrada de la acción de asignación personalizada.

  3. Cree una clase para las características de longitud fija, después de la clase VariableLength:

    /// <summary>
    /// Class to hold the fixed length feature vector. Used to define the
    /// column names used as output from the custom mapping action,
    /// </summary>
    public class FixedLength
    {
        /// <summary>
        /// This is a fixed length vector designated by VectorType attribute.
        /// </summary>
        [VectorType(Config.FeatureLength)]
        public int[]? Features { get; set; }
    }
    

    Esta clase se usa en la acción ResizeFeatures. Los nombres de sus propiedades (en este caso, solo una) se usan para indicar las columnas de DataView que se pueden usar como salida de la acción de asignación personalizada.

    Tenga en cuenta que el nombre de la propiedad Features viene determinado por el modelo de TensorFlow. Este nombre de propiedad no se puede cambiar.

  4. Cree una clase para la predicción después de la clase FixedLength:

    /// <summary>
    /// Class to contain the output values from the transformation.
    /// </summary>
    public class MovieReviewSentimentPrediction
    {
        [VectorType(2)]
        public float[]? Prediction { get; set; }
    }
    

    MovieReviewSentimentPrediction es la clase de predicción que se utiliza tras el entrenamiento del modelo. MovieReviewSentimentPrediction tiene una sola matriz float (Prediction) y un atributo VectorType.

  5. Cree otra clase que contenga valores de configuración, como la longitud del vector de características:

    static class Config
    {
        public const int FeatureLength = 600;
    }
    

Creación de la clase MLContext, el diccionario de búsqueda y la acción para cambiar el tamaño de las características

La clase MLContext es un punto de partida para todas las operaciones de ML.NET. La inicialización de mlContext crea un entorno de ML.NET que se puede compartir entre los objetos del flujo de trabajo de creación de modelos. Como concepto, se parece a DBContext en Entity Framework.

  1. Reemplace la línea Console.WriteLine("Hello World!") por el siguiente código para declarar e inicializar la variable mlContext:

    MLContext mlContext = new MLContext();
    
  2. Cree un diccionario para codificar palabras como enteros mediante el método LoadFromTextFile para cargar los datos de asignación de un archivo, como se aprecia en la tabla siguiente:

    Palabra Índice
    niños 362
    quiero 181
    incorrecto 355
    efectos 302
    sentimiento 547

    Agregue el código siguiente para crear la asignación de búsqueda:

    var lookupMap = mlContext.Data.LoadFromTextFile(Path.Combine(_modelPath, "imdb_word_index.csv"),
        columns: new[]
            {
                new TextLoader.Column("Words", DataKind.String, 0),
                new TextLoader.Column("Ids", DataKind.Int32, 1),
            },
        separatorChar: ','
        );
    
  3. Agregue un objeto Action para cambiar el tamaño de la matriz de enteros de palabras de longitud variable a una matriz de enteros de tamaño fijo, con las siguientes líneas de código:

    Action<VariableLength, FixedLength> ResizeFeaturesAction = (s, f) =>
    {
        var features = s.VariableLengthFeatures;
        Array.Resize(ref features, Config.FeatureLength);
        f.Features = features;
    };
    

Carga del modelo de TensorFlow entrenado previamente

  1. Agregue código para cargar el modelo de TensorFlow:

    TensorFlowModel tensorFlowModel = mlContext.Model.LoadTensorFlowModel(_modelPath);
    

    Una vez cargado el modelo, puede extraer su esquema de entrada y de salida. Los esquemas se muestran solo a efectos de interés y aprendizaje. No necesita este código para que la aplicación final funcione:

    DataViewSchema schema = tensorFlowModel.GetModelSchema();
    Console.WriteLine(" =============== TensorFlow Model Schema =============== ");
    var featuresType = (VectorDataViewType)schema["Features"].Type;
    Console.WriteLine($"Name: Features, Type: {featuresType.ItemType.RawType}, Size: ({featuresType.Dimensions[0]})");
    var predictionType = (VectorDataViewType)schema["Prediction/Softmax"].Type;
    Console.WriteLine($"Name: Prediction/Softmax, Type: {predictionType.ItemType.RawType}, Size: ({predictionType.Dimensions[0]})");
    
    

    El esquema de entrada es la matriz de longitud fija de palabras codificadas en enteros. El esquema de salida es una matriz float de probabilidades que indica si la opinión de una reseña es negativa o positiva. Estos valores suman 1, ya que la probabilidad de que sea positiva es el complemento de la probabilidad de que la opinión sea negativa.

Creación de la canalización de ML.NET

  1. Cree la canalización y divida el texto de entrada en palabras con la transformación TokenizeIntoWords para dividir el texto en palabras como la siguiente línea de código:

    IEstimator<ITransformer> pipeline =
        // Split the text into individual words
        mlContext.Transforms.Text.TokenizeIntoWords("TokenizedWords", "ReviewText")
    

    La transformación TokenizeIntoWords usa espacios para analizar el texto o la cadena por palabras. Crea otra columna y divide cada cadena de entrada en un vector de subcadenas según el separador definido por el usuario.

  2. Asigne las palabras a su codificación de enteros con la tabla de búsqueda que declaró anteriormente:

    // Map each word to an integer value. The array of integer makes up the input features.
    .Append(mlContext.Transforms.Conversion.MapValue("VariableLengthFeatures", lookupMap,
        lookupMap.Schema["Words"], lookupMap.Schema["Ids"], "TokenizedWords"))
    
  3. Cambie el tamaño de las codificaciones de enteros de longitud variable al de longitud fija que requiere el modelo:

    // Resize variable length vector to fixed length vector.
    .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
    
  4. Clasifique la entrada con el modelo de TensorFlow cargado:

    // Passes the data to TensorFlow for scoring
    .Append(tensorFlowModel.ScoreTensorFlowModel("Prediction/Softmax", "Features"))
    

    La salida del modelo de TensorFlow se denomina Prediction/Softmax. Tenga en cuenta que el nombre Prediction/Softmax viene determinado por el modelo de TensorFlow. Este nombre no se puede cambiar.

  5. Cree otra columna para la predicción de salida:

    // Retrieves the 'Prediction' from TensorFlow and copies to a column
    .Append(mlContext.Transforms.CopyColumns("Prediction", "Prediction/Softmax"));
    

    Tiene que copiar la columna Prediction/Softmax en otra cuyo nombre pueda usarse como propiedad en una clase de C#: Prediction. El carácter / no está permitido en un nombre de propiedad de C#.

Creación del modelo de ML.NET a partir de la canalización

  1. Agregue el código para crear el modelo a partir de la canalización:

    // Create an executable model from the estimator pipeline
    IDataView dataView = mlContext.Data.LoadFromEnumerable(new List<MovieReview>());
    ITransformer model = pipeline.Fit(dataView);
    

    Un modelo de ML.NET se crea a partir de la cadena de estimadores de la canalización llamando al método Fit. En este caso, no se adaptan los datos para crear el modelo, puesto que el modelo de TensorFlow ya se ha entrenado previamente. Proporcionamos un objeto de vista de datos vacío para satisfacer los requisitos del método Fit.

Uso del modelo para realizar una predicción

  1. Agregue el método PredictSentiment encima de la clase MovieReview:

    void PredictSentiment(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Agregue el código siguiente para crear PredictionEngine como la primera línea en el método PredictSentiment():

    var engine = mlContext.Model.CreatePredictionEngine<MovieReview, MovieReviewSentimentPrediction>(model);
    

    PredictionEngine es una API de conveniencia, que le permite realizar una predicción en una única instancia de datos. PredictionEngine no es seguro para subprocesos. Es aceptable usarlo en entornos de un solo subproceso o prototipo. Para mejorar el rendimiento y la seguridad para subprocesos en entornos de producción, use el servicio PredictionEnginePool, que crea un ObjectPool de objetos de PredictionEngine para su uso en toda la aplicación. Consulte esta guía sobre cómo usar PredictionEnginePool en una API web de ASP.NET Core.

    Nota

    La extensión del servicio PredictionEnginePool está actualmente en versión preliminar.

  3. Agregue un comentario para probar la predicción del modelo entrenado en el método Predict() mediante la creación de una instancia de MovieReview:

    var review = new MovieReview()
    {
        ReviewText = "this film is really good"
    };
    
  4. Pase los datos del comentario de prueba a Prediction Engine agregando las líneas de código siguientes al método PredictSentiment():

    var sentimentPrediction = engine.Predict(review);
    
  5. La función Predict() realiza una predicción sobre una sola fila de datos:

    Propiedad. Value Tipo
    Predicción [0.5459937, 0.454006255] float[]
  6. Muestre la predicción de opiniones con el código siguiente:

    Console.WriteLine($"Number of classes: {sentimentPrediction.Prediction?.Length}");
    Console.WriteLine($"Is sentiment/review positive? {(sentimentPrediction.Prediction?[1] > 0.5 ? "Yes." : "No.")}");
    
  7. Agregue una llamada a PredictSentiment después de la llamada al método Fit():

    PredictSentiment(mlContext, model);
    

Resultados

Compile y ejecute su aplicación.

Los resultados deberían ser similares a los indicados a continuación. Durante el procesamiento, se muestran mensajes. Puede ver las advertencias o mensajes de procesamiento. Estos mensajes se han quitado de los resultados siguientes para mayor claridad.

Number of classes: 2
Is sentiment/review positive ? Yes

¡Enhorabuena! Ha creado correctamente un modelo de Machine Learning para clasificar y predecir la opinión de los mensajes reutilizando un modelo de TensorFlow entrenado previamente en ML.NET.

Puede encontrar el código fuente para este tutorial en el repositorio dotnet/samples.

En este tutorial ha aprendido a:

  • Carga de un modelo de TensorFlow entrenado previamente
  • Transformación del texto de comentario del sitio web en características adecuadas para el modelo
  • Uso del modelo para realizar una predicción