1z1bwjcleh00gh5hcd91lza.png

La forma en que construimos modelos tradicionales de aprendizaje automático es entrenar primero los modelos en un «conjunto de datos de entrenamiento» (generalmente un conjunto de datos de valores históricos) y luego generamos predicciones en un nuevo conjunto de datos, el «conjunto de datos de inferencia». Si las columnas del conjunto de datos de entrenamiento y el conjunto de datos de inferencia no coinciden, su algoritmo de aprendizaje automático generalmente fallará. Esto se debe principalmente a niveles de factores nuevos o faltantes en el conjunto de datos de inferencia.

El primer problema: factores faltantes

Para los siguientes ejemplos, suponga que utilizó el conjunto de datos anterior para entrenar su modelo de aprendizaje automático. Codificó en caliente el conjunto de datos en variables ficticias y sus datos de entrenamiento completamente transformados se ven como a continuación:

Conjunto de datos de entrenamiento transformado con pd.get_dummies/imagen del autor

Ahora, introduzcamos el conjunto de datos de inferencia, esto es lo que usaría para hacer predicciones. Digamos que se da como a continuación:

# Creating the inference_data DataFrame in Python
inference_data = pd.DataFrame({
'numerical_1': [11, 12, 13, 14, 15, 16, 17, 18],
'color_1_': ['black', 'blue', 'black', 'green',
'green', 'black', 'black', 'blue'],
'color_2_': ['orange', 'orange', 'black', 'orange',
'black', 'orange', 'orange', 'orange']
})
Datos de inferencia con 3 columnas/imagen por autor.

Usando una estrategia ingenua de codificación one-hot como la que usamos anteriormente (pd.get_dummies)

# Converting categorical columns in inference_data to 
# Dummy variables with integers
inference_data_dummies = pd.get_dummies(inference_data,
columns=['color_1_', 'color_2_']).astype(int)

Esto transformaría su conjunto de datos de inferencia de la misma manera y obtendrá el siguiente conjunto de datos:

Conjunto de datos de inferencia transformado con pd.get_dummies/imagen del autor

¿Notas los problemas? El primer problema es que al conjunto de datos de inferencia le faltan las columnas:

missing_colmns =['color_1__red', 'color_2__pink', 
'color_2__blue', 'color_2__purple']

Si ejecutara esto en un modelo entrenado con el «conjunto de datos de entrenamiento», normalmente fallaría.

El segundo problema: nuevos factores

El otro problema que puede ocurrir con la codificación one-hot es si su conjunto de datos de inferencia incluye factores nuevos e invisibles. Consideremos nuevamente los mismos conjuntos de datos anteriores. Si examina detenidamente, verá que el conjunto de datos de inferencia ahora tiene una nueva columna: color_2__orange.

Este es el problema opuesto al anterior, y nuestro conjunto de datos de inferencia contiene nuevas columnas que nuestro conjunto de datos de entrenamiento no tenía. En realidad, esto es algo común y puede suceder si una de las variables de sus factores sufrió cambios. Por ejemplo, si los colores anteriores representan los colores de un automóvil y un fabricante de automóviles de repente comenzó a fabricar automóviles de color naranja, es posible que estos datos no estén disponibles en los datos de entrenamiento, pero aún así podrían aparecer en los datos de inferencia. En este caso, necesita una forma sólida de abordar el problema.

Se podría argumentar, bueno, ¿por qué no enumera todas las columnas del conjunto de datos de entrenamiento transformado como columnas que serían necesarias para su conjunto de datos de inferencia? El problema aquí es que a menudo no se sabe de antemano qué niveles de factor hay en los datos de entrenamiento.

Por ejemplo, se podrían introducir nuevos niveles periódicamente, lo que podría dificultar su mantenimiento. Además de eso, viene el proceso de hacer coincidir su conjunto de datos de inferencia con los datos de entrenamiento, por lo que necesitaría verificar todos los nombres de columnas transformadas reales que se incluyeron en el algoritmo de entrenamiento y luego compararlos con el conjunto de datos de inferencia transformado. Si faltara alguna columna, necesitaría insertar nuevas columnas con valores 0 y si tuviera columnas adicionales, como la color_2__orange columnas anteriores, sería necesario eliminarlas. Esta es una forma bastante engorrosa de resolver el problema y, afortunadamente, hay mejores opciones disponibles.

La solución a este problema es bastante sencilla; sin embargo, muchos de los paquetes y bibliotecas que intentan simplificar el proceso de creación de modelos de predicción no logran implementarla bien. La clave radica en tener una función o clase que primero se ajuste a los datos de entrenamiento y luego usar esa misma instancia de la función o clase para transformar tanto el conjunto de datos de entrenamiento como el conjunto de datos de inferencia. A continuación exploramos cómo se hace esto usando Python y R.

En pitón

Podría decirse que Python es uno de los mejores lenguajes de programación para el aprendizaje automático, en gran parte debido a su extensa red de desarrolladores y bibliotecas de paquetes maduras, y su facilidad de uso, que promueve un rápido desarrollo.

Con respecto a los problemas relacionados con la codificación one-hot que describimos anteriormente, se pueden mitigar utilizando la biblioteca scikit-learn, ampliamente disponible y probada, y más específicamente la sklearn.preprocessing.OneHotEncoder clase. Entonces, veamos cómo podemos usarlo en nuestros conjuntos de datos de entrenamiento e inferencia para crear una codificación one-hot robusta.

from sklearn.preprocessing import OneHotEncoder

# Initialize the encoder
enc = OneHotEncoder(handle_unknown='ignore')

# Define columns to transform
trans_columns = ['color_1_', 'color_2_']

# Fit and transform the data
enc_data = enc.fit_transform(training_data[trans_columns])

# Get feature names
feature_names = enc.get_feature_names_out(trans_columns)

# Convert to DataFrame
enc_df = pd.DataFrame(enc_data.toarray(),
columns=feature_names)

# Concatenate with the numerical data
final_df = pd.concat([training_data[['numerical_1']],
enc_df], axis=1)

Esto produce una final DataFramede valores transformados como se muestra a continuación:

Conjunto de datos de entrenamiento transformado con sklearn/imagen por autor

Si desglosamos el código anterior, vemos que el primer paso es inicializar una instancia de la clase de codificador. Usamos la opción handle_unknown='ignore' para evitar problemas con valores desconocidos para las columnas cuando usamos el codificador para transformar nuestro conjunto de datos de inferencia.

Después de eso, combinamos una acción de ajuste y transformación en un solo paso con el fit_transform método. Y finalmente, creamos un nuevo marco de datos a partir de los datos codificados y lo concatenamos con el resto del conjunto de datos original.