Loading [MathJax]/extensions/Safe.js
  • Introducción
  • Métodos de selección de variables
    • Métodos de filtro
    • Métodos de envoltura (wrapper)
    • Métodos integrados (embedded)
  • Librerías para selección de variables
  • Selección de variables con Scikit-learn
    • Selección por varianza
    • ANOVA
    • Regularización Lasso
    • Eliminación recursiva de variables
  • Selección de variables con Feature-engine
    • Modelos de una sola variable
    • Correlación
  • Más sobre selección de variables
  • Información de sesión
  • Instrucciones para citar


Más sobre ciencia de datos: cienciadedatos.net


Introducción

Un paso esencial en el desarrollo de modelos de machine learning consiste en seleccionar las variables más predictivas del conjunto de datos. Pero, ¿cómo hacerlo? Eso es lo que te voy a contar en este artículo.

Existen varios métodos de selección de variables. En machine learning, estos métodos se clasifican tradicionalmente en 3 grupos:

  • Métodos de filtro (del inglés, filter methods)

  • Métodos integrados (del inglés, embedded methods)

  • Métodos de envoltura (del inglés, wrapper methods)

Todos los métodos de selección de variables tienen sus ventajas y limitaciones. Por ejemplo, los métodos de filtro son óptimos para sets de datos gigantes, pero no tienen en cuenta la interacción entre variables o las características del modelo de machine learning. Otros métodos, como los de envoltura, tienen un costo computacional extremadamente alto, y por lo tanto, solo son aplicables a conjuntos de datos relativamente pequeños. Y hay métodos, claro, que se encuentran en un punto intermedio.

Además de existir diferentes métodos, también hay diferentes implementaciones de estos algoritmos en librerías de código abierto de Python.

Cubrir todos los métodos, o todas las implementaciones, en un artículo es una misión imposible. Para esto, escribí el libro Feature Selection in Machine Learning (por ahora solo disponible en inglés). En este artículo, en cambio, voy a presentarte los mecanismos comunes de los diferentes métodos de selección. Luego voy a contarte en mas detalle los métodos mas utilizados de cada grupo. Para terminar, te voy a mostrar como se usan las librerias de Python para selección de variables, destacando qué métodos de selección están disponibles en cada una.

¡Empecemos!

Métodos de selección de variables

Cuando seleccionamos variables, lo que hacemos es elegir un subconjunto de variables del conjunto de datos inicial, y vamos a utilizar este subconjunto para entrenar los algoritmos de machine learning. Al reducir el número de variables, podemos mejorar el rendimiento de los modelos, por ejemplo, evitando el sobreajuste, reducir el tiempo de entrenamiento y de predicción, y crear modelos más interpretables.

Tradicionalmente, los métodos de selección se han agrupado en tres categorías principales: métodos de filtro, métodos de envoltura (wrapper) y métodos integrados (embedded).

Grupos de metodos de seleccion de variables. Imagen tomada del libro "Feature Selection in Machine Learning"

Así que a continuación, te cuento un poco más de qué se trata cada grupo.

Métodos de filtro

Los métodos de filtro eligen variables basándose exclusivamente en sus propiedades, e ignorando su interacción con el modelo de machine learning y con otras variables. Estos métodos primero le asignan un ranking a cada variable, y luego eligen las mejores ranqueadas.

Para asignar un ranking a cada variable, se pueden usar diferentes procedimientos estadísticos, como el test de chi-cuadrado, ANOVA, correlación o información mutua. Y también se pueden utilizar procedimientos más simples, como evaluar la variabilidad o cardinalidad de la variable.

Luego del ranking, se procede a elegir las variables mejor clasificadas. Para esto, se pueden elegir arbitrariamente las mejores X variables, donde X es un numero arbitrario, o las variables en el percentilo superior.

Si el ranking consiste en un valor de probabilidad, por ejemplo, aquel retornado por los tests estadísticos que mencioné previamente, entonces también podemos usar un "alfa" estadístico, que es un valor de probabilidad, típicamente 0,05, y seleccionar aquellas variables cuyo ranking es menor que dicho alfa.

