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


15

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

Существует несколько подходов к решению этой проблемы, чтобы исключить строки с пропущенными значениями, пока они не заполнятся средними значениями признаков.

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

Но это вызывает у меня некоторые сомнения.

Почему любой столбец начинается? Я считаю, что один с наименьшими пропущенными значениями, пока тот, с наибольшим

Есть ли какой-нибудь порог пропущенных значений, который не стоит пытаться завершить? (например, если эта характеристика имеет только 10% заполненных значений, было бы более интересно исключить ее)

Есть ли какая-либо реализация в традиционных пакетах или других методах, устойчивых к отсутствию?


3
Вы ищете искомый термин «вменение», популярным современным выбором которого является множественное вменение. Обратите внимание, что исключение наблюдений с отсутствующими наблюдениями или замена отсутствующих наблюдений средним может привести к смещению данных. Начнем с Гельмана и др., Байесовский анализ данных, 3-е издание, «Глава 18: Модели для отсутствия данных».
Sycorax сообщает восстановить Monica

Спасибо за совет, я буду искать с этим термином и смотреть на cap18. Удаление линий может сильно сместить модель (если пропуски не случайны, что весьма вероятно), а размещение среднего значения может создать сильную «инерционную нагрузку» вокруг среднего значения, также в зависимости от экзогенности пропусков данных. Мой главный вопрос - лучший способ справиться с этим, и я бы предложил запустить предварительную регрессию для завершения данных перед основной регрессией (есть ли пакеты, которые это делают, или я должен их создать?)
sn3fru

Современные множественные вменения оценивают модель для отсутствующих и отсутствующих данных бок о бок. Байесовский подход к отсутствующим данным заключается в оценке распределения по отсутствующим данным, с учетом наблюдаемых данных и модели отсутствия. Статистическое ПО на питоне оставляет желать лучшего. Для данных TSCS, Amelia IIв R это хороший выбор. Или вы можете свернуть свое собственное использование stan.
Sycorax сообщает, что восстановит Монику

Ответы:


9

Техника, которую вы описываете, называется вменением последовательными регрессиями или множественным вменением связанными уравнениями. Этот метод был впервые применен Raghunathan (2001) и реализован в хорошо работающем R-пакете mice(van Buuren, 2012).

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

Приведенные выше авторы обычно рекомендуют начинать с переменной с наименьшим отсутствующим значением. Кроме того, техника обычно применяется байесовским способом (то есть является продолжением вашего предложения). Переменные посещаются чаще в процедуре вменения, а не только один раз. В частности, каждая переменная дополняется извлечениями из ее условного апостериорного предиктивного распределения, начиная с переменной, содержащей наименьшие пропущенные значения. Как только все переменные в наборе данных были завершены, алгоритм снова запускается с первой переменной, а затем повторяется до сходимости. Авторы показали, что этот алгоритм является гиббсовским, поэтому он обычно сходится к правильному многомерному распределению переменных.

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

На практике байесовское множественное вменение все еще является хорошим способом решения многомерных немонотонных проблем с отсутствующими данными. Кроме того, непараметрические расширения, такие как прогнозирование соответствия среднего значения, помогают ослабить предположения регрессионного моделирования.


Рагхунатан Т.Е., Лепковски Дж., Ван Хоувик Дж. И Соленбергер П. (2001). Многомерный метод для многократного вменения пропущенных значений с использованием последовательности моделей регрессии. Методология исследования, 27 (1), 85–95.

Schafer, JL, & Graham, JW (2002). Недостающие данные: наш взгляд на современное состояние. Психологические методы, 7 (2), 147–177. https://doi.org/10.1037/1082-989X.7.2.147

van Buuren, S. (2012). Гибкое вложение недостающих данных. Бока Ратон: CRC Press.


1
отличный ответ, с одной стороны, я рад, по крайней мере, выдвинул направление, которому я должен следовать, с другой стороны, мне грустно, что у меня нет гениального подхода, о котором я не думал. Что касается интерактивного предсказания пропущенных данных методом Байеса, как я могу воспроизвести что-то подобное в python? Это тоже регресс? и после прогнозирования всех возможных пропущенных данных, должен ли я перейти к предиктору, чтобы новые данные также участвовали в этом прогнозе? Большое спасибо за помощь, я верю, что это пойдет на пользу многим другим.
sn3fru

1
@ sn3fru Ну, на эти вопросы даются ответы в других местах. Я не знаю, существует ли реализация Python, но ее репликация не должна быть слишком сложной. Я полагаю, что это потребует небольшого изучения деталей алгоритма. В общем, любая байесовская модель может быть использована для создания множественных вменений, но miceалгоритм использует либо регрессию, либо прогнозирование среднего значения. Сначала вы дополняете недостающие данные отрисовками из наблюдаемого распределения, а затем последовательно вменяете. После завершения вы повторяете, но с использованием вновь вмененных значений. Новые данные, участвует да
Томка

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
Томка

Я не знаю, заинтересует ли их чем-то таким простым, я просто делюсь здесь, поскольку это может помочь другим людям, нуждающимся в решении, отсутствующим в кадре данных Pandas.
sn3fru

Ну, они могут быть заинтересованы в реализации этого на Python в целом, и они могут знать, кто-то уже сделал это. Я уже связывался со Стефом, и он очень отзывчивый и услужливый. Если есть реализация Python, также может быть полезно поделиться ею здесь в этой теме. См , например , pypi.python.org/pypi/fancyimpute/0.0.4
Томка

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.