Usage

建模流程由以下五个环节组成:

1. 数据探索性分析

工作内容

加载原始的训练数据

样例代码

# 原始数据读取
logger.info("start data loading >>>>>>>>>" )
base_dir = os.getcwd()
logger.info("load dataframe >>>>>>>>>" )
credit_data = pd.read_csv(os.path.join(base_dir, r'../data/germancredit.csv'))
numeric_feats = credit_data.select_dtypes(include=['int64','float64']).columns.tolist()
category_feats = list(set(credit_data.columns) - set(numeric_feats + ['creditability']))
logger.info("The dataset has %s pieces of data, %s numeric_feats, %s category_feats  >>>>>>>>>" %(len(credit_data),len(numeric_feats),len(category_feats)))
# 文字->数字映射
credit_data["flag"] = credit_data["creditability"].replace({"good": 0, "bad": 1})
logger.info("end data loading >>>>>>>>>" )

工作内容

  • 培养对数据的直觉
    • 对数据进行清洗

    • 对数据进行描述(描述统计量,图表)

    • 查看数据的分布

    • 比较数据之间的关系

样例代码

# 数据探索性分析
logger.info("start EDA >>>>>>>>>" )

featurebox_plot(credit_data, columns=numeric_feats, sub_col=2, picture_name=base_dir+"/output/箱形图")
logger.info("箱形图完成")

featuredis_plot(credit_data, columns=numeric_feats, label='flag',sub_col=3, picture_name=base_dir+"/output/数值型特征分布图")
logger.info("数值型特征分布图完成")

featurecategory_plot(X=credit_data, columns=category_feats, label="flag", sub_col=13,picture_name=base_dir+"/output/类别型特征分布图")
logger.info("类别型特征分布图完成")

featurecor_plot(X=credit_data, columns=numeric_feats+['flag'],picture_name=base_dir+"/output/相关性热图")
logger.info("相关性热图完成")

with timer('detect dataframe', logger):
    dec = DetectDF(credit_data)
    df_des = dec.detect(special_value_dict={-999:np.nan}, savefolder = base_dir +'/output')
    logger.info("数据探查统计表完成")

logger.info("end EDA >>>>>>>>>" )

模块明细

bm.visual.quick_visual.featurebox_plot()
  • 箱形图

  • 显示出一组数据的最大值、最小值、中位数、及上下四分位数。

_images/箱型图.png
bm.visual.quick_visual.featuredis_plot()
  • 数值型特征分布图

  • 查看特征分布情况

_images/数值型特征分布图.png
bm.visual.quick_visual.featurecategory_plot()
  • 类别型特征分布图

  • 查看特征分布情况

_images/类别型特征分布图.png
bm.visual.quick_visual.featurecor_plot()
  • 相关性热图

  • 研究两个或两个以上随机变量之间相互依存关系的方向和密切程度。

_images/相关性热图.png
bm.eda.data_detection.DetectDF
  • 数据探查统计表

  • 针对类别型特征计算:

    1. 数值类型
    2. 数据量
    3. 缺失值占比
    4. 唯一值个数
    5. 前五个最大值
    6. 前五个最小值
    
  • 针对数值型特征计算:

    1. 数值类型
    2. 数据量
    3. 缺失值占比
    4. 唯一值个数
    5. 平均值
    6. 标准差
    7. 最小值
    8. 1%分位数,10%分位数,50%分位数,75%分位数,90%分位数,99%分位数
    9. 最大值
    

2. 特征工程

  • 数据清洗
    • 缺失值的处理

    • 离群点处理

    • 噪声处理

  • 数据集成
    • 实体识别问题

    • 冗余问题

    • 数据值的冲突和处理

  • 数据规约
    • 维度规约
      • 属性子集选择

      • 单变量重要性

    • 维度变换
      • 主成分分析(PCA)和因子分析(FA)

      • 奇异值分解(SVD)

  • 数据变换
    • 规范化处理

    • 离散化处理

    • 稀疏化处理

