Metody obejścia problemu braku danych w uczeniu maszynowym

15

Praktycznie każda baza danych, w której chcemy przewidywać za pomocą algorytmów uczenia maszynowego, znajdzie brakujące wartości niektórych cech.

Istnieje kilka podejść do rozwiązania tego problemu, aby wykluczyć linie, w których brakuje wartości, dopóki nie wypełnią się średnimi wartościami cech.

Chciałbym zastosować nieco bardziej niezawodne podejście, które zasadniczo uruchomiłoby regresję (lub inną metodę), w której zmienną zależną (Y) byłaby każda kolumna, której brakuje wartości, ale tylko z wierszami tabeli które zawierają wszystkie dane i za pomocą tej metody przewidują brakujące wartości, uzupełnij tabelę według tabeli i przejdź do następnej „kolumny” z brakującymi wartościami i powtarzaj metodę, aż wszystko zostanie wypełnione.

Ale to budzi pewne wątpliwości.

Dlaczego zaczyna się jakakolwiek kolumna? Uważam, że ten z najmniejszymi brakującymi wartościami aż do tego z największym

Czy istnieje jakiś próg brakujących wartości, który nie jest wart próby jego uzupełnienia? (na przykład jeśli ta cecha ma tylko 10% wypełnionych wartości, nie byłoby bardziej interesujące, aby ją wykluczyć)

Czy istnieje jakakolwiek implementacja w tradycyjnych pakietach lub innych metodach odpornych na braki?

sn3fru
źródło
3
Pojęcie sztuki, którego szukasz, to „imputacja”, której wielokrotna imputacja jest popularnym, nowoczesnym wyborem. Należy zauważyć, że wykluczenie obserwacji z brakującymi obserwacjami lub zastąpienie brakujących obserwacji średnią może źle wpłynąć na dane. Jednym z nich jest Gelman i wsp., Bayesian Data Analysis 3rd Edition, „Rozdział 18: Modele brakujących danych”.
Sycorax mówi Przywróć Monikę
Dzięki za wskazówkę, przeszukam ten termin i spojrzę na cap18. Usunięcie linii może bardzo wpływać na model (jeśli braki nie są przypadkowe, co jest bardzo prawdopodobne), a umieszczenie wartości średniej może spowodować silne „obciążenie bezwładności” wokół średniej, również w zależności od egzogeniczności braków danych. Moje wielkie pytanie jest najlepszym podejściem do rozwiązania tego problemu i sugeruję, aby uruchomić regresje wstępne w celu uzupełnienia danych przed regresją główną (czy są jakieś pakiety, które to robią, czy powinienem je utworzyć?)
sn3fru
Współczesna wielokrotna imputacja szacuje model brakujących i brakujących danych obok siebie. Bayesowskie podejście do brakujących danych polega na oszacowaniu rozkładu brakujących danych, zależnie od obserwowanych danych i modelu brakujących danych. Oprogramowanie statystyczne w pythonie pozostawia wiele do życzenia. W przypadku danych TSCS Amelia IIw R jest dobrym wyborem. Lub możesz rzucić własny za pomocą stan.
Sycorax mówi Przywróć Monikę

Odpowiedzi:

9

Opisana technika nazywa się imputacją przez sekwencyjne regresje lub wielokrotną imputacją przez równania łańcuchowe. Technikę tę wprowadził Raghunathan (2001) i zaimplementował w dobrze działającym pakiecie R o nazwie mice(van Buuren, 2012).

W artykule Schafera i Grahama (2002) dobrze wyjaśniono, dlaczego średnia imputacja i skasowanie listowe (tak zwane wykluczenie linii) zwykle nie stanowią dobrych alternatyw dla wyżej wymienionych technik. Zasadniczo średnia imputacja nie jest warunkowa, a zatem może odchylać przypisane rozkłady w kierunku obserwowanej średniej. Zmniejszy to również wariancję, między innymi niepożądanymi wpływami na przypisany rozkład. Co więcej, usuwanie listowe rzeczywiście będzie działać tylko wtedy, gdy dane zostaną całkowicie przypadkowo pominięte, jak na przykład rzut monetą. Zwiększy to również błąd próbkowania, ponieważ wielkość próbki zostanie zmniejszona.

