머신 러닝에서 데이터 누락 문제를 해결하는 방법


15

기계 학습 알고리즘을 사용하여 예측하려는 거의 모든 데이터베이스는 일부 특성에 대해 누락 된 값을 찾습니다.

결 측값이있는 선을 제외하여 특성의 평균값으로 채워질 때 까지이 문제를 해결하는 몇 가지 방법이 있습니다.

기본적으로 종속 변수 (Y)가 누락 된 값을 가진 각 열이 될 수있는 회귀 (또는 다른 방법)를 실행하는 다소 강력한 접근 방식을 사용하고 싶습니다. 이 방법으로 모든 데이터를 포함하고 누락 된 값을 예측하고 테이블별로 테이블을 완성하고 누락 된 값이있는 다음 '열'로 이동하고 모든 것이 채워질 때까지 방법을 반복하십시오.

그러나 그것은 나에게 의심을 준다.

왜 어떤 열이 시작됩니까? 나는 결 측값이 가장 작은 것이 가장 많을 때까지

결 측값을 작성하려고 시도 할 가치가없는 임계 값이 있습니까? (예를 들어,이 특성에 채워진 값의 10 % 만있는 경우 제외하는 것이 더 흥미롭지 않습니다)

기존 패키지 또는 누락에 강한 다른 방법에는 어떤 종류의 구현이 있습니까?


3
당신이 찾고있는 예술의 용어는 "대치 (imputation)"이며,이 중 다중 대치가 대중적이고 현대적인 선택입니다. 관측치가 누락 된 관측치를 제외하거나 누락 된 관측치를 평균으로 바꾸면 데이터에 치명적일 수 있습니다. 시작해야 할 곳은 Gelman et al, Bayesian Data Analysis 3rd Edition, "18 장 : 결측 데이터 모델"입니다.
Sycorax는 Reinstate Monica

팁 주셔서 감사합니다, 나는 그 용어로 검색하고 cap18을 볼 것입니다. 선을 삭제하면 모형이 많이 왜곡 될 수 있으며 (결측이 임의적이지 않은 경우 매우 가능성이 높음) 평균을 배치하면 데이터 결측의 외 생성에 따라 평균 주위에 강한 '관성 부하'가 가해질 수 있습니다. 내 큰 질문은 이것을 처리하는 가장 좋은 방법이며 내 제안은 주 회귀 이전에 데이터를 완성하기 위해 사전 회귀 분석을 실행하는 것입니다 (이 작업을 수행하거나 패키지를 만들어야합니까?)
sn3fru

최신 다중 대치 (multiple imputation)는 누락 및 비결 측 데이터에 대한 모델을 나란히 추정합니다. 베이지 안에서 결측 데이터는 관측 된 데이터와 결측 모델에 따라 결측 데이터에 대한 분포를 추정하는 것입니다. 파이썬의 통계 소프트웨어는 많이 요구됩니다. TSCS 데이터의 경우 Amelia IIR에서 확실한 선택입니다. 또는을 사용하여 직접 롤백 할 수도 있습니다 stan.
Sycorax는 Reinstate Monica

답변:


9

설명하는 기술을 순차적 회귀에 의한 대치 또는 연쇄 방정식에 의한 다중 대치라고합니다. 이 기술은 Raghunathan (2001)에 의해 개척되어 잘 작동하는 R 패키지 mice(van Buuren, 2012)로 구현되었습니다 .

Schafer and Graham (2002)의 논문은 왜 평균 대치 및 목록 삭제 (일반적으로 라인 제외라고 함)가 위에 언급 된 기술을 대체 할 수 없는지 잘 설명합니다. 주로 평균 대치가 조건부가 아니므로 대치 된 분포를 관측 된 평균쪽으로 편향시킬 수 있습니다. 또한 분산 분포에 대한 다른 바람직하지 않은 영향 중에서도 분산을 줄입니다. 또한, 목록 삭제는 실제로 동전 뒤집기와 같이 데이터가 무작위로 완전히 누락 된 경우에만 작동합니다. 또한 샘플 크기가 줄어들면 샘플링 오류가 증가합니다.