Métodos de envoltura (wrapper)

Los métodos de envoltura "envuelven" al modelo predictivo en un algoritmo de búsqueda. ¿Qué significa esto? Que utilizan al modelo predictivo para asignar un valor o un ranking a subconjuntos de variables. Y luego, eligen el subconjunto que mejor rendimiento genera.

Los métodos de envoltura funcionan así: primero generan múltiples subconjuntos de variables. Luego entrenan el modelo de machine learning utilizando cada uno de estos subconjuntos y evalúan su rendimiento. Luego eligen el subconjunto que produjo el mejor modelo. ¡Fácil!

Los diferentes métodos en este grupo se diferencian entonces en cómo forman estos diferentes subconjuntos de datos.

El algoritmo de forward search o búsqueda progresiva genera subconjuntos agregando de a una variable en cada instancia. El algoritmo de backward search o eliminación progresiva elimina de a una variable a la vez. Y el algoritmo de búsqueda exhaustiva forma todos los subconjuntos de datos posibles dado un set de datos inicial.

Métodos integrados (embedded)

Los métodos integrados "integran" el procedimiento de selección en el entrenamiento del modelo predictivo. Lasso y la importancia de variables derivada de árboles de decisión son ejemplos clásicos de métodos integrados.

Lasso asigna un valor a los coeficientes de regresión de los modelos lineales, y si este valor es 0, entonces podemos eliminar dichas variables. Asimismo, podemos utilizar la importancia derivada de árboles de decisión para ranquear y luego elegir las variables más predictivas.

Librerías para selección de variables

Existen 3 librerías de Python con módulos para selección de variables:

  • Scikit-learn
  • MLXtend
  • Feature-engine

Scikit-learn es probablemente la mas usada, pero Feature-engine es la mas completa.

🔹 Scikit-learn incluye algoritmos para:

  • Métodos de filtro
  • Métodos de envoltura (wrapper)
  • Métodos integrados (embedded)
  • Eliminación recursiva de variables (Recursive Feature Elimination)

🔹 MLXtend ofrece algoritmos para implementar:

  • Búsqueda progresiva (forward selection)
  • Eliminación progresiva (backward selection)
  • Búsqueda exhaustiva (exhaustive search)

🔹 Feature-engine proporciona métodos alternativos basados en:

  • Métodos de filtro basados en cardinalidad
  • Correlación y duplicación
  • Rendimiento de modelos de machine learning
  • Permutación de variables (feature shuffling)
  • Métodos estadísticos como la ganancia de información o el PSI.

En la siguiente tabla te muestro una comparación de los algoritmos que soportan las diferentes librerías:

Métodos de selección de variables soportados por Scikit-learn, MLXtend y Feature-engine. Imagen tomada del blog de Train in Data.

A continuación, vamos a implementar varias técnicas de selección de variables con Scikit-learn y Feature-engine.

Selección de variables con Scikit-learn

Scikit-learn tiene algoritmos para métodos de filtro, envoltura e integrados, e incluye también la eliminación recursiva de variables.

Entre los métodos de filtro, podemos seleccionar características basándonos en la varianza de la variable o utilizando ANOVA, como muestro a continuación.

Selección por varianza

Con Scikit-learn, podemos eliminar variables irrelevantes analizando su variabilidad. Las variables cuya desviación estándar es cero son constantes y, por lo tanto, podemos eliminarlas.

Para esta demo, voy a crear un dataset con 10 variables, 3 de las cuales son constantes, y luego las voy a eliminar usando Scikit-learn:

## Librerias y funciones.
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.feature_selection import VarianceThreshold


# Set de datos con 10 variables, 3 de las cuales son constantes.
X, y = make_classification(
    n_samples=1000,
    n_features=10,
    n_classes=2,
    random_state=10,
)
X = pd.DataFrame(X)
X[[0, 5, 9]] = 1

# Eliminar variables constantes
sel = VarianceThreshold(threshold=0)
X_t = sel.fit_transform(X)

