Modelos y funciones personalizados de Sklearn

Los modelos personalizados pueden extender la funcionalidad de scikit-learn para satisfacer las necesidades de escenarios de aplicación específicos.

En scikit-learn, además de usar modelos y funciones de preprocesamiento ya disponibles, los usuarios también pueden crear modelos, transformadores y funciones personalizados según sus necesidades.

La implementación de modelos y funciones personalizados generalmente implica heredar de las clases base de scikit-learn, como BaseEstimator y TransformerMixin, y luego implementar los métodos específicos fit y predict.

Este capítulo explicará en detalle los siguientes aspectos:

  1. Transformador personalizado (Transformer)
  2. Estimador personalizado (Estimator)
  3. Pasos de pipeline personalizados
  4. Cómo mediante la herenciaBaseEstimatoryTransformerMixinimplementar algoritmos personalizados

1. Transformador personalizado (Transformer)

Un transformador es un componente utilizado para transformar datos, por ejemplo, estandarización, selección de características, etc. Los transformadores personalizados pueden heredar deTransformerMixin, e implementarfitytransformlos métodos.

Pasos para un transformador personalizado:

  • fitMétodo: generalmente se utiliza para aprender las propiedades de los datos (como la media, la varianza, los criterios de selección de características, etc.).fitEl método devuelve el propio transformador, lo que permite la llamada en cadena.
  • transformMétodo: aplica las propiedades aprendidas para transformar o procesar los datos.

Ejemplo de transformador personalizado: transformador de estandarización personalizado:

Supongamos que queremos implementar un transformador de estandarización personalizado. La estandarización consiste en escalar cada característica de los datos para que tenga una media de 0 y una varianza de 1.

Ejemplo

import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin

class CustomScaler(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        """
Calcular la media y la desviación estándar de cada característica
        """

        self.mean_ = np.mean(X, axis=0)
        self.std_ = np.std(X, axis=0)
        return self  # Devuelve el propio objeto

    def transform(self, X):
        """
Estandarizar los datos
        """

        return (X - self.mean_) / self.std_

# Probar el transformador personalizado
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# Cargar los datos
data = load_iris()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Crear el objeto transformador personalizado
scaler = CustomScaler()

# Usar la estandarización personalizada
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)

print("Scaled training data:\n", X_train_scaled)

La salida es la siguiente:

