首页 > 其他分享 >【金融风控】风控建模概述

【金融风控】风控建模概述

时间:2024-11-09 20:50:35浏览次数:3  
标签:uid df 模型 样本 建模 tp 风控 amount 概述

风控建模概述

内容介绍

  • 知道信贷审批业务的基本流程

  • 知道ABC评分卡是什么,有什么区别

  • 知道风控建模的流程

  • 掌握评分卡模型正负样本定义方法

  • 知道如何构建特征,如何评估特征

【理解】互联网金融风控体系介绍

  • 信贷审批业务基本流程

    • 四要素认证:银行卡持有人的姓名、身份证号、银行卡号、手机号

#A卡,申请评分卡
Application Score Card

#B卡,行为评分卡
Behavior Score Card

#C卡,催收评分卡
Collection Score Card
  • 互联网金融风控体系主要由三大部分组成

    • 用户数据:用户基本信息、用户行为信息、用户授权信息、外部接入信息。

      • 数据采集会涉及到埋点和爬虫技术,基本上业内的数据都大同小异。

        • 免费的运营商数据

        • 安卓可爬的手机内部信息(app名称,手机设备信息,部分app内容信息)

        • 收费的征信数据、各种信息校验、外部黑名单之类的

        • 特定场景的现金贷和消费金融会有自有的数据可供使用

          • 比如阿里京东自己的电商数据

          • 滴滴的司机数据、顺丰中通的快递数据

      • 用户基本信息(联系人,通讯录,学历...)

      • 用户行为信息(操作APP时的行为,注册,点击位置...)

      • 用户授权信息(运营商,学信网,设备IMEI....)

      • 外部接入信息(P2P信贷,其它金融机构如芝麻信用分...)

    • 策略体系:反欺诈规则、准入规则、运营商规则、风险名单、网贷规则

      • 收集来用户的信息之后,把用户信息输入到策略引擎

      • 欺诈规则

      • 准入规则(年龄,地域,通讯录,行为规则)

      • 运营商规则(通话规则)

      • 风险名单(黑名单,失信名单,法院名单)

      • 网贷(多头,白户...)

    • 机器学习模型:欺诈检测模型、准入模型、授信模型、风险定价、额度管理、流失预警、失联修复。

    贷前准入贷中管理贷后催收
    信用申请评分卡行为评分卡催收评分卡
    反欺诈申请反欺诈交易反欺诈
    运营用户响应模型用户流失模型、用户分群、用户画像失联修复
    其他套现识别、洗钱识别

【掌握】风控建模流程

评分卡简介

  • 风控模型其中包含了A/B/C卡。模型可以采用相同算法,一般以逾期天数来区分正负样本,也就是目标值Y的取值(0或1)

    • 贷前 申请评分卡 Application score card

    • 贷中 行为评分卡 Behavior score card

    • 贷后 催收评分卡 Collection score card

  • C卡因为用途不同Y的取值可能有区别

    • 公司有内催,有外催。外催回款率低,单价贵

    • 可以根据是否被内催催回来定义C卡的Y。

机器学习模型的完整工程流程

项目准备期 → 特征工程 → 模型构建 → 上线运营

  • 准备

    • 明确需求

    • 模型设计

      • 业务抽象成分类/回归问题

      • 定义标签(目标值)

    • 样本设计

  • 特征工程

    • 数据处理,选取合适的样本,并匹配出全部的信息作为基础特征

    • 特征构建

    • 特征评估

  • 模型

    • 模型训练

    • 模型评价

    • 模型调优

  • 上线运营

    • 模型交付

    • 模型部署

    • 模型监控

