Número especial de Connect(); de 2018

Volumen 33, número 13

Aprendizaje automático con ML.NET: El marco de aprendizaje automático para desarrolladores de .NET

Por James McCaffrey

La biblioteca de ML.NET está aún en versión preliminar. Toda la información está sujeta a cambios.

La biblioteca de ML.NET es una nueva colección de código abierto de aprendizaje automático (ML) que se puede usar para crear sistemas de predicción eficaces. Muchas bibliotecas de ML se escriben en C++ con una API de Python para facilitar la programación. Algunos ejemplos son scikit-learn, TensorFlow, CNTK y PyTorch. Sin embargo, si usa una biblioteca de ML basada en Python para crear un modelo de predicción, no es tan fácil para una aplicación de .NET usar el modelo entrenado. Afortunadamente, la biblioteca de ML.NET se puede usar directamente en aplicaciones .NET. Y, dado que ML.NET se puede ejecutar en .NET Core, también puede crear sistemas de predicción para macOS y Linux.

Una buena manera de ver hacia dónde se dirige este artículo es echar un vistazo al programa de demostración de la figura 1. La demostración crea un modelo de ML que predice los ingresos anuales de una persona en función de su edad, sexo e inclinación política (conservadora, moderada, liberal). Dado que el objetivo es predecir un valor numérico, esto es un ejemplo de un problema de regresión. Si el objetivo hubiera sido predecir la inclinación política a partir de la edad , el sexo y los ingresos, sería un problema de clasificación.

Programa de demostración heredado de ML.NET en acción
Figura 1 Programa de demostración heredado de ML.NET en acción

La demostración usa un conjunto de datos de entrenamiento ficticios con 30 elementos. Una vez entrenado el modelo, se aplicó a los datos de origen y se consiguió un error de valor cuadrático medio de 1,2630. Este valor de error es difícil de interpretar por sí mismo y es mejor usar el error de regresión para comparar modelos distintos.

Para finalizar, la demostración usa el modelo entrenado para predecir los ingresos anuales de un hombre de 40 años con una inclinación política conservadora. Los ingresos previstos son 72 401,38 USD. La demostración de la Figura 1 se escribió con el enfoque heredado de ML.NET, que es una buena manera de hacerse una idea de ML.NET para principiantes. En la segunda mitad de este artículo introductorio, analizaré un enfoque más reciente que es un poco más difícil de entender, pero es el mejor enfoque para un nuevo desarrollo.

En este artículo, se supone que tiene conocimientos intermedios o altos de programación con C#, pero no que tiene conocimiento alguno de la biblioteca de ML.NET. El código y los datos completos del programa de demostración se presentan en este artículo, y también están disponible en la descarga del archivo que lo acompaña. Mientras escribo este artículo, la biblioteca de ML.NET sigue en modo de versión preliminar y se está desarrollando muy rápidamente, por lo que parte de la información aquí presentada podría haber cambiado cuando la lea.

Programa de demostración

Para crear el programa de demostración, inicié Visual Studio 2017. La biblioteca de ML.NET funcionará con la versión gratuita de Community Edition o una de las ediciones comerciales de Visual Studio 2017. La documentación de ML.NET indica que se necesita Visual Studio 2017 y, de hecho, no pude conseguir que el programa de demostración funcionara con Visual Studio 2015. Creé un nuevo proyecto de aplicación de consola en C# y lo denominé IncomePredict. La biblioteca de ML.NET funcionará tanto con un tipo de aplicación de .NET Framework clásico como de .NET Core.

Después de cargar el código de plantilla, hice clic con el botón derecho en el archivo Program.cs en la ventana del Explorador de soluciones, le cambié el nombre a IncomeProgram.cs y permití que Visual Studio cambiase automáticamente el nombre de la clase Program. A continuación, en la ventana del Explorador de soluciones, hice clic con el botón derecho en el proyecto IncomePredict y seleccioné la opción Administrar paquetes NuGet. En la ventana de NuGet, seleccioné la pestaña Examinar y, después, escribí "ML.NET" en el campo de búsqueda. La biblioteca de ML.NET se hospeda en el paquete Microsoft.ML. Seleccioné la última versión (0.7.0) e hice clic en el botón Instalar. Después de unos segundos, Visual Studio respondió con un mensaje que indicaba que Microsoft.ML 0.7.0 se había instalado correctamente en IncomePredict.

Llegado este punto, ejecuté Compilar | Recompilar solución y obtuve un mensaje de error que indica que solo se admiten arquitecturas x64. En la ventana del Explorador de soluciones, hice clic con el botón derecho en el proyecto IncomePredict y seleccioné la entrada Propiedades. En la ventana Propiedades, seleccioné la pestaña Compilar de la izquierda y, a continuación, cambié la entrada Destino de la plataforma de "Cualquier CPU" a "x64". También me aseguré de que la versión de destino era .NET Framework 4.7. Con versiones anteriores del marco, obtenía un error relacionado con una de las dependencias de la biblioteca de matemáticas. A continuación, ejecuté Compilar | Recompilar solución y la operación se realizó correctamente. Al trabajar con bibliotecas en modo de versión preliminar como ML.NET, cabe esperar algunos obstáculos como este.

Datos de demostración

Después de crear el esqueleto del programa de demostración, el paso siguiente fue crear el archivo de datos de entrenamiento. Los datos se presentan en la Figura 2. Si está siguiendo estos pasos, en la ventana Explorador de soluciones, haga clic con el botón derecho del mouse en el proyecto IncomePredict, seleccione Agregar | Nueva carpeta y asigne a la carpeta el nombre "Data". Colocar los datos en una carpeta denominada Data no es obligatorio, pero es una práctica estándar. Haga clic con el botón derecho del mouse en la carpeta Data y seleccione Agregar | Nuevo elemento. Desde la ventana del cuadro de diálogo Nuevo elemento, seleccione el tipo Archivo de texto y asígnele el nombre PeopleData.txt.

Figura 2 Datos de personas

48, +1, 4.40, liberal
60, -1, 7.89, conservative
25, -1, 5.48, moderate
66, -1, 3.41, liberal
40, +1, 8.05, conservative
44, +1, 4.56, liberal
80, -1, 5.91, liberal
52, -1, 6.69, conservative
56, -1, 4.01, moderate
55, -1, 4.48, liberal
72, +1, 5.97, conservative
57, -1, 6.71, conservative
50, -1, 6.40, liberal
80, -1, 6.67, moderate
69, +1, 5.79, liberal
39, -1, 9.42, conservative
68, -1, 7.61, moderate
47, +1, 3.24, conservative
18, +1, 4.29, liberal
79, +1, 7.44, conservative
44, -1, 2.55, liberal
52, +1, 4.71, moderate
55, +1, 5.56, liberal
76, -1, 7.80, conservative
32, -1, 5.94, liberal
46, +1, 5.52, moderate
48, -1, 7.25, conservative
58, +1, 5.71, conservative
44, +1, 2.52, liberal
68, -1, 8.38, conservative

Copie los datos de la Figura 2 y péguelos en la ventana del editor, con cuidado de no dejar ninguna línea en blanco adicional al final.

El conjunto de datos de 30 elementos es artificial. La primera columna es la edad de una persona. La segunda columna indica el sexo y se codificó previamente como hombre = -1 y mujer = + 1. La biblioteca de ML.NET tiene métodos para codificar datos de texto, por lo que se podrían haber usado los valores "male" y "female" en los datos. La tercera columna son los ingresos anuales que se predicen, con valores divididos por 10 000. La última columna especifica la inclinación política (conservadora, moderada, liberal).

Dado que los datos tienen tres variables de previsión (edad, sexo y política), no se pueden mostrar en un gráfico bidimensional. No obstante, se puede hacer una idea clara de la estructura de los datos examinando el gráfico de ingresos anuales y edad de la Figura 3. El gráfico muestra que la edad en sí no se puede usar para obtener una predicción precisa de los ingresos.

Datos de ingresos
Figura 3 Datos de ingresos

Después de crear los datos de entrenamiento en la carpeta Data, debe crear una carpeta denominada Models para contener el modelo guardado porque el código de demostración asume que existe una carpeta denominada Models.

Código del programa

El código de demostración completo, con algunos cambios menores para ahorrar espacio, se presenta en la Figura 4. Una vez cargado el código de la plantilla en Visual Studio, en la parte superior de la ventana del editor, quité todas las referencias del espacio de nombres y las reemplacé por las existentes en la lista de códigos. Los diversos espacios de nombres Microsoft.ML hospedan toda la funcionalidad de ML.NET. El espacio de nombres Threading.Tasks es necesario para guardar o cargar un modelo heredado de ML.NET entrenado en el archivo.

Figura 4 Programa de ejemplo de ML.NET heredado