Cytowani powyżej autorzy zwykle zalecają rozpoczęcie od zmiennej zawierającej najmniej brakujące wartości. Ponadto technika jest zwykle stosowana w sposób bayesowski (tj. Rozszerzenie twojej sugestii). Zmienne są odwiedzane częściej w procedurze przypisania, nie tylko raz. W szczególności każdą zmienną uzupełnia losowanie z jej warunkowego rozkładu predykcyjnego z tyłu, zaczynając od zmiennej zawierającej najmniej brakujące wartości. Po zakończeniu wszystkich zmiennych w zestawie danych algorytm ponownie rozpoczyna się od pierwszej zmiennej, a następnie powtarza ją do zbieżności. Autorzy wykazali, że ten algorytm to Gibbs, dlatego zwykle jest zbieżny z poprawnym rozkładem zmiennych na wielu odmianach.

Zwykle, ponieważ wiążą się z tym pewne nie dające się przetestować założenia, w szczególności brak danych losowych (tj. To, czy dane są obserwowane, czy nie, zależy tylko od danych obserwowanych, a nie od wartości nieobserwowanych). Również procedury mogą być częściowo niekompatybilne, dlatego nazwano je PIGS (częściowo niekompatybilny sampler Gibbs).

W praktyce wielokrotna imputacja bayesowska jest nadal dobrym sposobem radzenia sobie z problemami z brakującymi danymi na wielu odmianach niemonotonowych. Ponadto rozszerzenia nieparametryczne, takie jak predykcyjne dopasowywanie średnich, pomagają rozluźnić założenia modelowania regresji.


Raghunathan, TE, Lepkowski, J., van Hoewyk, J., i Solenberger, P. (2001). Wielowymiarowa technika mnożenia imputujących brakujących wartości przy użyciu sekwencji modeli regresji. Metodologia badania, 27 (1), 85–95.

Schafer, JL i Graham, JW (2002). Brakujące dane: nasz pogląd na najnowszy stan wiedzy. Metody psychologiczne, 7 (2), 147–177. https://doi.org/10.1037/1082-989X.7.2.147

van Buuren, S. (2012). Elastyczne przypisywanie brakujących danych. Boca Raton: CRC Press.

tomka
źródło
1
doskonała reakcja, z jednej strony cieszę się, że posunąłem się co najmniej w kierunku, który muszę podążać, z drugiej strony przykro mi, że nie mam genialnego podejścia, o którym nie myślałem. W interaktywnym przewidywaniu brakujących danych metodą Bayesa, jak mogę odtworzyć coś takiego w Pythonie? Czy to też regresja? a po przewidywaniu wszystkich możliwych brakujących danych, czy powinienem przejść przez predyktor, aby nowe dane również uczestniczyły w tej prognozie? Wielkie dzięki za pomoc, wierzę, że przyniesie korzyść wielu innym.
sn3fru
1
@ sn3fru Cóż, odpowiedzi na te pytania znajdują się między innymi w referencjach. Nie wiem, czy istnieje implementacja w języku Python, ale jej replikacja nie powinna być zbyt trudna. Przypuszczam, że wymagałoby to trochę przestudiowania szczegółów algorytmu. Zasadniczo do tworzenia wielu imputów można użyć dowolnego modelu Bayesa, ale micealgorytm albo stosuje regresję, albo predykcyjne dopasowanie średnich. Na początku uzupełniasz brakujące dane, rysując z obserwowanego rozkładu, a następnie przypisujesz sekwencyjnie. Po zakończeniu powtórz, ale używając nowo przypisanych wartości. Nowe dane biorą udział, tak
tomka
4

Nie znalazłem niczego, co rozwiązałoby mój problem, dlatego napisałem funkcję, która łączy niektóre rozwiązania w ramce danych Pandas z brakującymi wartościami liczbowymi (z fantazyjnym wyobrażeniem) i kategoryczną (z losowym lasem).

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)
sn3fru
źródło
Fajnie, może to pomóc innym (nie sprawdziłem tego) - interesujące może być również skontaktowanie się z twórcą Rfunkcji mice, Stefem van Buurenem. Może być zainteresowany twoim kodem Python i / lub wskazać ci pracę innych ludzi w tym zakresie. stefvanbuuren.nl
tomka
Nie wiem, czy byliby zainteresowani czymś tak prostym, po prostu dzielę się tutaj, ponieważ może to pomóc innym osobom potrzebującym rozwiązania zaginionego w ramce danych Pandas.
sn3fru
Cóż, mogą być zainteresowani implementacją tego w Pythonie i mogą wiedzieć, czy ktoś już to zrobił. Skontaktowałem się wcześniej ze Stefem, który jest bardzo elastyczny i pomocny. Jeśli istnieje implementacja w języku Python, warto również udostępnić ją tutaj w tym wątku. Patrz np. Pypi.python.org/pypi/fancyimpute/0.0.4
tomka