项目准备期

  • 明确需求

    • 目标人群:新客,优质老客,逾期老客

    • 给与产品:额度,利率

    • 市场策略:冷启动,开拓市场,改善营收

    • 使用时限:紧急使用,长期部署

    • 举例

      • 业务需要针对全新客户开放一个小额现金贷产品,抢占新市场

      • 针对高风险薄数据新客的申请评分卡

  • 模型设计

    • 业务抽象成分类/回归问题

      • 风控场景下问题通常都可以转化为二分类问题:

        • 信用评分模型期望用于预测一个用户是否会逾期,逾期用户1

        • 营销模型期望用于预测一个用户被营销后是否会来贷款,没贷用户1

        • 失联模型期望用于预测一个用户是否会失联,失联用户1

          风控业务中,只有欺诈检测不是二分类问题。因为样本数量不足,可能是一个无监督学习模型

    • 模型算法

      • 规则模型

      • 逻辑回归

      • 集成学习

      • 融合模型

    • 模型输入

      • 数据源

      • 时间跨度

    • Y标签定义

      • 在构建信贷评分模型时,原始数据中只有每个人的当前逾期情况,没有负样本,负样本需要人为构建

      • 通常选一个截断点(阈值),当逾期超过某个阈值时,就认定该样本是一个负样本,未来不会还钱

      • 比如逾期15天为正负样本的标记阈值,Y = 1的客户均是逾期超过15天的客户

      • 逾期>15天时 Y = 1,那么Y=0如何定义

        • 只会将按时还款和逾期较少的那一部分人标记为0。如:将逾期<5天和没有逾期的人作为正样本

        • 逾期5~15天的数据(灰样本)会从样本中去掉,去掉“灰样本”,会使样本分布更趋于二项分布,对模型学习更加有利。

        • “灰样本”通常放入测试集中,用于确保模型在训练结束后,对该部分样本也有区分能力。

        #Y标签的定义
        逾期天数 <= 5,定义为不违约,0
        
        5 < 逾期天数 < 15,在训练集中去掉这部分数据。把这部分数据用于测试。
        
        逾期天数 >= 15,定义为违约,1
        
        10.21日 23:59:40
        10:22日 00:00:10
        
        中国银行,3天。
    • 样本选取

      • 代表性:样本必须能够充分代表总体。如消费贷客群数据不能直接用到小额现金贷场景

      • 充分性:样本集的数量必须满足一定要求。评分卡建模通常要求正负样本的数量都不少于1500个。随着样本量的增加,模型的效果会显著提升

      • 时效性:在满足样本量充足的情况下,通常要求样本的观测期与实际应用时间节点越接近越好。如银行等客群稳定的场景,观察期可长达一年半至两年。

      • 排除性(Exclusion):虽然建模样本需要具有代表整体的能力,但某些法律规定不满足特定场景贷款需求的用户不应作为样本,如对行为评分卡用户、无还款表现或欺诈用户均不应放入当前样本集。

      • 评分卡建模通常要求正负样本的数量>=1500,但当总样本量超过50000个时,许多模型的效果不再随着样本量的增加而有显著提升,而且数据处理与模型训练过程通常较为耗时。

      • 如果样本量过大,会为训练过程增加不必要的负担,需要对样本做欠采样(Subsampling)处理。由于负样本通常较少,因此通常只针对正样本进行欠采样。常见的欠采样方法分为:

        • 随机欠采样:直接将正样本欠采样至预期比例。

        • 分层抽样:保证抽样后,开发样本、验证样本与时间外样本中的正负样本比例相同。

        • 等比例抽样:将正样本欠采样至正负样本比例相等,即正样本量与负样本量之比为1:1。 需要注意的是,采样后需要为正样本添加权重。如正样本采样为原来的1/4,则为采样后的正样本增加权重为4,负样本权重保持为1。因为在后续计算模型检验指标及预期坏账时,需要将权重带入计算逻辑,才可以还原真实情况下的指标估计值,否则预期结果与实际部署后的结果会有明显偏差。

        • 而当负样本较少的时候,需要进行代价敏感加权或过采样(Oversampling)处理

        #1.样本数量
        1500-50000
        
        #2.样本不均衡
        代价敏感
        
      • 观察期和表现期

        • 观察期是指用户申请信贷产品前的时间段

        • 表现期是定义好坏标签的时间窗口,如果在该时间窗口内触发坏定义就是坏样本,反之就是好样本。

        • 举例: 要建立A卡模型, 观察期12个月,表现期3个月

          • 用户贷款前12个月的历史行为表现作为变量,用于后续建模

          • 如设定用户在到期3个月内未还款,即认为用户为负样本,则称表现期为3个月

          • 观察期:确定X

          • 表现期:确定Y

          • 无论是观察期还是表现期,都是用于训练模型的。

  • 训练数据测试数据划分

    • 数据集在建模前需要划分为3个子集:

      • 开发样本(Develop):开发样本与验证样本使用分层抽样划分,保证两个数据集中负样本占比相同

      • 验证样本(Valuation): 开发样本与验证样本的比例为6:4

      • 时间外样本(Out of Time,OOT): 通常使用整个建模样本中时间最近的数据, 用来验证模型对未来样本的预测能力,以及模型的跨时间稳定性。

  • 举例:

申请评分卡行为评分卡催收评分卡
客群新客未逾期老客逾期老客
观察期申请时点前一年当期某一日前一年当期还款日前一年
表现期FPD30DPD60DPD1->DPD30
  • 样本设计

    • 选取客群:新客,未逾期老客,逾期老客

    • 客群描述:首单用户、内部数据丰富、剔除高危职业、收入范围在XXXX

    • 客群标签:好: FPD<=5 坏: FPD>15, (5,15)灰样本,不参与训练,参与测试评估

训练集测试集
1月2月3月4月5月6月7月8月
总#100200300400500600700800
坏#366815121424
坏%3%3%2%2%3%2%2%3%

特征工程

  • 数据调研

    • 明确对目标人群有哪些可用数据, 明确数据获取逻辑

    • 明确数据的质量,覆盖度,稳定性

  • 特征构建

    • 误区:拿到数据之后,立即做特征

    • 构建特征之前需要明确

      • 数据源对应的具体数据表,画出ER图

      • 评估特征的样本集

        • B卡样本集不能包含逾期数据

        • C卡样本集不能包含按时还款的数据

      • 特征框架,确保对数据使用维度进行了全面思考

        • 确定思维框架, 与组内其它人讨论

    • 明确数据源对应的具体数据表

      • 明确数据是从哪里来的: (DE Data Engineer 数仓工程师)

      • 数据分析师拿到的数据可能是

        数仓原始表

        数仓重构表

      • 数仓原始表和数仓重构表可能数据量有差异,因为更新时间不同!

        尽量使用数仓工程师加工好的重构表,确保逻辑统一

        实时预测要确保生产数据库和数据仓库数据一致 (很难)

    • 画出类ER图 数据关系 一对一,一对多,多对多

      • 写SQL查询时要从 用户列表出发, Join其它表

        • 不能出现SELECT DISTINCT user_id FROM order_table

    • 明确评估特征的样本集

      • A卡:新申请客户没有内部信贷数据

      • B卡:未逾期老客户当期没有逾期信息

      • C卡:逾期老客户和未逾期老客的还款数据一定差别很大

    • 如何从原始数据中构建特征:指定特征框架,确保对数据使用维度进行了全面思考

      • 每个属性都可以从R(Recency) F(Frequency) M(Monetary)三个维度思考,来构建特征

      GPS
      经纬度R最近GPS所在省市区, 申请时间GPS所在省市区
      FGPS出现过的省市区,出现最多的省市区
      MGPS出现最多的省市区的GDP,人口,坏账率, 该地区的其他统计信息
      时间R最近一天/周/月的GPS数
      F过去N天/周/月的GPS的平均数, 早上/中午/晚上/上班日/周末GPS数
      MNone
      地址R最近GPS距离家庭/工作地址距离
      F出现最多GPS距离家庭/工作地址距离
      MGPS序列围绕家庭/工作地址的信息熵
      补充是否授权GPS,最近连续无GPS的天数
    • 特征构建方法

      • 用户静态信息特征:用户的姓名,性别,年龄

      • 用户时间截面特征

        • 截面时点电商购物GMV(Gross Merchandise Volume,商品交易总额)

        • 截面时点银行存款额

        • 截面时点逾期最大天数

      • 用户时间序列特征

        • 用户过去一个月的GPS数据

        • 用户过去六个月的银行流水

        • 用户过去一年的逾期记录

  • 特征评估

    • 什么是好的特征

      • 好的特征需要满足的条件(评估指标)

        • 覆盖度高,很多用户都能使用

        • 稳定,在后续较长时间可以持续使用 PSI (Population Stability Index)

        • 区分度好,好坏用户的特征值差别大 IV (Information Value)

      • 也可以用模型的评估指标来评估特征:单特征AUC, 单特征KS

      • 可以拿效果最好的单特征的AUC,KS来估计模型的效果

    • 特征评估报表

      全量样本带标签样本
      特征名称覆盖度缺失率零值率AUCKSIV
      合适范围内
    • 全量样本—覆盖度:全量样本上,有多少用户有这个特征

      • 全量样本:包含不带标签的样本

    • 缺失率:带标签样本缺失率,与全量样本覆盖度作对比,看差距是不是很大,选择差距不大的特征

    • 零值率:好多特征是计数特征,比如电商消费单数,通信录记录数,GPS数据,如零值太多,特征不好

    • 剔除风险趋势不合逻辑的特征,用常识和业务逻辑去评估

#1.特征
对目标值有作用的列。

#2.如何判断好的特征呢?
略。

#3.假设当前数据的列对模型的作用都不大,怎么办呢?
特征构造

模型构建

  • 设计实验

    • 训练模型时有很多可能的因素会影响模型效果

    • 我们需要通过设计实验去验证哪些因素是会提升模型效果的

  • 模型评估

    • 好的模型需要满足的条件:

      • 稳定,在后续较长时间可以持续使用 PSI (Population Stability Index)

      • 区分度好,好坏用户的信用分差别大 AUC, KS

    • 报表一:区分度,抓坏人能力在不同分段的表现

    分数段总人数坏人数坏人率KS
    [300, 550]
    [500, 600]
    [600, 700]
    [700, 750]
    [750, 800]
    [800, 850]
    [850, 950]
    • 报表二:跨时间稳定性

    分数段测试集1测试集2线上1期线上2期...
    [300, 550]10%10%
    [500, 600]20%20%
    [600, 700]20%20%
    [700, 750]25%25%
    [750, 800]20%20%
    [800, 850]4%4%
    [850, 950]1%1%
    决策点上比例50%50%
    总用户数30002000
    平均分730725
    PSI-0.01