En el código anterior, primero configuramos el transformador para eliminar variables constantes y, a continuación, aplicamos el método fit, seguido de transform. El VarianceThreshold encontró las variables constantes utilizando fit(). Con transform(), las eliminó de los datos. Entonces X_t contiene variables cuya variabilidad es mayor que 0.

ANOVA

ANOVA es un test estadístico adecuado para seleccionar variables continuas cuando la variable objetivo es categórica. Vamos a explorar cómo seleccionar variables utilizando ANOVA y Scikit-learn. Utilizaremos el conjunto de datos de cáncer de mama.

## Librerias y funciones.
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.model_selection import train_test_split

# Cargar dataset
breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = breast_cancer.target

# Separar dataset en conjunto de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

# Ranquear y seleccionar variables segun ANOVA
sel = SelectKBest(score_func = f_classif, k=10).fit(X_train, y_train)

# Eliminar variables no seleccionadas
X_train_t = sel.transform(X_train)
X_test_t = sel.transform(X_test)

Con SelectKBest indicamos el número de variables que queremos seleccionar. Generalmente es un valor arbitrario, pero podemos optimizarlo con validación cruzada. f_classif es la función de scikit-learn que implementa ANOVA.

Regularización Lasso

Lasso puede reducir algunos de los coeficientes de un modelo lineal a 0. Esto significa que estas variables no son predictivas y podemos eliminarlas. Aquí, te muestro cómo seleccionar variables utilizando Lasso en un conjunto de datos de regresión.

## Librerias y funciones.
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer, fetch_california_housing
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import Lasso, LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

A continuación importaremos el conjunto de datos de cáncer de mama de Scikit-learn con el objetivo de predecir si un tumor es benigno o maligno. Se trata de un conjunto de datos de clasificación. Luego, dividimos los datos en un conjunto de entrenamiento y otro de prueba:

# Cargar dataset
breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = breast_cancer.target

# Separar dataset en conjunto de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

Vamos a configurar el escalador estándar de Scikit-learn:

scaler = StandardScaler()
scaler.fit(X_train)
StandardScaler()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.

A continuación, seleccionaremos las variables utilizando la regresión logística con la regularización Lasso:

selector = SelectFromModel(
    LogisticRegression(C=0.5, penalty='l1', solver='liblinear', random_state=10))

selector.fit(scaler.transform(X_train), y_train)
SelectFromModel(estimator=LogisticRegression(C=0.5, penalty='l1',
                                             random_state=10,
                                             solver='liblinear'))
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.

Ejecutando selector.get_support() obtenemos un vector booleano con True para las variables que tienen coeficientes distintos de cero:

selector.get_support()
array([False,  True, False, False, False, False, False,  True,  True,
       False,  True, False, False, False, False,  True, False, False,
       False,  True,  True,  True,  True,  True,  True, False,  True,
        True,  True, False])

Podemos identificar así los nombres de las variables que se eliminarán:

removed_feats = X_train.columns[(selector.estimator_.coef_ == 0).ravel().tolist()]

removed_feats 
Index(['mean radius', 'mean perimeter', 'mean area', 'mean smoothness',
       'mean compactness', 'mean concavity', 'mean fractal dimension',
       'texture error', 'perimeter error', 'area error', 'smoothness error',
       'concavity error', 'concave points error', 'symmetry error',
       'worst compactness', 'worst fractal dimension'],
      dtype='object')

Podemos eliminar las variables de los conjuntos de entrenamiento y prueba de la siguiente manera:

X_train_selected = selector.transform(scaler.transform(X_train))
X_test_selected = selector.transform(scaler.transform(X_test))

Cambia el valor de la penalización (C) para ver si cambia el resultado. El mejor valor de C, y por tanto, el mejor subconjunto de características, puede determinarse con validación cruzada.

Eliminación recursiva de variables

La eliminación recursiva de variables es un proceso secuencial en el que se elimina una variable en cada iteración, y la importancia de las variables se vuelve a evaluar después de cada eliminación.

En Scikit-learn, podemos implementar la eliminación recursiva de características con el RFE o RFECV.

