Por diversas razones, muchos conjuntos de datos del mundo real contienen valores perdidos, a menudo codificados como espacios en blanco, NaN u otros marcadores de posición. Sin embargo, estos conjuntos de datos son incompatibles con los estimadores de scikit-learn que asumen que todos los valores en una matriz son numéricos y que todos tienen y tienen significado. Una estrategia básica para usar conjuntos de datos incompletos es descartar filas y / o columnas completas que contienen valores faltantes. Sin embargo, esto tiene el precio de perder datos que pueden ser valiosos (aunque estén incompletos). Una mejor estrategia es imputar los valores perdidos, es decir, inferirlos de la parte conocida de los datos. Ver el Glosario de términos comunes y elementos de API entrada en imputación.

6.4.1. Imputación univariante frente a multivariante

Un tipo de algoritmo de imputación es univariado, que imputa valores en la dimensión de característica i-ésima utilizando solo valores no perdidos en esa dimensión de característica (p. Ej. impute.SimpleImputer). Por el contrario, los algoritmos de imputación multivariante utilizan todo el conjunto de dimensiones de características disponibles para estimar los valores faltantes (p. Ej. impute.IterativeImputer).

6.4.2. Imputación de característica univariante

los SimpleImputer La clase proporciona estrategias básicas para imputar valores perdidos. Los valores faltantes se pueden imputar con un valor constante proporcionado o utilizando las estadísticas (media, mediana o más frecuente) de cada columna en la que se encuentran los valores faltantes. Esta clase también permite diferentes codificaciones de valores perdidos.

El siguiente fragmento muestra cómo reemplazar los valores faltantes, codificados como np.nan, utilizando el valor medio de las columnas (eje 0) que contienen los valores faltantes:

>>>import numpy as np
>>>from sklearn.impute import SimpleImputer
>>> imp = SimpleImputer(missing_values=np.nan, strategy='mean')>>> imp.fit([[1,2],[np.nan,3],[7,6]])
SimpleImputer()>>> X =[[np.nan,2],[6, np.nan],[7,6]]>>>print(imp.transform(X))[[4.2.][6.3.666...][7.6.]]

los SimpleImputer La clase también admite matrices dispersas:

>>>import scipy.sparse as sp
>>> X = sp.csc_matrix([[1,2],[0,-1],[8,4]])>>> imp = SimpleImputer(missing_values=-1, strategy='mean')>>> imp.fit(X)
SimpleImputer(missing_values=-1)>>> X_test = sp.csc_matrix([[-1,2],[6,-1],[7,6]])>>>print(imp.transform(X_test).toarray())[[3.2.][6.3.][7.6.]]

Tenga en cuenta que este formato no debe usarse para almacenar implícitamente los valores faltantes en la matriz porque lo densificaría en el momento de la transformación. Los valores faltantes codificados por 0 deben usarse con una entrada densa.

los SimpleImputer La clase también admite datos categóricos representados como valores de cadena o pandas categóricos cuando se usa la 'most_frequent' o 'constant' estrategia:

>>>import pandas as pd
>>> df = pd.DataFrame([["a","x"],...[np.nan,"y"],...["a", np.nan],...["b","y"]], dtype="category")...>>> imp = SimpleImputer(strategy="most_frequent")>>>print(imp.fit_transform(df))[['a''x']['a''y']['a''y']['b''y']]

6.4.3. Imputación de características multivariante

Un enfoque más sofisticado es utilizar el IterativeImputer class, que modela cada característica con valores perdidos en función de otras características, y utiliza esa estimación para la imputación. Lo hace de manera iterativa por turnos: en cada paso, una columna de características se designa como salida. y y las otras columnas de características se tratan como entradas X. Un regresor encaja (X,
y)
por conocido y. Luego, el regresor se usa para predecir los valores perdidos de y. Esto se hace para cada característica de forma iterativa y luego se repite para max_iter rondas de imputación. Se devuelven los resultados de la ronda de imputación final.

Nota

Este estimador sigue experimental por ahora: los parámetros predeterminados o los detalles de comportamiento pueden cambiar sin ningún ciclo de depreciación. Resolver los siguientes problemas ayudaría a estabilizar IterativeImputer: criterios de convergencia (# 14338), estimadores predeterminados (N.º 13286), y el uso de estado aleatorio (# 15611). Para usarlo, debe importar explícitamente enable_iterative_imputer.

>>>import numpy as np
>>>from sklearn.experimental import enable_iterative_imputer
>>>from sklearn.impute import IterativeImputer
>>> imp = IterativeImputer(max_iter=10, random_state=0)>>> imp.fit([[1,2],[3,6],[4,8],[np.nan,3],[7, np.nan]])
IterativeImputer(random_state=0)>>> X_test =[[np.nan,2],[6, np.nan],[np.nan,6]]>>># the model learns that the second feature is double the first>>>print(np.round(imp.transform(X_test)))[[1.2.][6.12.][3.6.]]

Ambos SimpleImputer y IterativeImputer se puede utilizar en Pipeline como una forma de construir un estimador compuesto que admita la imputación. Ver Imputar valores perdidos antes de construir un estimador.

6.4.3.1. Flexibilidad de IterativeImputer

Hay muchos paquetes de imputación bien establecidos en el ecosistema de ciencia de datos de R: Amelia, mi, mice, missForest, etc. missForest es popular y resulta ser una instancia particular de diferentes algoritmos de imputación secuencial que pueden implementarse con IterativeImputer pasando diferentes regresores que se utilizarán para predecir valores de características faltantes. En el caso de missForest, este regresor es un bosque aleatorio. Ver Imputación de valores perdidos con variantes de IterativeImputer.

6.4.3.2. Imputación múltiple o única

En la comunidad estadística, es una práctica común realizar múltiples imputaciones, generando, por ejemplo, m imputaciones separadas para una única matriz de características. Cada uno de estos m A continuación, las imputaciones se someten a la canalización de análisis posterior (por ejemplo, ingeniería de características, agrupamiento, regresión, clasificación). los m Los resultados del análisis final (por ejemplo, errores de validación retenidos) permiten al científico de datos comprender cómo los resultados analíticos pueden diferir como consecuencia de la incertidumbre inherente causada por los valores faltantes. La práctica anterior se llama imputación múltiple.

Nuestra implementación de IterativeImputer se inspiró en el paquete R MICE (Imputación multivariante por ecuaciones encadenadas) 1, pero se diferencia de él al devolver una sola imputación en lugar de múltiples imputaciones. Sin embargo, IterativeImputer también se puede utilizar para múltiples imputaciones aplicándolo repetidamente al mismo conjunto de datos con diferentes semillas aleatorias cuando sample_posterior=True. Consulte 2, capítulo 4 para obtener más información sobre las imputaciones múltiples frente a las únicas.

Sigue siendo un problema abierto en cuanto a la utilidad de la imputación simple frente a la imputación múltiple en el contexto de la predicción y la clasificación cuando el usuario no está interesado en medir la incertidumbre debido a los valores perdidos.

Tenga en cuenta que una llamada al transform método de IterativeImputer no se permite cambiar el número de muestras. Por lo tanto, no se pueden lograr imputaciones múltiples con una sola llamada a transform.

6.4.4. Referencias

1

Stef van Buuren, Karin Groothuis-Oudshoorn (2011). “Ratones: imputación multivariante por ecuaciones encadenadas en R”. Revista de software estadístico 45: 1-67.

2

Roderick JA Little y Donald B. Rubin (1986). “Análisis estadístico con datos perdidos”. John Wiley & Sons, Inc., Nueva York, NY, EE. UU.

6.4.5. Imputación de vecinos más cercanos

los KNNImputer La clase proporciona imputación para completar los valores perdidos utilizando el enfoque k-Vecinos más cercanos. De forma predeterminada, una métrica de distancia euclidiana que admite valores perdidos, nan_euclidean_distances, se utiliza para encontrar los vecinos más cercanos. Cada característica faltante se imputa utilizando valores de n_neighbors vecinos más cercanos que tienen un valor para la característica. Las características de los vecinos se promedian uniformemente o se ponderan por la distancia a cada vecino. Si a una muestra le falta más de una característica, los vecinos de esa muestra pueden ser diferentes según la característica particular que se impute. Cuando el número de vecinos disponibles es menor que n_neighbors y no hay distancias definidas al conjunto de entrenamiento, el promedio del conjunto de entrenamiento para esa característica se usa durante la imputación. Si hay al menos un vecino con una distancia definida, el promedio ponderado o no ponderado de los vecinos restantes se utilizará durante la imputación. Si una función siempre falta en el entrenamiento, se elimina durante transform. Para obtener más información sobre la metodología, consulte la ref. [OL2001].

El siguiente fragmento muestra cómo reemplazar los valores faltantes, codificados como np.nan, utilizando el valor medio de la característica de los dos vecinos más cercanos de las muestras con valores perdidos:

>>>import numpy as np
>>>from sklearn.impute import KNNImputer
>>> nan = np.nan
>>> X =[[1,2, nan],[3,4,3],[nan,6,5],[8,8,7]]>>> imputer = KNNImputer(n_neighbors=2, weights="uniform")>>> imputer.fit_transform(X)
array([[1.,2.,4.],[3.,4.,3.],[5.5,6.,5.],[8.,8.,7.]])
OL2001

Olga Troyanskaya, Michael Cantor, Gavin Sherlock, Pat Brown, Trevor Hastie, Robert Tibshirani, David Botstein y Russ B. Altman, Métodos de estimación de valores perdidos para microarrays de ADN, BIOINFORMATICS Vol. 17 no. 6, 2001 Páginas 520-525.

6.4.6. Marcando valores imputados

los MissingIndicator El transformador es útil para transformar un conjunto de datos en la matriz binaria correspondiente que indica la presencia de valores faltantes en el conjunto de datos. Esta transformación es útil junto con la imputación. Cuando se utiliza la imputación, preservar la información sobre los valores que faltaban puede ser informativo. Tenga en cuenta que tanto el SimpleImputer y IterativeImputer tener el parámetro booleano add_indicator (False por defecto) que cuando se establece en True proporciona una forma conveniente de apilar la salida del MissingIndicator transformador con la salida del imputador.

NaN se utiliza normalmente como marcador de posición para los valores perdidos. Sin embargo, obliga a que el tipo de datos sea flotante. El parámetro missing_values permite especificar otro marcador de posición como un entero. En el siguiente ejemplo, usaremos -1 como valores perdidos:

>>>from sklearn.impute import MissingIndicator
>>> X = np.array([[-1,-1,1,3],...[4,-1,0,-1],...[8,-1,1,0]])>>> indicator = MissingIndicator(missing_values=-1)>>> mask_missing_values_only = indicator.fit_transform(X)>>> mask_missing_values_only
array([[True,True,False],[False,True,True],[False,True,False]])

los features El parámetro se utiliza para elegir las características para las que se construye la máscara. Por defecto, es 'missing-only' que devuelve la máscara de imputador de las entidades que contienen valores perdidos en fit tiempo:

>>> indicator.features_
array([0,1,3])

los features El parámetro se puede configurar en 'all' para devolver todas las características, ya sea que contengan valores perdidos o no:

>>> indicator = MissingIndicator(missing_values=-1, features="all")>>> mask_all = indicator.fit_transform(X)>>> mask_all
array([[True,True,False,False],[False,True,False,True],[False,True,False,False]])>>> indicator.features_
array([0,1,2,3])

Al usar el MissingIndicator en un Pipeline, asegúrese de utilizar el FeatureUnion o ColumnTransformer para agregar las características del indicador a las características regulares. Primero obtenemos el iris conjunto de datos y agregue algunos valores faltantes.

>>>from sklearn.datasets import load_iris
>>>from sklearn.impute import SimpleImputer, MissingIndicator
>>>from sklearn.model_selection import train_test_split
>>>from sklearn.pipeline import FeatureUnion, make_pipeline
>>>from sklearn.tree import DecisionTreeClassifier
>>> X, y = load_iris(return_X_y=True)>>> mask = np.random.randint(0,2, size=X.shape).astype(bool)>>> X[mask]= np.nan
>>> X_train, X_test, y_train, _ = train_test_split(X, y, test_size=100,...                                                random_state=0)

Ahora creamos un FeatureUnion. Todas las funciones se imputarán utilizando SimpleImputer, para permitir que los clasificadores trabajen con estos datos. Además, agrega las variables indicadoras de MissingIndicator.

>>> transformer = FeatureUnion(...     transformer_list=[...('features', SimpleImputer(strategy='mean')),...('indicators', MissingIndicator())])>>> transformer = transformer.fit(X_train, y_train)>>> results = transformer.transform(X_test)>>> results.shape
(100,8)

Por supuesto, no podemos usar el transformador para hacer predicciones. Deberíamos envolver esto en un Pipeline con un clasificador (p. ej., un DecisionTreeClassifier) para poder hacer predicciones.

>>> clf = make_pipeline(transformer, DecisionTreeClassifier())>>> clf = clf.fit(X_train, y_train)>>> results = clf.predict(X_test)>>> results.shape
(100,)