วิธีการแก้ไขปัญหาข้อมูลขาดหายไปในการเรียนรู้ของเครื่อง


15

ฐานข้อมูลใด ๆ ที่เราต้องการทำนายโดยใช้อัลกอริทึมการเรียนรู้ของเครื่องจะค้นหาค่าที่ขาดหายไปสำหรับคุณลักษณะบางอย่าง

มีหลายวิธีในการแก้ไขปัญหานี้เพื่อแยกบรรทัดที่มีค่าหายไปจนกว่าพวกเขาจะเติมค่าเฉลี่ยของลักษณะ

ฉันต้องการใช้สำหรับวิธีที่ค่อนข้างแข็งแกร่งซึ่งโดยทั่วไปจะเรียกใช้การถดถอย (หรือวิธีอื่น) ซึ่งตัวแปรตาม (Y) จะเป็นคอลัมน์แต่ละคอลัมน์ที่มีค่าที่หายไป แต่มีเฉพาะแถวของตาราง ที่มีข้อมูลทั้งหมดและทำนายค่าที่ขาดหายไปด้วยวิธีนี้ให้ทำตารางตามตารางและย้ายไปยัง 'คอลัมน์' ถัดไปด้วยค่าที่หายไปและทำซ้ำวิธีจนกว่าทุกอย่างจะเต็ม

แต่นั่นทำให้ฉันสงสัย

ทำไมคอลัมน์เริ่มต้น ฉันเชื่อว่าคนที่มีค่าที่น้อยที่สุดจะหายไปจนกว่าคนที่มีค่ามากที่สุด

มีเกณฑ์ของค่าที่หายไปที่ไม่คุ้มค่าหรือไม่ที่จะพยายามทำให้เสร็จ (ตัวอย่างเช่นหากคุณลักษณะนี้มีเพียง 10% ของค่าที่เติมจะไม่น่าสนใจที่จะยกเว้น)

มีการนำไปใช้ในแพคเกจแบบดั้งเดิมหรือวิธีการอื่นที่ทนทานต่อการขาดหรือไม่


3
คำศัพท์ทางศิลปะที่คุณกำลังมองหาคือ "การใส่ความ" ซึ่งการใส่หลายครั้งนั้นเป็นตัวเลือกยอดนิยมและทันสมัย โปรดทราบว่าการยกเว้นการสังเกตด้วยการสังเกตที่ขาดหายไปหรือการแทนที่การสังเกตที่ขาดหายไปด้วยค่าเฉลี่ยอาจทำให้ข้อมูลอคติ จุดเริ่มต้นแห่งเดียวคือ Gelman et al, การวิเคราะห์ข้อมูลแบบเบย์รุ่นที่ 3, "บทที่ 18: แบบจำลองสำหรับข้อมูลที่ขาดหายไป"
Sycorax พูดว่า Reinstate Monica

ขอบคุณสำหรับเคล็ดลับฉันจะค้นหาด้วยคำนั้นและดูที่ cap18 การลบบรรทัดสามารถตั้งค่าแบบจำลองได้มาก (หากการพลาดไม่สุ่มซึ่งมีโอกาสมาก) และการวางค่าเฉลี่ยสามารถใส่ 'แรงเฉื่อย' รอบค่าเฉลี่ยที่แข็งแกร่งเช่นกันโดยขึ้นอยู่กับความผิดพลาดของข้อมูลที่ขาดหายไป คำถามใหญ่ของฉันคือวิธีที่ดีที่สุดในการจัดการกับปัญหานี้และข้อเสนอแนะของฉันคือเรียกใช้การถดถอยล่วงหน้าเพื่อทำให้ข้อมูลเสร็จสมบูรณ์ก่อนการถดถอยหลัก (มีแพ็คเกจใดที่ทำสิ่งนี้หรือฉันควรสร้างได้หรือไม่)
sn3fru