using System;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Legacy;
using Microsoft.ML.Legacy.Data;
using Microsoft.ML.Legacy.Transforms;
using Microsoft.ML.Legacy.Trainers;
using Microsoft.ML.Legacy.Models;
using System.Threading.Tasks;
// Microsoft.ML 0.7.0  Framework 4.7 Build x64
namespace IncomePredict
{
  class IncomeProgram
  {
    public class IncomeData {
      [Column("0")] public float Age;
      [Column("1")] public float Sex;
      [Column("2")] public float Income;
      [Column("3")] public string Politic;
    }
    public class IncomePrediction {
      [ColumnName("Score")]
      public float Income;
    }
    static void Main(string[] args)
    {
      Console.WriteLine("Begin ML.NET demo run");
      Console.WriteLine("Income from age, sex, politics");
      var pipeline = new LearningPipeline();
      string dataPath = "..\\..\\Data\\PeopleData.txt";
      pipeline.Add(new TextLoader(dataPath).
        CreateFrom<IncomeData>(separator: ','));
      pipeline.Add(new ColumnCopier(("Income", "Label")));
      pipeline.Add(new CategoricalOneHotVectorizer("Politic"));
      pipeline.Add(new ColumnConcatenator("Features", "Age",
        "Sex", "Politic"));
      var sdcar = new StochasticDualCoordinateAscentRegressor();
      sdcar.MaxIterations = 1000;
      sdcar.NormalizeFeatures = NormalizeOption.Auto;
      pipeline.Add(sdcar);
      // pipeline.N
      Console.WriteLine("\nStarting training \n");
      var model = pipeline.Train<IncomeData, IncomePrediction>();
      Console.WriteLine("\nTraining complete \n");
      string modelPath = "..\\..\\Models\\IncomeModel.zip";
      Task.Run(async () =>
      {
        await model.WriteAsync(modelPath);
      }).GetAwaiter().GetResult();
      var testData = new TextLoader(dataPath).
        CreateFrom<IncomeData>(separator: ',');
      var evaluator = new RegressionEvaluator();
      var metrics = evaluator.Evaluate(model, testData);
      double rms = metrics.Rms;
      Console.WriteLine("Root mean squared error = " +
        rms.ToString("F4"));
      Console.WriteLine("Income age 40 conservative male: ");
      IncomeData newPatient = new IncomeData() { Age = 40.0f,
        Sex = -1f, Politic = "conservative" };
      IncomePrediction prediction = model.Predict(newPatient);
      float predIncome = prediction.Income * 10000;
      Console.WriteLine("Predicted income = $" +
        predIncome.ToString("F2"));
      Console.WriteLine("\nEnd ML.NET demo");
      Console.ReadLine();
    } // Main
  } // Program
} // ns

Tenga en cuenta que la mayoría de los espacios de nombres tienen un identificador "Legacy". El programa de demostración usa lo que se llama API de canalización, que es sencilla y eficaz. El equipo de ML.NET está agregando una API nueva y más flexible, que explicaré en breve.

El programa define una clase anidada denominada IncomeData que describe la estructura interna de los datos de entrenamiento. Por ejemplo, la primera columna es:

[Column("0")]
public float Age;

Observe que el campo age se declara de tipo float, en lugar de tipo double. En la mayoría de sistemas de ML, el tipo float es el tipo numérico predeterminado, porque el aumento de la precisión que obtiene al usar el tipo double no suele compensar la pérdida de memoria y rendimiento resultante. Los nombres de campo de previsión se pueden especificar mediante el atributo ColumnName. Son opcionales y pueden ser lo que quiera; por ejemplo, [ColumnName("Age")].

El programa de demostración define una clase anidada denominada IncomePrediction para contener las predicciones del modelo:

public class IncomePrediction {
  [ColumnName("Score")]
  public float Income;
}

El nombre de columna "Score" es necesario, pero, como se muestra, el identificador de variable de cadena asociado no tiene que coincidir.

Creación y entrenamiento del modelo

El programa de demostración configura un modelo de ML no entrenado mediante estas instrucciones:

var pipeline = new LearningPipeline();
string dataPath = "..\\..\\Data\\IncomeData.txt";
pipeline.Add(new TextLoader(dataPath).
  CreateFrom<IncomeData>(separator: ','));

Puede pensar en un objeto LearningPipeline como un contenedor de metadatos que contiene los datos de entrenamiento y un algoritmo de entrenamiento. Este paradigma es un poco diferente de los que usan otras bibliotecas de ML. A continuación, la canalización realiza cierta manipulación de datos:

