Machine Learning | Cómo hacer predicciones en batch usando ML.NET

El framework ML.NET es de gran utilidad para crear aplicaciones con Machine Learning de punta a punta -end to end-, es decir, desde el entrenamiento de un modelo con datos históricos hasta la inferencia o predicción de un resultado con nuevos datos. Cuando creamos una aplicación utilizando ML.NET Model Builder podemos hacer predicciones de un resultado o una predicción a la vez, pero hay ocaciones en que necesitamos hacer muchas predicciones a la vez en forma de batch. En este post haremos un ejercicio para crear una aplicación que predice la cancelación de una reserva de hotel y modificaremos el código para hacer predicciones en batch a partir de varios registros en un archivo .csv.

Problema

Tenemos un dataset con el histórico de las reservas de varios hoteles y el registro de los cambios que tuvo la reserva. Con estos datos vamos a crear un modelo de Machine Learning para predecir si una reserva puede ser cancelada, modificada o no tener cambios. Este escenario puede ser útil para ofrecer un seguro de cancelación de reserva a un menor o mayor costo según el resultado de la predicción.

Dataset

Contamos con un Dataset tomado de kaggle y modificado para marcar tres categorías en la columna de reservation_status, esta puede tener los valores: Booking-Changed; Canceled; Check-Out

Solución

Crearemos un modelo de Machine Learning usando el framework ML.NET. Ya que son tres categorías las que queremos predecir (Booking-Changed; Canceled; Check-Outdebemos crear un modelo de clasificación multiclase (multiclass classification).

El proyecto completo se puede descargar del repositorio de GitHub

Usaremos ML.NET Model Builder para crear la aplicación -para conocer más sobre ML.NET puedes ver este post aquí-. Seguiremos los siguientes pasos para crear la aplicación.

  • Primero creamos en Visual Studio 2019 un proyecto ASP.NET Core MVC en el cual crearemos una simple interfaz para cargar un archivo .cvs con los datos a predecir en batch. Este proyecto lo llamaremos Multiclass_Classification_Batch.
  • Ahora agregamos un proyecto de Machine Learning usando la extensión de Model Builder y seleccionaremos la opción Text Classification. Aunque la opción parezca confusa esta es la opción que podemos usar para cualquier tipo de clasificación binara (binary) o multiclase (Multiclass).
ML.NET Model Builder (Text Classification)
  • Cuando seleccionemos el archivo con el dataset para el entrenamiento del modelo debemos asegurarnos que el archivo contenga una columna id, de esta forma cuando hagamos la predicción en batch podremos identificar sus resultados por el ‘id’ del registro. Sien embargo no queremos que el ‘id’ influya en el entrenamiento por lo que debemos desmarcar esa columna como parte de las características (features). La columna a predecir (label) será la columna reservation_status, esta contiene el estado de la reserva (Booking-Changed; Canceled; Check-Out)
  • Model Builder realizará el entrenamiento del modelo y seleccionará el mejor algoritmo por nosotros, al final se agregará a la solución los proyectos para entrenar y consumir el modelo y nos quedará de esta forma
ML.NET proyectos

Ahora realizaremos las modificaciones al código para hacer una predicción en batch con nuevos registros de reservas de hotel. El primer cambio que debemos hacer es en la clase ModelOutput, esta clase contiene la estructura con el resultado de una predicción, pero como vamos a hacer predicciones en batch vamos a agregar la columna id para poder identificar a cada predicción -por eso es importante que el archivo con los datos de entrenamiento también tengan la columna id-.

public class ModelOutput
{
    // ColumnName attribute is used to change the column name from
    // its default value, which is the name of the field.
    [ColumnName("id")]
    public float Id { get; set; }

    [ColumnName("PredictedLabel")]
    public String Prediction { get; set; }
    public float[] Score { get; set; }
}

Ahora vamos a modificar el archivo ConsumeModel, este archivo contienen el método para hacer predicciones para una nueva reserva de hotel, aquí agregamos un método PredictBatch para hacer las predicciones en batch con nuevas reservas en un archivo .csv y el resultado también será un archivo .csv con las predicciones.

public static string PredictBatch(string dataPath)
{
    MLContext mlContext = new MLContext();

    // Load model
    ITransformer mlModel = mlContext.Model.Load(GetAbsolutePath(MLNetModelPath), out var modelInputSchema);

    IDataView inputData = mlContext.Data.LoadFromTextFile<ModelInput>(dataPath,
                                                                    separatorChar: ',',
                                                                    hasHeader: true);

    var transformedDataView = mlModel.Transform(inputData);

    var predictions = mlContext.Data.CreateEnumerable<ModelOutput>(transformedDataView, false).ToList();

    IDataView outputView = mlContext.Data.LoadFromEnumerable<ModelOutput>(predictions);

    string dataPathOutput = Path.GetDirectoryName(dataPath) + @"\predictions.csv";
    using (FileStream stream = new FileStream(dataPathOutput, FileMode.Create))
    {
        mlContext.Data.SaveAsText(outputView, stream,
                                  separatorChar: ',',
                                  headerRow: true, schema: false);
    }

    return dataPathOutput;
}

Lo interesante de este código es el uso del método LoadFromEnumerable que lo usamos para crear un IDataView con la estructura ModelOutput, lo que demuestra que este método se puede usar con cualquier estructura, no solo con la del ModelInput. Además usamos el método SaveAsText para transformar fácilmente un objeto de tipo List a un archivo .csv sin necesidad de escribir código adicional para este propósito.

Ahora solo nos resta crear una interfaz web en el proyecto Multiclass_Classification_Batch para cargar un archivo con los registros de las reservas de hotel que queremos predecir y descargar el archivo con las predicciones de respuesta. Esto lo haremos directamente en la página Index y agregamos el siguiente código en el HomeController.

[HttpPost]
public async Task<FileResult> Index(IFormFile formFile)
{
    if (formFile != null && formFile.Length > 0)
    {
        string pathImgPredict = Path.Combine(pathPrediction, ConsumeModel.MLNetBatchFileName);
        pathImgPredict = ConsumeModel.GetAbsolutePath(pathImgPredict);
        pathImgPredict = Path.GetFullPath(pathImgPredict);

        using (var stream = System.IO.File.Create(pathImgPredict))
        {
            await formFile.CopyToAsync(stream);
        }

        var predictionsFile = ConsumeModel.PredictBatch(pathImgPredict);

        var streamResult = await System.IO.File.ReadAllBytesAsync(predictionsFile);

        return File(streamResult, "application/csv;charset=utf-8", "Predictions.csv");
    }
    return null;
}

El resultado final de nuestra aplicación será este:

Nótese como en el archivo de respuesta con las predicciones consta la columna Id para poder identificar a qué reserva corresponde cada predicción.

ML CSV

El proyecto completo se puede descargar del repositorio de GitHub

Artículos relacionados

Machine Learning | Trabajar con múltiples fuentes de datos usando ML.NET

Machine Learning | 5 ventajas de la programación orientada a objetos para la ingeniería de datos

¿Por qué las empresas deberían tener un Agile Coach? (y no un consultor de proyectos)

La implementación de metodologías ágiles como Scrum es fundamental para la transformación digital de las empresas, y el rol del Agile Coach se está convirtiendo en uno de los más demandadas rápidamente. En las empresas tradicionales este es el rol del consultor o asesor de proyectos, pero ¿qué es un Agile Coach? y ¿cómo puede hacer que la empresa y sus trabajadores lleguen a conseguir sus objetivos marcados?

¿Qué es un Agile Coach?

Un agile coach es un experto en agilidad, no solo en Scrum o una sola metodología, tiene las competencias y aptitudes necesarias para ayudar a las empresas hacia una transformación agile en sus estructuras organizativas, procesos y herramientas de trabajo. Así como guiar a las personas en la adopción de la mentalidad agile, lo que le permite comprender los principios y valores ágiles. Además, promueve la auto organización de los equipos, autonomía y responsabilidad en el proyecto.

Un agile coach está muy enfocado a la gente -sobre los números-. Su labor es crítica en guiar a los equipos de trabajo en el camino del agilismo, por lo que la experiencia técnica no es suficiente, también se requiere las aptitudes y actitudes de un coach profesional tales como como facilitador, formador, mentor y coach. En definitiva, pretende que las personas den lo mejor de sí mismos.

¿Cuáles son las habilidades de un Agile Coach?

Las principales habilidades de un Agile Coach se resumen en la siguiente infografía

Agile Coach infografia
¿Por qué es necesario un Agile Coach?

Transformar una empresa en ágil, es una labor difícil que implica cambios de procesos, mentalidad y cultura.  Se requiere una visión global de la empresa que le permita ayudar al desarrollo y cambio profesional de sus empleados. Un Agile Coach, localizará los problemas, y notificará a los equipos sobre ellos, de tal forma que sean ellos quienes establezcan la mejor estrategia para solucionarlos.

Artículos relacionados

¿Cómo Scrum puede ayudarnos a gestionar los nuevos equipos remotos?

Machine Learning | Cómo generar nuevos datasets usando bootstrap y ML.NET

Bootstrap es una técnica de remuestreo utilizada para estimar estadísticas de una población mediante el muestreo de un conjunto de datos con reemplazo. En palabras más simples; imaginemos que tenemos una muestra de datos en un dataset y queremos generar una nueva muestra de igual o menor tamaño, entonces tomamos un dato del dataset original de manera aleatoria y la colocamos en un nuevo dataset, a la vez que devolvemos el dato seleccionado al dataset original, y repetimos el proceso hasta generar la nueva muestra deseada. Este enfoque de muestreo se llama muestreo con reemplazo (sampling with replacement).

Fuente: Bootstrap aggregating bagging

Lo interesante de esta técnica es que permite que un dato sea parte de una nueva muestra más de una vez o ni una sola vez. Esto tiene algunas ventajas estadísticas para que las nuevas muestras generadas tengan una mejor distribución que las muestra original.

Esta técnica de bootstrap puede ser muy útil en los siguientes casos.

Cuando se quiere mejorar la distribución de los datos. En el caso de ML.NET la técnica de bootstrap utiliza una distribución de Poisson(1) para generar el nuevo dataset.

Cuando se tiene un dataset muy pequeño y se necesitan más muestras. Ya que los nuevos dataset que genera el remuestreo con bootstrap tiene una valides estadística, estos se pueden usar para entrenar varios modelos con los nuevos dataset o inclusive combinarlos para generar un nuevo dataset con un mayor número de datos.

Para probar un modelo con los datos “fuera de la bolsa” (out-of-bag). Ya que un dato dentro de un dataset puede no ser seleccionado para formar parte del remuestreo, estos datos no seleccionados se los puede usar para generar un nuevo dataset llamado “out-of-bag¨” y usarlo como dataset de prueba para evaluar un modelo generado con un dataset de entrenamiento.

Bootstrap con ML.NET

El código de ejemplo del uso de bootstrap con ml.net, al igual que otros ejemplos está disponible en GitHub.

Primero, y como siempre, iniciamos nuestro objeto mlContext, en este caso no especificamos un seed ya que variaremos ese dato en el método BootstrapSample. Luego cargaremos un dataset con 1000 registros desde un archivo de texto, en este caso son datos de reservas de hotel y su precio.

MLContext mlContext = new MLContext();

            //Cargamos el dataset original
            string dataPath = GetAbsolutePath("../../../data/HotelBookingsRate.tsv");
            var data = mlContext.Data.LoadFromTextFile<ModelInput>(dataPath,
                                                    separatorChar: '\t', hasHeader: true);

En el primer ejemplo crearemos dos remuestreos (bags), cada uno con una semilla diferente (seed), y veremos los resultados en consola.

//Creamos dos remuestreos (bags)
            for (int i = 0; i < 2; i++)
            {
                //generamos el nuevo dataset usando Bootstrap
                var resample = mlContext.Data.BootstrapSample(data, seed: i);

                var enumerable = mlContext.Data
                    .CreateEnumerable<ModelInput>(resample, reuseRowObject: false);

                Console.WriteLine($"Print sample preview out of {enumerable.Count()}");
                PrintHeaders(typeof(ModelInput));

                //ver los datos del nuevo dataset
                //estos dataset los podemos usar para entrenar un modelo
                foreach (var row in enumerable.Take(10))
                {
                    PrintValues(row);
                }
                Console.WriteLine();
            }

En el segundo ejemplo vemos como crear un dataset “out-of-bag” con los datos no seleccionados en el remuestreo, esta técnica nos sirve para usar este dataset como dataset de pruebas para evaluar un modelo generado, nótese en el resultado que el tamaño de este dataset es mucho menor.

//Creamos un remuestreo y un dataset out-of-bag
            //Este dataset lo podemos usar para probar o evaluar un modelo
            var resampleOob = mlContext.Data.BootstrapSample(data, 1, complement: true);

            var enumerableOob = mlContext.Data
                    .CreateEnumerable<ModelInput>(resampleOob, reuseRowObject: false);

            Console.WriteLine($"Print sample preview out of {enumerableOob.Count()}");
            PrintHeaders(typeof(ModelInput));
            foreach (var row in enumerableOob.Take(10))
            {
                PrintValues(row);
            }
Artículos relacionados

Machine Learning | Cómo predecir más de una categoría usando ML.NET

Machine Learning | Trabajar con múltiples fuentes de datos usando ML.NET

Machine Learning | Trabajar con múltiples fuentes de datos usando ML.NET

Cuando desarrollamos modelos de machine learning normalmente debemos trabajar unificando datos de diferentes fuentes como archivos .csv, bases de datos o integraciones con APIs. Una de las ventajas de la programación orientada a objetos es que podemos desarrollar funciones para recuperar datos de múltiples fuentes e instanciarlos en un mismo objeto, sin depender de la compatibilidad de los paquetes que utilicemos. En este post veremos cómo instanciar el objeto de origen de datos (dataset) desde múltiples fuentes usando el framework ML.NET.

En la arquitectura del desarrollo de un modelo de machine learning con ML.NET debemos siempre tener un objeto que represente el origen de datos (dataset) y que por convención lo llamamos ModelInput. Este objeto se lo puede instanciar con los datos de entrenamiento, pruebas o inferencia.

Usando ML.NET podemos cargar los datos para instanciar el objeto ModelInput desde un archivo .csv, desde una tabla en SQL Server, o desde cualquier otra fuente usando un objeto Enumerable. Veamos un ejemplo de una función que utiliza estas tres funcionalidades para cargar datos para el entrenamiento de un modelo.

private static IDataView LoadDataView(string source)
{
    IDataView trainingDataView;

    if (source == "textFile")
    {
        var tmpPath = GetAbsolutePath(TRAIN_DATA_FILEPATH);
        trainingDataView = mlContext.Data.LoadFromTextFile<ModelInput>(
                                    path: tmpPath, hasHeader: true,
                                    separatorChar: '\t', allowQuoting: true,
                                    allowSparse: false);
    }
    else if (source == "SQL")
    {
        DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
        DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, CONNECTION_STRING, SQL_COMMAND);
        trainingDataView = loader.Load(dbSource);
    }
    else
    {
        //Load form a json file or a rest API
        var data = File.ReadAllText("json1.json");
        var inMemoryCollection = JsonConvert.DeserializeObject<IEnumerable<ModelInput>>(data);

        trainingDataView = mlContext.Data.LoadFromEnumerable<ModelInput>(inMemoryCollection);
    }

    return trainingDataView;
}

