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

Publicado por Diego Zumarraga Mera

Experto en transformación digital, Machine Learning, Desarrollo Web, Arquitecto Azure

A %d blogueros les gusta esto: