赞助

机器学习-特征工程-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)

posted @ 2020-01-17 18:51  HappyPuppy  阅读(1716)  评论(0编辑  收藏  举报