Методи вирішення проблеми відсутності даних у машинному навчанні


15

Практично будь-яка база даних, яку ми хочемо передбачити, використовуючи алгоритми машинного навчання, знайде відсутні значення для деяких характеристик.

Існує кілька підходів для вирішення цієї проблеми, щоб виключити рядки, у яких відсутні значення, поки вони не заповняться середніми значеннями характеристик.

Я хотів би скористатися дещо більш надійним підходом, який би в основному виконував регресію (або інший метод), де залежна змінна (Y) буде кожним із стовпців, у яких відсутні значення, але лише з рядками таблиці , які містять усі дані, і передбачити пропущені значення за допомогою цього методу, заповніть таблицю за таблицею та перейдіть до наступного 'стовпчика' з пропущеними значеннями та повторіть метод, поки все не заповниться.

Але це викликає у мене певні сумніви.

Чому якийсь стовпець починається? Я вважаю, що той, з найменшими відсутніми значеннями, до того, хто має найбільше

Чи є поріг відсутніх значень, який не варто намагатися виконати? (наприклад, якщо ця характеристика містить лише 10% заповнених значень, не було б цікавіше виключити її)

Чи є якась реалізація в традиційних пакетах чи інших методах, які є надійними для пропусків?


3
Термін мистецтва, який ви шукаєте, - це "імпутація", серед яких багаторазова імпутація - популярний, сучасний вибір. Зауважте, що виключення спостережень із відсутніми спостереженнями або заміна пропущених спостережень середнім може погано змістити дані. Слід почати - Гельман та ін., 3-е видання Bayesian Data Analysis , "Розділ 18: Моделі відсутніх даних".
Sycorax каже, що повернеться до Моніки

Дякую за підказку, я проведу пошук із цим терміном і перегляну шапку18. Видалення ліній може сильно змістити модель (якщо пропуски не випадкові, що дуже ймовірно), а розміщення середнього значення може спричинити сильне "інерційне навантаження" навколо середнього значення, також залежно від екзогенності пропусків даних. Моє велике питання - це найкращий підхід для вирішення цього питання, і я запропонував би запустити попередні регресії для заповнення даних до основної регресії (чи є якісь пакети, які роблять це чи я повинен створити?)
sn3fru

Сучасна множинна імпутація оцінює модель для відсутніх та відсутніх даних одночасно. Байєсівські дані про відсутні дані є для оцінки розподілу за відсутніми даними, що залежить від спостережуваних даних та моделі відсутності. Статистичне програмне забезпечення в python залишає бажати кращого. Для даних TSCS, Amelia IIв R - ґрунтовний вибір. Або ви можете скачати своє власне використання stan.
Sycorax каже, що повернеться Моніка

Відповіді:


9

Описана вами методика називається імпутацією послідовними регресіями або багаторазовою імпутацією ланцюговими рівняннями. Техніку запровадили Рагхунатан (2001) та впровадили у добре працюючому пакеті R, названому mice(van Buuren, 2012).

Документ Schafer and Graham (2002) добре пояснює, чому середнє імпутація та списування видалення (те, що ви називаєте виключенням рядка) зазвичай не є хорошими альтернативами вищезгаданим методам. В основному середня імпутація не є умовною, і, таким чином, може зміщувати імпутовані розподіли у напрямку спостережуваного середнього. Це також зменшить дисперсію, серед інших небажаних впливів на імпульсний розподіл. Крім того, видалення за списком дійсно буде спрацьовувати лише у тому випадку, якщо дані повністю відсутні випадковим чином, як, наприклад, перевернути монету. Також це збільшить помилку вибірки, оскільки зменшиться розмір вибірки.