Scaled training data:
 [[-1.47393679  1.20365799 -1.56253475 -1.31260282]
 [-0.13307079  2.99237573 -1.27600637 -1.04563275]
 [ 1.08589829  0.08570939  0.38585821  0.28921757]
 [-1.23014297  0.75647855 -1.2187007  -1.31260282]
 [-1.7177306   0.30929911 -1.39061772 -1.31260282]
....

Explicación:

La clase CustomScaler implementa un proceso de estandarización, similar a StandardScaler en scikit-learn.

  • fitEl método calcula la media y la desviación estándar de los datos de entrenamiento y guarda estos valores.
  • transformEl método, basándose enfitla media y la desviación estándar calculadas en el método fit, transforma los datos.

2. Estimador personalizado (Estimator)

Un estimador se refiere al modelo en sí, como regresores, clasificadores, etc.

Un estimador personalizado debe heredar de la clase BaseEstimator e implementar los métodos fit y predict.

Pasos para un estimador personalizado:

  • fitMétodo: se utiliza para entrenar el modelo y calcular los parámetros necesarios (como pesos, sesgos, etc.).
  • predictMétodo: realiza predicciones sobre los datos de entrada basándose en los parámetros entrenados.

Ejemplo de estimador personalizado: un clasificador simple

Supongamos que queremos implementar un clasificador muy simple: usar la media de cada característica como umbral; si el valor supera la media, se predice la clase 1; de lo contrario, se predice la clase 0.

Ejemplo

from sklearn.base import BaseEstimator
import numpy as np

class SimpleClassifier(BaseEstimator):
    def fit(self, X, y):
        """
Entrenar el modelo: calcular la media de cada característica
        """

        self.mean_ = np.mean(X, axis=0)
        return self  # Devuelve el propio objeto

    def predict(self, X):
        """
Clasificar basándose en la media: si el valor de la característica es mayor que la media, predecir 1; de lo contrario, 0
        """

        return (X > self.mean_).astype(int)

# Probar el clasificador personalizado
X_train = np.array([[1.5, 2.5], [2.0, 3.0], [3.5, 4.5], [4.0, 5.0]])
y_train = np.array([0, 0, 1, 1])

# Crear el objeto clasificador personalizado
classifier = SimpleClassifier()

# Entrenar el modelo
classifier.fit(X_train, y_train)

# Realizar la predicción
X_test = np.array([[2.5, 3.5], [1.0, 2.0]])
y_pred = classifier.predict(X_test)

print("Predictions:", y_pred)

La salida es la siguiente:

Predictions: [[0 0]
 [0 0]]

Explicación:

  • fitEl método calcula la media de los datos de entrenamiento y la almacenaself.mean_en.
  • predictEl método realiza predicciones de clasificación comparando los datos de prueba con la media.

Este tipo de clasificador personalizado no es muy común en la práctica, pero muestra cómo crear un modelo simple usando BaseEstimator.


3. Pasos de pipeline personalizados

scikit-learn permite usar transformadores y estimadores personalizados como pasos de un pipeline. Esto permite integrar el preprocesamiento de datos y el entrenamiento del modelo en un flujo de trabajo. Los modelos y funciones personalizados pueden trabajar con el pipeline igual que los transformadores y estimadores integrados.

Uso de transformadores y estimadores personalizados en un pipeline

Ejemplo

import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline


class CustomScaler(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        """
Calcular la media y la desviación estándar de cada característica
        """

        self.mean_ = np.mean(X, axis=0)
        self.std_ = np.std(X, axis=0)
        return self  # Devuelve el propio objeto

    def transform(self, X):
        """
Estandarizar los datos
        """

        return (X - self.mean_) / self.std_
   

class SimpleClassifier(BaseEstimator):
    def fit(self, X, y):
        """
Entrenar el modelo: calcular la media de cada característica
        """

        self.mean_ = np.mean(X, axis=0)
        return self  # Devuelve el propio objeto

    def predict(self, X):
        """
Clasificar basándose en la media: si el valor de la característica es mayor que la media, predecir 1; de lo contrario, 0
        """

        return (X > self.mean_).astype(int)

# Probar el clasificador personalizado
X_train = np.array([[1.5, 2.5], [2.0, 3.0], [3.5, 4.5], [4.0, 5.0]])
y_train = np.array([0, 0, 1, 1])

# Crear el pipeline con la estandarización y el clasificador personalizados
pipeline = Pipeline([
    ('scaler', CustomScaler()),  # Estandarización personalizada
    ('classifier', SimpleClassifier())  # Clasificador personalizado
])

# Entrenar el pipeline
pipeline.fit(X_train, y_train)

X_test = np.array([[2.5, 3.5], [1.0, 2.0]])
# Predecir
y_pred = pipeline.predict(X_test)
print("Predictions:", y_pred)

La salida es la siguiente:

Predictions: [[0 0]
 [0 0]]

Explicación:

Usamos CustomScaler y SimpleClassifier como pasos del pipeline, aprovechando que el pipeline ejecuta automáticamente el preprocesamiento de datos y el entrenamiento del modelo.

De esta manera, todo el flujo de trabajo del pipeline se puede completar con un solo método fit y predict, manteniendo eficiencia y simplicidad.


Cómo implementar algoritmos personalizados heredando de BaseEstimator y TransformerMixin

  • BaseEstimator: es la clase base de todos los estimadores de scikit-learn. Proporcionaget_params()yset_params()métodos, lo que permite que los estimadores personalizados puedanGridSearchCVtrabajar conjuntamente con herramientas como GridSearchCV, etc.
  • TransformerMixin: es la clase base de todos los transformadores de scikit-learn. Proporcionafit_transform()método, lo que permite que los transformadores puedanPipelineusarse conjuntamente.

Al heredar de estas dos clases base, podemos crear fácilmente nuestros propios modelos y funciones personalizados, y podemos utilizar las herramientas de scikit-learn (como GridSearchCV y Pipeline) para la optimización y evaluación.

Ejemplo completo de transformador y estimador personalizados:

Ejemplo

from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np

class CustomEstimator(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        # Simular un 'modelo' simple: calcular la media de cada característica
        self.mean_ = np.mean(X, axis=0)
        return self

    def transform(self, X):
        # Estandarizar los datos basándose en la media
        return X - self.mean_

    def predict(self, X):
        # Método de predicción simple: si el valor de la característica es mayor que la media, predecir 1; de lo contrario, 0
        return (X > self.mean_).astype(int)

# Usar el estimador y el transformador personalizados
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# Cargar los datos
data = load_iris()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Crear el pipeline
pipeline = Pipeline([
    ('custom', CustomEstimator())
])

# Entrenar el modelo
pipeline.fit(X_train, y_train)

# Predecir
y_pred = pipeline.predict(X_test)
print("Predictions:", y_pred)

En el ejemplo anterior, creamos un estimador personalizado, CustomEstimator, que no solo realiza la estandarización (transform), sino también la predicción (predict). Luego, lo usamos como parte de un pipeline para entrenar y predecir.

La salida se muestra a continuación:

Predictions: [[1 0 1 1]
 [0 1 0 0]
 [1 0 1 1]
 [1 0 1 1]
 [1 0 1 1]
 [0 1 0 0]
 [0 0 0 1]
 [1 1 1 1]
 [1 0 1 1]
 [0 0 1 1]
...
Otras extensiones