pipeline.Add(new ColumnCopier(("Income", "Label")));
pipeline.Add(new CategoricalOneHotVectorizer("Politic"));
pipeline.Add(new ColumnConcatenator("Features", "Age",
  "Sex", "Politic"));

La versión heredada de ML.NET requiere que la columna que contiene los valores que se van a predecir se identifique como "Label", por lo que el método ColumnCopier crea un duplicado en memoria de la columna Income. Un enfoque alternativo es, simplemente, asignar a la columna Income el nombre Label en la definición de clase que define la estructura de los datos de entrenamiento.

El instructor solo funciona con datos numéricos, de modo que es necesario convertir los valores de texto de la columna Politic en enteros. El método CategoricalOneHotVectorizer convierte “conservative”, “moderate” y “liberal” en (1, 0, 0), (0, 1, 0) y (0, 0, 1). Un enfoque alternativo es precodificar manualmente los datos de texto.

El método ColumnConcatenator combina las tres columnas de predicción en una sola columna denominada Features. Este esquema de nomenclatura es necesario. El algoritmo de aprendizaje se agrega a la canalización y el modelo se entrena de este modo:

var sdcar = new StochasticDualCoordinateAscentRegressor();
sdcar.MaxIterations = 1000;
sdcar.NormalizeFeatures = NormalizeOption.Auto;
pipeline.Add(sdcar);
var model = pipeline.Train<IncomeData, IncomePrediction>();

El ascenso estocástico de coordenadas duales es un algoritmo relativamente sencillo para entrenar un modelo de regresión de forma lineal. Otros instructores regresión heredados son FastForestRegressor, FastTreeRegressor, GeneralizedAdditiveModelRegressor, LightGbmRegressor, OnlineGradientDescentRegressor y OrdinaryLeastSquaresRegressor. Cada uno de ellos tiene sus ventajas y desventajas, por lo que no hay un algoritmo mejor para un problema de regresión. Comprender las diferencias entre cada tipo de regresor y clasificador no es sencillo, y requiere una lectura detenida de la documentación.

Una vez configurado el objeto de canalización, entrenar el modelo es una operación de una sola instrucción. Si consulta el resultado que se muestra en la Figura 1, observará que el método Train hace mucho trabajo automáticamente. Dado que la canalización usa la normalización automática, el entrenador analizó las columnas de edad e ingresos, y decidió que se deben escalar mediante la normalización mínima/máxima. Esto convierte todos los valores de edad e ingresos en valores entre 0,0 y 1,0 para que los valores relativamente grandes (por ejemplo, una edad de 52) no sobrecarguen los valores más pequeños (por ejemplo, los ingresos de 4,58). La normalización suele mejorar la precisión del modelo resultante.

El método Train también usa la regularización L1 y L2, que es otra técnica de ML estándar para mejorar la precisión de un modelo. En pocas palabras, con la regularización, se desaconsejan los valores de peso extremo en el modelo. Y con esto, a su vez, se desaconseja el sobreajuste del modelo. En resumen, ML.NET realiza todo tipo de procesamiento avanzado sin tener que configurar explícitamente los valores de parámetro. Bien.

Guardar y evaluar el modelo

Una vez entrenado el modelo de regresión, se guarda en el disco de la siguiente manera:

string modelPath = "..\\..\\Models\\IncomeModel.zip";
Task.Run(async () =>
{
  await model.WriteAsync(modelPath);
}).GetAwaiter().GetResult();

El código supone la existencia de un directorio denominado Model dos niveles por encima del programa ejecutable. Una alternativa consiste en codificar de forma rígida la ruta de acceso. Dado que el método WriteAsync es asincrónico, no es tan fácil llamarlo. Puede adoptar varios enfoques. Mi enfoque preferido es la técnica de contenedor mostrada. La falta de un método no asincrónico para guardar un modelo de ML.NET es un poco sorprendente, incluso para una biblioteca que está en modo de versión preliminar.

El modelo se evalúa con estas instrucciones:

var testData = new TextLoader(dataPath).
  CreateFrom<IncomeData>(separator: ',');
var evaluator = new RegressionEvaluator();
var metrics = evaluator.Evaluate(model, testData);
double rms = metrics.Rms;
Console.WriteLine("Model root mean squared error = " +
  rms.ToString("F4"));

En la mayoría de los escenarios de ML tendría dos archivos de datos: uno solo para el entrenamiento y un segundo conjunto de datos de prueba para la evaluación del modelo. Por motivos de simplicidad, el programa de demostración reutiliza el archivo de datos de 30 elementos para la evaluación de modelos.

El método Evaluate devuelve un objeto agregado que contiene el valor cuadrático medio para el modelo entrenado que se aplica a los datos de prueba. Otras métricas que devuelve un evaluador de regresión incluyen R cuadrado (el coeficiente de determinación) y L1 (suma de errores absolutos).

Para muchos problemas de ML, la métrica más útil es la precisión de predicción. No hay ninguna definición inherente de precisión para un problema de regresión porque debe definir lo que hace que una predicción sea correcta. El enfoque habitual consiste en escribir una función personalizada en que un valor de predicción se considera correcto si se encuentra dentro de un determinado porcentaje del valor real en los datos de entrenamiento. Por ejemplo, si establece el porcentaje delta en 0,10 y un valor de ingresos real es 6,00, una predicción correcta tendría un valor entre 5,40 y 6,60.

Usar el modelo entrenado

El programa de demostración predice los ingresos anuales de un hombre de 40 años conservador como se indica a continuación:

Console.WriteLine("Income for age 40 conservative male: ");
IncomeData newPatient = new IncomeData() { Age = 40.0f,
  Sex = -1f, Politic = "conservative" };
IncomePrediction prediction = model.Predict(newPatient);
float predIncome = prediction.Income * 10000;
Console.WriteLine("Predicted income = $" +
  predIncome.ToString("F2"));

Observe que los literales numéricos de edad y sexo usan el modificador "f" porque el modelo espera valores de tipo float. En este ejemplo, el modelo entrenado estaba disponible porque el programa había finalizado el aprendizaje. Si quisiera realizar una predicción de un programa diferente, podría cargar el modelo entrenado con el método ReadAsync a lo largo de las líneas de:

PredictionModel<IncomeData, IncomePrediction> model = null;
Task.Run(async () =>
{
  model = await PredictionModel.ReadAsync<IncomeData,
    IncomePrediction>(modelPath);
}).GetAwaiter().GetResult();

Después de cargar el modelo en memoria, para usarlo, llamaría al método Predict, como se mostró anteriormente.

El nuevo enfoque de la API de ML.NET

El enfoque de canalización heredada es sencillo y eficaz, y proporciona una interfaz coherente para el uso de clasificadores y regresores de ML.NET. Pero el enfoque heredado tiene algunas características arquitectónicas que limitan la extensibilidad de la biblioteca, por lo que el equipo de ML.NET ha creado un nuevo enfoque más flexible, que se explica mejor con un ejemplo.

Suponga que tiene el mismo conjunto de datos: edad, sexo, ingresos, política. Y suponga que quiere predecir la inclinación política a partir de las otras tres variables. Se presenta un programa de demostración para crear un clasificador mediante el nuevo enfoque de API de ML.NET en la Figura 5. Este programa usa una combinación híbrida de estilo antiguo y nuevo estilo, y está pensado para crear un puente entre los dos. Cabe destacar que los ejemplos de código más recientes de la documentación de ML.NET proporcionan técnicas más sofisticadas y, en algunos casos, mejores.

Figura 5 Ejemplo de clasificación de lista de códigos

using System;
using Microsoft.ML;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Runtime.Data;
using Microsoft.ML.Transforms.Conversions;
// Microsoft.ML 0.7.0  Framework 4.7 Build x64
namespace PoliticPredict
{
  class PoliticProgram
  {
    public class PoliticData {
      [Column("0")] public float Age;
      [Column("1")] public float Sex;
      [Column("2")] public float Income;
      [Column("3")]
      [ColumnName("Label")]
      public string Politic;
    }
    public class PoliticPrediction  {
      [ColumnName("PredictedLabel")]
      public string PredictedPolitic;
    }
    static void Main(string[] args)
    {
      var ctx = new MLContext(seed: 1);
      string dataPath = "..\\..\\Data\\PeopleData.txt";
      TextLoader textLoader =
        ctx.Data.TextReader(new TextLoader.Arguments()
      {
        Separator = ",", HasHeader = false,
        Column = new[] {
          new TextLoader.Column("Age", DataKind.R4, 0),
          new TextLoader.Column("Sex", DataKind.R4, 1),
          new TextLoader.Column("Income", DataKind.R4, 2),
          new TextLoader.Column("Label", DataKind.Text, 3)
        }
      });
      var data = textLoader.Read(dataPath);
      var est = ctx.Transforms.Categorical.MapValueToKey("Label")
       .Append(ctx.Transforms.Concatenate("Features", "Age",
         "Sex", "Income"))
       .Append(ctx.MulticlassClassification.Trainers
         .StochasticDualCoordinateAscent("Label", "Features",
         maxIterations: 1000))
       .Append(new KeyToValueEstimator(ctx, "PredictedLabel"));
      var model = est.Fit(data);
      var prediction = model.MakePredictionFunction<PoliticData,
        PoliticPrediction>(ctx).Predict(
          new PoliticData() {
            Age = 40.0f, Sex = -1.0f, Income = 8.55f
          });
      Console.WriteLine("Predicted party is: " +
        prediction.PredictedPolitic);
      Console.ReadLine();
    } // Main
  } // Program
} // ns

