18 votos

Métodos para solucionar el problema de los datos perdidos en el aprendizaje automático

Prácticamente cualquier base de datos en la que queramos hacer predicciones mediante algoritmos de aprendizaje automático encontrará valores perdidos para algunas de las características.

Hay varios enfoques para abordar este problema, para excluir las líneas que tienen valores perdidos hasta que se llenan con los valores medios de las características.

Me gustaría utilizar para un enfoque algo más robusto, que básicamente ejecutar una regresión (u otro método) donde la variable dependiente (Y) sería cada una de las columnas que tienen valores perdidos, pero sólo con las filas de la tabla que contienen todos los datos , y predecir los valores perdidos con este método, completar la tabla por la tabla y pasar a la siguiente "columna" con valores perdidos y repetir el método hasta que todo se llena.

Pero eso me genera algunas dudas.

¿Por qué cualquier inicio de columna? Creo que la que tiene menos valores perdidos hasta la que tiene más

¿Existe algún umbral de valores perdidos que no merezca la pena intentar completar? (por ejemplo, si esta característica sólo tiene el 10% de los valores rellenados, ¿no sería más interesante excluirla?)

¿Existe algún tipo de implementación en paquetes tradicionales u otros métodos que sean robustos a los fallos?

6 votos

El término de arte que está buscando es "imputación", de la cual la imputación múltiple es una opción popular y moderna. Tenga en cuenta que excluir las observaciones que faltan o sustituir las observaciones que faltan por la media puede sesgar gravemente los datos. Un lugar para empezar es Gelman et al, Análisis bayesiano de datos 3ª edición, "Capítulo 18: Modelos para datos perdidos".

0 votos

Gracias por el dato, buscaré con ese término y miraré el cap18. Borrar líneas puede sesgar mucho el modelo (si las faltas no son aleatorias, lo que es muy probable) y colocar la media puede poner una fuerte "carga inercial" alrededor de la media, dependiendo también de la exogeneidad de las faltas de datos. Mi gran pregunta es cuál es el mejor enfoque para manejar esto y mi sugerencia sería ejecutar pre-regresiones para completar los datos antes de la regresión principal (¿hay algún paquete que haga esto o debería crear uno?)

1 votos

La imputación múltiple moderna estima un modelo para los datos que faltan y los que no faltan, uno al lado del otro. El enfoque bayesiano de los datos que faltan consiste en estimar una distribución sobre los datos que faltan, condicionada por los datos observados y el modelo de falta. El software estadístico en python deja mucho que desear. Para los datos de TSCS, Amelia II en R es una opción sólida. O bien, puede hacer su propio trabajo utilizando stan .

12voto

ThomasKlausch Puntos 968

La técnica que describes se llama imputación por regresiones secuenciales o imputación múltiple por ecuaciones encadenadas. La técnica fue iniciada por Raghunathan (2001) e implementada en un paquete de R que funciona bien, llamado mice (van Buuren, 2012).

Un artículo de Schafer y Graham (2002) explica bien por qué la imputación de la media y la eliminación de la lista (lo que usted llama exclusión de líneas) no suelen ser buenas alternativas a las técnicas mencionadas. Principalmente, la imputación de la media no es condicional y, por tanto, puede sesgar las distribuciones imputadas hacia la media observada. También reducirá la varianza, entre otros impactos indeseables en la distribución imputada. Además, la supresión de la lista sólo funcionará si los datos faltan completamente al azar, como al lanzar una moneda. También aumentará el error de muestreo, ya que el tamaño de la muestra se reduce.

Los autores citados anteriormente suelen recomendar que se empiece por la variable con menos valores perdidos. Además, la técnica suele aplicarse de forma bayesiana (es decir, una extensión de su sugerencia). Las variables se visitan más veces en el procedimiento de imputación, no sólo una vez. En concreto, cada variable se completa con extracciones de su distribución predictiva posterior condicional, empezando por la variable que presenta menos valores perdidos. Una vez que se han completado todas las variables de un conjunto de datos, el algoritmo vuelve a empezar por la primera variable y se reitera hasta la convergencia. Los autores han demostrado que este algoritmo es de Gibbs, por lo que suele converger a la distribución multivariante correcta de las variables.

Por lo general, porque hay algunos supuestos no comprobables, en particular los datos no observados al azar (es decir, que el hecho de que los datos se observen o no depende sólo de los datos observados, y no de los valores no observados). Además, los procedimientos pueden ser parcialmente incompatibles, por lo que se les ha llamado PIGS (muestreador de Gibbs parcialmente incompatible).

En la práctica, la imputación múltiple bayesiana sigue siendo una buena forma de tratar los problemas de datos perdidos multivariantes no monótonos. Además, las extensiones no paramétricas, como el emparejamiento de medias predictivas, ayudan a relajar los supuestos de los modelos de regresión.


Raghunathan, T. E., Lepkowski, J., van Hoewyk, J., & Solenberger, P. (2001). A multivariate technique for multiply imputing missing values using a sequence of regression models. Survey Methodology, 27(1), 85-95.

Schafer, J. L., y Graham, J. W. (2002). Missing data: Nuestra visión del estado del arte. Psychological Methods, 7(2), 147-177. https://doi.org/10.1037/1082-989X.7.2.147

van Buuren, S. (2012). Flexible Imputation of Missing Data. Boca Ratón: CRC Press.

1 votos