En el código anterior se observa las tres funciones que tiene el objeto mlContext.Data para cargar datos al ModelInput

  • LoadFromTextFile() Carga datos desde cualquier archivo .csv o .tsv
  • CreateDatabaseLoader() Carga datos desde una base SQL Server o Azure SQL
  • LoadFromEnumerable() Carga datos desde cualquier lista, se puede usar para cargar datos desde una API o desde un archivo json

Con esta sencilla función podemos cargar datos tanto para el entrenamiento de un modelo o para realizar predicciones de un modelo ya entrenado.

Artículos relacionados: Cómo predecir más de una categoría usando ML.NET

Artículos relacionados: Segmentación de clientes usando ML.NET

Machine Learning | 5 ventajas de la programación orientada a objetos para la ingeniería de datos

Para quienes hemos trabajado toda nuestra vida con lenguajes orientados a objetos como Java, C# o Ruby, cuando incursionamos en el mundo de la ciencia de datos nos puede resultar muy complicado el adaptarnos a lenguajes como Python que es muy popular en este campo debido a la facilidad de aprendizaje para quienes no tienen bases de programación, pero para quienes ya tenemos fuertes conocimientos de desarrollo el usar un lenguaje de programación orientado a objetos también puede tener muchas ventajas para usarlo en la ciencia e ingeniería de datos.

A continuación veremos 5 ventajas de la POO para la ciencia e ingeniería de datos

1 Evitar duplicidad de código. La POO nos permite -y obliga- a encapsular una funcionalidad dentro de un objeto que es descrito con sus propiedades y funciones. Esto ayuda a estandarizar el desarrollo y que los programadores sepan en donde ubicar sus funciones de forma ordenada y lógica, evitando que cada programador agregue funciones específicas para sus necesidades en lugar de diseñarlas de manera reusable y dentro de un contexto adecuado. Veamos un ejemplo de una función completa para crear un modelo de clasificación binaria pero muy simple gracias al uso de funciones encapsuladas y en contexto con la clase creada.

public static class ModelBuilder
{
    // Create MLContext to be shared across the model creation workflow objects 
    // Set a random seed for repeatable/deterministic results across multiple trainings.
    private static MLContext mlContext = new MLContext(seed: 1);

