Task3-特征工程

2020-09-21  本文已影响0人  buaa徐侃

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

一、数据预处理

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。

附: 异常检测的方法

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
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

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/

分箱方法

三、特征选择

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)
上一篇下一篇

猜你喜欢

热点阅读