模型概率值与分数的转换-附python代码

无论评分卡建模和是机器学习建模,最终的输出结果都是概率值,并不是一个特定范围的分数,现给大家介绍一个方法。

1.基本定义

坏用户的概率为P
好用户的概率为1-P
好坏比(好坏用户的比值叫比率,这里用坏用户与好用户的比值)odds=p/(1-p)
模型的评分设定的分值刻度可以通过将分值表示为比率对数的线性表达式,即

Score = A - B * ln(odds),其中A,B是常数

2.评分转换

设odds=p/(1-p)时对应的分数为Score
设定当每增加1倍时,增加的分数PDO(point of double odds),即比率翻番的倍数
将odds=p/(1-p)对应的分数Score,2*odds对应的分数Score + PDO,带入分数公式得到如下的两个公式:

在这里插入图片描述
即:
在这里插入图片描述

此时给定比率odds=1/20,即此时坏样本占比为1/(1+20)≈ 4.76%,对应的分数为800分,比率翻番的倍数PDO=50.

def cfunc(ratio,basescore,double):
    x = Symbol('x')
    y = Symbol('y')
    out = solve([basescore -(x-y * np.log(ratio)), basescore -(x-y * np.log(2*ratio) + double)], [x, y])
    a = np.round(float(out.get(x)),2)
    b = np.round(float(out.get(y)),2)
    title = str(a) + '-' + str(b) + '*log(odds)'
    score_i = []
    score_j = []
    for i in np.arange(0.10,1.,0.10):
        score_sig = out.get(x) - out.get(y) * np.log(i /(1-i))
        score_i.append(int(score_sig))
    score_prob = pd.DataFrame({'prob':np.arange(0.10,1.00,0.10),'score':score_i})
    for j in [0.01,0.05,0.95,0.99]:
        score_sig = out.get(x) - out.get(y) * np.log(j / (1 - j))
        if score_sig > 850:
            score_sig = 850
        elif score_sig < 300:
            score_sig = 300
        else:
            score_sig = score_sig
        score_j.append(int(score_sig))
    score_prob_j = pd.DataFrame({'prob': [0.01,0.05,0.95,0.99], 'score': score_j})
    score_prob = score_prob.append(score_prob_j).sort_values(['prob'],ascending=False)
    # plot and save
    filepath = os.path.split(os.path.realpath(__file__))[0] + '\output'
    if not os.path.exists(filepath):
        os.mkdir(filepath)
    prob_plot(score_prob, title,filepath)

    return score_prob

注:为了将分数限定在300~850之间,将过大或过小的分数采用盖帽法原理予以限制

最终将坏样本的概率与分数对应的关系,通过折线图体现出来

def prob_plot(score_prob,title,filepath):
    import matplotlib.pyplot as plt
    plt.plot(score_prob.prob, score_prob.score, marker='o', mec='r', mfc='w', label='prob_to_score')
    plt.legend(loc=0)
    plt.plot(np.ones(score_prob.shape[0]) * 0.5, score_prob.score, mfc='r')
    for c, d in zip(score_prob.prob, score_prob.score):
        plt.text(c, d + 0.3, str(round(d)), ha='left', va='bottom', fontsize=10.5)
    plt.xticks(np.arange(0.00, 1.01, 0.10))
    plt.yticks(np.arange(0, 1001, 100))
    # plt.margins(0)
    plt.subplots_adjust(bottom=0.10)
    plt.title(title)
    plt.xlabel('prob')
    plt.ylabel("score")
    plt.savefig((filepath + '/{title}.jpg').format(title=str(title)[-3:-1]),dpi=900)

结果如下:
在这里插入图片描述

感兴趣的小伙伴可以自己设置不同的odds、Score和PDO,得到不同的比例关系

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值