위에서 인용 한 저자는 일반적으로 최소 결 측값을 갖는 변수로 시작하는 것이 좋습니다. 또한이 기술은 일반적으로 베이지안 방식 (예 : 제안의 확장)으로 적용됩니다. 변수는 대치 절차에서 한 번만 아니라 자주 방문합니다. 특히, 각 변수는 최소 결 측값을 특징으로하는 변수부터 시작하여 조건부 후부 예측 분포를 통해 완성됩니다. 데이터 세트의 모든 변수가 완료되면 알고리즘은 첫 번째 변수에서 다시 시작한 다음 수렴 될 때까지 반복합니다. 저자들은이 알고리즘이 깁스 (Gibbs)라는 것을 보여 주었으며, 일반적으로 변수의 올바른 다변량 분포로 수렴합니다.

일반적으로, 임의의 데이터에서 누락 된 (예를 들어, 데이터가 관찰되는지의 여부는 관찰되지 않은 값이 아니라 관찰 된 데이터에만 의존하는) 일부 검증 불가능한 가정이 있기 때문에. 또한 절차가 부분적으로 호환되지 않을 수 있으므로 PIGS (부분적으로 호환되지 않는 Gibbs 샘플러)라고합니다.

실제로 베이지안 다중 대치는 여전히 다변량 비 모노톤 누락 데이터 문제를 처리하는 좋은 방법입니다. 또한 예측 평균 일치와 같은 비모수 확장은 회귀 모델링 가정을 완화하는 데 도움이됩니다.


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

van Buuren, S. (2012). 결측 데이터의 유연한 대치. 보카 레이 톤 : CRC Press.


1
훌륭한 반응, 한편으로는, 내가 따라야 할 방향을 적어도 발전 시켜서 기쁘다. 반면에, 내가 생각하지 않은 온화한 접근을하지 않는 것은 슬프다. bayes 방법으로 누락 된 데이터를 대화식으로 예측할 때 어떻게 파이썬에서 이와 같은 것을 재현 할 수 있습니까? 회귀인가? 가능한 모든 누락 된 데이터를 예측 한 후 새 데이터도 해당 예측에 참여하도록 예측 변수를 검토해야합니까? 도움을 주셔서 감사합니다. 많은 사람들에게 도움이 될 것입니다.
sn3fru

1
@ sn3fru 글쎄,이 질문들은 다른 곳에서 참조로 대답됩니다. 파이썬 구현이 존재하는지는 알지 못하지만 복제는 어렵지 않아야합니다. 알고리즘의 세부 사항을 약간 연구해야한다고 생각합니다. 일반적으로 모든 베이지안 모델을 사용하여 여러 대치를 만들 수 있지만 mice알고리즘은 회귀 또는 예측 평균 일치를 사용합니다. 처음에 관측 된 분포에서 그림을 그리면서 누락 된 데이터를 완성한 다음 순차적으로 대치합니다. 완료되면 새로 대치 된 값을 사용하여 반복합니다. 새로운 데이터가 참여합니다. 예
톰카

4

내 문제를 해결하는 것을 찾지 못했기 때문에 숫자 값이 누락 된 (팬시 임 프루트) 범주 (임의의 포리스트)가있는 팬더 데이터 프레임에 일부 솔루션을 혼합하는 함수를 작성했습니다.

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함수 작성자 인 miceStef van Buuren 에게 연락하는 것도 흥미로울 수 있습니다 . 그는 파이썬 코드에 관심이 있거나 이와 관련하여 다른 사람들의 작업을 지적 할 수 있습니다. stefvanbuuren.nl
tomka

그들이 너무 간단한 것에 관심이 있는지는 모르겠습니다. 팬더 데이터 프레임에서 누락 된 문제를 해결 해야하는 다른 사람들을 도울 수 있기 때문에 여기서 공유하고 있습니다.
sn3fru

글쎄 그들은 일반적으로 파이썬으로 구현하는 데 관심이 있고 누군가 이미 그것을했는지 알 수 있습니다. Stef에 연락 한 적이 있으며 매우 반응이 좋고 도움이됩니다. 파이썬 구현이 있다면이 스레드 아래에서 공유하는 것이 유용 할 수도 있습니다. 예를 들어, 참조 pypi.python.org/pypi/fancyimpute/0.0.4
tomka

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.