Автори, які цитуються вище, зазвичай рекомендують починати зі змінної із найменшими відсутніми значеннями. Також методику зазвичай застосовують байєсівським способом (тобто розширенням вашої пропозиції). Змінні відвідуються частіше в процесі імпутації, не лише один раз. Зокрема, кожна змінна комплектується малюнками з її умовного заднього прогнозного розподілу, починаючи з змінної, що містить найменш відсутні значення. Після того, як всі змінні в наборі даних будуть виконані, алгоритм знову починається з першої змінної, а потім повторно повторюється до конвергенції. Автори показали, що цей алгоритм є Гіббсом, тому він зазвичай сходить до правильного багатофакторного розподілу змінних.

Зазвичай, тому що є якісь нестабільні припущення, зокрема відсутні у випадкових даних (тобто, чи спостерігаються дані чи ні, залежить лише від спостережуваних даних, а не від незабезпечених значень). Також процедури можуть бути частково несумісними, через що вони отримали назву PIGS (частково несумісний пробовідбірник Гіббса).

На практиці багаторазова імпутація Баєса все ще є хорошим способом вирішити багатовимірні немонотонні проблеми з відсутніми даними. Крім того, непараметричні розширення, такі як середнє значення прогнозування, допомагають послабити припущення щодо моделювання регресії.


Raghunathan, TE, Lepkowski, J., van Hoewyk, J., & Solenberger, P. (2001). Багатовимірна техніка множення введення відсутніх значень за допомогою послідовності регресійних моделей. Методологія опитування, 27 (1), 85–95.

Schafer, JL, & Graham, JW (2002). Відсутні дані: наш погляд на сучасний стан Психологічні методи, 7 (2), 147–177. https://doi.org/10.1037/1082-989X.7.2.147

ван Бурен, С. (2012). Гнучка імітація відсутніх даних. Бока Ратон: Преса CRC.


1
відмінна відповідь, з одного боку, я радий, що я просунув хоча б той напрямок, який я повинен слідувати, з іншого боку, мені сумно, що не маю геніального підходу, про який я не думав. Що стосується інтерактивного прогнозування відсутніх даних методом Байєса, як я міг відтворити щось подібне в python? Це теж регресія? і після передбачення всіх можливих відсутніх даних я повинен перейти за прогнозом, щоб нові дані також брали участь у цьому прогнозі? Дуже дякую за допомогу, я вірю, що це піде на користь багатьом іншим.
sn3fru

1
@ sn3fru Ну, на ці запитання, серед інших місць, відповіді. Мені невідомо, чи існує реалізація Python, але тиражувати її не повинно бути надто складно. Я вважаю, що це зажадає трохи вивчити деталі алгоритму. Загалом, будь-яка байєсівська модель може використовуватися для створення декількох імпульсів, але miceалгоритм або використовує регресію, або середнє прогностичне узгодження. Ви спочатку заповнюєте відсутні дані, витягуючи із спостережуваного розподілу, а потім вводите послідовно. Після завершення ви повторите, але використовуючи щойно введені значення. Нові дані беруть участь, так
tomka

4

Я не знайшов нічого, що вирішило б мою проблему, тому я написав функцію, яка змішує деякі рішення для фрейму даних Pandas з пропущеними числовими значеннями (з fancyimpute) та категоричною (із випадковим лісом).

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)

Приємно, це може допомогти іншим (я цього не перевіряв) - можливо, вам також буде цікаво зв’язатися із творцем Rфункції miceСтеф ван Бурен. Він може зацікавитись вашим кодом Python та / або вказати на роботу інших людей у ​​цьому плані. stefvanbuuren.nl
tomka

Я не знаю, чи не зацікавило б їх щось таке просте, я просто поділюсь тут, оскільки це може допомогти іншим людям, які потребують вирішення відсутніх у фреймі даних Pandas.
sn3fru

Ну, вони можуть бути зацікавлені в застосуванні цього в Python взагалі, і вони можуть знати, чи вже хтось це зробив. Я раніше контактував із Стефом, і він дуже чуйний і корисний. Якщо є реалізація Python, також може бути корисним поділитися нею тут під цим потоком. Дивіться, наприклад, pypi.python.org/pypi/fancyimpute/0.0.4
tomka

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.