    public static void CreateModel()
    {
        var tmpPath = GetAbsolutePath(TRAIN_DATA_FILEPATH);
        // Load Data
        IDataView trainingDataView = mlContext.Data.LoadFromTextFile<ModelInput>(
                                        path: tmpPath, hasHeader: true,
                                        separatorChar: '\t', allowQuoting: true,
                                        allowSparse: false);


        // Build training pipeline
        IEstimator<ITransformer> trainingPipeline = BuildTrainingPipeline(mlContext);

        // Evaluate quality of Model
        Evaluate(mlContext, trainingDataView, trainingPipeline);

        // Train Model
        ITransformer mlModel = TrainModel(mlContext, trainingDataView, trainingPipeline);

        tmpPath = GetAbsolutePath(MODEL_FILEPATH);
        // Save model
        SaveModel(mlContext, mlModel, tmpPath, trainingDataView.Schema);
    }
}

2 Trabajar con diferentes fuentes de datos. Ya sea para realizar una exploración de datos o para construir un modelo de Machine Learning, siempre vamos a depender de un origen de datos al que debemos acceder. En Python es muy común la práctica de trabajar con archivos .csv y copiar el archivo en cada proyecto para poder acceder a él. Cuando trabajamos con objetos tenemos la ventaja de que al objeto lo podemos instancias de diferentes formas sin importar su origen o sin depender de una librería específica para cada origen. Veamos un ejemplo para instanciar un objeto en una sola función para tres tipos de orígenes diferentes.

private static IDataView LoadDataView(string source)
{
    IDataView trainingDataView;

    if (source == "textFile")
    {
        var tmpPath = GetAbsolutePath(TRAIN_DATA_FILEPATH);
        trainingDataView = mlContext.Data.LoadFromTextFile<ModelInput>(
                                    path: tmpPath, hasHeader: true,
                                    separatorChar: '\t', allowQuoting: true,
                                    allowSparse: false);
    }
    else if (source == "SQL")
    {
        DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();
        DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, CONNECTION_STRING, SQL_COMMAND);
        trainingDataView = loader.Load(dbSource);
    }
    else
    {
        //Load form a json file or a rest API
        var data = File.ReadAllText("json1.json");
        var inMemoryCollection = JsonConvert.DeserializeObject<IEnumerable<ModelInput>>(data);

        trainingDataView = mlContext.Data.LoadFromEnumerable<ModelInput>(inMemoryCollection);
    }

    return trainingDataView;
}

3 Modelos fuertemente tipados. Aunque la posibilidad de no declarar variables o objetos y no especificar su tipo puede ser muy atractivo cuando recién se aprende un nuevo lenguaje, lo cierto es que en grandes proyectos esto puede causar mucha confusión sobretodo cuando el mantenimiento de un código lo tiene que hacer un desarrollador diferente al que lo creó. En la ciencia de datos este puede ser un problema en particular cuando se trabaja con diferentes tipos de modelos, en un lenguaje orientado a objetos podemos usar objetos genéricos para su creación pero instanciarlos fuertemente tipado para explorar con precisión sus características como métricas y parámetros. Veamos un ejemplo de código para instanciar un modelo multiclase.

public static IEstimator<ITransformer> BuildTrainingPipeline(MLContext mlContext)
{
    // Data process configuration with pipeline data transformations 
    var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("reservation_status", "reservation_status")
                              .Append(mlContext.Transforms.Categorical.OneHotEncoding(new[] { new InputOutputColumnPair("hotel", "hotel"), new InputOutputColumnPair("arrival_date_month", "arrival_date_month"), new InputOutputColumnPair("meal", "meal"), new InputOutputColumnPair("country", "country") }))
                              .Append(mlContext.Transforms.Concatenate("Features", new[] { "hotel", "arrival_date_month", "meal", "country" }));
    // Set the training algorithm
    var trainer = mlContext.MulticlassClassification.Trainers.LightGbm(new LightGbmMulticlassTrainer.Options() { NumberOfIterations = 200, LearningRate = 0.2938725f, NumberOfLeaves = 60, MinimumExampleCountPerLeaf = 10, UseCategoricalSplit = true, HandleMissingValue = false, MinimumExampleCountPerGroup = 10, MaximumCategoricalSplitPointCount = 32, CategoricalSmoothing = 20, L2CategoricalRegularization = 0.5, UseSoftmax = false, Booster = new GradientBooster.Options() { L2Regularization = 0.5, L1Regularization = 1 }, LabelColumnName = "reservation_status", FeatureColumnName = "Features" })
                              .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));

    var trainingPipeline = dataProcessPipeline.Append(trainer);

    return trainingPipeline;
}

4 Fácil integración con otros sistemas. Los lenguajes como C# tienen frameworks de desarrollo muy completos como .NetFramework o .NetCore que eliminan la dependencia de diferentes paquetes de diferentes creadores para las funciones más básicas, esto mejora sustancialmente la compatibilidad cuando se quiere integrar modelos y predicciones de Machine Learning con las aplicaciones de negocio o APIs de terceros. Veamos un ejemplo de un código para predecir un resultado utilizando un modelo de Machine Learning.

public static ModelOutput Predict(ModelInput input)
{
    // Create new MLContext
    MLContext mlContext = new MLContext();

    // Load model & create prediction engine
    string modelPath = @"MLModel.zip";
    ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema);
    var predEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);

    // Use model to make prediction on input data
    ModelOutput result = predEngine.Predict(input);
    return result;
}

5 Establecer estándares de trabajo. Finalmente la programación orientada a objetos nos permite desarrollar siguiendo patrones de diseño y de trabajo como TDD, Dependency Injection, entre otros, lo cual facilita mucho el mantenimiento del código y mejora su calidad, sobre todo cuando los proyectos crecen y se tiene a varios desarrolladores compartiendo y desarrollando una misma funcionalidad.

Artículos relacionados: Machine Learning | Cómo predecir más de una categoría usando ML.NET

Machine Learning | Cómo predecir más de una categoría usando ML.NET

Una de las ventajas de usar el framework ML.NET para la ciencia e ingeniería de datos es la posibilidad de crear experimentos para la creación de modelos de Machine Learning de manera automatizada. En este post vamos a usar la clase MulticlassClassificationExperiment incluida en el paquete Microsoft.ML.AutoML para crear un modelo para predecir la probabilidad de cancelación o cambio en la reserva de un hotel.

El código fuente del proyecto se puede descargar de este repositorio en GitHub

Problema

Tenemos un dataset con el histórico de las reservas de varios hoteles y el registro de los cambios que tuvo la reserva. Con estos datos vamos a crear un modelo de Machine Learning para predecir si una reserva puede ser cancelada, modificada o no tener cambios. Este escenario puede ser útil para ofrecer un seguro de cancelación de reserva a un menor o mayor costo según el resultado de la predicción.

Dataset

Contamos con un Dataset tomado de kaggle y modificado para marcar tres categorías en la columna de reservation_status, esta puede tener los valores: Booking-Changed; Canceled; Check-Out

Solución

Crearemos un modelo de Machine Learning usando el framework ML.NET. Ya que son tres categorías las que queremos predecir (Booking-Changed; Canceled; Check-Out) debemos crear un modelo de clasificación multiclase (multiclass classification). Lo haremos de forma automática para que el framework seleccione el mejor algoritmo y los mejores parámetros para nuestro dataset, no tendremos que preocuparnos por la parte matemática, estadística o el tipo de algoritmo a utilizar.

Ya que nuestro modelo debe ser de clasificación multiclase (multiclass classification) usaremos el método CreateMulticlassClassificationExperiment para crear el modelo de forma automática.

Como en toda solución de Machine Learning seguiremos los siguientes pasos para crear el modelo.

  • Preparar y cargar los datos de entrenamiento y prueba
  • Entrenar el modelo para le predicción de los valores deseados
  • Evaluar la precisión del modelo
  • Consumir el modelo desde una aplicación

Los datos los cargaremos en un objeto IDataView desde un archivo de texto con el siguiente código

// Load Data
var tmpPath = GetAbsolutePath(TRAIN_DATA_FILEPATH);
IDataView trainingDataView = mlContext.Data.LoadFromTextFile<ModelInput>(
                                path: tmpPath,
                                hasHeader: true,
                                separatorChar: '\t',
                                allowQuoting: true,
                                allowSparse: false);

var splitData = mlContext.Data
    .TrainTestSplit(trainingDataView, testFraction: 0.15);

El método mlContext.Data.TrainTestSplit() nos sirve para tomar una muestra de nuestro dataset que será usado para probar el modelo creado

Para entrenar el modelo usaremos el método CreateMulticlassClassificationExperiment, al invocarlo necesitamos especificar el tiempo en segundos que queremos que dure el experimento, dependiendo del tamaño de nuestro dataset mientras más tiempo dure el entrenamiento más algoritmos serán probados hasta encontrar el de mejor precisión. El código para crear el experimento es el siguiente.

// STEP 2: Run AutoML experiment
Console.WriteLine($"Running AutoML Multiclass classification experiment for {ExperimentTime} seconds...");
ExperimentResult<MulticlassClassificationMetrics> experimentResult = mlContext.Auto()
         .CreateMulticlassClassificationExperiment(ExperimentTime)                .Execute(trainingDataView, labelColumnName: "reservation_status");

Para usar este método dentro del objeto de contexto mlContext debemos instalar el paquete nuget Microsoft.ML.Auto

using Microsoft.ML.AutoML;

Hasta ahí ese es todo el código que necesitamos para crear nuestro modelo de clasificación multiclase. Pero antes de poder usarlo debemos conocer sus métricas y su precisión para hacer predicciones. Lo primero que podemos observar es el algoritmo seleccionado para el modelo y las métricas que lo calificaron como el mejor algoritmo para nuestros datos. Esto lo podemos hacer con este código

// STEP 3: Print metric from the best model
RunDetail<MulticlassClassificationMetrics> bestRun = experimentResult.BestRun;
Console.WriteLine($"Total models produced: {experimentResult.RunDetails.Count()}");
Console.WriteLine($"Best model's trainer: {bestRun.TrainerName}");
Console.WriteLine($"Metrics of best model from validation data --");
PrintMulticlassClassificationMetrics(bestRun.ValidationMetrics);

El siguiente paso es probar el modelo con datos de prueba no incluidos en el entrenamiento y ver si las métricas son similares a las métricas del entrenamiento del modelo.

// STEP 4: Evaluate test data
IDataView testDataViewWithBestScore = bestRun.Model.Transform(splitData.TestSet);
var testMetrics = mlContext.MulticlassClassification.CrossValidate(testDataViewWithBestScore, bestRun.Estimator, numberOfFolds: 5, labelColumnName: "reservation_status");
Console.WriteLine($"Metrics of best model on test data --");
PrintMulticlassClassificationFoldsAverageMetrics(testMetrics);

Los resultados de este experimento en resumen son los siguientes

  • Mejor algoritmo seleccionado: LightGbmMulti. Una de las ventajas de generar un modelo de forma automática es que la selección del algoritmo no está sesgada por la preferencia del data scientist, durante el experimento se han probado varios algoritmos y configuraciones
  • Precisión del modelo: 97%
  • Con los datos de prueba se obtuvo en promedio un 97% de precision en las predicciones lo que nos una confianza bastante buena para poder usar nuestro modelo generado

El siguiente paso es guardar el modelo en un archivo .zip para luego usarlo desde una aplicación

// Save model
SaveModel(mlContext, bestRun.Model, MODEL_FILEPATH, trainingDataView.Schema);

Como último paso crearemos una clase ConsumeModel y un método Predict() para consumir el modelo y probar una predicción con los datos de una nueva reserva de hotel.

// Create new MLContext
MLContext mlContext = new MLContext();

