数据挖掘实践(金融风控)——task3:特征工程
文章目录
- 一.数据预处理
- 1.缺失值填充
- 2.时间格式处理
- 3.对象类型特征转换到数值
- 4.类别特征处理
- 二.异常值处理
- 1.方法一:均方差
- 方法二:箱线图
- 三.数据分桶
- 1.固定宽度分箱
- 2.分位数分箱
- 3.卡方分箱及其他分箱方法的尝试
- 四.特征交互
- 五.特征编码
- 1.labelEncode 直接放入树模型中
- 2.逻辑回归等模型要单独增加的特征工程
- 六.特征选择
- 1.Filter:基于特征间的关系进行筛选
- 2.Wrapper (RFE)
- 3.Embedded
一.数据预处理
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')
1.缺失值填充
首先将变量划分为数值型变量和非数值型变量
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)
- 把所有缺失值替换为指定的值0
data_train = data_train.fillna(0) - 向用缺失值上面的值替换缺失值
data_train = data_train.fillna(axis=0,method=‘ffill’) - 纵向用缺失值下面的值替换缺失值,且设置最多只填充两个连续的缺失值
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())
2.时间格式处理
将具体日期转换为与2007-06-01这个日期的时间差
#转化成时间格式
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
3.对象类型特征转换到数值
原来的employmentLength变量为xx years,需要将字符串转换为具体整形变量
def employmentLength_to_int(s):if pd.isnull(s):return selse: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)
earliesCreditLine变量为日期,更改为年份
for data in [data_train, data_test_a]:data['earliesCreditLine'] = data['earliesCreditLine'].apply(lambda s: int(s[-4:]))
4.类别特征处理
# 像等级这种类别特征,是有优先级的可以labelencode或者自映射
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})# 类型数在2之上,又不是高维稀疏的,且纯分类特征
for data in [data_train, data_test_a]:data = pd.get_dummies(data, columns=['subGrade', 'homeOwnership', 'verificationStatus', 'purpose', 'regionCode'], drop_first=True)
二.异常值处理
当发现异常值后,一定要先分清是什么原因导致的异常值,然后再考虑如何处理。首先,如果这一异常值并不代表一种规律性的,而是极其偶然的现象,或者说你并不想研究这种偶然的现象,这时可以将其删除。其次,如果异常值存在且代表了一种真实存在的现象,那就不能随便删除。在现有的欺诈场景中很多时候欺诈数据本身相对于正常数据勒说就是异常的,我们要把这些异常点纳入,重新拟合模型,研究其规律。能用监督的用监督模型,不能用的还可以考虑用异常检测的算法来做。(注意test的数据不能删。)
1.方法一:均方差
在统计学中,如果一个数据分布近似正态,那么大约 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 * 3lower_rule = data_mean - outliers_cut_offupper_rule = data_mean + outliers_cut_offdata[fea+'_outliers'] = data[fea].apply(lambda x:str('异常值') if x > upper_rule or x < lower_rule else '正常值')return datadata_train = data_train.copy()
for fea in numerical_fea:data_train = find_outliers_by_3segama(data_train,fea)print(data_train[fea+'_outliers'].value_counts())print(data_train.groupby(fea+'_outliers')['isDefault'].sum())print('*'*10)#删除异常值
for fea in numerical_fea:data_train = data_train[data_train[fea+'_outliers']=='正常值']data_train = data_train.reset_index(drop=True)
方法二:箱线图
四分位数会将数据分为三个点和四个区间,IQR = Q3 -Q1,下触须=Q1 − 1.5x IQR,上触须=Q3 + 1.5x IQR;
三.数据分桶
- 目的:从模型效果上来看,特征分箱主要是为了降低变量的复杂性,减少变量噪音对模型的影响,提高自变量和因变量的相关度。从而使模型更加稳定。
- 对象:将连续变量离散化 / 将多状态的离散变量合并成少状态
- 原因:数据的特征内的值跨度可能比较大,对有监督和无监督中如k-均值聚类它使用欧氏距离作为相似度函数来测量数据点之间的相似度。都会造成大吃小的影响,其中一种解决方法是对计数值进行区间量化即数据分桶也叫做数据分箱,然后使用量化后的结果。
- 优点:
- 处理缺失值:当数据源可能存在缺失值,此时可以把null单独作为一个分箱。
- 处理异常值:当数据中存在离群点时,可以把其通过分箱离散化处理,从而提高变量的鲁棒性(抗干扰能力)。例如,age若出现200这种异常值,可分入“age > 60”这个分箱里,排除影响。
- 业务解释性:我们习惯于线性判断变量的作用,当x越来越大,y就越来越大。但实际x与y之间经常存在着非线性关系,此时可经过WOE变换。
- 基本原则:
(1)最小分箱占比不低于5%
(2)箱内不能全部是好客户
(3)连续箱单调
1.固定宽度分箱
# 通过除法映射到间隔均匀的分箱中,每个分箱的取值范围都是loanAmnt/1000
data['loanAmnt_bin1'] = np.floor_divide(data['loanAmnt'], 1000)## 通过对数函数映射到指数宽度分箱
data['loanAmnt_bin2'] = np.floor(np.log10(data['loanAmnt']))
2.分位数分箱
data['loanAmnt_bin3'] = pd.qcut(data['loanAmnt'], 10, labels=False)
3.卡方分箱及其他分箱方法的尝试
略
四.特征交互
交互特征的构造非常简单,使用起来却代价不菲。如果线性模型中包含有交互特征对,那它的训练时间和评分时间就会从 O(n) 增加到 O(n2),其中 n 是单一特征的数量。
for col in ['grade', 'subGrade']: temp_dict = data_train.groupby([col])['isDefault'].agg(['mean']).reset_index().rename(columns={'mean': col + '_target_mean'})temp_dict.index = temp_dict[col].valuestemp_dict = temp_dict[col + '_target_mean'].to_dict()data_train[col + '_target_mean'] = data_train[col].map(temp_dict)data_test_a[col + '_target_mean'] = data_test_a[col].map(temp_dict)# 其他衍生变量 mean 和 std
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')
五.特征编码
1.labelEncode 直接放入树模型中
#label-encode:subGrade,postCode,title
# 高维类别特征需要进行转换
for col in tqdm(['employmentTitle', 'postCode', 'title','subGrade']):le = LabelEncoder()le.fit(list(data_train[col].astype(str).values) + list(data_test_a[col].astype(str).values))data_train[col] = le.transform(list(data_train[col].astype(str).values))data_test_a[col] = le.transform(list(data_test_a[col].astype(str).values))
print('Label Encoding 完成')
2.逻辑回归等模型要单独增加的特征工程
- 对特征做归一化,去除相关性高的特征
- 归一化目的是让训练过程更好更快的收敛,避免特征大吃小的问题
- 去除相关性是增加模型的可解释性,加快预测过程。
# 举例归一化过程
#伪代码
for fea in [要归一化的特征列表]:data[fea] = ((data[fea] - np.min(data[fea])) / (np.max(data[fea]) - np.min(data[fea])))
六.特征选择
特征选择技术可以精简掉无用的特征,以降低最终模型的复杂性,它的最终目的是得到一个简约模型,在不降低预测准确率或对预测准确率影响不大的情况下提高计算速度。特征选择不是为了减少训练时间(实际上,一些技术会增加总体训练时间),而是为了减少模型评分时间。
1.Filter:基于特征间的关系进行筛选
- 方差选择法:先要计算各个特征的方差,然后根据设定的阈值,选择方差大于阈值的特征
from sklearn.feature_selection import VarianceThreshold
# 其中参数threshold为方差的阈值
VarianceThreshold(threshold=3).fit_transform(train,target_train)
- 相关系数法:皮尔森相关系数衡量变量之间的线性相关性。 结果的取值区间为 [-1,1] , -1 表示完全的负相关, +1表示完全的正相关,0 表示没有线性相关。
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)
- 卡方检验:卡方检验是用于检验自变量对因变量的相关性。 假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距。 其统计量如下: χ2=∑(A−T)2T,其中A为实际值,T为理论值(卡方只能运用在正定矩阵上,否则会报错)
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#参数k为选择的特征个数SelectKBest(chi2, k=5).fit_transform(train,target_train)
- 互信息法:互信息也是评价自变量对因变量的相关性的。 在feature_selection库的SelectKBest类结合最大信息系数法可以用于选择特征
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)
2.Wrapper (RFE)
递归特征消除法 递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。 在feature_selection库的RFE类可以用于选择特征
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.Embedded
- 基于惩罚项的特征选择法 使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。 在feature_selection库的SelectFromModel类结合逻辑回归模型可以用于选择特征
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也可用来作为基模型进行特征选择。 在feature_selection库的SelectFromModel类结合GBDT模型可以用于选择特征
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
#GBDT作为基模型的特征选择
SelectFromModel(GradientBoostingClassifier()).fit_transform(train,target_train)
本博客内容来自datawhale数据挖掘组队学习
数据挖掘实践(金融风控)——task3:特征工程相关推荐
- 金融风控实战——特征工程上
特征工程 业务建模流程 将业务抽象为分类or回归问题 定义标签,得到y 选取合适的样本,并匹配出全部的信息作为特征来源 特征工程+模型训练+模型评价与调优(相互之间可能会有交互) 输出模型报告 上线与 ...
- 零基础入门数据挖掘-Task3 特征工程
Datawhale 零基础入门数据挖掘-Task3 特征工程 前言 内容介绍 数据清洗 缺失值 异常值 箱型图 3∂原则 Box-Cox 变换 特征缩放 特征编码 特征工程 特征提取 特征选择 特征构 ...
- 【数据挖掘】金融风控 Task02 数据分析
[数据挖掘]金融风控 Task02 数据分析 1. 探索性数据分析(EDA)概述 1. 1 探索性数据分析概念 1.2 探索性数据分析目的 1.3 探索性数据分析(EDA)与传统统计分析(Classi ...
- 数据挖掘之金融风控-贷款违约预测 02数据分析
数据挖掘之金融风控-贷款违约预测 02数据分析 数据挖掘之金融风控-贷款违约预测 02数据分析 1. 学习目标 2. 学习内容 3. 学习过程 3.1 导入库并读取数据集 3.2 数据集基本信息 3. ...
- 【算法竞赛学习】二手车交易价格预测-Task3特征工程
二手车交易价格预测-Task3 特征工程 三. 特征工程目标 Tip:此部分为零基础入门数据挖掘的 Task3 特征工程部分,带你来了解各种特征工程以及分析方法,欢迎大家后续多多交流. 赛题:零基础入 ...
- 零基础入门数据挖掘之金融风控-贷款违约预测
零基础入门数据挖掘之金融风控-贷款违约预测 摘要 1.数据概况 2.数据读取 3.分类指标评价计算 摘要 在实践中学,很高兴有这次机会,与志同道合的小伙伴一起学习,本次主要通过天池实际比赛项目学习数据 ...
- Task3 特征工程(智慧海洋)
Task3 特征工程(智慧海洋) 这里写目录标题 Task3 特征工程(智慧海洋) 目标: 内容: 1. 特征工程概述 1.1 特征构建 1.2 特征提取和特征选择 2. 赛题特征工程 分箱特征 v. ...
- 【数据挖掘】金融风控 Task01 赛题理解
[数据挖掘]金融风控 Task01 赛题理解 1.赛题介绍 1.1赛题概况 1.2 数据概况 1.3 预测指标 1.3.1 混淆矩阵 1.3.2 准确率.精确率.召回率.F1 Score 1.3.3 ...
- 【算法竞赛学习】数字中国创新大赛智慧海洋建设-Task3特征工程
智慧海洋建设-Task3 特征工程 此部分为智慧海洋建设竞赛的特征工程模块,通过特征工程,可以最大限度地从原始数据中提取特征以供算法和模型使用.通俗而言,就是通过X,创造新的X'以获得更好的训练.预测 ...
- Task3 特征工程
智慧海洋竞赛实践 专题三 文章目录 智慧海洋竞赛实践 专题三 1. 特征工程概述 1.1 特征构建 1.2 特征提取和特征选择 2. 数据预处理 2.1 读入数据 2.2 基本处理 3. 基础特征 3 ...
最新文章
- STM32 基础系列教程 11 – ADC 轮询
- AIC-赤池信息准则、BIC-贝叶斯信息准则
- C语言再学习 -- printf、scanf占位符
- 每日程序C语言48-字符串排序
- 解决vlc-android播放http视频退出问题
- python 切片函数,python切片详解
- PSIM软件学习---03 电路的创建与仿真
- 解决Windows 2003终端服务许可证过期的办法
- HALCON 21.11:深度学习笔记---设置超参数(5)
- 原 Spring RestTemplate中几种常见的请求方式
- 利用Druid Monitor做数据库连接异常排查
- 十大城市11月房价止跌回升 上海涨幅最高
- openFOAM当中的收敛问题
- matlab遗传算法外卖配送优化(新的约束条件)【matlab优化算法十六】
- 解决Ubuntu终端里面显示路径名称太长
- PDF Reader Pro,功能强大的 PDF 阅读编辑器
- GAMES101-现代计算机图形学学习笔记(作业01)
- LAC+CELLID定位手机位置
- 静静默默,习惯一个人
- 吉利闯入“工业互联网”,李书福的“微笑曲线”能否如愿?