特征工程

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。

常见的特征工程包括:

1.异常值处理

  • 通过箱线图(或 3-Sigma)分析删除异常值;
  • BOX-COX 转换(处理有偏分布);
  • 长尾截断;

2. 缺失值处理

  • 不处理(针对类似 XGBoost 等树模型);
  • 删除(缺失数据太多);
  • 插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等;
  • 分箱,缺失值一个箱;

3.特征归一化/标准化

  • 标准化(转换为标准正态分布);
  • 归一化(抓换到 [0,1] 区间);
  • 针对幂律分布,可以采用公式: l o g ( 1 + x 1 + m e d i a n ) log(\frac{1+x}{1+median}) log(1+median1+x)

4. 数据分桶

  • 等频分桶;
  • 等距分桶;
  • Best-KS 分桶(类似利用基尼指数进行二分类);
  • 卡方分桶;

5. 特征构造

  • 构造统计量特征,报告计数、求和、比例、标准差等;
  • 时间特征,包括相对时间和绝对时间,节假日,双休日等;
  • 地理信息,包括分箱,分布编码等方法;
  • 非线性变换,包括 log/ 平方/ 根号等;
  • 特征组合,特征交叉;
  • 其他。

6. 特征选择

完成数据预处理后,需要选择有意义的特征输入模型进行训练。通常从以下两个方面考虑来选择特征:
(1) . 特征是否发散:如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,分布严重失衡,那这个特征对于样本的区分没有太大作用。
(2) . 特征与目标的相关性:应当优选选择与目标相关性高的特征。

  • 过滤式(filter):按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。
    * Relief
    * 方差选择法
    * 相关系数法
    * 卡方检验法
    * 信息增益、互信息法
  • 包裹式(wrapper):根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
    * LVM(Las Vegas Wrapper)
    * 递归特征消除法
  • 嵌入式(embedding):先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。
    * 基于惩罚项的特征选择法(正则化,L1:Lasso;L2:Ridge)
    * 基于树模型的特征选择法(熵、信息增益)

7. 降维

  • 主成分分析法(PCA)
  • 线性判别分析法(LDA)
  • 独立成分分析法( ICA)

特征标准化、特征选择、降维等可直接调用sklearn.preprocessing,sklearn.feature_selection和sklearn.decomposition处理。

部分参考代码

异常值处理

def outliers_proc(data, col_name, scale=3):
    """
    用于清洗异常值,默认用 box_plot(scale=3)进行清洗
    :param data: 接收 pandas 数据格式
    :param col_name: pandas 列名
    :param scale: 尺度
    :return:
    """

    def box_plot_outliers(data_ser, box_scale):
        """
        利用箱线图去除异常值
        :param data_ser: 接收 pandas.Series 数据格式
        :param box_scale: 箱线图尺度,
        :return:
        """
        iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
        val_low = data_ser.quantile(0.25) - iqr
        val_up = data_ser.quantile(0.75) + iqr
        rule_low = (data_ser < val_low)
        rule_up = (data_ser > val_up)
        return (rule_low, rule_up), (val_low, val_up)

    data_n = data.copy()
    data_series = data_n[col_name]
    rule, value = box_plot_outliers(data_series, box_scale=scale)
    index = np.arange(data_series.shape[0])[rule[0] | rule[1]]
    print("Delete number is: {}".format(len(index)))
    data_n = data_n.drop(index)
    data_n.reset_index(drop=True, inplace=True)
    print("Now column number is: {}".format(data_n.shape[0]))
    index_low = np.arange(data_series.shape[0])[rule[0]]
    outliers = data_series.iloc[index_low]
    print("Description of data less than the lower bound is:")
    print(pd.Series(outliers).describe())
    index_up = np.arange(data_series.shape[0])[rule[1]]
    outliers = data_series.iloc[index_up]
    print("Description of data larger than the upper bound is:")
    print(pd.Series(outliers).describe())
    
    fig, ax = plt.subplots(1, 2, figsize=(10, 7))
    sns.boxplot(y=data[col_name], data=data, palette="Set1", ax=ax[0])
    sns.boxplot(y=data_n[col_name], data=data_n, palette="Set1", ax=ax[1])
    return data_n

高度共线性变量处理

#以下代码
#通过删除所比较的两个特征之一,根据我们为相关系数选择的阈值来移除共线特征
#它还打印其删除的相关性,以便我们看到调整阈值的效果。
#此处将阈值设置为0.9,如果特征之间的相关系数超过该值,则删除一对特征中的一个。 
def remove_collinear_features(x, threshold):
    '''
    Objective:
       删除数据帧中相关系数大于阈值的共线特征。 删除共线特征可以帮助模型泛化并提高模型的可解释性。
        
    Inputs: 
        阈值:删除任何相关性大于此值的特征
    
    Output: 
        仅包含非高共线特征的数据帧
    '''
    
    # 在数据副本上进行操作
    x = x.copy()
    
    # 仅对v_系列特征进行处理
    x_numeric = x[['v_0', 'v_1', 'v_2', 'v_3', 'v_4', 'v_5', 'v_6', 'v_7',
                    'v_8', 'v_9', 'v_10', 'v_11', 'v_12', 'v_13', 'v_14']]
    
    
    # 计算相关性矩阵
    corr_matrix = x_numeric.corr()
    iters = range(len(corr_matrix.columns) - 1)
    drop_cols = []

    # 迭代相关性矩阵并比较相关性
    for i in iters:
        for j in range(i):
            item = corr_matrix.iloc[j:(j+1), (i+1):(i+2)]
            col = item.columns
            row = item.index
            val = abs(item.values)
            
            # 如果相关性超过阈值
            if val >= threshold:
                # 打印有相关性的特征和相关值
                print(col.values[0], "|", row.values[0], "|", round(val[0][0], 3))
                drop_cols.append(col.values[0])

    # 删除每对相关列中的一个
    drops = set(drop_cols)
    x = x.drop(columns = drops)
    
    # 将得分添加回数据

               
    return x
异常处理: 通过箱线图(或 3-Sigma)分析删除异常值; BOX-COX 转换(处理有偏分布); 长尾截断; 特征归一化/标准化: 标准化(转换为标准正态分布); 归一化(抓换到 [0,1] 区间); 针对幂律分布,可以取log 数据分桶: 等频分桶; 等距分桶; Best-KS 分桶(类似利用基尼指数进行二分类); 卡方分桶; 缺失值处理: 不处理(针对类似 XGBoost 等树模型); 删除(缺失数据太多); 插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等; 分箱,缺失值一个箱; 特征构造: 构造统计量特征,报告计数、求和、比例、标准差等; 时间特征,包括相对时间和绝对时间,节假日,双休日等; 地理信息,包括分箱,分布编码等方法; 非线性变换,包括 log/ 平方/ 根号等; 特征组合,特征交叉; 仁者见仁,智者见智。 特征筛选 过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系数法/卡方检验法/互信息法; 包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有 LVM(Las Vegas Wrapper) ; 嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有 lasso 回归; 降维 PCA/ LDA/ ICA; 特征选择也是一种降维。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值