機器學習-特征工程-Missing value和Category encoding


好了,大家現在進入到機器學習中的一塊核心部分了,那就是特征工程,洋文叫做Feature Engineering。實際在機器學習的應用中,真正用於算法的結構分析和部署的工作只占很少的一部分,相反,用於特征工程的時間基本都占70%以上,因為是實際的工作中,絕大部分的數據都是非標數據。因而這一塊的內容是非常重要和必要的,如果想要提高機器學習應用開發的效率,feature engineering就像一把鑰匙,一個加速器,能給整個項目帶來事半功倍的效果。另外,feature engineering做的好不好,直接關系到后面的模型的質量。正因為上面的原因,feature engineering我准備詳細的解釋,我准備花三篇隨筆說完。這是第一篇,主要介紹兩部分,分別是missing value的處理和categorical data的處理。其中missing value的處理相對簡單,復雜的是categorical data的處理,有很多種處理方式,我們在這邊就直說常用的5中方式。那么好啦,咱們就直接進入主題內容吧。

  • Missing value

missing value 顧名思義就是有些實際數據中,有很多的數值是缺失的,那么怎么處理這些缺失的數據,就變成了一個很有必要的事情。基本上,咱們處理missing value的方法就是三種,分別是:dropping, Imputation, 和 An extension to imputation。那下面就這三種方法分別來進行代碼的演示和結果的展示

  1. Dropping。顧名思義,dropping的意思就是整個刪除掉一整行的數據。這里的意思就是,如果某一列數據含有空數據NaN, 那么就直接刪除掉這一整行的數據,它的操作如下所示
    missing_data_cols = [col for col in train_X.columns if train_X[col].isna().any()]
    #drop missing data columns
    reduced_train_X = train_X.drop(missing_data_cols, axis =1)

    上面代碼的第一句是為了找出所有含有空數據的column,第二句代碼的意思就是刪除掉這些含有空數據的column,記住axis參數設置成1代表着是column,如果設置成0或者沒有設置,則默認指刪除行row。

  2. Imputation。這里對於處理missing value的第二種方法是指的填充的方法(不知道翻譯的對不對哈),它是什么意思呢,其實很簡單,它的意思就是將這個空值的element,根據一定的條件填充數據,這里的條件可以是平均值,中位數,出現頻率最高的等,具體采用哪種方式,還是按照里面的參數strategy進行設置的。具體的代碼實現方式,是通過下面來演示
    from sklearn.impute import SimpleImputer
    my_imputer = SimpleImputer(strategy = "mean")
    my_imputer.fit_transform(train_X)
    imputed_train_X = pd.DataFrame(my_imputer.fit_transform(train_X))

    注意這里需要引進一個新的庫進行數據處理,那就是sklearn, 它是sci-kit learn的縮寫。這個庫也是一個很牛逼的庫,它和TensorFlow的功能一樣,提供了豐富的數據處理方面的接口,可以極大的方便咱們的數據處理,也提供了很多常用的模型供咱們選擇,在機器學習領域可以說是經常用到的。上面第二行代碼就是設置通過什么方式來impute,這里設置的是平均數。第三行返回的是一個numpy array,第四行咱們將這個impute過后的numpy array轉化成dataframe。

  3. An Extension to Imputation。從這個命名咱們可以看出它是對上面imputation的一種補充,是基於imputation的。它實際上是先添加幾個column(有哪些column有missing value,咱們就添加幾個column),這些添加的column是boolean值,如果某一行對應是missing value,這個Boolean值就是True, 如果不是missing value,則是False。咱們看看下面的代碼和圖片能夠更加深刻的理解。
    X_train_extension = train_X.copy()
    X_val_extension = val_X.copy()
    
    #making columns with missing data
    for col in missing_data_cols:
        X_train_extension[col + "_was_missing"] = train_X[col].isnull()
    
        
    #imputation
    my_imputer = SimpleImputer()
    X_train_extension_impute = pd.DataFrame(my_imputer.fit_transform(X_train_extension))

     

     上面展示了代碼還有一小段結果的截圖。大家可以很明顯的看出來添加了三個新的columns。這里的順序根據代碼也可以看出來,是先添加新的columns,然后再imputation。

  • Categorical Data encoding