การใส่ข้อมูลหลายตัวสมัยใหม่ประเมินรูปแบบสำหรับข้อมูลที่ขาดหายไปและไม่ขาดหายไปแบบคู่ขนาน Bayesian รับข้อมูลที่ขาดหายไปคือการประเมินการกระจายตัวของข้อมูลที่ขาดหายไปตามเงื่อนไขของข้อมูลที่สังเกตได้และตัวแบบสำหรับความหายไป ซอฟแวร์สถิติในหลามออกมากที่ต้องการ สำหรับข้อมูล TSCS Amelia IIใน R เป็นตัวเลือกที่มั่นคง stanหรือคุณอาจจะม้วนของคุณเองโดยใช้
Sycorax พูดว่า Reinstate Monica

คำตอบ:


9

เทคนิคที่คุณอธิบายเรียกว่าการใส่ความโดยลำดับถดถอยหรือการใส่หลายโดยสมการที่ถูกผูกมัด เทคนิคนี้บุกเบิกโดย Raghunathan (2001) และนำไปใช้ในแพ็คเกจ R ที่ใช้งานได้ดีที่เรียกว่าmice(van Buuren, 2012)

บทความโดย Schafer and Graham (2002) อธิบายได้ดีว่าเหตุใดค่าเฉลี่ยของการลบและการลบแบบรายการ (สิ่งที่คุณเรียกว่าการแยกบรรทัด) มักจะไม่มีทางเลือกที่ดีสำหรับเทคนิคดังกล่าวข้างต้น ความหมายหลักของการใส่ความไม่เป็นเงื่อนไขและทำให้สามารถมีอคติการกระจายที่ใส่เข้าไปในค่าเฉลี่ยที่สังเกตได้ นอกจากนี้ยังจะลดความแปรปรวนรวมถึงผลกระทบอื่น ๆ ที่ไม่พึงประสงค์ต่อการกระจายที่กำหนดไว้ นอกจากนี้การลบแบบรายการตามความเป็นจริงจะใช้ได้ก็ต่อเมื่อข้อมูลหายไปโดยการสุ่มเช่นเดียวกับการพลิกของเหรียญ นอกจากนี้ยังเพิ่มข้อผิดพลาดในการสุ่มตัวอย่างเนื่องจากขนาดตัวอย่างจะลดลง

ผู้เขียนที่ยกมาข้างต้นมักจะแนะนำให้เริ่มต้นด้วยตัวแปรที่มีค่าน้อยที่สุดที่หายไป นอกจากนี้เทคนิคนี้มักใช้ในแบบเบย์ (เช่นส่วนขยายของข้อเสนอแนะของคุณ) ตัวแปรถูกเยี่ยมชมบ่อยขึ้นในขั้นตอนการใส่ร้ายไม่เพียงครั้งเดียว โดยเฉพาะอย่างยิ่งตัวแปรแต่ละตัวจะเสร็จสมบูรณ์โดยดึงออกมาจากการกระจายการคาดการณ์หลังเงื่อนไขของมันเริ่มต้นด้วยตัวแปรที่มีค่าที่หายไปน้อยที่สุด เมื่อตัวแปรทั้งหมดในชุดข้อมูลเสร็จสมบูรณ์อัลกอริทึมจะเริ่มต้นอีกครั้งที่ตัวแปรแรกจากนั้นทำซ้ำอีกครั้งจนกว่าการบรรจบกัน ผู้เขียนได้แสดงให้เห็นว่าอัลกอริทึมนี้คือกิ๊บส์ดังนั้นจึงมักจะมาบรรจบกับการกระจายตัวแปรหลายตัวแปรที่ถูกต้อง