// Load model & create prediction engine
string modelPath = @"MLModel.zip";
ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema);
var predEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel, modelInputSchema);

// Use model to make prediction on input data
ModelOutput result = predEngine.Predict(input);
return result;

Una recomendación de diseño es crear las clases ConsumeModel, ModelInput y ModelOutput en un solo proyecto, puede ser el mismo en el que creamos y entrenamos el modelo, de esa forma, En la aplicación para consumir el modelo y hacer una predicción con nuevos datos solo deberemos referencias el proyecto con la clase ConsumeModel y no será necesario instalar los paquetes de Microsoft.ML.

El código en la aplicación para predecir el cambio de estado en una reserva de hotel se verá así.

Console.WriteLine("Tiempo de anticipacion: ");
string leadTime = Console.ReadLine();
Console.WriteLine("Cuarto reservado: ");
string cuartoReservado = Console.ReadLine();
Console.WriteLine("Precio promedio: ");
string adr = Console.ReadLine();
Console.WriteLine("Pais: ");
string country = Console.ReadLine();
Console.WriteLine("Cambios previos: ");
string cambiosPrevios = Console.ReadLine();


ModelInput bookingData = CreateBookingData(leadTime, cuartoReservado, cambiosPrevios, adr, country);

ModelOutput bookingPredict = PredecirCambioReserva(bookingData);

Console.WriteLine($"\n\nActual Reservation_status: {bookingData.Reservation_status} \nPredicted Reservation_status value {bookingPredict.Prediction} \nPredicted Reservation_status scores: [{String.Join(",", bookingPredict.Score)}]\n\n");

En este caso simulamos la entrada de solo cinco variables de todo el dataset, realizamos la predicción y además vemos la métrica de cada categoría.

El código fuente del proyecto se puede descargar de este repositorio en GitHub

Artículos Relacionados

Segmentación de clientes usando ML.NET

¿Cómo Scrum puede ayudarnos a gestionar los nuevos equipos remotos?

La gestión de equipos remotos requiere las mismas habilidades e instrucciones que cualquier equipo presencial: Objetivos claros, retroalimentación, interacción, enfoque. Pero la distancia añade retos adicionales, la adopción de un marco de trabajo ágil como Scrum puede ayudarnos a superar estos retos.

En el mercado existen muchas herramientas tecnológicas que nos ayudan a mantenernos conectados y ¨”cercanos” y son altamente recomendadas como Microsoft Teams, Google Meet, Slack y por supuesto la estrella de las reuniones Zoom. Pero estas herramientas no nos ayudan a superar ciertos retos culturales y relacionadas al comportamiento humano. Veamos algunos de estos retos que se presentan en equipos remotos.

1 Perdida de identidad con la compañía. Este es un problema crítico y crece cada día sin que nos demos cuenta. Los humanos tendemos a socializar en grupo. En la oficina se forman amistades entre las personas. Todos son parte de un mismo equipo en la compañía. Cuando la gente trabaja remotamente, y ya nos e comparte un café o un desayuno, se forma una sensación extraña. Se pierden los nexos y conexiones con las personas que ya no conocemos. La consecuencia es que la compañía se divide en grupos y estos grupos van a tener mayor dificultad para trabajar en conjunto.

2 El conocimiento no llega a los equipos. Aún en equipos que han trabajado juntos por muchos años, enfrentan retos en la transferencia de conocimiento. En muchos casos, el equipo de desarrollo está alejado del product owner. Además, el equipo de desarrollo está alejado de los usuarios del producto que están creando y dependen del product owner para entender los requerimientos.

3 Pérdida de comunicación. Cuando un equipo trabaja de forma presencial, conversa. almuerzan, se toman un café juntos, y las reuniones son más frecuentes. pero en un equipo remoto esto no sucede. El problema es que un equipo remoto necesita aún más comunicación. La comunicación es clave para superar los retos que hemos visto. Así que tenemos que encontrar los mecanismos para aumentar la comunicación en equipos remotos.

4 La caja negra. Cuando el equipo remoto está alejado, no vemos lo que está haciendo ni quién está trabajando en nuestro producto. El equipo remoto se convierte en una caja negra, Enviamos requerimientos y esperamos una salida. En este entorno se vuelve más necesario la adopción del agilismo. Los miembros del equipo remoto tienen que ser vistos como un solo equipo, tenemos que saber cómo cada miembro aporta al equipo, la caja negra tiene que ser abierta

Ya conocemos los retos, ahora respondamos la pregunta ¿Cómo Scrum puede ayudarnos a gestionar los nuevos equipos remotos?

El Scrum Master toma más importancia en una organización.

El Scrum Master es el rol por excelencia para remover los impedimentos del equipo y hay algunas recomendaciones que puede seguir para mantener al equipo comunicado y unido.

Adaptar y mantener una disciplina en el uso de herramientas. Pasar de las herramientas físicas como paneles Kanban y las reuniones diarias presenciales a herramientas digitales y reuniones virtuales tomará tiempo de adaptación. Para esto el Scrum Master deberá generar el hábito de uso de las herramientas para el trabajo remoto.

Sprints más cortos para mantener los objetivos simples. Sprints y retrospectivas cada semana pueden ser más efectivos en equipos remotos para no descuidar el enfoque en los objetivos y avances del proyecto.

Reuniones más interactivas y en equipos más pequeños. Es de vital importancia mantener el interés en las reuniones remotas y esto se puede perder si hay muchos participantes, la recomendación es que se armen equipos más pequeños para que todos puedan -y deban- participar activamente en la reunión y que todos aporten algo.

El Product Owner debe conocer las nuevas necesidades de los clientes

En la llamada “nueva normalidad” las necesidades de los clientes no van a ser las mismas. El valor que las empresas y sus servicios aportan a la sociedad van a tomar mucha más importante que antes. El Product Owner debe conocer esas nuevas necesidades para definir con más prioridad los productos que tengan estén alineados con estas nuevas necesidades. Además el Product Owner debe convertirse en un experto en experiencia del cliente ya que en la actualidad esto hace la diferencia entre el éxito o fracaso de un producto.

