使用手工特征提升模型性能

简介: 本文将使用信用违约数据集介绍手工特征的概念和创建过程。

通过对原始数据进行手工的特征工程,我们可以将模型的准确性和性能提升到新的水平,为更精确的预测和更明智的业务决策铺平道路, 可以以前所未有的方式优化模型并提升业务能力。

原始数据就像一个没有图片的拼图游戏——但通过特征工程,我们可以将这些碎片拼在一起,虽然拥有大量数据确实是寻求建立机器学习模型的金融机构的宝库,但同样重要的是要承认并非所有数据都提供信息。并且手工特征是人工设计出来,每一步操作能够说出理由,也带来了可解释性。

特征工程不仅仅是选择最好的特征。它还涉及减少数据中的噪音和冗余,以提高模型的泛化能力。这是至关重要的,因为模型需要在看不见的数据上表现良好才能真正有用。

数据集描述

本文中描述的数据集经过匿名处理和屏蔽,以维护客户数据的机密性。特征可分类如下:

  D_* = 拖欠变量
  S_* = 支出变量
  P_* = 支付变量
  B_* = 平衡变量
  R_* = 风险变量

总共有 100 个整数特征和 100 个浮点特征代表过去 12 个月客户的状态。该数据集包含有关客户报表的信息,从 1 到 13 不等。客户的每张信用卡报表之间可能有 30 到 180 天的间隔(即客户的信用卡报表可能缺失)。每个客户都由一个客户 ID 表示。customer_ID=0的客户前5条的样本数据如下所示:

在 700 万个 customer_ID 中,98% 的标签为“0”(好客户,无默认),2% 的标签为“1”(坏客户,默认)。

数据集很大,所以我们使用cudf来加速处理,如果你没有安装cudf,那么使用pandas也是一样的

 # LOAD LIBRARIES
 import pandas as pd, numpy as np # CPU libraries
 import cudf # GPU libraries
 import matplotlib.pyplot as plt, gc, os
 
 df = cudf.read_parquet('./data.parquet')

特征生成方法

有数百种想法可用于生成特征;但是我们还确保这些特征有助于提高模型的性能,下图显示了特征工程中使用的一些基本方法:

聚合特征

聚合是理解复杂数据的秘诀。通过计算分类分组变量(如 customer_ID (C_ID) 或产品类别)的汇总统计数据或数值变量的聚合,我们可以发现一些不可见的模式和趋势。借助均值、最大值、最小值、标准差和中值等汇总统计数据,我们可以构建更准确的预测模型,并从客户数据、交易数据或任何其他数值数据中提取有意义的见解。

可以计算每个客户的这些统计属性

 cat_features = ["B_1","B_2","D_1","D_2","D_10","P_21","D_126","D_3","D_42","R_66","R_68"]
 num_features = [col for col in all_cols if col not in cat_features] #all features accept cateforical features.
 test_num_agg = df.groupby("customer_ID")[num_features].agg(['mean', 'std', 'min', 'max', 'last','median']) #grouping by customerID
 test_num_agg.columns = ['_'.join(x) for x in test_num_agg.columns]

均值:一个数值变量的平均值,可以给出数据集中趋势的一般意义。平均值可以捕获:

客户拥有的平均银行余额。

  • 平均客户支出。
  • 两个信用报表之间的平均时间(信用付款之间的时间)。
  • 借钱的平均风险。

标准偏差 (Std):衡量数据围绕均值的分布情况,可以深入了解数据的变异程度。余额的高度可变性表明客户有消费。

最小值和最大值可以捕获客户的财富,也可以捕获有关客户支出和风险的信息。

中位数:当数据高度倾斜时,使用平均值并不是一个更好的主意,因此可以使用中值(可以使用数值的中间值。

最新值可能是最重要的特征,因为它们包含有关发布给客户的最新已知信用声明的信息,也就表明目前客户账户的最新状态。

独热编码

对分类变量使用上述统计属性是不明智的,因为计算最小值、最大值或标准偏差并不能给我们任何有用的信息。那么我们应该怎么做呢?可以使用像count这样的特征,和唯一的数量来计算特征,最新的值也可以使用

 cat_features = ["B_1","B_2","D_1","D_2","D_10","P_21","D_126","D_3","D_42","R_66","R_68"]
 test_cat_agg = df.groupby("customer_ID")[cat_features].agg(['count', 'last', 'nunique'])
 test_cat_agg.columns = ['_'.join(x) for x in test_cat_agg.columns]

但是这些信息不会捕获客户是否被归类到特定的类别中。所以我们通过对变量进行独热编码,然后对变量(例如均值、总和和最后)进行聚合来实现。

平均值将捕获客户属于该类别的总次数/银行对帐单总数的比率。总和将只是客户属于该类别的总次数。

 from cuml.preprocessing import OneHotEncoder
 df_categorical = df_last[cat_features].astype(object)
 ohe = OneHotEncoder(drop='first', sparse=False, dtype=np.float32, handle_unknown='ignore')
 ohe.fit(df_categorical)with open("ohe.pickle", 'wb') as f: 
     pickle.dump(ohe, f) #save the encoder so that it can be used for test data as well df_categorical = pd.DataFrame(ohe.transform(df_categorical).astype(np.float16),index=df_categorical.index).rename(columns=str)
 df_categorical['customer_ID']=df['customer_ID']
 df_categorical.groupby('customer_ID').agg(['mean', 'sum', 'last'])

基于排名的特征

在预测客户行为方面,基于排名的特征是非常重要的。通过根据收入或支出等特定属性对客户进行排名,我们可以深入了解他们的财务习惯并更好地管理风险。

使用 cudf 的 rank 函数,我们可以轻松计算这些特征并使用它们来为预测提供信息。例如,可以根据客户的消费模式、债务收入比或信用评分对客户进行排名。然后这些特征可用于预测违约或识别有可能拖欠付款的客户。

基于排名的特征还可用于识别高价值客户、目标营销工作和优化贷款优惠。例如,可以根据客户接受贷款提议的可能性对客户进行排名,然后将排名最高的客户作为目标。

 df[feat+'_rank']=df[feat].rank(pct=True, method='min')

PCT用于是否做百分位排名。客户的排名也可以基于分类特征来计算。

 df[feat+'_rank']=df.groupby([cat_feat]).rank(pct=True, method='min')

特征组合

特征组合的一种流行方法是线性或非线性组合。这包括采用两个或多个现有特征,将它们组合在一起创建一个新的复合特征。然后使用这个复合特征来识别单独查看单个特征时可能不可见的模式、趋势和相关性。

例如,假设我们正在分析客户消费习惯的数据集。可以从个人特征开始,比如年龄、收入和地点。但是通过以线性或非线性的方式组合这些特性,可以创建新的复合特性,使我们能够更多地了解客户。可以结合收入和位置来创建一个复合特征,该特征告诉我们某一地区客户的平均支出。

但是并不是所有的特征组合都有用。关键是要确定哪些组合与试图解决的问题最相关,这需要对数据和问题领域有深刻的理解,并仔细分析创建的复合特征和试图预测的目标变量之间的相关性。

下图展示了一个组合特征并将信息用于模型的过程。作为筛选条件,这里只选择那些与目标相关性大于最大值 0.9 的特征。

 features=[col for col in train.columns if col not in ['customer_ID',target]+cat_features]
 for feat1 in features:
   for feat2 in features:
     th=max(np.corr(feat1,Y)[0],np.corr(feat1,Y)[0]) #calculate threshold
     feat3=df[feat1]-df[feat2] #difference feature
     corr3=np.corr(feat3,Y)[0]
     if(corr3>max(th,0.9)): #if correlation greater than max(th,0.9) we add it as feature
       df[feat1+'_'+feat2]=feat3

基于时间/日期的特征

在数据分析方面,基于时间的特征非常重要。通过根据时间属性(例如月份或星期几)对数据进行分组,可以创建强大的特征。这些特征的范围可以从简单的平均值(如收入和支出)到更复杂的属性(如信用评分随时间的变化)。

借助基于时间的特征,还可以识别在孤立地查看数据时可能看不到的模式和趋势。下图演示了如何使用基于时间的特征来创建有用的复合属性。

首先,计算一个月内的值的平均值(可以使用该月的某天或该月的某周等),将获得的DF与原始数据合并,并取各个特征之间的差。

 features=[col for col in train.columns if col not in ['customer_ID',target]+cat_features]
 month_Agg=df.groupby([month])[features].agg('mean')#grouping based on month feature
 month_Agg.columns = ['_month_'.join(x) for x in month_Agg.columns]
 month_Agg.reset_index(inplace=True)
 df=df.groupby(month_Agg,on='month')
 for feat in features: #create composite features b taking difference
   df[feat+'_'+feat+'_month_mean']=df[feat]-df[feat+'_month_mean']

还可以通过使用时间作为分组变量来创建基于排名的特征,如下所示

 features=[col for col in train.columns if col not in ['customer_ID',target]+cat_features]
 month_Agg=df.groupby([month])[features].rank(pct=True) #grouping based on month feature
 month_Agg.columns = ['_month_'.join(x) for x in month_Agg.columns]
 month_Agg.reset_index(inplace=True)
 df=pd.concat([df,month_Agg],axis=1) #concat to original dataframe

滞后特征

滞后特征是有效预测金融数据的重要工具。这些特征包括计算时间序列中当前值与之前值之间的差值。通过将滞后特征纳入分析,可以更好地理解数据中的模式和趋势,并做出更准确的预测。

如果滞后特征显示客户连续几个月按时支付信用卡账单,可能会预测他们将来不太可能违约。相反,如果延迟特征显示客户一直延迟或错过付款,可能会预测他们更有可能违约。

 # difference function calculate the lag difference for numerical features 
 #between last value and shift last value.
 def difference(groups,num_features,shift):
     data=(groups[num_features].nth(-1)-groups[num_features].nth(-1*shift)).rename(columns={f: f"{f}_diff{shift}" for f in num_features})
     return data
 #calculate diff features for last -2nd last, last -3rd last, last- 4th last
 def get_difference(data,num_features):
     print("diff features...")
     groups=data.groupby('customer_ID')
     df1=difference(groups,num_features,2).fillna(0)
     df2=difference(groups,num_features,3).fillna(0)
     df3=difference(groups,num_features,4).fillna(0)
     df1=pd.concat([df1,df2,df3],axis=1)
     df1.reset_index(inplace=True)
     df1.sort_values(by='customer_ID')
     del df2,df3
     gc.collect()
     return df1train_diff = get_difference(df, num_features)

基于滚动窗口的特性

这些特征只是取最后3(4,5,…x)值的平均值,这取决于数据,因为基于时间的最新值携带了关于客户最新状态的信息。

 xth=3 #define the window size
 df["cumulative"]=df.groupby('customer_ID').sort_values(by=['time'],ascending=False).cumcount()
 last_info=df[df["cumulative"]<=xth]
 last_info = last_info.groupby("customer_ID")[num_features].agg(['mean', 'std', 'min', 'max', 'last','median']) #grouping by customerID
 last_info.columns = ['_'.join(x) for x in last_info.columns]

其他的特征提取方法

上面的方法已经创建了足够多的特征来构建一个很棒的模型。但是根据数据的性质,还可以创建更多的特征。例如:可以创建像null计数这样的特征,它可以计算客户当前的总null值,从而帮助捕获基于树的算法无法理解的特征分布。

 def calc_nan(df,features):
     print("calculating nan_info...")
     df_nan = (df[features].mul(0) + 1).fillna(0) #marke non_null values as 1 and null as zero
     df_nan['customer_ID'] = df['customer_ID']
     nan_sum = df_nan.groupby("customer_ID").sum().sum(axis=1) #total unknown values for a customer
     nan_last = df_nan.groupby("customer_ID").last().sum(axis=1)#how many last values that are not known
     del df_nan
     gc.collect()
     return nan_sum,nan_last

这里可以不使用平均值,而是使用修正的平均值,如基于时间的加权平均值或 HMA(hull moving average)。

总结

在本文中介绍了一些在现实世界中用于预测违约风险的最常见的手工特性策略。但是总是有新的和创新的方法来设计特征,并且手工设置特征的方法是费时费力的,所以我们将在后面的文章中介绍如何实用工具进行自动的特征生成。

https://avoid.overfit.cn/post/2740ca61afb3438dbb8ab36b2250f37e

作者:Priyanshu Chaudhary

目录
相关文章
|
6月前
|
编解码 并行计算 算法
除了NMS参数,还有哪些因素会影响YOLOv3模型的检测性能?
除了NMS参数,还有哪些因素会影响YOLOv3模型的检测性能?
|
2月前
|
机器学习/深度学习 数据可视化 数据建模
使用ClassificationThresholdTuner进行二元和多类分类问题阈值调整,提高模型性能增强结果可解释性
在分类问题中,调整决策的概率阈值虽常被忽视,却是提升模型质量的有效步骤。本文深入探讨了阈值调整机制,尤其关注多类分类问题,并介绍了一个名为 ClassificationThresholdTuner 的开源工具,该工具自动化阈值调整和解释过程。通过可视化功能,数据科学家可以更好地理解最优阈值及其影响,尤其是在平衡假阳性和假阴性时。此外,工具支持多类分类,解决了传统方法中的不足。
41 2
使用ClassificationThresholdTuner进行二元和多类分类问题阈值调整,提高模型性能增强结果可解释性
|
5月前
|
存储 人工智能 缓存
大模型压缩量化方案怎么选?无问芯穹Qllm-Eval量化方案全面评估:多模型、多参数、多维度
【6月更文挑战第26天】无问芯穹Qllm-Eval评估了11个大模型(如OPT、LLaMA2)在多种参数配置和任务下的量化效果,探索权重量化、激活量化等方法对性能、速度和内存的影响。研究发现,W4、W4A8量化通常保持在2%的性能损失范围内,但最佳策略取决于模型大小、任务类型及硬件,提示了选择压缩方案时需灵活适应。[[arxiv.org/pdf/2402.18158.pdf](https://arxiv.org/pdf/2402.18158.pdf)]
79 6
|
6月前
|
机器学习/深度学习 自然语言处理 测试技术
SUPRA:无须额外训练,将Transformer变为高效RNN,推理速度倍增
`Transformers`模型因其在多种任务上的优秀性能而广泛采用,但其内存需求和推理成本随词元数量指数增长。为解决这一问题,论文《Linearizing Large Language Models》提出`SUPRA`方法,将预训练的`Transformers`转换为递归神经网络(RNN),实现有效推理并降低训练成本至原来的5%。`SUPRA`通过将注意力机制线性化并用`GroupNorm`替代`softmax`,保持预训练模型的优势。经过微调,转换后的模型在标准语言理解和长上下文任务中保持高性能,展示了在长序列处理方面的潜力,但仍有改进空间。
143 2
|
5月前
高效、可泛化的高斯重建框架,只需3张视图即可快速推理,45秒便可完成优化
【6月更文挑战第12天】MVSGaussian是一种新型3D高斯表示方法,利用多视图立体技术进行高效、可泛化的高斯重建,仅需3张视图就能快速推理。它采用几何感知的高斯表示和混合高斯渲染,实现实时新视图生成与高质量重建。通过多视图几何一致聚合策略,MVSGaussian能快速优化场景。在多种数据集上表现出优越性能,但受限于输入图像质量和数量,且训练与优化过程可能耗时。论文链接:[Fast Generalizable Gaussian Splatting Reconstruction from Multi-View Stereo](https://arxiv.org/abs/2405.12218)
102 3
|
4月前
|
机器学习/深度学习 索引 Python
。这不仅可以减少过拟合的风险,还可以提高模型的准确性、降低计算成本,并帮助理解数据背后的真正含义。`sklearn.feature_selection`模块提供了多种特征选择方法,其中`SelectKBest`是一个元变换器,可以与任何评分函数一起使用来选择数据集中K个最好的特征。
。这不仅可以减少过拟合的风险,还可以提高模型的准确性、降低计算成本,并帮助理解数据背后的真正含义。`sklearn.feature_selection`模块提供了多种特征选择方法,其中`SelectKBest`是一个元变换器,可以与任何评分函数一起使用来选择数据集中K个最好的特征。
|
6月前
|
数据采集
【大模型】大语言模型训练数据中的偏差概念及其可能的影响?
【5月更文挑战第5天】【大模型】大语言模型训练数据中的偏差概念及其可能的影响?
|
6月前
|
机器学习/深度学习
大模型开发: 解释批量归一化以及它在训练深度网络中的好处。
批量归一化(BN)是2015年提出的加速深度学习训练的技术,旨在解决内部协变量偏移、梯度消失/爆炸等问题。BN通过在每层神经网络的小批量数据上计算均值和方差,进行标准化处理,并添加可学习的γ和β参数,保持网络表达能力。这样能加速训练,降低超参数敏感性,对抗过拟合,简化初始化。BN通过稳定中间层输入分布,提升了模型训练效率和性能。
171 3
|
11月前
|
存储 JSON 自然语言处理
使用ExLlamaV2量化并运行EXL2模型
量化大型语言模型(llm)是减少这些模型大小和加快推理速度的最流行的方法。在这些技术中,GPTQ在gpu上提供了惊人的性能。与非量化模型相比,该方法使用的VRAM几乎减少了3倍,同时提供了相似的精度水平和更快的生成速度。
188 0
下一篇
无影云桌面