Vamos a seleccionar variables recursivamente utilizando la importancia derivada del modelo de random forest. Utilizaremos el conjunto de datos de cáncer de mama, y separaremos los datos en un conjunto de datos de entrenamiento y un conjunto de datos de prueba.

## Librerias y funciones.
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFE
from sklearn.model_selection import train_test_split

# Cargar dataset
breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = breast_cancer.target

# Separar dataset en conjunto de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

# Especificar el modelo de random forest
clf = RandomForestClassifier(n_estimators=10, random_state=10)

# Eliminacion recursiva
sel_ = RFE(
    clf,
    n_features_to_select=8,
    step=2,
)
sel_.fit(X_train, y_train)

# Eliminar variables de los conjuntos de datos
X_train_selected = sel_.transform(X_train)
X_test_selected = sel_.transform(X_test)

Aquí, RFE entrena un random forest con todas las variables, y luego remueve la variable menos importante. A continuación, entrena otro random forest con las variables restantes y remueve la más importante, y así sucesivamente, hasta obtener un set de datos de 8 variables en nuestro caso.

Selección de variables con Feature-engine

Feature-engine contiene algoritmos para seleccionar variables basadas en la eliminación o adición recursiva, permutación de variables, índice de estabilidad de población, valor medio de la variable respuesta, cardinalidad y más. Consulta la documentación de Feature-engine para obtener más información.

En este artículo te muestro cómo seleccionar variables basándonos en modelos de una sola variable y en correlación.

Modelos de una sola variable

Una buena manera de determinar si una variable es predictiva consiste en entrenar un modelo de machine learning usando solamente esa variable. Luego, usamos el rendimiento del modelo para ranquear las variables y seleccionar las variables mejor ranqueadas.

## Librerias y funciones.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from feature_engine.selection import SelectBySingleFeaturePerformance

# Cargar dataset
breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = breast_cancer.target

# Separar dataset en conjunto de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

# Seleccionar variables entrenando random forests de una variable
sel = SelectBySingleFeaturePerformance(
    estimator=RandomForestClassifier(random_state=10),
    scoring='roc_auc',
    cv=3,
    threshold=None,
)

# Seleccionar y eliminar variables en set de entrenamiento
X_train_t = sel.fit_transform(X_train, y_train)

# Eliminar variables en set de prueba
X_test_t = sel.transform(X_test)

En el código anterior, entrenamos random forests con cada una de las variables en el set de datos, y luego obtuvimos el ROC-AUC de cada modelo. Con este ROC-AUC ranqueamos las variables y elegimos aquellas variables que resultaron en modelos con ROC-AUC mayor que 0.5.

Hagamos un gráfico de barras para visualizar la importancia de las variables asignada por los modelos:

pd.Series(sel.feature_performance_).sort_values(
    ascending=False).plot.bar(figsize=(8, 4))
plt.ylabel('roc-auc')
plt.title('ROC-AUC de modelos de una variable');

Correlación

Al entrenar modelos lineales como la regresión lineal o logística, la multicolinealidad puede afectar al rendimiento del modelo. Por lo tanto, puede ser útil eliminar las variables correlacionadas antes de entrenar dichos modelos.

Feature-engine tiene algoritmos que seleccionan variables basándose en su correlación. El SmartCorrelationSelector, en particular, encuentra grupos de variables correlacionadas y retiene aquella con menos datos faltantes, mayor cardinalidad o variabilidad, mayor correlacion con el target, o mayor importancia segun el modelo indicado.

Podemos encontrar variables correlacionadas utilizando el método pandas.corr.

## Librerias y funciones.
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.tree import DecisionTreeClassifier
from feature_engine.selection import SmartCorrelatedSelection

# Crear dataframe con variables correlacionadas
def make_data():
    X, y = make_classification(n_samples=1000,
                               n_features=12,
                               n_redundant=4,
                               n_clusters_per_class=1,
                               weights=[0.50],
                               class_sep=2,
                               random_state=1)

    # transform arrays into pandas df and series
    colnames = ['var_'+str(i) for i in range(12)]
    X = pd.DataFrame(X, columns=colnames)
    return X, y