En un nivel muy alto, muchas tareas de ML tienen cinco fases: cargar y transformar datos de entrenamiento en memoria, crear un modelo, entrenar el modelo, evaluar y guardar el modelo, y usar el modelo. Tanto las API de ML.NET nuevas como las heredadas pueden realizar estas operaciones, pero el nuevo enfoque es, claramente, superior (en mi opinión, al menos) para escenarios de ML realistas en un sistema de producción.

Una característica clave de la nueva API de ML.NET es la clase MLContext. Tenga en cuenta que se usa el objeto ctx al leer los datos de entrenamiento, al crear el modelo de predicción y al realizar una predicción.

Aunque no sea evidente en el código, otra ventaja de la nueva API sobre el enfoque heredado es que puede leer datos de entrenamiento de varios archivos. No me encuentro a menudo con este escenario, pero cuando lo hago, la capacidad de leer varios archivos supone un gran ahorro de tiempo.

Otra característica de la nueva API es la capacidad para crear modelos de predicción de dos maneras diferentes, llamadas estáticas y dinámicas. El enfoque estático le ofrece todas las funcionalidades de Visual Studio IntelliSense durante el desarrollo. El enfoque dinámico se puede usar cuando la estructura de los datos se debe determinar en tiempo de ejecución.

Resumen

Si ha leído este artículo, y ejecutado y comprendido el relativamente sencillo código de demostración, el próximo paso debería ser adentrarse en la nueva API de ML.NET. A diferencia de muchos proyectos de código abierto que tienen documentación muy breve o insuficiente, la documentación de ML.NET es excelente. Los ejemplos de bit.ly/2AVM1oL son un fantástico punto de partida.

Aunque la biblioteca de ML.NET es nueva, sus orígenes se remontan a muchos años atrás. Poco después de la presentación de Microsoft .NET Framework en 2002, Microsoft Research inició un proyecto denominado TMSN (text mining search and navigation, navegación y búsqueda de minería de texto) para que los desarrolladores de software pudieran incluir código de ML en productos y tecnologías de Microsoft. El proyecto tuvo un gran éxito y, con los años, se expandió en tamaño y uso interno en Microsoft. Allá por el año 2011, se cambió el nombre de la biblioteca por TLC ("the learning code", código de aprendizaje). TLC se usa ampliamente en Microsoft y se encuentra en la versión 3.10, actualmente. La biblioteca de ML.NET es un descendiente directo de TLC,donde se han quitado las características específicas de Microsoft. He utilizado las dos bibliotecas y, en muchos sentidos, el elemento secundario de ML.NET ha superado al elemento principal.

Este artículo apenas muestra la superficie de la biblioteca de ML.NeT. Una nueva funcionalidad interesante y eficaz de ML.NET es la capacidad de consumir y usar modelos de red neuronal profunda creados por otros sistemas, como PyTorch y CNTK. La clave para esta interoperabilidad es el estándar Open Neural Network Exchange (ONNX). Pero ese tema lo dejamos para otro artículo.


El Dr. James McCaffrey trabaja para Microsoft Research en Redmond, Washington. Ha colaborado en varios productos clave de Microsoft, como Internet Explorer y Bing. Puede ponerse en contacto con el Dr. McCaffrey en jamccaff@microsoft.com.

Gracias a los siguientes expertos técnicos de Microsoft por revisar este artículo: Ankit Asthana, Chris Lauren, Cesar De la Torre Llorente, Beth Massi, Shahab Moradi, Gal Oshri, Shauheen Zahirazami


Comente este artículo en el foro de MSDN Magazine