โดยทั่วไปแล้วเนื่องจากมีข้อสันนิษฐานที่ไม่สามารถทดสอบได้ที่เกี่ยวข้องโดยเฉพาะอย่างยิ่งข้อมูลสุ่มที่หายไป (เช่นข้อมูลถูกสังเกตหรือไม่นั้นขึ้นอยู่กับข้อมูลที่สังเกตเท่านั้นและไม่ได้อยู่ในค่าที่ไม่ได้ถูกสงวนไว้) ขั้นตอนยังสามารถใช้งานร่วมกันไม่ได้บางส่วนซึ่งเป็นสาเหตุที่เรียกว่า 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) Imputation ยืดหยุ่นของข้อมูลที่ขาดหายไป Boca Raton: CRC Press


1
การตอบสนองที่ดีเยี่ยมในมือข้างหนึ่งฉันดีใจที่มีขั้นสูงอย่างน้อยทิศทางที่ฉันจะต้องปฏิบัติตามในมืออื่น ๆ ที่ฉันเศร้าที่จะไม่มีวิธีการที่เป็นมิตรที่ฉันไม่คิด ในการทำนายแบบโต้ตอบของข้อมูลที่หายไปโดยวิธี Bayes ฉันจะทำซ้ำสิ่งนี้ในหลามได้อย่างไร มันเป็นความถดถอยด้วยหรือไม่? และหลังจากทำนายข้อมูลที่หายไปทั้งหมดที่เป็นไปได้ฉันควรจะไปทำนายเพื่อให้ข้อมูลใหม่มีส่วนร่วมในการทำนายนั้นหรือไม่ ขอบคุณมากสำหรับความช่วยเหลือฉันเชื่อว่ามันจะเป็นประโยชน์ต่อคนอื่น ๆ
sn3fru

1
@ sn3fru ดีคำถามเหล่านี้มีคำตอบในการอ้างอิงท่ามกลางสถานที่อื่น ๆ ฉันไม่ทราบว่ามีการใช้ Python อยู่หรือไม่ แต่การทำซ้ำมันไม่ควรยากเกินไป ฉันคิดว่ามันจะต้องศึกษารายละเอียดของอัลกอริทึมสักหน่อย โดยทั่วไปแล้วตัวแบบแบบเบย์ใด ๆ สามารถใช้เพื่อสร้าง imputes หลายอัน แต่miceอัลกอริทึมนั้นใช้การถดถอยหรือการจับคู่ค่าเฉลี่ยการทำนาย ตอนแรกคุณกรอกข้อมูลที่หายไปโดยดึงจากการแจกแจงที่สังเกตได้จากนั้นใส่ค่าตามลำดับ เมื่อเสร็จแล้วคุณจะทำซ้ำ แต่ใช้ค่าที่ใส่เข้าไปใหม่ ข้อมูลใหม่เข้าร่วมใช่
tomka

4

ฉันไม่พบสิ่งใดที่แก้ไขปัญหาของฉันดังนั้นฉันจึงเขียนฟังก์ชั่นที่ผสมผสานการแก้ปัญหาบางอย่างกับดาต้าดาต้าแพนด้าที่มีค่าตัวเลขที่ขาดหายไป (กับ 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ฟังก์ชั่นmiceStef van Buuren เขาอาจสนใจโค้ด Python ของคุณและ / หรือชี้ให้คุณเห็นงานของคนอื่นในเรื่องนี้ stefvanbuuren.nl
tomka

ฉันไม่รู้ว่าพวกเขาจะสนใจอะไรที่เรียบง่ายฉันแค่แบ่งปันที่นี่เพราะมันสามารถช่วยให้คนอื่น ๆ ต้องแก้ปัญหาที่ขาดหายไปในดาต้าดาต้าแพนด้า
sn3fru

พวกเขาอาจสนใจที่จะนำไปใช้กับ Python โดยทั่วไปและพวกเขาอาจรู้ว่ามีคนทำไปแล้วหรือไม่ ฉันเคยติดต่อ Stef มาก่อนและเขาตอบสนองและช่วยเหลือดีมาก หากมีการใช้ Python อาจมีประโยชน์ในการแบ่งปันที่นี่ภายใต้หัวข้อนี้ ดูเช่นpypi.python.org/pypi/fancyimpute/0.0.4
Tomka

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.