阿里云天池金融风控训练营【Task3 特征工程】学习笔记
金融风控训练营 Task3 特征工程 学习笔记
这份学习笔记是关于阿里云天池·龙珠计划金融风控训练营的内容。
具体链接如下:
https://tianchi.aliyun.com/specials/activity/promotion/aicampfr
一、学习知识点概要
文章目录
- 金融风控训练营 Task3 特征工程 学习笔记
-
【
-
数据分桶
-
特征交互
-
特征编码
-
特征选择
-
三、学习问题与解答
-
四、学习思考与总结
-
-
二、学习内容
1. 内容介绍
-
数据预处理
- 缺失值的填充
- 时间格式处理
- 对象类型特征转换到数值
-
异常值处理
- 基于3segama原则
- 基于箱型图
-
数据的分类整理
-
等宽区间划分
-
百分位数值分类
- 离散数值数据的分类整理
- 连续数值数据的区间划分
-
卡方分箱(选做作业)
-
基于不同特征求组合;基于不同特征求衍生;额外基于不同特征求探索(选做作业)
-
特征编码
- one-hot编码
- label-encode编码
-
特征选择
- 1 Filter
- 2 Wrapper (RFE)
- 3 Embedded
2. 代码示例
1. 此次学习所用到的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns #基于matplotlib的图形可视化
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')
2. 特征预处理
缺失值处理
参考于:
1.
填充固定值
df.fillna(0,inplace=True) #填充0
df.fillna(df.mean(),inplace=True) #填充均值
df.fillna(df.median(),inplace=True) #填充中位数
df.fillna(df.mode(),inplace=True) #填充众数
填充上下条的数据
df.fillna(method='pad',inplace=True) #填充前一条数据的值,但前一条不一定有值
df.fillna(method='bfill',inplace=True) #填充后一条数据的值,但后一条不一定有值
填充插值得到的数据
用插值法拟合出缺失的数据,再进行填充
for f in features: #插值法填充
df[f] = df[f].interpolate()
df.dropna(inplace=True)
填充KNN数据
填充近邻的数据,用knn计算临近的k个数据,再填充均值
from fancyimpute import KNN
train_data_x = pd.DataFrame(KNN(k=6).fit_transform(train_data_x), columns=features)
填充模型预测的值
把缺失值作为新的label,建立模型得到预测值,然后进行填充
选择具有适当缺失值数量的特征应用随机森林算法RF来进行拟合,并对其余缺失特征以均值进行填充
时间格式处理
#转化成时间格式
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
类别特征处理
# 部分类别特征
cate_features = ['grade', 'subGrade', 'employmentTitle', 'homeOwnership', 'verificationStatus', 'purpose', 'postCode', 'regionCode', \
'applicationType', 'initialListStatus', 'title', 'policyCode']
for f in cate_features:
print(f, '类型数:', data[f].nunique())
pandas.get_dummies 官方文档

3. 异常值处理
发现异常值:先分清是什么原因导致 → 再考虑如何处理
①极其偶然的现象,或者不需要研究这种偶然的现象 → 直接删除
②异常值存在且代表了一种真实存在的现象 → 不能随便删除
将这些异常点纳入分析,并基于监督学习与异常检测算法重新训练模型结构以揭示其分布规律
(1)删除含有异常值的记录:直接删除
(2)视为缺失值:利用缺失值处理的方法进行处理
(3)平均值修正:用前后两个观测值的平均值修正该异常值
发现异常值主要有以下几种方法:
该文章深入探讨了机器学习领域中常见的正则化方法及其应用效果对比研究。具体而言,在线学习算法与批量学习算法在处理大数据集时展现出显著差异性:在线学习算法通过逐步更新权重矩阵W实现了数据处理效率的最大优化;而批量学习算法基于最小二乘法原理构建损失函数框架并结合梯度下降优化器实现了分类器性能的最大化提升;基于最小二乘法原理构建损失函数框架并结合梯度下降优化器实现了分类器性能的最大化提升;基于最小二乘法原理构建损失函数框架并结合梯度下降优化器实现了分类器性能的最大化提升
3∂原则

