金融风控训练营赛题理解(task 3 特征工程)学习笔记

本学习笔记为阿里云天池龙珠计划Docker训练营的学习内容,学习链接为:https://github.com/datawhalechina/team-learning-data-mining/tree/master/FinancialRiskControl

学习目标:

  • 学习特征预处理、缺失值、异常值处理、数据分桶等特征处理方法
  • 学习特征交互、编码、选择的相应方法

首先,我们思考为什么要学习特征工程

答:特征工程,就是对原始数据进行一系列工程处理,将其提炼为特征,做为输入供算法和模型使用。特征工程的目的是去除原始数据中的杂质和冗余,设计更高效的特征以刻画求解的问题与预测模型之间的关系。[^1]

举一个例子,现在出一个二分类问题,请你使用逻辑回归,设计一个身材分类器。输入数据X:身高和体重 ,标签为Y:身材等级(胖,不胖)。显然,不能单纯的根据体重来判断一个人胖不胖,姚明很重,他胖吗?显然不是。针对这个问题,一个非常经典的特征工程是,BMI指数,BMI=体重/(身高^2)。 这样,通过BMI指数,就能非常显然地帮助我们,刻画一个人身材如何。甚至,你可以抛弃原始的体重和身高数据。[^2]

一、学习知识概要

  • 决策树一些介绍
  • 数据预处理
    • 缺失值的填充
    • 时间格式处理
    • 对象类型特征转换到数值
  • 异常值处理
    • 基于3σ原则
    • 基于箱型图
  • 数据分箱
    • 固定宽度分箱
    • 分位数分箱
      • 离散数值型数据分箱
      • 连续数值型数据分箱
    • 卡方分箱(选做作业)
  • 特征交互
    • 特征和特征之间组合
    • 特征和特征之间衍生
    • 其他特征衍生的尝试(选做作业)
  • 特征编码
    • one-hot编码
    • label-encoder编码
  • 特征选择
    • 1 Filter
    • 2 Wrapper (RFE)
    • 3 Embedded

二、学习内容

2.1 决策树一些介绍

因为该节内容涉及决策树,所以各位可以先了解一下决策树,它是一个非常常见并且优秀的机器学习算法,它易于理解、可解释性强,其可作为分类算法,也可用于回归模型。

  • 有兴趣深度了解的可以参考知乎博主阿泽的文章
  • 决策树的特性及优缺点可参考博主keepreder

先介绍该节内容主要用到的包:catboost
本质上是决策树算法
适用于:需要特别多的前期数据处理和特征数值化的任务

Catboost 一个超级简单实用的boost算法:https://www.jianshu.com/p/49ab87122562

  • 它自动采用特殊的方式处理类别型特征(categorical features)。首先对categorical features做一些统计,计算某个类别特征(category)出现的频率,之后加上超参数,生成新的数值型特征(numerical features)。这也是我在这里介绍这个算法最大的motivtion,有了catboost,再也不用手动处理类别型特征了。
  • catboost还使用了组合类别特征,可以利用到特征之间的联系,这极大的丰富了特征维度。
  • catboost的基模型采用的是对称树,同时计算leaf-value方式和传统的boosting算法也不一样,传统的boosting算法计算的是平均数,而catboost在这方面做了优化采用了其他的算法,这些改进都能防止模型过拟合。

其中对称树与普通的决策树有些许区别,大部分的GBM模型用的都是普通的决策树,对称树在GBM中主要有三点优势:

1、拟合模式相对简单,因为每一层都是一个判断条件

2、可以提高预测速度

3、对称树的结构本身比普通决策树自由度小,可以看作是加入了penalty,或者看作regularization

2.2 数据预处理

先导入包和数据集,并查找出数据中的对象特征和数值特征

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import datetime ##时间格式库
from tqdm import tqdm  #显示循环的进度条的库
from sklearn.preprocessing import LabelEncoder #提供了许多方便的用于做数据预处理工具
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2 #特征选择库
from sklearn.preprocessing import MinMaxScaler
import xgboost as xgb  #机器学习算法
import lightgbm as lgb  #机器学习算法
from catboost import CatBoostRegressor #机器学习算法
import warnings  #非致命提醒库
from sklearn.model_selection import StratifiedKFold, KFold  ##实现了多个交叉验证器类以及用于学习曲线、数据集分割的函数
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score, log_loss  #混淆矩阵模块
warnings.filterwarnings('ignore')
data_train =pd.read_csv('train.csv')
data_test_a = pd.read_csv('testA.csv')

