1.13. Selección de características¶
Las clases del módulo sklearn.feature_selection
pueden utilizarse para la selección de características / reducción de la dimensionalidad en conjuntos de muestras, ya sea para mejorar las puntuaciones de exactitud de los estimadores o para aumentar su rendimiento en conjuntos de datos de muy alta dimensión.
1.13.1. Remover características con varianza baja¶
VarianceThreshold
es una aproximación simple a la selección de características. Elimina todas las características cuya varianza no alcanza un determinado umbral. Por defecto, elimina todas las características de varianza cero, es decir, las características que tienen el mismo valor en todas las muestras.
Por ejemplo, supongamos que tenemos un conjunto de datos con características booleanas y queremos eliminar todas las características que sean uno o cero (activadas o desactivadas) en más del 80% de las muestras. Las características booleanas son variables aleatorias de Bernoulli, y la varianza de dichas variables viene dada por
de manera que podamos seleccionar utilizando el umbral .8 * (1 - .8)
:
>>> from sklearn.feature_selection import VarianceThreshold
>>> X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
>>> sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
>>> sel.fit_transform(X)
array([[0, 1],
[1, 0],
[0, 0],
[1, 1],
[1, 0],
[1, 1]])
Como se esperaba, VarianceThreshold
ha eliminado la primera columna, que tiene una probabilidad de \(p = 5/6 > .8\) de contener un cero.
1.13.2. Selección de características univariantes¶
La selección de características univariantes funciona mediante la selección de las mejores características basadas en pruebas estadísticas univariantes. Puede verse como un paso de preprocesamiento de un estimador. Scikit-learn expone las rutinas de selección de características como objetos que implementan el método transform
:
SelectKBest
elimina todas las características excepto las de mayor puntuación de :math:`k
SelectPercentile
elimina todas las características excepto las del porcentaje de puntuación más alto especificado por el usuarioaplicando pruebas estadísticas univariantes comunes para cada característica: tasa de falsos positivos
SelectFpr
, tasa de falsos descubrimientosSelectFdr
, o error por familiaSelectFwe
.
GenericUnivariateSelect
permite realizar la selección de características univariantes con una estrategia configurable. Permite seleccionar la mejor estrategia de selección univariante con el estimador de búsqueda de hiperparámetros.
Por ejemplo, podemos realizar una prueba \(\chi^2\) a las muestras para recuperar sólo las dos mejores características de la siguiente manera:
>>> from sklearn.datasets import load_iris
>>> from sklearn.feature_selection import SelectKBest
>>> from sklearn.feature_selection import chi2
>>> X, y = load_iris(return_X_y=True)
>>> X.shape
(150, 4)
>>> X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
>>> X_new.shape
(150, 2)
Estos objetos toman como entrada una función de puntuación que devuelve puntuaciones univariantes (univariate scores) y valores p (o sólo puntuaciones para SelectKBest
y SelectPercentile
):
Para regresión:
f_regression
,mutual_info_regression
Para clasificación:
chi2
,f_classif
,mutual_info_classif
Los métodos basados en la prueba F estiman el grado de dependencia lineal entre dos variables aleatorias. Por otro lado, los métodos de información mutua pueden capturar cualquier tipo de dependencia estadística, pero al no ser paramétricos, requieren más muestras para una estimación precisa.
Selección de características con datos dispersos
Si utiliza datos dispersos (es decir, datos representados como matrices dispersas), chi2
, mutual_info_regression
, mutual_info_classif
se ocuparán de los datos sin hacerlos densos.
Advertencia
Ten cuidado de no utilizar una función de puntuación de regresión con un problema de clasificación, ya que obtendrás resultados inservibles.
1.13.3. Eliminación recursiva de características¶
Dado un estimador externo que asigna pesos a las características (por ejemplo, los coeficientes de un modelo lineal), el objetivo de la eliminación recursiva de características (RFE
) es seleccionar características considerando recursivamente conjuntos cada vez más pequeños de características. En primer lugar, el estimador se entrena con el conjunto inicial de características y la importancia de cada una de ellas se obtiene a través de algún atributo específico (como coef_
, feature_importances_
) u otro invocable. A continuación, las características menos importantes se eliminan del conjunto actual de características. Este procedimiento se repite recursivamente en el conjunto reducido (pruned) hasta que se alcanza el número deseado de características a seleccionar.
RFECV
realiza la RFE en un bucle de validación cruzada para encontrar el número óptimo de características.
Ejemplos:
Eliminación recursiva de características: Un ejemplo de eliminación recursiva de características que muestra la relevancia de los píxeles en una tarea de clasificación de dígitos.
Eliminación recursiva de características con validación cruzada: Un ejemplo de eliminación recursiva de características con ajuste automático del número de características seleccionadas con validación cruzada.
1.13.4. Selección de características mediante SelectFromModel¶
SelectFromModel
es un metatransformador que puede utilizarse junto con cualquier estimador de la importancia de cada característica a través de un atributo específico (tales como coef_
, feature_importances_
) o invocable después del ajuste. Las características se consideran poco importantes y se eliminan si la importancia correspondiente de los valores de las características está por debajo del parámetro threshold
proporcionado. Aparte de especificar el umbral numéricamente, hay heurísticas integradas que permiten encontrar un umbral utilizando un argumento de cadena. Las heurísticas disponibles son «mean», «median» y múltiplos flotantes de éstas como «0.1*mean». En combinación con el criterio threshold
, se puede utilizar el parámetro max_features
para establecer un límite en el número de características a seleccionar.
Para ver ejemplos de cómo se debe utilizar, consulta las secciones que siguen.
1.13.4.1. Selección de características basada en L1¶
Linear models penalizados con la norma L1 tienen soluciones dispersas: muchos de sus coeficientes estimados son cero. Cuando el objetivo es reducir la dimensionalidad de los datos para utilizarlos con otro clasificador, pueden utilizarse junto con SelectFromModel
para seleccionar los coeficientes no nulos. En particular, los estimadores dispersos útiles para este propósito son los Lasso
para la regresión, y de LogisticRegression
y LinearSVC
para la clasificación:
>>> from sklearn.svm import LinearSVC
>>> from sklearn.datasets import load_iris
>>> from sklearn.feature_selection import SelectFromModel
>>> X, y = load_iris(return_X_y=True)
>>> X.shape
(150, 4)
>>> lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
>>> model = SelectFromModel(lsvc, prefit=True)
>>> X_new = model.transform(X)
>>> X_new.shape
(150, 3)
Con las SVM y la regresión logística, el parámetro C controla la dispersión: cuanto menor sea C, menos características serán seleccionadas. Con Lasso, cuanto mayor sea el parámetro alfa, menos características se seleccionarán.
Ejemplos:
Clasificación de documentos de texto utilizando características dispersas: Comparación de diferentes algoritmos para la clasificación de documentos, incluida la selección de características basada en L1.
Recuperación del L1 y muestreo con compresión (compressive sensing)
Para una buena elección de alfa, el Lasso puede recuperar completamente el conjunto exacto de variables no nulas utilizando sólo unas pocas observaciones, siempre que se cumplan ciertas condiciones específicas. En particular, el número de muestras debe ser «suficientemente grande», o los modelos L1 se comportarán de forma aleatoria, en donde » suficientemente grande» depende del número de coeficientes no nulos, del logaritmo del número de características, de la cantidad de ruido, del menor valor absoluto de los coeficientes no nulos y de la estructura de la matriz de diseño X. Además, la matriz de diseño debe mostrar ciertas propiedades específicas, como no estar demasiado correlacionada.
No hay una regla general para seleccionar un parámetro alfa para la recuperación de coeficientes distintos de cero. Puede establecerse mediante validación cruzada (LassoCV
o LassoLarsCV
), aunque esto puede conducir a modelos insuficientemente penalizados: la inclusión de un pequeño número de variables no relevantes no es perjudicial para la puntuación de la predicción. BIC (LassoLarsIC
) tiende, por el contrario, a establecer valores altos de alfa.
Referencia Richard G. Baraniuk «Compressive Sensing», IEEE Signal Processing Magazine [120] July 2007 http://users.isr.ist.utl.pt/~aguiar/CS_notes.pdf
1.13.4.2. Selección de características basada en árboles¶
Los estimadores basados en árboles (ver el módulo sklearn.tree
y el bosque de árboles en el módulo sklearn.ensemble
) pueden utilizarse para calcular la importancia de características basadas en impurezas, que a su vez pueden utilizarse para descartar características irrelevantes (cuando se combinan con el metatransformador SelectFromModel
):
>>> from sklearn.ensemble import ExtraTreesClassifier
>>> from sklearn.datasets import load_iris
>>> from sklearn.feature_selection import SelectFromModel
>>> X, y = load_iris(return_X_y=True)
>>> X.shape
(150, 4)
>>> clf = ExtraTreesClassifier(n_estimators=50)
>>> clf = clf.fit(X, y)
>>> clf.feature_importances_
array([ 0.04..., 0.05..., 0.4..., 0.4...])
>>> model = SelectFromModel(clf, prefit=True)
>>> X_new = model.transform(X)
>>> X_new.shape
(150, 2)
Ejemplos:
Importancia de las características con los bosques de árboles: ejemplo sobre datos sintéticos que muestran la recuperación de las características efectivamente significativas.
Importancia de los píxeles con un bosque paralelo de árboles: ejemplo de datos de reconocimiento facial.
1.13.5. Selección secuencial de características¶
La selección secuencial de características [sfs] (SFS) está disponible en el transformador SequentialFeatureSelector
. SFS puede funcionar hacia adelante (forward) o hacia atrás (backward):
Forward-SFS es un procedimiento ambicioso (greedy) que encuentra de forma iterativa la mejor característica nueva para añadir al conjunto de características seleccionadas. Concretamente, empezamos con cero características y encontramos la que maximiza una puntuación validada de forma cruzada cuando se entrena un estimador con esta única característica. Una vez seleccionada esa primera característica, repetimos el procedimiento añadiendo una nueva característica al conjunto de características seleccionadas. El procedimiento se detiene cuando se alcanza el número deseado de características seleccionadas, determinado por el parámetro n_features_to_select
.
Backward-SFS sigue la misma idea, pero funciona en la dirección opuesta: en lugar de empezar sin ninguna característica y añadirla codiciosamente, empezamos con todas las características y eliminamos codiciosamente las características del conjunto. El parámetro direction
controla si se utiliza el SFS hacia adelante o hacia atrás.
En general, la selección hacia adelante (forward) y la selección hacia atrás (backward) no dan resultados equivalentes. Además, una puede ser mucho más rápida que la otra dependiendo del número de características seleccionadas que se soliciten: si tenemos 10 características y queremos que se seleccionen 7, la selección hacia delante necesitaría realizar 7 iteraciones mientras que la selección hacia atrás sólo necesitaría llevar a cabo 3.
SFS difiere de RFE
y SelectFromModel
en que no requiere que el modelo subyacente exponga un atributo coef_
o feature_importances_
. Sin embargo, puede ser más lento, en comparación con los otros enfoques, ya que es necesario evaluar más modelos. Por ejemplo, en la selección hacia atrás, la iteración que va de m
características a m - 1
características utilizando la validación cruzada de k partes requiere el ajuste de m * k
modelos, mientras que RFE
sólo requeriría un único ajuste, y SelectFromModel
siempre hace un único ajuste y no requiere iteraciones.
Referencias:
1.13.6. Selección de rasgos como parte de un pipeline¶
La selección de características se utiliza generalmente como un paso de preprocesamiento antes de realizar el aprendizaje propiamente dicho. La forma recomendada de hacer esto en scikit-learn es utilizar un Pipeline
:
clf = Pipeline([
('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))),
('classification', RandomForestClassifier())
])
clf.fit(X, y)
En este fragmento utilizamos un LinearSVC
junto con SelectFromModel
para evaluar la importancia de las características y seleccionar las más relevantes. A continuación, se entrena un RandomForestClassifier
en la salida transformada, es decir, utilizando sólo las características relevantes. Puedes realizar operaciones similares con los otros métodos de selección de características y también con clasificadores que proporcionan una forma de evaluar la importancia de las características, por supuesto. Puedes consultar los ejemplos de Pipeline
para más detalles.