缺失值的处理

在金融风控场景,只有少数用户被标注为欺诈用户,剩下的大量用户均属于未标注用户。此时若直接将未标注用户视为白名单构建二分类器进行监督学习,会出现两个问题:
  1. 正样本和负样本的比例不均衡,正样本的数目远远大于负样本,影响分类器的算法效果。

  2. 实际情况正样本中也包含着少量负样本,属于带噪声的数据,严重影响算法学习到的特征,降低最终算法的准确率。

因此,此类场景需要使用PU bagging算法,为未标记样本打上正负标签

样例代码

logger.info("start data preprocessing >>>>>>>>>" )
estimator = LGBMClassifier(n_estimators=200, max_depth=2, learning_rate=0.1)
bc = BaggingClassifierPU(base_estimator=estimator, n_estimators = 30, n_jobs = -1, max_samples = len(credit_data[credit_data['flag']==1]))
bc.fit(credit_data[numeric_feats], credit_data['flag'])
score_arr = bc.oob_decision_function_[:,1] # 使用训练集的袋外估计计算的决策函数。 正样本数据点,也许还有一些未标记的数据点,在bootstrap过程中被遗漏了。 在这些情况下,`oob_decision_function_` 包含 NaN。
credit_data['score_pb'] = score_arr
credit_data = credit_data[(credit_data['score_pb'].isna()) | (credit_data['score_pb']<0.9)] # score_pb是数据属于正样本的概率
logger.info('PUbagging恢复了%s个负样本:' %len(credit_data[(credit_data['flag']==0)]))
logger.info('恢复后的数据共有%s个样本:' %len(credit_data))
logger.info("end data preprocessing >>>>>>>>>" )

模块明细

bm.prep.baggingPU.BaggingClassifierPU()

特征粗筛:过滤法(IV+PSI)

工作内容

代码样例

# 计算IV
iv_details = cal_total_var_iv(credit_data,numeric_feats=numeric_feats,category_feats=category_feats,target='flag',max_interval=10,numeric_method='chi',category_method='default')
iv_details.to_csv(os.path.join(base_dir +'/output',r'iv_details.csv'), index=False)

# WOE-IV图
wiplot(binx=iv_details[iv_details["variable"] == "credit.amount"], title="Woe", display_iv=True,picture_name=base_dir+"/output/WOE_IV图")

# 计算psi
except_array = credit_data['credit.amount'][:500]
accept_arry = credit_data['credit.amount'][500:]
psi_df = numeric_var_cal_psi(except_array,accept_arry,bins=10,bucket_type='bins',detail=True)
psi_df.to_csv(os.path.join(base_dir +'/output', r'psi.csv'))

模块明细

bm.feature.metrics.cal_iv_psi.cal_total_var_iv()

为全量特征计算IV

可选参数:

numeric_method = ['chi', 'tree', 'distance', 'quantile', 'interpolate', 'mixed']
category_method = ['chi', 'tree', 'default']

分箱方法参数对照表

分箱方法

参数明细

适用特征

不分箱

default

类别型特征,类别数少于10

卡方分箱

chi

数值型、类别型特征

决策树分箱

tree

数值型、类别型特征

等宽分箱

distance

数值型特征

等频分箱

quantile

数值型特征

插值分箱

interpolate

数值型特征

混合分箱

mixed

数值型特征

分箱的好坏可以用WOE-IV图来评估

_images/WOE_IV图.png

bm.feature.metrics.cal_iv_psi.numeric_var_cal_psi()

为某一特征计算PSI

特征细筛:嵌入法(特征重要度计算)

工作内容

  • 空缺值过滤

  • 单一值过滤

  • 共线性(相关性)特征过滤

  • 计算特征重要性,筛选有效特征

代码样例

# 特征筛选
logger.info("start featuring selection >>>>>>>>>" )
fs = FeatureSelector(data=credit_data,
                    target='flag',
                    base_features=numeric_feats+category_feats,
                    category_features=category_feats)