Estas habilidades deben ser reforzadas en el Product Owner ya que en equipos remotos es quizá el único punto de contacto entre el negocio y el equipo de desarrollo, de esta manera evitamos la dependencia de involucrar a usuarios o más miembros al equipo del proyecto.

El conocimiento tiene que estar más disponible para todos.

El objetivo es asegurarse que todos los miembros del equipo tengan acceso igualitario a información crucial del proyecto, hay que romper el paradigma de “información reservada” o el miedo a que “se van a llevar el conocimiento”.

Un equipo presencial tiene más interacciones con el usuario y Product Owners. EN equipos remotos se necesita un plan para acceder a esa información. Reuniones de planificación más efectivas, más involucramiento del Product Owner en estas reuniones y pensamiento creativo para obtener mejor feedback de los usuarios en las etapas del proyecto.

Fallar rápido y barato

Una de las bases de Scrum y el agilismo es tomar decisiones más rápidas, con la premisa de que demasiado análisis puede ser más costoso que ejecutar una idea aunque esta sea fallida. Esto toma más relevancia en momentos de cambio o de incertidumbre. En tiempos en que muchos negocios tienen que reinventarse o cambiar la propuesta de sus negocios, no podemos pasar demasiado tiempo esperando encontrar la solución perfecta. Un producto más simple con objetivos claros puede determinar el éxito o fracaso en la adaptación de nuestro negocio.

Artículos relacionados: ¿El Coronavirus acelerará la transformación digital de las empresas?

¿El Coronavirus acelerará la transformación digital de las empresas?

La transformación digital ha potenciado las estrategias de negocio de pequeñas, medianas y grandes empresas mediante el uso de plataformas digitales para cumplir con las expectativas de sus clientes.

Las plataformas digitales se encuentran disponibles desde hace varios años pero muchas compañías no las han implementado para transformar sus negocios y encontrar mayores oportunidades para crecer, ser más eficientes y diferenciarse de la competencia.

La llegada del coronavirus ha puesto a prueba a miles de compañías en el mundo que no estaban preparadas para afrontar una pandemia económica y menos para operar en tiempos de confinamiento preventivo decretado por muchos países en el mundo, poniendo en jaque la economía mundial y por ende a muchas compañías que no han empezado a implementar la transformación digital.

Ahora los negocios están obligadas a transformarse y estas son 4 razones por las que el Coronavirus acelerará la transformación digital en las empresas

1. El teletrabajo se volverá parte de la cultura empresarial.

Según Forbes el 29% de los trabajadores remotos dicen que son más felices que los trabajadores que deben estar en un lugar fijo.

El teletrabajo puede ser mucho más productivo que el trabajo presencial si se lo realiza con las herramientas y el liderazgo adecuado. En teletrabajo pierde sentido la evaluación por tiempo de trabajo y gana prioridad la evaluación por objetivos y resultados. Es verdad que no todas las funciones se pueden adecuar al trabajo remoto de la misma forma, pero aquellas que funciones que se pueden cumplir de forma remota sin impacto al cliente deberán seguir siendo impulsadas por las empresas aún cuando se levanten las medidas de confinamiento.

2. Las empresas adoptarán las tecnologías en la nube como estrategia para adaptarse a los cambios.

Migrar los procesos a servicios en la nube como AWS o Microsoft Azure permite a las empresas usar herramientas tecnológicas más actualizadas, seguras y flexibles a los cambios, sin embargo los líderes de las compañías deben asegurarse que esta transición sea de manera gradual y bien estratégica donde puedan garantizar que los empleados y el equipo de la compañía en general tenga todos los conocimientos para empezar a operar de una manera más digital.

Los servicios en la nube también ayudan a que las empresas adopten el teletrabajo de forma más rápida. Empresas como Google, Microsoft y Zoom están ofreciendo funciones gratuitas para sus herramientas de comunicación y colaboración, lo que permite crear una política de trabajo remoto para llevar los registros diarios, trabajos basados en tareas y diferentes planes individuales para que las personas se adapten a esta forma de hacer teletrabajo.

3. El e-commerce está cambiando el paradigma de la interacción entre el cliente y la empresa.

Según Marc Benioff, CEO de Salesforce, “cada transformación digital comenzará y terminará con el cliente”, es así como muchas nuevas empresas están adoptando modelos similares, encontrando en el e-commerce y las plataformas digitales una nueva forma de hacer negocios de manera más remota, eficaz, reduce los costos y mejora la experiencia de los clientes.

El e-commerce también trae el reto a las empresas de conocer más a sus clientes para brindarle servicios y experiencias personalizadas, utilizar modelos de machine learning para recomendaciones y digitalizar todos los puntos de interacción con el cliente tanto en la preventa como en postventa.

4. El agilismo será la principal forma de trabajo para desarrollar productos.

Muchos expertos coinciden en que luego de la pandemia enfrentaremos una “nueva normalidad” pero todavía el panorama es muy incierto. Las empresas deben estar mejor preparadas para adaptarse a los cambios de forma rápida y responder a las nuevas necesidades de los clientes. Los marcos de trabajo ágiles como Scrum deberán ser adoptados por todas las áreas de la empresa, ya no será una característica solo de las áreas de tecnología. La colaboración y el trabajo en equipos multidisciplinarios harán la diferencia entre las empresas que puedan adaptarse a diferentes modelos de negocio y desarrollar productos adecuados a la “nueva normalidad”

Artículo relacionado: Scrum explicado con Masterchef

Data Storytelling | La importancia de saber contar historias

En estos días de confinamiento debido al Coronavirus Covid19 vemos tantos números a diario de casos en todo el mundo, Las noticias en la mañana actualizan los datos, la cadena de televisión de la tarde repite los datos, y todas las cuentan en RRSS repiten y repiten los mismos datos. ¿De qué nos ha servido repetir y actualizar tanto los números de contagios en el país y el mundo? ¿Qué historia nos está contando esos datos?

