【机器学习】催收评分卡模型(Collection Scorecard)
国家对非法催收的打击力度越来越大,旨在构建一个健康、有序的金融市场环境。同时,金融机构也应加强内部管理,合规经营,特别是重视催收评分卡的建设,共同促进金融市场的稳定发展。
催收评分卡概述
评分卡可分为申请评分卡(A卡)、行为评分卡(B卡)、催收评分卡(C卡)。不同的卡使用场景不一样,A卡用于贷前申请环节,用来区分客户好坏;B卡用于贷中环节,根据观察行为预测未来一段时间发生逾期/违约的概率;C卡主要用于贷后环节.申请评分卡、行为评分卡和催收评分卡常合并称为“ABC卡”,应用在贷前、贷中和贷后管理。催收评分卡所在风控环节如下图:
催收评分卡与其他评分卡的区别
催收评分卡(C卡)与申请评分卡(A卡)和行为评分卡(B卡)相比,有其独特的特点:
-
使用时间:C卡专注于贷后阶段,尤其是客户出现逾期后的风险评估。
-
数据要求:C卡需要更全面的数据,包括客户的逾期信息、催收历史和对催收措施的反应等。
-
模型构建:C卡模型需要考虑催收策略的影响,因此会加入与催收相关的变量。
-
预测目的:C卡的目的是预测客户对催收措施的反应,指导金融机构采取最有效的催收策略。
催收评分卡作用
催收评分卡作用是预判对逾期用户的催收力度。对于信誉较好的用户,不催收或轻量催收即可回款。对于有长时间逾期倾向的用户,需要从逾期开始就重点催收。逾期天数越多,催收难度越大。
催收评分卡通过量化分析,有效提升催收效率,最大化收回欠款,减少资产损失,帮助金融机构更有效地管理逾期贷款。Toby老师将带您全面了解催收评分卡的构建、应用及其在金融风控中的重要性。
催收评分卡的应用场景
催收评分卡在金融风控中的应用场景广泛,主要包括:
-
逾期风险评估:预测借款人未来逾期的可能性,帮助金融机构识别高风险客户群体。
-
催收策略制定:根据评分结果,对不同风险等级的客户采取差异化的催收策略。
-
催收效果监控:通过比较催收前后的评分变化,评估催收措施的有效性。
-
坏账准备金计提:评分结果可作为坏账准备金计提的依据,帮助金融机构合理预估潜在的信贷损失。
-
客户关系管理:识别有潜在还款困难的客户,提前进行沟通和协助,维护客户关系。
催收评分卡的构建思
催收评分卡的构建是一个系统工程,涉及到数据收集、特征工程、模型开发等多个环节。以下是构建催收评分卡的基本思路:
1.数据收集与清洗:金融机构需要整合来自不同渠道的数据,如基本信息、银行交易记录、社交媒体行为、信用历史等,以获得全面的客户画像,维度尽可能丰富。数据收集后进行清洗,去除重复、处理缺失值和异常值。在特殊月份和活动周期客户信息变化比较大,容易引起变量值较大波动。数据清洗中剔除特殊月份的样本,还有做活动引流时样本,保证出催动作和客群情况的稳定性。我看互联网上有些文章称要保证样本的均衡,这是不实际,不合理的。金融风控真实数据就是高度不平衡,我们人为55开平衡后,会误导模型判断能力。
2.特征选择和数据来源:重点关注还款意愿和还款能力,包括客户收入、资产情况、履约行为和催收记录等。基于原始数据生成新的特征,如交易频率、消费习惯等,并挑选对风险预测最有价值的特征。
3.模型构建:选择合适的分类模型,如逻辑回归、随机森林等,进行训练,并将其结果转化为直观的信用分数。银行最常用的是采用逻辑回归等统计模型,结合WOE(Weight of Evidence)和IV(Information Value)等指标,评估变量的预测能力。
4. 模型验证:通过KS统计量、AUC值、Gini系数等指标,验证模型的区分能力和预测精度。使用精确率、召回率、F1分数、ROC曲线下的面积(AUC)等评估指标,通过交叉验证、网格搜索等方法调整模型参数,提升预测准确性。Toby老师根据多年建模经验,催收评分卡的AUC一般比较高,很多高于0.8,原因是建立c卡时,用户已经有大量逾期数据表现。如果用户之前有逾期,那么后面也有逾期倾向。
5.模型部署与监控:将模型部署到生产环境,并建立监控机制,定期检查模型表现,确保模型的稳定性和有效性。如果模型性能例如AUC,ks下降太厉害,或PSI高于0.25,Toby老师建议重新建模,迭代模型。
催收评分卡的细分
催收评分卡和申请评分卡和行为评分卡不太一样,一般申请评分卡和行为评分卡使用一个模型就可以了,但是催收评分卡由三个模型构成:(不同的模型功能目的不一样,其中失联预测模型是比较重要的)
-
还款率模型
-
账龄滚动模型
-
失联预测模型
还款率模型
账龄滚动模型
失联预测模型
催收评分卡-还款率模型的代码实现
催收评分卡代码如下,还款率模型完之后还可以对其进行延伸,预测出来的催回还款率假设定一个阈值(80%,自己可以定),大于80%为可摧回,小于为不可催回,之后可以使用二分类的逻辑回归对客户情况进行预测该客户是可摧回还是不可催回。
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import GridSearchCV
def MakeupMissingCategorical(x):
if str(x) == 'nan':
return 'Unknown'
else:
return x
def MakeupMissingNumerical(x,replacement):
if np.isnan(x):
return replacement
else:
return x
'''
第一步:文件准备
'''
foldOfData = 'H:/'
mydata = pd.read_csv(foldOfData + "还款率模型.csv",header = 0,engine ='python')
#催收还款率等于催收金额/(所欠本息+催收费用)。其中催收费用以支出形式表示
mydata['rec_rate'] = mydata.apply(lambda x: x.LP_NonPrincipalRecoverypayments /(x.AmountDelinquent-x.LP_CollectionFees), axis=1)
#还款率假如大于1,按作1处理
mydata['rec_rate'] = mydata['rec_rate'].map(lambda x: min(x,1))
#整个开发数据分为训练集、测试集2个部分
trainData, testData = train_test_split(mydata,test_size=0.4)
'''
第二步:数据预处理
'''
#由于不存在数据字典,所以只分类了一些数据
categoricalFeatures = ['CreditGrade','Term','BorrowerState','Occupation','EmploymentStatus','IsBorrowerHomeowner','CurrentlyInGroup','IncomeVerifiable']
numFeatures = ['BorrowerAPR','BorrowerRate','LenderYield','ProsperRating (numeric)','ProsperScore','ListingCategory (numeric)','EmploymentStatusDuration','CurrentCreditLines',
'OpenCreditLines','TotalCreditLinespast7years','CreditScoreRangeLower','OpenRevolvingAccounts','OpenRevolvingMonthlyPayment','InquiriesLast6Months','TotalInquiries',
'CurrentDelinquencies','DelinquenciesLast7Years','PublicRecordsLast10Years','PublicRecordsLast12Months','BankcardUtilization','TradesNeverDelinquent (percentage)',
'TradesOpenedLast6Months','DebtToIncomeRatio','LoanFirstDefaultedCycleNumber','LoanMonthsSinceOrigination','PercentFunded','Recommendations','InvestmentFromFriendsCount',
'Investors']
'''
类别型变量需要用目标变量的均值进行编码
'''
encodedFeatures = []
encodedDict = {}
for var in categoricalFeatures:
trainData[var] = trainData[var].map(MakeupMissingCategorical)
avgTarget = trainData.groupby([var])['rec_rate'].mean()
avgTarget = avgTarget.to_dict()
newVar = var + '_encoded'
trainData[newVar] = trainData[var].map(avgTarget)
encodedFeatures.append(newVar)
encodedDict[var] = avgTarget
#对数值型数据的缺失进行补缺
trainData['ProsperRating (numeric)'] = trainData['ProsperRating (numeric)'].map(lambda x: MakeupMissingNumerical(x,0))
trainData['ProsperScore'] = trainData['ProsperScore'].map(lambda x: MakeupMissingNumerical(x,0))
avgDebtToIncomeRatio = np.mean(trainData['DebtToIncomeRatio'])
trainData['DebtToIncomeRatio'] = trainData['DebtToIncomeRatio'].map(lambda x: MakeupMissingNumerical(x,avgDebtToIncomeRatio))
numFeatures2 = numFeatures + encodedFeatures
'''
第三步:调参
对基于CART的随机森林的调参,主要有:
1,树的个数
2,树的最大深度
3,内部节点最少样本数与叶节点最少样本数
4,特征个数
此外,调参过程中选择的误差函数是均值误差,5倍折叠
'''
X, y= trainData[numFeatures2],trainData['rec_rate']
param_test1 = {'n_estimators':range(60,91,5)}
gsearch1 = GridSearchCV(estimator = RandomForestRegressor(min_samples_split=50,min_samples_leaf=10,max_depth=8,max_features='sqrt' ,random_state=10),param_grid = param_test1, scoring='neg_mean_squared_error',cv=5)
gsearch1.fit(X,y)
gsearch1.best_params_, gsearch1.best_score_
best_n_estimators = gsearch1.best_params_['n_estimators']
param_test2 = {'max_depth':range(3,15), 'min_samples_split':range(10,101,10)}
gsearch2 = GridSearchCV(estimator = RandomForestRegressor(n_estimators=best_n_estimators, min_samples_leaf=10,max_features='sqrt' ,random_state=10,oob_score=True),param_grid = param_test2, scoring='neg_mean_squared_error',cv=5)
gsearch2.fit(X,y)
gsearch2.best_params_, gsearch2.best_score_
best_max_depth = gsearch2.best_params_['max_depth']
best_min_samples_split = gsearch2.best_params_['min_samples_split']
param_test3 = {'min_samples_leaf':range(1,20,2)}
gsearch3 = GridSearchCV(estimator = RandomForestRegressor(n_estimators=best_n_estimators, max_depth = best_max_depth,max_features='sqrt',min_samples_split=best_min_samples_split,random_state=10,oob_score=True),param_grid = param_test3, scoring='neg_mean_squared_error',cv=5)
gsearch3.fit(X,y)
gsearch3.best_params_, gsearch3.best_score_
best_min_samples_leaf = gsearch3.best_params_['min_samples_leaf']
numOfFeatures = len(numFeatures2)
mostSelectedFeatures = numOfFeatures/2
param_test4 = {'max_features':range(3,numOfFeatures+1)}
gsearch4 = GridSearchCV(estimator = RandomForestRegressor(n_estimators=best_n_estimators, max_depth=best_max_depth,min_samples_leaf=best_min_samples_leaf,min_samples_split=best_min_samples_split,random_state=10,oob_score=True),param_grid = param_test4, scoring='neg_mean_squared_error',cv=5)
gsearch4.fit(X,y)
gsearch4.best_params_, gsearch4.best_score_
best_max_features = gsearch4.best_params_['max_features']
#把最优参数全部获取去做随机森林拟合
cls = RandomForestRegressor(n_estimators=best_n_estimators,max_depth=best_max_depth,min_samples_leaf=best_min_samples_leaf,min_samples_split=best_min_samples_split,max_features=best_max_features,random_state=10,oob_score=True)
cls.fit(X,y)
trainData['pred'] = cls.predict(trainData[numFeatures2])
trainData['less_rr'] = trainData.apply(lambda x: int(x.pred > x.rec_rate), axis=1)
np.mean(trainData['less_rr'])
err = trainData.apply(lambda x: np.abs(x.pred - x.rec_rate), axis=1)
np.mean(err)
#随机森林评估变量重要性
importance=cls.feature_importances_
featureImportance=dict(zip(numFeatures2,importance))
featureImportance=sorted(featureImportance.items(),key=lambda x:x[1],reverse=True)
'''
第四步:在测试集上测试效果
'''
#类别型数据处理
for var in categoricalFeatures:
testData[var] = testData[var].map(MakeupMissingCategorical)
newVar = var + '_encoded'
testData[newVar] = testData[var].map(encodedDict[var])
avgnewVar = np.mean(trainData[newVar])
testData[newVar] = testData[newVar].map(lambda x: MakeupMissingNumerical(x, avgnewVar))
#连续性数据处理
testData['ProsperRating (numeric)'] = testData['ProsperRating (numeric)'].map(lambda x: MakeupMissingNumerical(x,0))
testData['ProsperScore'] = testData['ProsperScore'].map(lambda x: MakeupMissingNumerical(x,0))
testData['DebtToIncomeRatio'] = testData['DebtToIncomeRatio'].map(lambda x: MakeupMissingNumerical(x,avgDebtToIncomeRatio))
testData['pred'] = cls.predict(testData[numFeatures2])
testData['less_rr'] = testData.apply(lambda x: int(x.pred > x.rec_rate), axis=1)
np.mean(testData['less_rr'])
err = testData.apply(lambda x: np.abs(x.pred - x.rec_rate), axis=1)
np.mean(err)
上述模型采用了随机森林模型。
随机森林(Random Forest,RF)是一种集成学习方法,主要用于分类、回归和其他任务的机器学习算法。它是由多棵决策树组成的一个森林,通过构建多棵树并对它们的预测结果进行汇总来工作。随机森林算法是由Leo Breiman在2001年提出的,是机器学习领域中最受欢迎的算法之一。
基于回归树的随机森林(元分类器是由许多回归树构成,每一个元分类器模型并行运行得出一个预测值,取所有元分类器模型的平均值作为最终的预测值)
催收评分卡模型大概汇总了关键信息,下面Toby老师补充一下催收业务知识。
信贷客户管理的周期
要学习催收评分卡,首先要先了解一下信贷客户管理的周期。
客户关系管理流程的概览,它分为四个主要阶段:获客、准入、经营和逾期。每个阶段都包含了不同的策略和活动,旨在优化客户获取、管理及维护的全过程。以下是每个阶段的详细内容:
获客阶段
-
精准营销
-
需求识别:识别潜在客户的需求。
-
客户画像:构建客户的特征模型。
-
营销场景:设计适合的营销环境和活动。
-
预审批、预授信:在正式审批前对客户进行预先评估和信用授权。
-
准入阶段
-
资料核查
-
身份核实与反欺诈:验证客户身份的真实性并防止欺诈行为。
-
信息核验:检查客户提供信息的准确性。
-
黑名单查询:检查客户是否在不良信用记录名单中。
-
综合资质评估:对客户的总体资质进行评估。
-
经营阶段
-
存量客户管理
-
存量客户评估:对现有客户的信用状况进行评估。
-
贷中行为监控:在贷款期间监控客户的行为。
-
交叉销售:向现有客户推销其他产品或服务。
-
逾期阶段
-
催收与专卖
-
失联修复:尝试重新联系失联的客户。
-
公债管理:管理公开的债务信息。
-
催收服务资产买卖:处理和买卖催收服务相关的资产。
-
这些策略和活动共同构成了一个全面的客户关系管理框架,旨在提高客户满意度、优化风险管理和增加企业收益。
逾期客户分类
很多银行风控策略过于呆板,缺乏人性。人性是健忘的,部分用户逾期几毛钱,几元钱忘了还,过了3个月-6个月后就被银行的风控策略定义为坏客户,加入黑名单,这些用户要去申请其它银行信用卡几乎不可能。其实对于逾期,不能一棍子打死,逾期有时候罚息对于公司来说也是一种收益,所以我们需要对逾期客户进行分类,不同客户类别采取的催收手段都是不一样的。
其中风险等级(第四类>第三类>第二类>第一类)
第一类:轻度
-
描述:客户的还款意愿和还款能力都是良好的。逾期还款是由于特殊原因造成的,例如因生意出差在外地未能及时赶回、忘记还款日期、或因特殊情况暂时没有时间处理还款事宜,导致出现数天的逾期。
-
管理措施:通常这类逾期比较容易处理,金融机构可能会通过提醒或简单的催收措施来解决问题。
第二类:中轻度
-
描述:客户的还款意愿仍然是良好的,但还款能力出现了问题。这可能是由于临时的经济困难或其他财务问题导致的。
-
管理措施:金融机构可能需要提供一些财务咨询或还款计划调整,帮助客户恢复还款能力。
第三类:中度
-
描述:客户没有还款意愿或还款意愿恶化,但仍然有还款能力。这可能是由于客户对贷款条件不满或其他个人原因导致的。
-
管理措施:金融机构可能需要采取更积极的催收措施,或者重新协商贷款条件,以恢复客户的还款意愿。
第四类:重度
-
描述:客户既没有还款意愿,还款能力也弱化或完全丧失。这是最严重的情况,客户可能面临长期的财务困难或其他问题。
-
管理措施:金融机构可能需要采取法律行动或其他强制措施来追回债务,同时也可能需要对这类客户进行更深入的财务分析和风险评估。
这种分类方法有助于金融机构更有效地管理和预测逾期风险,从而制定相应的风险控制和客户管理策略。
催收的流程
催收的流程大致可以分为以下几步:
第一步:短信催收
-
时间范围:还款日的7-15天内。
-
描述:如果持卡人在这段时间内没有还款,银行会发送短信提醒客户还款。
第二步:电话催收
-
时间范围:逾期超过30天。
-
描述:如果客户逾期不止一次,并且本次逾期超过了30天,银行会通过电话进行催收。
第三步:实地催收
-
时间范围:逾期超过90天。
-
描述:在这个阶段,如果客户仍未还款,银行可能会派遣人员上门进行催收。
第四步:诉诸法院
-
时间范围:逾期时间更长。
-
描述:如果逾期时间继续延长,银行可能会通过法务部门提起法律诉讼,以追回债务。
第五步:第三方催收
-
描述:如果上述步骤都无法成功回收债务,银行可能会将逾期的资产打包卖给专业的催收公司,由这些公司继续进行催收工作。
第三方催收可能涉及非法和暴力催收,如果闹出人命了,公安部门会介入。第三方催收行为必须遵循法律法规,任何形式的暴力催收都是不可接受的。根据《中华人民共和国刑法修正案(十一)》,催收非法债务罪是针对采取暴力、“软暴力”等手段催收高利放贷等产生的非法债务的行为,自2021年3月1日起施行。此外,公安部等九部门联合部署,严打软暴力催收、套路贷,特别强调了对侵犯个人隐私信息的打击。暴力催收行为不仅违反社会公德,还可能触犯《中华人民共和国刑法》和《中华人民共和国治安管理处罚法》。如果催收行为导致严重后果,如债务人受伤或死亡,公安部门会介入调查,相关责任人将面临法律的严厉制裁。因此,催收机构和人员必须严格遵守法律规定,不得采取任何非法手段进行催收。
催收业务知识
业务上催收一般分为多个坐席,M1,M2,M3等不同坐席员工经验和业务能力相差甚大。AI人工智能常用于前期自动化催收。
C卡主要是在贷款逾期的第一个月(M1阶段)起作用,因为这时候催收成功的几率最高,一旦客户逾期进入到第二个月(M2),催收难度就会增加。因此,金融机构的催收策略和模型都会特别关注M1阶段。
在M1阶段,催收工作主要分为三类模型:
-
缓催模型:这个模型针对的是那些可能因为忘记而逾期的客户,他们往往只需要一点点提醒就会还款。缓催模型的目的是通过减少催收动作来节省人力成本。
-
迁徙率模型:这个模型用来预测资产从一种状态转变为另一种状态的可能性,比如从正常状态转变为坏账状态,帮助金融机构预估不良资产的风险。
-
失联模型:这个模型关注的是如何识别和处理那些联系不上的客户。它的关键点在于确定什么情况下将客户定义为失联,比如连续几次电话未接通。失联模型帮助金融机构及时采取措施,比如委托外部机构或修复失联信息。
催收绩效指标
-
催收绩效的衡量标准包括多个关键指标,用以评估催收工作的成效:
-
回款率:成功回收的欠款金额与总欠款金额的比例。
-
递延率:未能按时回收的欠款金额与到期应回收欠款金额的比例。
-
BP/PTP%:即回款率与目标回款率的比例,用于衡量实际回收与目标回收之间的差距。
-
PRC%:即实际回收金额与预期回收金额的比例,反映催收效率。
-
PTP%:即催收周期内实际回收金额与周期开始时欠款总额的比例。
-
KPTP%:可能指的是关键绩效指标与目标的比率,具体含义可能因机构而异。
-
-
操作绩效的衡量标准则侧重于催收过程中的操作效率和效果:
-
外呼次数:催收人员进行的电话外呼总数,反映催收活动的频率。
-
有效拨打率:成功接通的电话次数与外呼次数的比例,衡量外呼效率。
-
其他查找成效:可能包括催收人员在查找失联客户、收集客户信息等方面的成效
-
总结
催收评分卡作为金融风控的精细化管理工具,其构建和应用需要综合考虑数据、模型、市场变化等多方面因素。通过科学的方法和持续的优化,催收评分卡能够有效地帮助金融机构提高催收效率,降低资产损失,同时优化客户关系管理。随着金融科技的发展,催收评分卡模型将更加智能化、高效化,为金融机构提供更加精准、全面的风险管理支持。最后Toby老师提醒一下各个金融公司,切勿非法暴力催收,合法合规经营。