fs.identify_all(config = CONFIG)
# 特征重要性可视化
select_data, importance_feats, features_name = fs.filter_results()
select_data.to_csv(os.path.join(base_dir +'/output', r"selected_training_data.csv"), encoding='utf-8')
logger.info("end featuring selection >>>>>>>>>" )

模块明细

bm.feature.selector_market.FeatureSelector

本模块涉及配置文件的修改,详细内容请参考 配置文件

3. 算法选型+模型评估

样例代码

training_data = pd.read_csv(os.path.join(base_dir +'/output', r"selected_training_data.csv"), encoding='utf-8', index_col=0)
trn_x, tes_x, _, _ = train_test_split(training_data, training_data['flag'], test_size=0.2)

# 模型初始化
select_numeric_feats = training_data.select_dtypes(include=['int64','float64']).columns.tolist()
select_numeric_feats.remove("flag")
select_category_feats = list(set(training_data.columns) - set(numeric_feats + ['flag']))
select_base_feature = select_numeric_feats + select_category_feats
target = "flag"
model = Model(param_dict=CONFIG['lgb_params'], numeric_feature=select_numeric_feats, category_feature=select_category_feats)
pipe_model = model.make_pipeline_model(model_type='lgb')

# 准备数据
train_datas, train_targets = model.data_preprocess(datas=trn_x, base_features=select_base_feature, target=target)
test_datas, test_targets = model.data_preprocess(datas=tes_x, base_features=select_base_feature, target=target)

# 报表
vis = reports_plot(pipe_model, X_train=train_datas, y_train=train_targets, X_test=test_datas,
              y_test=test_targets, binary=True, picture_name=base_dir+"/output/报表")
logger.info("报表完成")

# 特征重要性
feature_importance_plot(importance_feats, picture_name=base_dir+"/output/特征重要性")
logger.info("特征重要性图完成")

# shap
shap_plot(vis.estimator, train_datas,all_feature_names, picture_name=base_dir+"/output/shap_force", mode="force")
shap_plot(vis.estimator, train_datas,all_feature_names, picture_name=base_dir+"/output/shap_summary", mode="summary")
logger.info("shap图完成")

模块明细

bm.model.models.Model

  • 本模块目前支持三类机器学习模型
    • LightGBM分类器

    • XGBoost分类器

    • voting(集成学习)分类器

  • 本模板涉及配置文件的修改,详细内容请参考 配置文件

模型评估报表

详细解读请参考 模型评估

_images/exmaple_report.png

4. 模型可解释性

force_plot(单样本特征影响图)

下图展示了每个特征都各自有其贡献,将模型的预测结果从基本值(base value)推动到最终的取值(model output);将预测推高的特征用红色表示,将预测推低的特征用蓝色表示

  • 由于 Treeshap 是对对数几率(log odd ratio)进行解释,所以出现负数。

  • 具有负向影响的变量变为 x0_co-applicant 和 x3_no checking account 等,

  • 具有正向影响的特征变量加入 credit.amount, duration.in.month, installment.rate.in.percentage.of.disposable.income

  • 其他变量的 Shapley Value 由于值太小就不一一列举。

_images/shap_force.png

summary_plot(多样本特征影响图)

summary plot 为每个样本绘制其每个特征的SHAP值,这可以更好地理解整体模式,并允许发现预测异常值。每一行代表一个特征,横坐标为SHAP值。一个点代表一个样本,颜色表示特征值(红色高,蓝色低)。

  • 比如,这张图表明credit.amount特征较高的取值会提高的信用卡审批通过的概率

_images/shap_summary.png

特征重要性图

传统的importance的计算方法效果不好,SHAP提供了另一种计算特征重要性的思路。

  • 取每个特征的SHAP值的绝对值的平均值作为该特征的重要性,得到一个标准的条形图(multi-class则生成堆叠的条形图)

  • 在特种重要性图中,status.of.existing.checking.account 该特征最重要,其次是 credit.amount,duration.in.month

_images/特征重要性.png