Cuando trabajamos con datos debemos recordar siempre una cosa: dato que no cuenta algo no sirve de nada, absolutamente de nada. Por eso desde hace un tiempo se viene hablando de esta tendencia del Data Storytelling que busca cambiar la forma de presentar los datos para que tengan sentido dentro de una historia, que muestre las métricas clave, las comparaciones entre fechas o diagramas de dispersión, es decir, en mensajes persuasivos y efectivos que sean difíciles de olvidar.

¿Qué es Storytelling?

Aunque el concepto de Data Storytelling parezca novedoso, en realidad el Storytelling no es más que el arte de contar historias. Este concepto se ha usado en el mundo de la comunicación y el marketing desde hace mucho tiempo para mejorar la narración de historias en libros, comunicaciones y campañas comerciales.

Lo interesante del Data Storytelling es que combina el mundo del análisis de datos -donde no somos expertos en contar historias- y el mundo de la comunicación -donde no somos expertos en analizar datos. Por suerte para ustedes en este post veremos un poco de los dos mundos.

¿Por qué es importante?

El storytelling en marketing se usa como una técnica en la que cuentas una historia a tu comunidad con el objetivo de lograr una mejor conexión con ellos a través de las emociones.

Según Forbes, en un minuto se ven más de 4 millones de videos de Youtube en el mundo, se postean más de 46 mil fotos en Instagram y se hacen más de 500 mil comentarios en Facebook. En este mundo plagado de datos e información solo las historias son capaces de destacar por encima del resto de mensajes y generan un vínculo profundo con su audiencia.

Veamos un ejemplo claro

En este ejemplo de Johnie Walker, que nos muestra la historia de éxito del caminante que se convirtió en el ícono de la marca, podemos resaltar algunas características claves de una buena historia y que nos servirán para aplicarlo al Data Storytelling.

Características del Storytelling

#1 Personaje: La historia debe ser narrada con un personaje central, puede ser real o ficticio, el tener un personaje hace que la historia sea más humana y genera empatía con la audiencia. En el caso de Johnie Walker todos los valores de la empresa son un reflejo de los valores de su personaje principal. Su historia cuenta el éxito pero también las dificultades que tuvo que superar, esto genera la empatía y la conexión con la audiencia.

#2 Objetivo: Se debe plantear claramente qué queremos comunicar con nuestra historia, qué queremos vender, qué necesidad vamos a solucionar. Las personas van a escuchar nuestra historia porque lo que vamos a contar les interesa para solucionar algún problema o les deja una enseñanza que les va a ser útil.

#3 Experiencia: Las experiencias personales generan una conexión emocional muy fuerte y poderosa con la audiencia. En el caso de Johnie Walker esto está narrado como una aventura que nos enseña cómo superar retos con valores que se mantienen en el tiempo, al final nos están vendiendo eso, los valores de su marca.

Vista esta introducción al Storytelling, ahora debemos plantearnos ¿Cómo empato estos conceptos con el Data Storytelling? Para esto debemos recordar las características que tiene la teoría del Data Storytelling

Características del Data Storytelling

#1 Narrativa y datos: la combinación de ambos sirve para ofrecer a la audiencia una explicación sobre los mismos.

#2 Visualización y datos: como ves en la imagen, la palabra enlighten (que significa iluminar) es el resultado de la combinación de ambos. Añadir una visualización a los datos ayuda informar de forma entretenida e inteligible.

#3 Narrativa y visualización: esta combinación tiene como resultado la captación de clientes.

El problema al momento de estudiar Data Storytelling es que su teoría se centra mucho en la parte de datos y de visualización, pero la clave está en saber hacer una buena narrativa, y aquí es donde podemos aplicar todos los conceptos que vimos del Storytelling.

Recordemos lo mencionado al inicio del post: dato que no cuenta algo no sirve de nada, absolutamente de nada.

Ejemplos en casos de Coronavirus

Volvamos al ejemplo coyuntural del Coronavirus, ¿De qué nos sirve repetir estos datos todos los días?

Datos Coronavirus Ecuador

Las gráficas de arriba no contestan ni las preguntas más básicas ¿Cómo avanza la curva de contagios? ¿Los contagios nuevos son mayores o menores a los del día anterior? ¿Cuándo se verán resultados de las medidas de aislamiento tomadas?

Comparemos con las siguientes gráficas.

Gráficos avance coronavirus

El gráfico de arriba parece simple, pero revelaba lo que a muchos sorprendió en los últimos días cuando los casos en Italia comenzaron a desacelerar. Para quienes seguíamos estas gráficas sabíamos que lo más probable era que el crecimiento exponencial dure 31 días, tal cual sucedió en China.

Claro, esto está lejos de contar una historia todavía, veamos otros ejemplos

La gráfica de arriba ya se parece más a una historia, vemos la relación de las medidas de aislamiento tomadas en China con el crecimiento de casos diarios.

Para ver un ejemplo mejor elaborado podemos citar el caso del Financial Times que ha publicado un sitio con muchos gráficos que muestran tendencias y desagrega los datos de contagios a nivel mundial.

Grafico Coronavirus Financial Times

¿Qué importancia tiene el análisis de datos? En este reportaje de la BBC sobre el caso de Singapore demuestra que su clave para contener los contagios no fueron los hashtags, ni la compra de papel higiénico o las críticas al gobierno, la clave fueron los DATOS, Singapore aprendió de la crisis del SARS en 2003 y sabía que la clave para contener los contagios era recopilar todos los datos de los visitantes al país para poder reconstruir su historia de contactos desde su ingreso al país.

Pero no todas las historias tienen que ser con datos super elaborados y luego de grandes análisis matemáticos. Para concluir este post les dejo un ejemplo excelente de cómo contar una historia corta pero muy interesante en estos tiempos de confinamiento.

Artículo relacionado: Introducing the Timeline Storyteller custom visual for Microsoft Power BI