Metodi per aggirare il problema della mancanza di dati nell'apprendimento automatico


15

Praticamente qualsiasi database che vogliamo fare previsioni usando algoritmi di machine learning troverà valori mancanti per alcune delle caratteristiche.

Esistono diversi approcci per risolvere questo problema, per escludere le linee che hanno valori mancanti fino a quando non si riempiono con i valori medi delle caratteristiche.

Vorrei utilizzare per un approccio un po 'più robusto, che sostanzialmente eseguirebbe una regressione (o un altro metodo) in cui la variabile dipendente (Y) sarebbe ciascuna delle colonne che hanno valori mancanti ma solo con le righe della tabella che contengono tutti i dati e prevedono i valori mancanti con questo metodo, completano la tabella accanto alla tabella e passano alla 'colonna' successiva con valori mancanti e ripetono il metodo fino a riempire tutto.

Ma questo mi dà qualche dubbio.

Perché una colonna inizia? Credo che quello con i più piccoli valori mancanti fino a quello con più

Esiste una soglia di valori mancanti che non vale la pena provare a completarla? (ad esempio, se questa caratteristica ha solo il 10% dei valori riempiti, non sarebbe più interessante escluderla)

Esiste un tipo di implementazione in pacchetti tradizionali o altri metodi robusti per i mancati?


3
Il termine dell'arte che stai cercando è "imputazione", di cui l'imputazione multipla è una scelta popolare e moderna. Si noti che l'esclusione di osservazioni con osservazioni mancanti o la sostituzione di osservazioni mancanti con la media può compromettere gravemente i dati. Un punto di partenza è Gelman et al, Bayesian Data Analysis 3rd Edition, "Capitolo 18: Modelli per dati mancanti".
Sycorax dice di ripristinare Monica

Grazie per la punta, cercherò con quel termine e guarderò il cap18. L'eliminazione delle linee può distorcere molto il modello (se le mancanze non sono casuali, il che è molto probabile) e posizionare la media può mettere un forte "carico inerziale" attorno alla media, anche in base all'esogeneità delle mancanze di dati. La mia grande domanda è l'approccio migliore per gestire questo e il mio suggerimento sarebbe di eseguire pre-regressioni per completare i dati prima della regressione principale (ci sono pacchetti che lo fanno o dovrei crearne uno?)
sn3fru,

La moderna imputazione multipla stima un modello per i dati mancanti e non mancanti affiancati. L'affermazione bayesiana sui dati mancanti è quella di stimare una distribuzione sui dati mancanti, in base ai dati osservati e al modello di mancanza. Il software statistico in Python lascia molto a desiderare. Per i dati TSCS, Amelia IIin R è una scelta solida. Oppure puoi usare il tuo rotolo stan.
Sycorax dice di ripristinare Monica

Risposte:


9

La tecnica che descrivi si chiama imputazione da regressioni sequenziali o imputazione multipla da equazioni concatenate. La tecnica è stata introdotta da Raghunathan (2001) e implementata in un pacchetto R ben funzionante chiamato mice(van Buuren, 2012).

Un articolo di Schafer e Graham (2002) spiega bene perché l'imputazione media e la cancellazione listwise (ciò che chiamate esclusione di linea) di solito non sono buone alternative alle tecniche sopra menzionate. L'imputazione della media principale non è condizionata e quindi può influenzare le distribuzioni imputate verso la media osservata. Ridurrà anche la varianza, tra gli altri impatti indesiderati sulla distribuzione imputata. Inoltre, la cancellazione listlist funzionerà davvero solo se i dati mancano completamente a caso, come il lancio di una moneta. Inoltre aumenterà l'errore di campionamento, poiché la dimensione del campione viene ridotta.

