机器学习-特征工程-Feature generation 和 Feature selection

  1. 概述:上节我们说了特征工程是机器学习的一个核心内容。而后我们已经学习了特征工程中的基础内容,分别是missing value handling和categorical data encoding的一些方法技巧。可是光会前面的一些内容,还不足以应付实际的工做中的不少状况,例如若是我们的原始数据的features太多,我们应该选择那些features做为我们训练的features?或者我们的features太少了,我们能不能利用现有的features再创造出一些新的与我们的target有更加紧密联系的features呢?这些都是我们feature engineering中常常遇到的场景,这里涉及到的一些经常使用技术也是每个作机器学习或是数据分析的工程师必需要掌握的。上面提到的技术,我们一般叫作:feature generation和feature selection。下面我们就来讲一说这两个技术点吧
  2. Feature generation。对于这个技术点,其实没有什么诀窍,就是一个,深入理解我们的数据的意义再加上一点点创造力。你们是否是很懵逼,哈哈,这就完啦????哈哈固然不是啦,可是这一块缺失没有一个统一的模式,具备必定的随机性。可是经过总结,我们能够总结一下经常使用的模式,方便你们在应用的时候参考。                                                                                        2.1 Interaction。这个其实就是至关于交叉的意思,我们能够将几个features直接的拼接在一块儿,造成一个“有意思”的新的feature,记住必定要有意义的,不然你不但白搞了,甚至原来好好的数据都被你搞砸了,不要为了装逼而装逼,咱要装逼于无形之中。那么这个有什么意义呢?首先它能将多个columns装换成一个column,方便我们的数据处理;其次在有些特定的数据中,这种interaction更加能反映出数据的本质。具体怎么操做了,我们经过一个简单的代码来展现,注意我只截取了我代码的一部分,默认数据都已经加载完毕,因此不要纠结个人代码的变量和数据哈,你们主要看过程和思路
    interactions = data_raw["category"]+"_"+data_raw["country"]
    baseline_data = baseline_data.assign(category_country = label_encoder.fit_transform(interactions))

    上面的第一句代码就是我们interaction的部分,第二句是讲interaction事后的数据label encoding而且加入到我们的数据集里面,简单明了。上面是将原始数据中的category 和 country链接在一块儿从而造成一个新的feature                                       2.2 numerical transforming。这是什么意思呢,对于有些numerical data的columns,他们的数据分布是很不均匀的,或者说他们的数值太大或者过小,有的时候不适合我们的数据的训练,可能会出现vanishing gradient或者gradient explode的状况。具体啥叫vanishing gradient和gradient exploding,我们在后面的内容在慢慢解释。暂时只须要知道这是个很麻烦的事情就行了,会致使我们训练的模型不那么牛逼就好了。那么我们经过什么方法解决呢?这里主要经过一些常见的数学的方式来解决,例如用log 或者 sqrt等等方式。我们能够经过下面的代码来简单的展现一下html

    np.sqrt(baseline_data['goal'])
    np.log(baseline_data['goal'])

    从上面我们能够看出,这里我们主要仍是经过numpy里面提供的API进行处理的,很是简单,简单跟1同样,好了这里就说到这了。    对了,忘记一个事儿,就是numerical transforming在tree-based模型中没有什么卵用的,由于tree-based的全部模型都是scale invariant的,就是tree-based模型都是不care数据的大小分布的。                                                                           2.3 rolling。这个就比较高级一点啦(相比前两种方式),首先我们先要明白rolling的概念,其实rolling就是至关于在我们的数据(series)上面卡上一个fixed-size的小window,而后对于这个window覆盖的数据进行一些简单的计算,例如:counting,mean,sum等等。若是你们仍是以为不懂,我把它的官方连接贴在这里,你们本身去看看,里面还有不少实例:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.rolling.html#pandas.Series.rolling 。那么我先写一个简单的小例子给你们参考一下哈api

    launched = pd.Series(data_raw.index,data_raw.launched,name="count_7_days").sort_index()
    count_7_days = launched.rolling('7d').count()
    count_7_days.index = launched.values
    count_7_days
    = count_7_days.reindex(data_raw.index)

    我先简单解释一下上面代码的意思哈,第一句是让时间做为这个series的index,第二句rolling是计算最近7天的的数量,第三第四句是讲数据还原到以前的index的顺序,房间从新join到原来的数据集中。那么rolling这种方式通常在什么状况下用呢?通常在你的数据有datetime的时候,或者前面数据会影响到后面的结果的时候,你们能够考虑一下下,可是这个是不必定的,仍是须要你们有必定的creativity的。例如上面的例子就是统计最近7天一共上传的APP的数量,来判断某一个APP是否被下载的应用场景。通常状况下,最近上传的APP数量太多,被下载的几率就越低,因此他们仍是有必定关联关系的。因此我generate一个新的feature仍是有必定道理的。                                                                                                                                                       2.4 Time delta。从这个命名中我们能够知道,这个跟time确定有关系,这个你们猜的很对。time delta也是有必定随机性的,有时须要有时也不须要,也是要根据实际的数据的特性来决定的,甚至是根据工程师本身来决定的,跟上面的rolling有点类似。为了方便解释这其中的细节,我也是直接来一个例子而后慢慢解释app

    def time_since_last_project_same_category(series):
        return series.diff().dt.total_seconds()/3600
    df = data_raw[['category','launched']].sort_values('launched')
    group_category = df.groupby('category')
    timedeltas = group_category.transform(time_since_last_project_same_category)
    timedeltas = timedeltas.fillna(timedeltas.mean()).reindex(baseline_data.index)

    上面前两行是一个计算相邻datatime之间的相差多少个小时,第三行建立一个按照排序好的launched time为index的dataframe, 第四行是按照category的条件来group前面建立的df, 第五行是计算group里面相邻数据之间的time delta,而且返回一个series, 第六行是填充这些空数据,而且按照原始数据的方式index从新排序方便加入到原始数据。流程就这样结束了。上面的场景是计算同一个category相邻app上传的时间差,这个其实也是会影响到我们的APP是否被下载的因素。因此这个也是我们的一个creativity,实际状况中变幻无穷,必定要根据实际状况来定,不能为了装逼而装逼,必定要根据实际的业务须要,不然拔苗助长。 好了,其实关于feature generation还有不少种方式,例若有些事计算两个columns之间的差值,取模等等,这里没有统一的标准,惟一的捷径和key就是我们必定得理解我们每个columns和dataset的实际业务的意思,不然再牛逼的generation也拯救不了你。下面我们进入到这一章的最后一节feature selection吧。dom

  3. Feature selection。当我们吧missing value, categorical data handling, feature generation这个繁杂的步骤都走完了,我们就来到了feature engineering的最后一步了,那就是feature selection。根据意思就是我们到底我们最后选择哪些数据来训练我们的模型,数据选的好,模型的适用范围,效率,准确性都更好,不然我们前面的努力可能会毁于一旦。关于feature selection我我的以为是我的经验和一些selection技术的结合,才能选出最好的features做为训练的样本。我的经验,就是工程师本身对于数据的理解程度,有些features一看就和target没有半毛钱的关系,我们确定直接排除这些features,例如我们的手机设备号和手机价格一看就一点关系都没有,我们确定直接删除手机设备号这个feature;有些features一看就和target有很强的关系,例如手机内存大小和手机的价格一看就有很强的关联性,因此我们确定要选择这个内存的feature。我的经验以外还有不少模棱两可的features怎么办呢?就跟我前面说的那样,我们还能够用一些技术手段来选择。下面我们来介绍两种经常使用的feature selection的技术。                                                                                                                                                   3.1 F-classification method。这种方式是单独计算每个column和target的关联性,而后选出关联性最强的f个columns,这里f的值是我们自定义的。具体的实现细节我们不须要了解的那么深,由于sklearn已经帮助我们造好轮子了,从下面的代码,我们来感觉一下它的魅力吧
    from sklearn.feature_selection import SelectKBest, f_classif
    selector = SelectKBest(score_func = f_classif, k = 5)
    train,valid,test = get_data_splits(baseline_data, 0.1)
    feature_cols = train.columns.drop("outcome")
    X_new = selector.fit_transform(train[feature_cols],train["outcome"] )

    #get back to the features we kept
    features = pd.DataFrame(selector.inverse_transform(X_new), index = train.index, columns = feature_cols)
    #drop the columns that the values are all 0s
    feature_cols_final = features.columns[features.var()!=0]
    features_final = features[feature_cols_final]机器学习

    从上面的代码我们能够看出来,首先得从sklearn.feature_selection这个模块中引进SelectKBest和f_classif两个子模块;第二步就是建立一个Selector实例对象,这个selector最终返回多少个features是经过我们的参数K来控制的,selector的最终选择哪些features也是经过f_classif这个函数来控制的;最后就是这个selector的transform了,将features和target做为参数分别传递给他,他会自动搞定,而且返回K个features, 而后再将numpy array返回到dataframe的格式。这种方式的只能计算出每个feature和target的linear dependency,并不能一次性包括全部的features进行关联性计算。                                                       3.2 L1 Regression。L1 Regression能够直接包括全部的features一次性的计算这个columns和target的关联性。关联性越强,数值越大。它不须要制定最后返回多少个features,它是根据L1的结果自动帮助我们features。可是它的运行速度要远远慢于上面k-classif的方法,但是好处就是通常状况下L1 Regression的运行结果要好于K-classif, 但也不必定澳,只能说大部分状况是这样的。函数

    from sklearn.linear_model import LogisticRegression
    from sklearn.feature_selection import SelectFromModel
    train,valid,test = get_data_splits(baseline_data, 0.1)
    X, y = train[train.columns.drop("outcome")], train["outcome"]
    logistic_model = LogisticRegression(C=1, penalty="l1", random_state=7).fit(X,y)
    selector = SelectFromModel(logistic_model,prefit=True)
    X_new = selector.transform(X)
    features = pd.DataFrame(selector.inverse_transform(X_new),index = train.index, columns = feature_cols)
    feature_cols_final = features.columns[features.var()!=0]

    总结:上面就是通常的的特征工程的feature selection和feature generation的通常方法,我们上面讲了不少种的方式,实际状况中具体选择哪种仍是要根据实际状况,必定不要死读书。feature generation通常就是interaction,numerical generation,rolling和time delta四种方式。feature selection通常用到的技术手段就是就是f-classif和L1 regression几种方式。学习

相关文章
相关标签/搜索