#模型评价指标:
AUC:越大越好(通用评价指标)
KS:越大越好(金融风控下特殊指标)

上线运营

模型交付→模型部署→模型监控

  • 模型交付

    • 交付流程

      1 提交特征和模型报表 2 离线结果质量复核 (无缺失,无重复,存储位置正确,文件名规范) 3 保存模型文件,确定版本号,提交时间 4 老大审批,通知业务方 5 线上部署,案例调研, 持续监控

    • 特征报告

      1 特征项目需求 2 特征项目任务列表 3 特征项目时间表 4 类ER图 5 样本设计 6 特征框架 7 每周开发进度和结果 8 每周讨论反馈和改进意见笔记 9 特征项目交付说明 10 特征项目总结

    • 模型报告

      1 模型项目需求

      2 模型项目任务列表

      3 模型项目时间表

      4 模型设计

      5 样本设计

      6 模型训练流程和实验设计

      7 每周开发进度和结果

      8 每周讨论反馈和改进意见笔记

      9 模型项目交付说明

      10 模型项目总结

  • 模型部署

    • 确保开发环境和生产环境、测试环境一致性(灾备,回归)

    • 使用PMML文件或Flask API进行部署

    • 一定要做:对一批客户进行离线打分和线上打分,确保离线结果和线上结果一致

  • 模型监控

    • 特征监控:特征稳定性

    • 模型监控:模型稳定性

【实现】业务规则挖掘

规则挖掘简介

  • 两种常见的风险规避手段

    • AI模型

    • 规则

  • 如何使用规则进行风控

    • 使用一系列判断逻辑对客户群体进行区分,不同群体逾期风险有显著差别

      • 举例:多头借贷数量是否超过一定数量

    • 如果一条规则将用户划分到高风险组,则直接拒绝,如果划分到低风险组则进入到下一规则

  • 规则和AI模型的优缺点

    • 规则,可以快速使用,便于业务人员理解,但判断相对简单粗暴一些,单一维度不满足条件直接拒绝

    • AI模型,开发周期长,对比使用规则更复杂,但更灵活,用于对风控精度要求高的场景

  • 可以通过AI模型辅助建立规则引擎,决策树很适合规则挖掘的场景

规则挖掘案例

  • 案例背景

    • 某互联网公司拥有多个业务板块,每个板块下都有专门的贷款产品

      • 外卖平台业务的骑手可以向平台申请“骑手贷”

      • 电商平台业务的商户可以申请“网商贷”

      • 网约车业务的司机可以向平台申请“司机贷”

    • 公司有多个类似的场景,共用相同的规则引擎及申请评分卡,贷款人都是该公司的兼职人员

    • 近期发现,“司机贷”的逾期率较高

      • 整个金融板块30天逾期率为1.5%(3%以内)

      • “司机贷”产品的30天逾期超过了5%(亏钱)

  • 期望解决方案

    • 现有的风控架构趋于稳定

    • 希望快速开发快速上线,解决问题

      • 尽量不使用复杂的方法

      • 考虑使用现有数据挖掘出合适的业务规则

  • 数据字典

    变量类型基础变量名释义
    数值型oil_amount加油升数
    discount_amount折扣金额
    sale_amount促销金额
    amount总金额
    pay_amount实际支付金额
    coupon_amount优惠券金额
    payment_coupon_amount支付优惠券金额
    分类型channel_code渠道
    oil_code油品品类(规格)
    scene场景
    source_app来源端口(1货车帮、2微信)
    call_source订单来源(1:中化扫描枪 2:pos 3:找油网 4:油掌柜5:司机自助加油 6 油站线)
    class_new用户评级
    日期时间create_dt账户创建时间
    oil_actv_dt放款时间
    标签bad_ind正负样本标记
  • 加载数据

import pandas as pd
import numpy as np
data = pd.read_excel('../data/rule_data.xlsx')
data.head()

显示结果:

uidoil_actv_dtcreate_dttotal_oil_cntpay_amount_totalclass_newbad_indoil_amountdiscount_amountsale_amountamountpay_amountcoupon_amountpayment_coupon_amountchannel_codeoil_codescenesource_appcall_source
0A82177102018-08-192018-08-17275.048295495.4B03308.561760081.01796001.01731081.08655401.01.01.013203
1A82177102018-08-192018-08-16275.048295495.4B04674.682487045.02537801.02437845.012189221.01.01.013203
2A82177102018-08-192018-08-15275.048295495.4B01873.06977845.0997801.0961845.04809221.01.01.012203
3A82177102018-08-192018-08-14275.048295495.4B04837.782526441.02578001.02484441.012422201.01.01.012203
4A82177102018-08-192018-08-13275.048295495.4B02586.381350441.01378001.01328441.06642201.01.01.012203
  • 查看class_new

data.class_new.unique()

显示结果:

array(['B', 'E', 'C', 'A', 'D', 'F'], dtype=object)
  • 原始数据的特征太少,考虑在原始特征基础上衍生出一些新的特征来,将特征分成三类分别处理

    • 数值类型变量:按照id分组后,采用多种方式聚合,衍生新特征

    • 分类类型变量,按照id分组后,聚合查询条目数量,衍生新特征

    • 其它:日期时间类型,是否违约(标签),用户评级等不做特征衍生处理

org_list = ['uid','create_dt','oil_actv_dt','class_new','bad_ind']
agg_list = ['oil_amount','discount_amount','sale_amount','amount','pay_amount','coupon_amount','payment_coupon_amount']
count_list = ['channel_code','oil_code','scene','source_app','call_source']
  • 创建数据副本,保留底表,并查看缺失情况

df = data[org_list].copy()
df[agg_list] = data[agg_list].copy()
df[count_list] = data[count_list].copy()
df.isna().sum()

显示结果:

<span style="background-color:#f8f8f8">uid                         <span style="color:#116644">0</span>
create_dt                <span style="color:#116644">4944</span>
oil_actv_dt                 <span style="color:#116644">0</span>
class_new                   <span style="color:#116644">0</span>
bad_ind                     <span style="color:#116644">0</span>
oil_amount               <span style="color:#116644">4944</span>
discount_amount          <span style="color:#116644">4944</span>
sale_amount              <span style="color:#116644">4944</span>
amount                   <span style="color:#116644">4944</span>
pay_amount               <span style="color:#116644">4944</span>
coupon_amount            <span style="color:#116644">4944</span>
payment_coupon_amount    <span style="color:#116644">4946</span>
channel_code                <span style="color:#116644">0</span>
oil_code                    <span style="color:#116644">0</span>
scene                       <span style="color:#116644">0</span>
source_app                  <span style="color:#116644">0</span>
call_source                 <span style="color:#116644">0</span>
dtype: int64</span>
  • 查看数值型变量的分布情况

df.describe()

显示结果:

bad_indoil_amountdiscount_amountsale_amountamountpay_amountcoupon_amountpayment_coupon_amountchannel_codeoil_codescenesource_appcall_source
count50609.00000045665.0000004.566500e+044.566500e+044.566500e+044.566500e+0445665.00000045663.00000050609.00000050609.00000050609.00000050609.00000050609.000000
mean0.017764425.3761071.832017e+051.881283e+051.808673e+059.043344e+050.576853149.3953971.4763781.6178941.9065190.3060722.900729
std0.132093400.5962442.007574e+052.048742e+051.977035e+059.885168e+050.494064605.1388231.5114703.0741660.3672800.8936820.726231
min0.0000001.0000000.000000e+000.000000e+001.000000e+005.000000e+000.0000000.0000000.0000000.0000000.0000000.0000000.000000
25%0.000000175.4400006.039100e+046.200100e+045.976100e+042.988010e+050.0000001.0000001.0000000.0000002.0000000.0000003.000000
50%0.000000336.1600001.229310e+051.279240e+051.209610e+056.048010e+051.0000001.0000001.0000000.0000002.0000000.0000003.000000
75%0.000000557.6000002.399050e+052.454010e+052.360790e+051.180391e+061.000000100.0000001.0000000.0000002.0000000.0000003.000000
max1.0000007952.8200003.916081e+063.996001e+063.851081e+061.925540e+071.00000050000.0000006.0000009.0000002.0000003.0000004.000000
  • 缺失值填充

    • 对creat_dt做补全,用oil_actv_dt来填补

    • 截取申请时间和放款时间不超过6个月的数据(考虑数据时效性)

#定义一个函数,用来填充时间为空的字段
def time_isna(x,y):
    if str(x) == 'NaT':
        x = y
    return x

df2 = df.sort_values(['uid','create_dt'],ascending = False)

#进行时间填充
df2['create_dt'] = df2.apply(lambda x: time_isna(x.create_dt,x.oil_actv_dt),axis = 1)

#计算时间的差值,考虑到数据的时效性,选择最近6个月的数据
df2['dtn'] = (df2.oil_actv_dt - df2.create_dt).apply(lambda x :x.days)
df = df2[df2['dtn']<180]
df.head()

显示结果:

uidcreate_dtoil_actv_dtclass_newbad_indoil_amountdiscount_amountsale_amountamountpay_amountcoupon_amountpayment_coupon_amountchannel_codeoil_codescenesource_appcall_sourcedtn
50608B964363919850357032018-10-082018-10-08B0NaNNaNNaNNaNNaNNaNNaN692340
50607B964363919846933972018-10-112018-10-11E0NaNNaNNaNNaNNaNNaNNaN692340
50606B964363919772174682018-10-172018-10-17B0NaNNaNNaNNaNNaNNaNNaN692340
50605B964363919764808922018-09-282018-09-28B0NaNNaNNaNNaNNaNNaNNaN692340
50604B964363919721060432018-10-192018-10-19A0NaNNaNNaNNaNNaNNaNNaN692340
  • 将用户按照id编号排序,并保留最近一次申请时间,确保每个用户有一条记录

base = df[org_list]
base['dtn'] = df['dtn']
base = base.sort_values(['uid','create_dt'],ascending = False)
base = base.drop_duplicates(['uid'],keep = 'first')
base.shape

显示结果:

(11099, 6)

  • 特征衍生

    • 对连续统计型变量进行函数聚合

    • 方法包括对历史特征值计数、求历史特征值大于0的个数、求和、求均值、求最大值、求最小值、求方差、求极差等

gn = pd.DataFrame()
for i in agg_list:
    tp = df.groupby('uid').apply(lambda df:len(df[i])).reset_index()
    tp.columns = ['uid',i + '_cnt']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求历史特征值大于0的个数
    tp = df.groupby('uid').apply(lambda df:np.where(df[i]>0,1,0).sum()).reset_index()
    tp.columns = ['uid',i + '_num']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求和
    tp = df.groupby('uid').apply(lambda df:np.nansum(df[i])).reset_index()
    tp.columns = ['uid',i + '_tot']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求平均值
    tp = df.groupby('uid').apply(lambda df:np.nanmean(df[i])).reset_index()
    tp.columns = ['uid',i + '_avg']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求最大值
    tp = df.groupby('uid').apply(lambda df:np.nanmax(df[i])).reset_index()
    tp.columns = ['uid',i + '_max']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求最小值
    tp = df.groupby('uid').apply(lambda df:np.nanmin(df[i])).reset_index()
    tp.columns = ['uid',i + '_min']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求方差
    tp = df.groupby('uid').apply(lambda df:np.nanvar(df[i])).reset_index()
    tp.columns = ['uid',i + '_var']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
    #求极差
    tp = df.groupby('uid').apply(lambda df:np.nanmax(df[i]) -np.nanmin(df[i]) ).reset_index()
    tp.columns = ['uid',i + '_ran']
    if gn.empty:
        gn = tp
    else:
        gn = pd.merge(gn,tp,on = 'uid',how = 'left')
  • 查看衍生结果

gn.columns

显示结果:

Index(['uid', 'oil_amount_cnt', 'oil_amount_num', 'oil_amount_tot',
       'oil_amount_avg', 'oil_amount_max', 'oil_amount_min',
       'oil_amount_var_x', 'oil_amount_var_y', 'discount_amount_cnt',
       'discount_amount_num', 'discount_amount_tot', 'discount_amount_avg',
       'discount_amount_max', 'discount_amount_min', 'discount_amount_var_x',
       'discount_amount_var_y', 'sale_amount_cnt', 'sale_amount_num',
       'sale_amount_tot', 'sale_amount_avg', 'sale_amount_max',
       'sale_amount_min', 'sale_amount_var_x', 'sale_amount_var_y',
       'amount_cnt', 'amount_num', 'amount_tot', 'amount_avg', 'amount_max',
       'amount_min', 'amount_var_x', 'amount_var_y', 'pay_amount_cnt',
       'pay_amount_num', 'pay_amount_tot', 'pay_amount_avg', 'pay_amount_max',
       'pay_amount_min', 'pay_amount_var_x', 'pay_amount_var_y',
       'coupon_amount_cnt', 'coupon_amount_num', 'coupon_amount_tot',
       'coupon_amount_avg', 'coupon_amount_max', 'coupon_amount_min',
       'coupon_amount_var_x', 'coupon_amount_var_y',
       'payment_coupon_amount_cnt', 'payment_coupon_amount_num',
       'payment_coupon_amount_tot', 'payment_coupon_amount_avg',
       'payment_coupon_amount_max', 'payment_coupon_amount_min',
       'payment_coupon_amount_var_x', 'payment_coupon_amount_var_y'],
      dtype='object')
  • 对dstc_lst变量求distinct个数

gc = pd.DataFrame()
for i in count_list:
    tp = df.groupby('uid').apply(lambda df: len(set(df[i]))).reset_index()
    tp.columns = ['uid',i + '_dstc']
    if gc.empty:
        gc = tp
    else:
        gc = pd.merge(gc,tp,on = 'uid',how = 'left')
  • 将变量组合在一起

fn = pd.merge(base,gn,on= 'uid')
fn = pd.merge(fn,gc,on= 'uid') 
fn.shape

显示结果:

(11099, 67)

  • merge过程中可能会出现缺失情况,填充缺失值

fn = fn.fillna(0)
fn.head(100)

显示结果:

uidcreate_dtoil_actv_dtclass_newbad_inddtnoil_amount_cntoil_amount_numoil_amount_totoil_amount_avg...payment_coupon_amount_maxpayment_coupon_amount_minpayment_coupon_amount_var_xpayment_coupon_amount_var_ypayment_coupon_amount_varchannel_code_dstcoil_code_dstcscene_dstcsource_app_dstccall_source_dstc
0B964363919850357032018-10-082018-10-08B00100.000.00...0.00.00.00.00.011111
1B964363919846933972018-10-112018-10-11E00100.000.00...0.00.00.00.00.011111
2B964363919772174682018-10-172018-10-17B00100.000.00...0.00.00.00.00.011111
3B964363919764808922018-09-282018-09-28B00100.000.00...0.00.00.00.00.011111

100 rows × 67 columns

  • 训练决策树模型

x = fn.drop(['uid','oil_actv_dt','create_dt','bad_ind','class_new'],axis = 1)
y = fn.bad_ind.copy()
from sklearn import tree
dtree = tree.DecisionTreeRegressor(max_depth = 2,min_samples_leaf = 500,min_samples_split = 5000)
dtree = dtree.fit(x,y)
  • 输出决策树图像,并作出决策

    • 需要安装 Graphviz 软件,下载地址Download | Graphviz

      • 下载之后需要配置环境变量,把安装目录如C:/Programming/Graphviz/bin/

    • 需要安装两个python库

#1.相比复杂,但比较友好的方式
import pydotplus 
from IPython.display import Image
from six import StringIO

dot_data = StringIO()
tree.export_graphviz(dtree, out_file=dot_data,
                         feature_names=x.columns,
                         class_names=['bad_ind'],
                         filled=True, rounded=True,
                         special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue()) 
Image(graph.create_png())

#2.另外一种画图方式,简单
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
plot_tree(model,feature_names=x.columns,
                         class_names=['bad_ind'],
                         filled=True, rounded=True)
plt.show()

显示结果:

  • 利用结果划分用户

group_1 = fn.loc[(fn.amount_tot>48077.5)&(fn.amount_cnt>3.5)].copy()
group_1['level'] = 'past_A'
group_2 = fn.loc[(fn.amount_tot>48077.5)&(fn.amount_cnt<=3.5)].copy()
group_2['level'] = 'past_B'
group_3 = fn.loc[fn.amount_tot<=48077.5].copy()
group_3['level'] = 'past_C'
  • 如果拒绝past_C类客户,则可以使整体负样本占比下降至0.021

  • 如果将past_B也拒绝掉,则可以使整体负样本占比下降至0.012

  • 至于实际对past_A、past_B、past_C采取何种策略,要根据利率来做线性规划,从而实现风险定价

小结

  • 信贷审批业务的基本流程

    • 申请→ 审批 → 放款→ 还款 → 再次申请 → 复贷审批

                 ↙↘                       ↘                            ↙↘

               规则       模型            逾期→催收           规则          模型

  • ABC评分卡

    • A申请,B行为,C催收

    • 针对客群不同,可用数据不同,Y定义不同

  • 风控建模的流程

    • 项目准备 → 特征工程 → 建模 → 上线运营

      明确需求 数据处理 模型训练 模型交付

      模型设计 特征构建 模型评价 模型部署

      样本设计 特征评估 模型调优 模型监控

  • 评分卡模型正负样本定义方法

    • 一般习惯Y = 1 为坏用户(违约)

    • Y=1 选取:用DPD30,DPD15.... (根据具体业务情况)做截断,删除灰色部分用户

    • 未逾期,或逾期5天以内作为好用户

  • 如何构建特征,如何评估特征

    • 特征构建

      • 画出E-R图,知道数据在哪些表中保存,表与表之间关系

      • 知道那些数据可以用

      • 单个特征从三个维度RFM考虑生成新特征

      • 用户时间截面特征

      • 用户时间序列特征

    • 特征评估

      • 覆盖度

      • 稳定性 PSI

      • 区分度 IV 单特征AUC/KS

  • 规则引擎如何工作

    • 使用一系列判断逻辑对客户群体进行区分,不同群体逾期风险有显著差别

    • 可以通过机器学习模型,辅助规则挖掘

标签:uid,df,模型,样本,建模,tp,风控,amount,概述
From: https://blog.csdn.net/2201_75415080/article/details/143650895

相关文章

  • 【金融风控】相关业务介绍及代码详解
    金融风控相关业务介绍【了解】项目整体介绍1.风控业务和风控报表</span>零售金融产品相关的指标风控建模流程​#2.特征工程特征构造特征筛选​3.评分卡模型构建逻辑回归集成学习XGBoostLightGBM模型评估​#4.样本不均衡问题/异常点检测【了解】今日内容介......
  • 词典编译配置文件概述
    概述《汉文博士》允许使用者自己编写词典文件。本文简要讲述了词典编译过程和相关配置文件的编写方法。读者需具备XML和正则表达式的基础知识。词典编译器《汉文博士》的词典编译器可在“文件”菜单中点击“词典编译器”调出。编译前,需点击“加载”按钮指定配置文件。选定配......
  • 计算机网络:网络安全(网络安全概述)_网络安全概论
    一、网络安全的概念与特征由于计算机网络多样的连接形式、不均匀的终端分布,以及网络的开放性和互联性等特征,使通过互联网传输的数据较易受到监听、截获和攻击。伴随着虚拟化、大数据和云计算技术等各种网络新技术广泛而深入的应用,如今网络安全问题已经和几乎所有传统的安全问......
  • 【SPIE出版,往届稳定EI检索】2024智能视觉与数据建模国际学术会议(ICIVD 2024,12月13-15
    2024智能视觉与数据建模国际学术会议2024InternationalConferenceonIntelligentVisionandDatamodeling(ICIVD2024)重要信息会议官网:www.iccaid.net2024InternationalConferenceonIntelligentVisionandDatamodeling(ICIVD2024)www.iccaid.......
  • StarUML建模工具安装学习与汉化最新零基础详细教程【一键式下载】(适用于Windows、MacO
    StarUML破解安装下载教程前言:StarUML破解与汉化安装下载教程,仅供学习研究和交流使用,禁止作为商业用途或其他非法用途!仓库作者:X1a0He,经仓库作者授权使用。目录StarUML破解安装下载教程1.下载准备1.1一键式准备【懒人准备】1.2学习式准备1.2.1学习准备2.window......
  • Blender 常用建模操作
    常用简单介绍挤出快捷键:E挤出是2个动作,生成加移动,所以右键撤销只能撤销移动内插快捷键:I内插仅是一个动作倒角快捷键:Ctrl+B滚动滚轮可以增加倒角的段数环切快捷键:Ctrl+R滚动滚轮可以增加倒角的段数挤出详细介绍沿轴线挤出或者自动挤出挤出流形可以向内挤出,避......
  • 车载信息娱乐系统软件:Alpine IVI二次开发_(1).车载信息娱乐系统概述
    车载信息娱乐系统概述什么是车载信息娱乐系统车载信息娱乐系统(In-VehicleInfotainment,IVI)是指安装在汽车内的多媒体系统,通常包括导航、音响、电话连接、互联网访问等功能。这些系统旨在为驾驶员和乘客提供丰富的信息和娱乐体验,同时确保行车安全和便利性。随着汽车技术......
  • Shell概述、编写及执行脚本、Shell变量+数值运算
    一、shell基本介绍 1.1 什么是shell◆ 在Linux内核与用户之间的解释器程序◆通常指/bin/bash◆负责向内核翻译及传达用户/程序指令◆相当于操作系统的“外壳”1.2 shell使用方式◆交互式 ——命令行-----人工干预、智能化程度高-----逐条解释执行、效率......
  • 数学建模_BP神经网络预测新数据模型(多输入单输出)回归预测模型+Matlab代码包教会使用
    基于BP神经网络新数据预测的多输入单输出回归预测模型简介这段代码实现了一个BP神经网络BackpropagationNeuralNetwork用于回归预测任务,并包含新数据的预测功能。该模型通过多层前馈神经网络学习输入特征与目标变量之间的非线性映射关系,并使用反向传播算法优化权重和偏置......
  • 数学建模_BP神经网络模型(多输入单输出)回归预测模型+Matlab代码包教会使用,直接替换
    基于BP神经网络的多输入单输出回归预测模型简介该模型使用了BP神经网络BackpropagationNeuralNetwork进行多输入单输出的回归预测。BP神经网络是一种常见的多层前馈神经网络,通过反向传播算法来优化权重和偏置,从而最小化预测误差。具体模型原理就不再细说了,需要可以翻看......