Gli autori sopra citati di solito raccomandano di iniziare con la variabile che presenta i valori meno mancanti. Inoltre, la tecnica viene generalmente applicata in modo bayesiano (ovvero un'estensione del tuo suggerimento). Le variabili vengono visitate più spesso nella procedura di imputazione, non solo una volta. In particolare, ogni variabile è completata da disegni dalla sua distribuzione predittiva posteriore condizionale, a partire dalla variabile che presenta i valori meno mancanti. Una volta che tutte le variabili in un set di dati sono state completate, l'algoritmo ricomincia dalla prima variabile e quindi re-itera fino alla convergenza. Gli autori hanno dimostrato che questo algoritmo è Gibbs, quindi di solito converge alla corretta distribuzione multivariata delle variabili.

Di solito, poiché vi sono alcune assunzioni non verificabili, in particolare mancanti di dati casuali (ovvero se i dati sono osservati o meno dipende solo dai dati osservati e non dai valori non osservati). Inoltre, le procedure possono essere parzialmente incompatibili, motivo per cui sono state chiamate PIGS (campionatore Gibbs parzialmente incompatibile).

In pratica, l'imputazione multipla bayesiana è ancora un buon modo per affrontare i problemi di dati mancanti non monotone multivariati. Inoltre, estensioni non parametriche come la corrispondenza media predittiva aiutano a rilassare i presupposti del modello di regressione.


Raghunathan, TE, Lepkowski, J., van Hoewyk, J., & Solenberger, P. (2001). Una tecnica multivariata per moltiplicare l'imputazione dei valori mancanti usando una sequenza di modelli di regressione. Metodologia del sondaggio, 27 (1), 85–95.

Schafer, JL e Graham, JW (2002). Dati mancanti: la nostra visione dello stato dell'arte. Metodi psicologici, 7 (2), 147–177. https://doi.org/10.1037/1082-989X.7.2.147

van Buuren, S. (2012). Imputazione flessibile di dati mancanti. Boca Raton: CRC Press.


1
ottima risposta, da un lato sono felice di aver avanzato almeno la direzione che devo seguire, dall'altro sono triste di non avere un approccio geniale che non pensavo. Sulla previsione interattiva dei dati mancanti con il metodo bayes, come potrei riprodurre qualcosa di simile in Python? È anche una regressione? e dopo aver previsto tutti i possibili dati mancanti, dovrei andare oltre il predittore in modo che anche i nuovi dati partecipino a tale previsione? Molte grazie per l'aiuto, credo che ne trarranno beneficio molti altri.
sn3fru,

1
@ sn3fru Bene, queste domande trovano risposta nei riferimenti, tra gli altri posti. Non sono a conoscenza dell'esistenza di un'implementazione di Python, ma replicarla non dovrebbe essere troppo difficile. Suppongo che richiederebbe un po 'di studio dei dettagli dell'algoritmo. In generale, qualsiasi modello bayesiano può essere utilizzato per creare più imputes, ma l' micealgoritmo utilizza la regressione o la corrispondenza media predittiva. Inizialmente si completano i dati mancanti attingendo dalla distribuzione osservata e quindi imputati in sequenza. Una volta finito, ripeti, ma usando i valori appena imputati. Partecipano i nuovi dati, sì
tomka,

4

Non ho trovato nulla che risolva il mio problema, quindi ho scritto una funzione che mescola alcune soluzioni a un frame di dati Pandas con valori numerici mancanti (con fancyimpute) e categorici (con una foresta casuale).

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)

Bene, questo potrebbe aiutare gli altri (non l'ho verificato) - potrebbe anche essere interessante contattare il creatore della Rfunzione mice, Stef van Buuren. Potrebbe essere interessato al tuo codice Python e / o indirizzarti al lavoro di altre persone al riguardo. stefvanbuuren.nl
tomka

Non so se sarebbero interessati a qualcosa di così semplice, sto solo condividendo qui perché può aiutare altre persone che hanno bisogno di risolvere i dispersi in un frame di dati Pandas.
sn3fru,

Beh, potrebbero essere interessati a implementarlo in Python in generale e potrebbero sapere se qualcuno lo ha già fatto. Ho già contattato Stef ed è molto disponibile e disponibile. Se esiste un'implementazione di Python, può essere utile condividerla qui sotto questo thread. Vedi ad esempio pypi.python.org/pypi/fancyimpute/0.0.4
tomka,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.