###正态分布标准差
import numpy as np
import matplotlib.pyplot as plt
def find_outliter_std(random_data,c):
anomalies = []
random_data_std = np.std(random_data)
random_data_mean = np.mean(random_data)
anomaly_cut_off = random_data_std * c
lower_limit = random_data_mean - anomaly_cut_off
upper_limit = random_data_mean + anomaly_cut_off
#print(lower_limit)
for outlier in random_data:
if outlier > upper_limit or outlier < lower_limit:
anomalies.append(1)
else:
anomalies.append(0)
res4=pd.merge(pd.DataFrame(random_data),pd.DataFrame(anomalies),left_index=True,right_index=True)
res4.columns=['values','is_outliter']
return res4
箱线图
import numpy as np
import pandas as pd
import scipy
def find_outliter_quantile(random_data,c):
anomalies = []
random_data_q1 = np.quantile(random_data,0.25)
random_data_q3 = np.quantile(random_data,0.75)
anomaly_cut_off = (random_data_q3-random_data_q1) * c #c一般为1.5或者3,但是个人认为可以根据实际业务情况进行更改,比如涨幅超过1倍的情况就是极端异常的情况,那我们可以c取值为1
lower_limit = random_data_q1 - anomaly_cut_off
upper_limit = random_data_q3 + anomaly_cut_off
for outlier in random_data:
if outlier > upper_limit or outlier < lower_limit:
anomalies.append(1)
else:
anomalies.append(0)
res5=pd.merge(pd.DataFrame(random_data),pd.DataFrame(anomalies),left_index=True,right_index=True)
res5.columns=['values','is_outliter']
return res5
if __name__=='__main__':
data=np.array([1338,1338,2,1047,688,520,1408,225,206,280])
outliers=find_outliter_quantile(random_data,c)
DBSCAN
from sklearn.cluster import DBSCAN
import numpy as np
def dbscan(random_data):
outlier_detection = DBSCAN(min_samples = 2, eps = 3)
clusters = outlier_detection.fit_predict(random_data)
print (list(clusters).count(-1))
res2=pd.DataFrame(random_data,list(clusters)).reset_index()
res2.columns=['is_outliter','values']
return res2
k-means
####k-means方法异常点检测#####
from sklearn import preprocessing
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def kmeans(data):
data_scale = preprocessing.scale(data)#处理后需要转为dataframe,或者直接手动求均值、方差转换
model = KMeans(n_clusters = 2,max_iter = 1000) # k=2,一类认为是异常的,一类是不异常的,最大迭代次数可以根据实际情况进行修改
model.fit(data_scale)
data_scale = pd.DataFrame(data_scale)
#data_scale = pd.DataFrame(data_scale,index = data.index)
data_scale['labels'] = model.labels_
res3=pd.merge(data_scale,pd.DataFrame(data),left_index=True,right_index=True)
res3.columns=['distance','labels','values']
#print (res3)
return res3
孤立森林
#孤立森林
#最好对数据集去重,在确定孤立点,因为如果多个异常点聚集,那么就不孤立了
from sklearn.ensemble import IsolationForest
import numpy as np
def isolationforest(random_data):
clf = IsolationForest(behaviour = 'new',max_samples='auto', random_state = 1, contamination= 'auto')
preds = clf.fit_predict(random_data)
print (list(preds).count(-1))
res1=pd.DataFrame(random_data,list(preds)).reset_index()
res1.columns=['is_outliter','values']
return res1
数据分桶
特征分箱目的
降低变量的复杂性
减少变量噪音对模型的影响
提高自变量和因变量的相关度
使模型更加稳定。
数据分桶的对象:
将连续变量离散化
将多状态的离散变量合并成少状态
分箱的原因:
值跨度大,造成大吃小的影响
分箱的优点:
处理缺失值:将缺失值归为一类单独分箱
处理异常值:在数据集中出现离群点时,可以通过分箱方法将其离散化处理以提升变量的鲁棒性(抗干扰能力),即减少对结果的影响
业务解释性:实际中x与y之间可能存在非线性关系,在这种情况下可以通过WOE变换来建立模型
!分箱的基本原则:
(1)最小分箱占比不低于5%
(2)箱内不能全部是好客户
(3)连续箱单调
固定宽度分箱:按10的幂分组
# 通过除法映射到间隔均匀的分箱中,每个分箱的取值范围都是loanAmnt/1000
data['loanAmnt_bin1'] = np.floor_divide(data['loanAmnt'], 1000)
## 通过对数函数映射到指数宽度分箱
data['loanAmnt_bin2'] = np.floor(np.log10(data['loanAmnt']))
分位数分箱:
data['loanAmnt_bin3'] = pd.qcut(data['loanAmnt'], 10, labels=False)
特征交互
特征和特征间的交互衍生出新的特征,多尝试
特征编码
labelEncode 直接放入树模型中
#进行转换
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))
特征选择
精简掉无用的特征,降低最终模型的复杂性,得到一个简约模型
在不降低预测准确率或对预测准确率影响不大的情况下,提高计算速度
特征选择不是为了减少训练时间,而是为了减少模型评分时间
方法:
1 Filter(基于特征间的关系进行筛选)
方差选择法
先计算各个特征的方差,然后根据设定的阈值,选择方差 >阈值的特征
from sklearn.feature_selection import VarianceThreshold
#其中参数threshold为方差的阈值
VarianceThreshold(threshold=3).fit_transform(train,target_train)
相关系数法(pearson 相关系数)
特征和响应变量之间关系
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)
卡方检验(正定矩阵)
检验自变量对因变量的相关性
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#参数k为选择的特征个数
SelectKBest(chi2, k=5).fit_transform(train,target_train)
互信息法
评价自变量对因变量的相关性
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)
递归特征消除法
多轮训练
每轮训练后,消除若干权值系数的特征
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
基于惩罚项的特征选择法
进行降维
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)
三、学习问题与解答
Q: 什么是特征工程?
基于数据领域的相关知识和经验,在人工智能领域中构建一个能够生成最优特征的机器学习算法的最佳实践。
将原始数据转化为特征后,并非仅仅为了描述它们本身;而是为了更准确地描述这些数据,并建立模型以便实现最佳性能水平。
Q: 为什么需要特征工程?
A: 特征工程的重要性:
- 准确性越高时,则系统的适应性更好
- 准确性越高时,则系统的架构会更加简洁
- 当数据集的准确性越高时,则系统的运行效率将显著提升
总体来说, 我们的目的是为了从海量数据中筛选出对我们有帮助的特征, 并使我们在后续构建模型的过程中更加便捷
我们的研究结果与所选模型、获取的数据以及采用的特征息息相关;这些数据属性直接决定了我们模型的表现能力;因此,在进行建模过程中对重要性进行关注就显得尤为重要
特征工程的步骤:
- 特征选择 2. 特征提取 3. 特征构造
参考:
该种算法基于以下条件实现资源消耗优化:目标函数为最小化总计算时间;约束条件包括计算节点的处理能力及通信开销;采用分层分布式架构以提升系统吞吐量;同时引入动态负载均衡机制以平衡各节点的工作量分配。经过实证分析表明,在上述条件下所设计的算法能够有效降低系统的总体能耗水平;并且通过改进的机制设计和计算模型优化,在提高系统效率的同时也显著提升了资源利用率。
四、学习思考与总结
特征工程与数据之间存在密切的关系,在实际应用中往往需要根据具体情况灵活处理以达到最佳效果。本课程向大家介绍了若干特征工程的方法和若干思路,请大家在深入理解的基础上自行梳理并加以运用才能获得理想的结果。在初期学习阶段可能有诸多手段均可应用,请大家通过实践来掌握具体运用这些方法则需要通过实践来掌握何种最适合当前任务的特点以便后续工作能够顺利开展
