美文网首页
Task3-特征工程

Task3-特征工程

作者: buaa徐侃 | 来源:发表于2020-09-21 22:09 被阅读0次

    这一部分是特征工程,主要是数据处理以及变量衍生两大块内容。机器学习比赛中,发现一个好的特征,往往就能带来非常大的提升,因而在整个项目周期中,可以安排一半时间考虑特征工程相关的内容,这个步骤是最需要静下心来仔细挖掘的。

    一、数据预处理

    1.1 缺失值

    数据的缺失是经常遇到的情况,尤其在实际业务数据中(比赛数据相对更加饱满,可能已经被人为处理过)。但同时,不可以盲目的进行缺失值填充。数据的缺失也蕴含着一定的信息,不假思索的进行填充,可能导致最终模型效果的下降和数据的污染(毕竟填充数据也是人工经验为主)。
    在金融风控中,评分卡模型会单独对 NULL(None/空)等列单独进行WOE计算,视为一个单独的分箱,这样能保留数据缺失背后的含义。
    同时在目前流行的集成树模型中,其算法都内置了对于缺失值的处理(会选择使得增益最大的分裂方向),因而我认为现阶段可以不处理缺失值。
    可能在时间序列相关模型中,可以尝试进行缺失值填充(用缺失值前一位来填充,表示前1天数据),这个后续可以继续学习一下。
    附:一些常见的处理方法


    image.png

    1.2 异常值

    异常值同样是数据处理会经常遇到的情况。对于一些明由于系统异常导致的数据错误情况,且错误数据量非常少,那我们可以直接剔除数据。但更多时候,由于本身数据量较少,简单粗暴的剔除这些看似异常的数据,可能会降低模型预测能力(毕竟数据越多模型一般也会越好一些)。因而我们在保留这些异常数据的前提下,对异常数据进行一些处理。
    这些异常情况,包含了数据过大、过小,还有一些数值偏离了本身的业务含义范围,都需要分别考虑。

    1.2.1 WOE转换

    WOE可以将某一个区间内的数值都映射到一个数值中,例如将年龄区间[60,60+) 范围内的数值都映射到0.12,那么遇到一个年龄99的人,可以直接映射到0.12这个数值。

    1.2.2 盖帽?

    不知道学名是啥,将大于某个阈值的数值都直接设置该阈值。例如年龄设置了60岁的阈值,那在数据中把超过60岁的情况都直接赋值为60。

    附: 异常检测的方法

    • 3\sigma法则
      在统计学中,如果一个数据分布近似正态,那么大约 68% 的数据值会在均值的一个标准差范围内,大约 95% 会在两个标准差范围内,大约 99.7% 会在三个标准差范围内。因而可以将超过这个范围的数值作为异常值
    def find_outliers_by_3segama(data,fea):
        data_std = np.std(data[fea])
        data_mean = np.mean(data[fea])
        outliers_cut_off = data_std * 3
        lower_rule = data_mean - outliers_cut_off
        upper_rule = data_mean + outliers_cut_off
        data[fea+'_outliers'] = data[fea].apply(lambda x:str('异常值') if x > upper_rule or x <lower_rule else '正常值')
        return data
    
    • 箱型图
      四分位数会将数据分为三个点和四个区间,IQR = Q3 -Q1,下触须=Q1 − 1.5x IQR,上触须=Q3+ 1.5x IQR;超过这个范围的都可以认为是异常值。

    • Isolation Forest

    from sklearn.ensemble import IsolationForest
    import pandas as pd
    
    clf = IsolationForest(max_samples=100, random_state=42)
    table = pd.concat([input_table['Mean(ArrDelay)']], axis=1)
    clf.fit(table)
    output_table = pd.DataFrame(clf.predict(table))```python
    
    • DBSCAN
      DBSCAN聚类方法,有时间再补上

    1.3 时间类型处理

    1.3.1 issueDate

    做时间差,代码如下:

    for data in [data_train, data_test_a]:
        data['issueDate'] = pd.to_datetime(data['issueDate'],format='%Y-%m-%d')
        startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d')
        #构造时间特征
        data['issueDateDT'] = data['issueDate'].apply(lambda x: x-startdate).dt.days
    

    1.3.2 employmentLength

    将2 years 转换为2,去除后缀 years,映射到数值型。

    def employmentLength_to_int(s):
         if pd.isnull(s):
              return s
         else:
              return np.int8(s.split()[0])
    for data in [data_train, data_test_a]:
         data['employmentLength'].replace(to_replace='10+ years', value='10 years', inplace=True)
         data['employmentLength'].replace('< 1 year', '0 years', inplace=True)
         data['employmentLength'] = data['employmentLength'].apply(employmentLength_to_int)
    

    1.4 类别特征处理

    1.4.1 有序类别

    grade/subgrade

    for data in [data_train, data_test_a]:
        data['grade'] = data['grade'].map({'A':1,'B':2,'C':3,'D':4,'E':5,'F':6,'G':7})
    

    1.4.2 无序类别

    for data in [data_train, data_test_a]:
         data = pd.get_dummies(data, columns=[ 'homeOwnership', 'verificationStatus','purpose', 'regionCode'], drop_first=True)
    

    二、变量衍生

    2.1 结合业务含义

    使用底层数据来衍生变量时可以事先设计好框架,一般可以按照 时间范围+统计变量+统计指标,然后做笛卡尔积。
    但是本次比赛提供的数据,相对比较完善,后续可以用来加工的比较少。
    这部分后续在补充。

    2.2 特征交互

    这种方式相对暴力,直接两两特征选择,然后进行加减乘除,得到交互特征。
    此外可以在原始数据基础上,结合均值、标准差、斜度等指标,得到一系列统计指标

    for df in [data_train, data_test_a]:
        for item in ['n0','n1','n2','n2.1','n4','n5','n6','n7','n8','n9','n10','n11','n12','n13','n14']:
            df['grade_to_mean_' + item] = df['grade'] / df.groupby([item])['grade'].transform('mean')
            df['grade_to_std_' + item] = df['grade'] / df.groupby([item])['grade'].transform('std')
    

    附 WOE 转换

    说明:https://zhuanlan.zhihu.com/p/80134853/

    • 目的
      从模型效果上来看,特征分箱主要是为了降低变量的复杂性,减少变量噪音对模型的影响,提高自变量
      和因变量的相关度。从而使模型更加稳定。
    • 优点
      a. 处理缺失值:当数据源可能存在缺失值,此时可以把null单独作为一个分箱。
      b. 处理异常值:当数据中存在离群点时,可以把其通过分箱离散化处理,从而提高变量的鲁棒性(抗干扰
      能力)。例如,age若出现200这种异常值,可分入“age > 60”这个分箱里,排除影响。
      c. 业务解释性:我们习惯于线性判断变量的作用,当x越来越大,y就越来越大。但实际x与y之间经常存在
      着非线性关系,此时可经过WOE变换。

    分箱方法

    • 等频
    • 等距
    • 卡方分箱
    • BestKS分箱(常用)

    三、特征选择

    3.1 Filter

    3.1.1 方差选择法

    from sklearn.feature_selection import VarianceThreshold
    #其中参数threshold为方差的阈值
    VarianceThreshold(threshold=3).fit_transform(train,target_train)
    

    3.1.2 相关系数法

    from sklearn.feature_selection import SelectKBest
    from scipy.stats import pearsonr
    #选择K个最好的特征,返回选择特征后的数据
    #第一个参数为计算评估特征是否好的函数,该函数输入特征矩阵和目标向量,
    #输出二元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数
    #参数k为选择的特征个数
    SelectKBest(k=5).fit_transform(train,target_train) 
    

    3.1.3 互信息

    from sklearn.feature_selection import SelectKBest
    from minepy import MINE
    #由于MINE的设计不是函数式的,定义mic方法将其为函数式的,
    #返回一个二元组,二元组的第2项设置成固定的P值0.5
    def mic(x, y):
        m = MINE()
        m.compute_score(x, y)
        return (m.mic(), 0.5)
    #参数k为选择的特征个数
    SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T,k=2).fit_transform(train,target_train)
    

    3.2 Wrapper

    递归特征消除法 递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,
    再基于新的特征集进行下一轮训练。在feature_selection库的SelectFromModel类结合逻辑回归模型可以用于选择特征,

    from sklearn.feature_selection import RFE
    from sklearn.linear_model import LogisticRegression
    #递归特征消除法,返回特征选择后的数据
    #参数estimator为基模型
    #参数n_features_to_select为选择的特征个数
    RFE(estimator=LogisticRegression(),
    n_features_to_select=2).fit_transform(train,target_train)
    

    3.3 Embedded

    基于惩罚项的特征选择法 使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。

    from sklearn.feature_selection import SelectFromModel
    from sklearn.linear_model import LogisticRegression
    #带L1惩罚项的逻辑回归作为基模型的特征选择
    SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(train,target_train)
    

    基于树模型的特征选择 树模型中GBDT也可用来作为基模型进行特征选择。

    from sklearn.feature_selection import SelectFromModel
    from sklearn.ensemble import GradientBoostingClassifier
    #GBDT作为基模型的特征选择
    SelectFromModel(GradientBoostingClassifier()).fit_transform(train,target_train)
    

    相关文章

      网友评论

          本文标题:Task3-特征工程

          本文链接:https://www.haomeiwen.com/subject/zlwbyktx.html