Excelente respuesta, por un lado me alegra haber avanzado al menos en la dirección que debo seguir, por otro lado me entristece no tener un planteamiento genial que no había pensado. Sobre la predicción interactiva de datos perdidos por el método bayes, ¿cómo podría reproducir algo así en python? ¿Es una regresión también? y después de predecir todos los posibles datos perdidos, ¿debo repasar el predictor para que los nuevos datos también participen en esa predicción? Muchas gracias por la ayuda, creo que beneficiará a muchos otros.

1 votos

@sn3fru Pues esas preguntas están respondidas en las referencias, entre otros lugares. Desconozco si existe una implementación en Python, pero replicarla no debería ser muy difícil. Supongo que habría que estudiar un poco los detalles del algoritmo. En general, cualquier modelo bayesiano puede utilizarse para crear múltiples imputaciones, pero el mice El algoritmo utiliza la regresión o la coincidencia de medias predictivas. Inicialmente se completan los datos que faltan mediante extracciones de la distribución observada y luego se imputan secuencialmente. Una vez terminado se repite, pero utilizando los nuevos valores imputados. Los nuevos datos participan, sí

4voto

user1017446 Puntos 16

No encontré nada que resolviera mi problema así que escribí una función que mezcla algunas soluciones a un dataframe de Pandas con valores numéricos perdidos (con fancyimpute) y categóricos (con un bosque aleatorio).

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
import fancyimpute as fi

def separe_numeric_categoric(df):
    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
    df_n = df.select_dtypes(include=numerics)
    df_c = df.select_dtypes(exclude=numerics)
    print(f'The DF have {len(list(df_n))} numerical features and {len(list(df_c))} categorical fets')
    return df_n, df_c

def find_missing(df):
    total = df.isnull().sum().sort_values(ascending=False)
    percent = (df.isnull().sum()/df.isnull().count()).sort_values(ascending=False)
    filter(lambda x: x>=minimum, percent)
    return percent

def count_missing(df):
    missing = find_missing(df)
    total_columns_with_missing = 0
    for i in (missing):
        if i>0:
            total_columns_with_missing += 1
    return total_columns_with_missing

def remove_missing_data(df,minimum=.1):
    percent = find_missing(df)
    number = len(list(filter(lambda x: x>=(1.0-minimum), percent)))
    names = list(percent.keys()[:number])
    df = df.drop(names, 1, errors='ignore')
    print(f'{number} columns exclude because haven`t minimium data.')
    return df

def one_hot(df, cols):
    for each in cols:
        dummies = pd.get_dummies(df[each], prefix=each, drop_first=False)
        df = pd.concat([df, dummies], axis=1)
    df = df.drop(cols, axis=1)
    return df

def impute_missing_data(df,minimium_data=.1):
    columns_missing = count_missing(df)
    print(f'Total columns with missing values: {count_missing(df)} of a {len(list(df))} columns in df')

    # remove features without minimium size of information
    df = remove_missing_data(df,minimium_data)

    numerical_df, categorical_df = separe_numeric_categoric(df)

    # Autocomplete using MICE for numerical features.
    try:
        df_numerical_complete = fi.MICE(verbose=False).complete(numerical_df.values)
        n_missing = count_missing(df)
        print(f'{columns_missing-n_missing} numerical features imputated')

        # Complete the columns name.
        temp = pd.DataFrame(columns=numerical_df.columns, data=df_numerical_complete)

        # df temp com os dados numericos completados e os categóricos.
        df = pd.concat([temp, categorical_df], axis=1)

    except Exception as e:
        print(e)
        print('Without Missing data in numerical features')

    missing = find_missing(df)
    names = missing.keys()
    n = 0
    for i, c in enumerate(missing):
        if c > 0:
            col = names[i]
            print(f'Start the prediction of {col}')
            clf = RandomForestClassifier()
            le = LabelEncoder()
            ## inverter a ordem da predição das categóricas pode melhorar a precisao.
            categorical_train = list(categorical_df.loc[:,categorical_df.columns != col])

            temp = one_hot(df,categorical_train)
            df1 = temp[temp[col].notnull()]
            df2 = temp[temp[col].isnull()]
            df1_x = df1.loc[:, df1.columns != col]
            df2_x = df2.loc[:, df1.columns != col]

            df1_y = df1[col]
            le.fit(df1_y)
            df1_y = le.transform(df1_y)
            clf.fit(df1_x, df1_y)
            df2_yHat = clf.predict(df2_x)
            df2_yHat = le.inverse_transform(df2_yHat)
            df2_yHat = pd.DataFrame(data=df2_yHat, columns=[col])
            df1_y = le.inverse_transform(df1_y)
            df1_y = pd.DataFrame(data=df1_y,columns=[col])

            df2_x.reset_index(inplace=True)   
            result2 = pd.concat([df2_yHat, df2_x], axis=1)
            try:
                del result2['index']
            except:
                pass

            df1_x.reset_index(inplace=True)
            result1 = pd.concat([df1_y, df1_x], axis=1)
            try:
                del result1['index']
            except:
                pass

            result = pd.concat([result1, result2])
            result = result.set_index(['Id'])
            df.reset_index()            
            try:
                df.set_index(['Id'],inplace=True)
            except:
                pass
            df[col] = result[col]

            n += 1

    print(f'Number of columns categorical with missing data solved: {n}')

    return df

df = impute_missing_data(df)

0voto

Manuel Puntos 6

Aunque suele ser más complicado, puede intentar crear una Distribución de Entropía Máxima basada en los datos que tiene.

http://proceedings.mlr.press/v5/huang09a/huang09a.pdf

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X