X, y = make_data()

# Identificar grupos de variables correlacionadas, y de cada grupo
# seleccionar la que tiene mayor importancia segun random forests
tr = SmartCorrelatedSelection(
    variables=None,
    method="pearson",
    threshold=0.8,
    missing_values="raise",
    selection_method="model_performance",
    estimator=DecisionTreeClassifier(random_state=1),
    scoring='roc_auc',
    cv=3,
)

# Encontrar variables correlacionadas y eliminarlas del set de datos
Xt = tr.fit_transform(X, y)
Xt
var_0 var_1 var_2 var_3 var_5 var_7 var_10 var_11
0 1.471061 -2.376400 -0.247208 1.210290 0.091527 -2.230170 2.070526 -1.989335
1 1.819196 1.969326 -0.126894 0.034598 -0.186802 -1.447490 1.184820 -1.309524
2 1.625024 1.499174 0.334123 -2.233844 -0.313881 -2.240741 -0.066448 -0.852703
3 1.939212 0.075341 1.627132 0.943132 -0.468041 -3.534861 0.713558 0.484649
4 1.579307 0.372213 0.338141 0.951526 0.729005 -2.053965 0.398790 -0.186530
... ... ... ... ... ... ... ... ...
995 1.803380 -1.363868 -0.048464 -1.241394 -0.136638 2.354715 -0.144619 0.555170
996 2.073749 0.263967 1.269868 2.260748 -0.959332 2.312738 -0.182916 1.193456
997 2.442529 0.528868 0.230641 -0.854581 -1.066801 2.573196 0.021500 -2.710394
998 1.451356 -0.871014 -0.117844 -1.865016 -0.276940 -1.587082 0.340473 0.149377
999 1.721321 -0.534328 -0.331306 -1.288487 0.364444 -2.451474 -0.416476 -0.111816

1000 rows × 8 columns

Más sobre selección de variables

Si quieres aprender más sobre la selección de variables y cómo llevarla a cabo en Python, consulta mi curso y libro:

Puedes consultar también:

Información de sesión

import session_info
session_info.show(html=False)
-----
feature_engine      1.8.3
matplotlib          3.10.1
numpy               2.1.3
pandas              2.2.3
session_info        v1.0.1
sklearn             1.6.1
-----
IPython             9.1.0
jupyter_client      8.6.3
jupyter_core        5.7.2
notebook            6.5.7
-----
Python 3.12.9 | packaged by Anaconda, Inc. | (main, Feb  6 2025, 18:56:27) [GCC 11.2.0]
Linux-6.11.0-29-generic-x86_64-with-glibc2.39
-----
Session information updated at 2025-07-21 10:00

Instrucciones para citar

¿Cómo citar este documento?

Si utilizas este documento o alguna parte de él, te agradecemos que lo cites. ¡Muchas gracias!

Selección de Variables en Machine Learning con Python por Soledad Galli, disponible bajo una licencia Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 DEED) en https://www.cienciadedatos.net/documentos/py67-seleccion-variables-machine-learning-python.html

¿Te ha gustado el artículo? Tu ayuda es importante

Tu contribución me ayudará a seguir generando contenido divulgativo gratuito. ¡Muchísimas gracias! 😊

Become a GitHub Sponsor

Creative Commons Licence

Este documento creado por Soledad Galli tiene licencia Attribution-NonCommercial-ShareAlike 4.0 International.

Se permite:

  • Compartir: copiar y redistribuir el material en cualquier medio o formato.

  • Adaptar: remezclar, transformar y crear a partir del material.

Bajo los siguientes términos:

  • Atribución: Debes otorgar el crédito adecuado, proporcionar un enlace a la licencia e indicar si se realizaron cambios. Puedes hacerlo de cualquier manera razonable, pero no de una forma que sugiera que el licenciante te respalda o respalda tu uso.

  • No-Comercial: No puedes utilizar el material para fines comerciales.

  • Compartir-Igual: Si remezclas, transformas o creas a partir del material, debes distribuir tus contribuciones bajo la misma licencia que el original.