数据大概长这样

id	loanAmnt	term	interestRate	installment	   grade	subGrade	employmentTitle	employmentLength	homeOwnership	...	 n5	  n6    n7	   n8	  n9	 n10	 n11	n12    n13	 n14
0	35000.0	      5	        19.52	       917.97	     E	       E2	          320.0	         2 years	          2	        ...	9.0	  8.0	4.0	   12.0	  2.0	 7.0	 0.0	0.0	   0.0	 2.0
numerical_fea = list(data_train.select_dtypes(exclude=['object']).columns) #数值列
category_fea = list(filter(lambda x: x not in numerical_fea,list(data_train.columns))) #类别特征列
label = 'isDefault'
numerical_fea.remove(label)
2.21 缺失值的填充

在比赛中数据预处理是必不可少的一部分,对于缺失值的填充往往会影响比赛的结果,在比赛中不妨尝试多种填充然后比较结果选择结果最优的一种;
比赛数据相比真实场景的数据相对要“干净”一些,但是还是会有一定的“脏”数据存在,清洗一些异常值往往会获得意想不到的效果。

  • 把所有缺失值替换为指定的值0

    data_train = data_train.fillna(0)

  • 用缺失值上面的值填充缺失值

    data_train = data_train.fillna(axis=0,method=‘ffill’)
    bfill是用缺失值下面的值填充缺失值
    二维中axis=0表示行,1表示列

  • 纵向用缺失值下面的值填充缺失值,且设置最多只填充两个连续的缺失值

    data_train = data_train.fillna(axis=0,method=‘bfill’,limit=2)

#查看缺失值情况
data_train.isnull().sum() #查看每列有多少缺失值
#以下展示部分结果

在这里插入图片描述

#按照平均数填充数值型特征
data_train[numerical_fea] = data_train[numerical_fea].fillna(data_train[numerical_fea].median())
data_test_a[numerical_fea] = data_test_a[numerical_fea].fillna(data_train[numerical_fea].median())
#按照众数填充对象型特征
data_train[category_fea] = data_train[category_fea].fillna(data_train[category_fea].mode())
data_test_a[category_fea] = data_test_a[category_fea].fillna(data_train[category_fea].mode())
#以下展示部分结果

在这里插入图片描述

值得注意的是结果中只有object变量‘employmentLength’没有被填充,下面的方法是将object对象转化成int或float(取出或替换数值),再进行填充,但还有一种方法是采用下面的代码:
data_train[‘employmentLength’].replace(np.nan,‘10 years’,inplace=True)
data_test_a[‘employmentLength’].replace(np.nan,‘10 years’,inplace=True)
它会将缺失值直接填用别的进行替换,方便后续一并处理

#查看类别特征
category_fea
-----------------------------------
['grade', 'subGrade', 'employmentLength', 'issueDate', 'earliesCreditLine']

category_fea:对象型类别特征需要进行预处理,其中[‘issueDate’]为时间格式特征。

2.22 时间格式处理
#转化成时间格式 将表中的时间转化成python可以处理的时间格式
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  #返回的是每个时间距开始时间的间隔天数
data_train['employmentLength'].value_counts(dropna=False).sort_index()
# sort_index(axis=0,ascending=True)按索引行排升序,sort_values()按值行排升序

在这里插入图片描述

#employmentLength 的样式如:2 years,是object类型,在上面没有被填充,所以我们应该把数字取出来,将他转化为int或float类型再进行填充
#要将其中的数字取出来
def employmentLength_to_int(s):
    if pd.isnull(s):
        return s
    else:
        return np.int8(s.split()[0]) #将数据转化为int8类型,节省内存
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) #replace是替换函数
    data['employmentLength'] = data['employmentLength'].apply(employmentLength_to_int) #apply()是应用函数

replace用法

data['employmentLength'].value_counts(dropna=False).sort_index()

在这里插入图片描述

  • 对earliesCreditLine进行预处理
data_train[
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值