上面一節主要講的是Missing value的一些簡單的處理方式,在實際的數據處理中,咱們大部分時間遇到的數據並不是numerical data,相反,咱們大部分時間遇到的都是categorical data,可是在咱們的計算機處理數據的時候,處理的都是numerical data,所以咱們得想辦法將這些categorical data轉成numerical才行。實際中咱們經常使用的策略就是下面的五種方式,下面咱們來一個個講解一下,這一塊也是咱們的重點內容。

  1. dropping。和前面的missing data一樣,直接dropping是最簡單粗暴的方法,雖然這是最簡單的方法,但是實際中,這種方式卻並不常用,因為她往往不利於咱們的模型。極端的想一下,如果咱們的dataframe都是categorical的數據,難道咱們直接把他們全部刪除?????哈哈,那咱們還訓練個毛模型。但是,咱們還是得了解一下,畢竟在極少數的情況下,咱們還是要用到的。咱們直接看代碼演示,然后解釋一下
    X_train_result_drop = X_train_result.select_dtypes(exclude=["object"])

    看看上面這一句簡單的代碼,通過dataframe的select_dtypes方法,傳遞一個exclude參數,因為在dataframe中object的數據類型就是categorical data,所以上面的api直接就是刪除了所有categorical data的數據。

  2. Label encoding。對於有些categorical data,咱們可以給每一個category賦值一個數字,例如Female=0,Male = 1等等。那么哪些categorical data適合label encoding呢?就是那些一列數據中category的種類不是特別多的數據。例如一列categorical data一共有20個category或者50個category都是OK的,如果直接有1000多category,那么簡單的labeling的效率就不高了,結果也可能不理想。這其實在實際的處理中還是經常會用到的。下面通過一句簡單的代碼進行演示。注意,這里都是用sklearn這個組件來進行的演示的,並沒有用其他的例如TensorFlow來演示。
    from sklearn.preprocessing import LabelEncoder
    label_encoder = LabelEncoder() X_train_result_label[col] = label_encoder.fit_transform(X_train_result[col])#one column after one column

    咱們也可以看出,咱們得先創建一個LabelEncoder實例對象,然后對每一個categorical data的column分別應用encoder, 如果需要對多個categorical column進行lable encoding, 咱們得寫一個循環,分別對每一個column 進行label encoding。

  3.  one-hot encoding。這是一個大家可能最常用到的一種category encoding的方法,至少在我學習機器學習的過程中,這是最常見到的一種方式,那么到底什么是one-hot encoding呢?這里沒有一個官方的定義,最直接的方法就是先看一下下面的圖片,這是最直接的方式,也最簡單易懂                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 現在咱們來解釋一下,首先先計算出一個category column中一共有多少個categories,然后有多少category就創建多少個columns,每一個category對應一個column,最后在相對應的位置填充1,其他則填充0。故而新創建的dataframe中,每一行只有一個1 其他都是0。這也是one-hot encoding這個名字的來歷。那咱們來看看one hot encoding的代碼實現吧

    from sklearn.preprocessing import OneHotEncoder
    one_hot_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
    X_train_result_one_hot = pd.DataFrame(one_hot_encoder.fit_transform(X_train_result[object_cols]))

    和之前的label encoding一樣,它也需要引用sklearn這個庫,但是它是先實例化一個OneHotEncoder對象,然后用這個encoder一次性的應用於多個categorical columns, 而不像label encoding那樣要一個column一個column的調用。one hot encoding是categorical data encoding中最常用的技術了,但是在有些情況下也不是很適用,例如:如果一個categorical column的categories太多的話,例如1000個,10000個等等,那么它就不適用於one hot encoding了,因為有1000個categories,就會產生1000個columns,產生的數據就太大了,而且很容易會產生overfitting的情況。

  4. Count encoding

    這也是一種簡單而且高效的encoding方法,它是先計算一個categorical column中的每一個category出現的次數,然后就將這些category用次數來代替,同一個category被代替后,數值是一樣的,有點和series.values_countt()有點類似,大家滿滿體會一下哈。這種方式和label encoding一樣的簡單,而且Python也幫助咱們處理好了細節部分,咱們可以通過下面的方式直接調用它的接口進行計算

    import category_encoders as ce
    count_encoder = ce.CountEncoder()
    categorical_data_ce = count_encoder.fit_transform(ks[categorical_cols])

    從上面的代碼,咱們可以看出來,它也是encoder直接作用於多個categorical columns。

  5. Target encoding                                                                                                                                                                                                                                                                                                                                                                                                        Target encoding是根據target來計算category的,然后來替代的。那么它的具體流程是什么呢? 其實呢它是很簡單的,就是先看每一個category對應的target值,然后計算相對應的target的平均數,最后用這個平均數來代替每一個category。其實就是這么的so easy。老規矩,咱們先看看如何實現的

    import category_encoders as ce
    target_encoder = ce.TargetEncoder(cols=categorical_cols)
    target_encoder.fit_transform(train[categorical_cols], train.outcome)

    從上面咱們可以看出,整體的步驟和count encoding很相似。但是這種方法也有一個致命的弱點,那就是這里的encoding太過於依賴target了,有很大的可能會有data leakage的風險,target encoding與target有很強的correlation,就有很強的data leakage的風險。所以大家在選擇target encoding的時候一定要仔細考慮分析數據后在選擇。

總結:最后國際慣例咱們先來總結一下feature engineering的第一部分,就是category data和missing value的處理。上面的一些方法是最簡單常用的一些方法了,大家一定要熟悉理解應用,這里也設計到一些庫的使用,我會在后面詳細叫大家怎么用。missing value常用的處理方式是:1. dropping

      2. Imputation

      3. Extension to Imputation

然后category data的處理主要是下面的5中方式,這里大家一定要理解

      1. Dropping

      2. Label encoding

      3. one hot encoding (最常用)

      4. Count encoding

      5. Target encoding (risk of data leakage)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM