QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1385|回复: 0
打印 上一主题 下一主题

python风控模型举例

[复制链接]
字体大小: 正常 放大

907

主题

66

听众

17万

积分

  • TA的每日心情
    开心
    2023-3-15 17:49
  • 签到天数: 224 天

    [LV.7]常住居民III

    社区QQ达人 邮箱绑定达人 元老勋章 发帖功臣 新人进步奖 优秀斑竹奖 金点子奖 原创写作奖 最具活力勋章 助人为乐奖 风雨历程奖

    跳转到指定楼层
    1#
    发表于 2021-6-2 11:27 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    生成样本

    首先,本文用以示例,故使用代码创造的一些假样本。

    import numpy as np

    import pandas as pd

    n_sample = 1000

    df_score = pd.DataFrame({
    'user_id': [u for u in range(n_sample)],

    'label':np.random.randint(2, size=n_sample),

    'score': 900*np.random.random(size=n_sample),

    'term': 20201+np.random.randint(5, size=n_sample)

    })



    然后我们统计下分term的总人数,坏人数和坏人比例:

    df_score.groupby('term').agg(total=('label', 'count'),

    bad=('label', 'sum'),

    bad_rate=('label', 'mean'))



    02

    区分度指标

    计算区分度指标KS、AUC、GINI的helper function如下:

    from sklearn.metrics import roc_auc_score, roc_curve

    def get_auc(ytrue, yprob):

    auc = roc_auc_score(ytrue, yprob)

    if auc < 0.5:

    auc = 1 - auc

    return auc

    def get_ks(ytrue, yprob):

    fpr, tpr, thr = roc_curve(ytrue, yprob)

    ks = max(abs(tpr - fpr))

    return ks

    def get_gini(ytrue, yprob):

    auc = get_auc(ytrue, yprob)

    gini = 2 * auc - 1

    return gini

    这里对原有sklearn的auc计算做了一点修改,如果AUC<0.5的话会返回1-AUC, 这样能忽略区分度的方向性。

    然后对每个term做区分度的计算:

    df_metrics = pd.DataFrame({
    'auc': df_score.groupby('term').apply(lambda x: get_auc(x['label'], x['score'])),

    'ks': df_score.groupby('term').apply(lambda x: get_ks(x['label'], x['score'])),

    'gini': df_score.groupby('term').apply(lambda x: get_gini(x['label'], x['score']))

    })



    这里先分成2步:

    简单对随机生成的信用分按固定分数区间分段;

    按照分段计算PSI:使用pivot_table把数据按照term进行排列计算每个term上的人数比例。

    df_score['score_bin'] = pd.cut(df_score['score'], [0, 500, 700, 800, 900])

    df_total = pd.pivot_table(df_score,

    values='user_id',

    index='score_bin',

    columns=['term'],

    aggfunc="count",

    margins=True)

    df_ratio = df_total.div(df_total.iloc[-1, :], axis=1)



    根据人数比例计算PSI再放回表格内

    eps = np.finfo(np.float32).eps

    lst_psi = list()

    for idx in range(1, len(df_ratio.columns)-1):

    last, cur = df_ratio.iloc[0, -1: idx-1]+eps, df_ratio.iloc[0, -1: idx]+eps

    psi = sum((cur-last) * np.log(cur / last))

    lst_psi.append(psi)

    df_ratio.append(pd.Series([np.nan]+lst_psi+[np.nan],

    index=df_ratio.columns,

    name='psi'))



    统计总人数分布和坏用户比例的分布,其实在上面计算PSI的时候已经计算出人数分布,就是上面的df_ratio:

    df_total = pd.pivot_table(df_score,

    values='user_id',

    index='score_bin',

    columns=['term'],

    aggfunc="count",

    margins=True)

    df_ratio = df_total.div(df_total.iloc[-1, :], axis=1)
    剩余内容请前往原文查看
    ————————————————
    版权声明:本文为CSDN博主「你一直在玩儿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_33758343/article/details/112962601

    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-11 01:52 , Processed in 0.284450 second(s), 52 queries .

    回顶部