Skip to content

Latest commit

 

History

History
248 lines (216 loc) · 11.7 KB

2020-06-23_Python信用风险建模_B站视频.org

File metadata and controls

248 lines (216 loc) · 11.7 KB

Python信用风险建模

第十四集 因变量与自变量

要对PD, LGD, EAD建立模型,它们都是回归模型。

  • PD: 逻辑回归(Logistic regression)
  • LGD: Beta回归(Beta regression)
  • EAD: Beta回归(Beta regression)

不同模型的因变量:

  • PD: Loan status列
  • LGD: recoveries列
  • EAD: total recovered principal列

不同自变量的预处理方式不同:

  • 离散变量:categorical, 取有限值
    • 无序离散变量: 按离散值处理
    • 有序离散变量: 按连续值处理
  • 连续变量:数值型,可以取无限个值, 按连续值处理

PD模型要求所有的自变量都必须是categorical,这是为了方便呈现和易于转化成评分卡。 所以预处理就是要把所有变量转化成区间形式。

  • 对于离散变量有时要先进行区间合并,再转化成dummy变量。
  • 对于连续变量要先fine classing, 再coarse classing, 再转化成dummy变量

再将这些dummy变量送入模型中。

第十五集 将数据载入到Python

第十六集 预处理一些连续变量

首先要确保所有的连续变量是numeric类型。

第十七集 预处理一些离散变量

pd.get_dummies(loan_data['grade'])
pd.get_dummies(loan_data['grade'], prefix='grade', prefix_sep='_')

loan_data_dummies = [pd.get_dummies(loan_data['grade'], prefix = 'grade', prefix_sep = ':'),
                     pd.get_dummies(loan_data['sub_grade'], prefix = 'sub_grade', prefix_sep = ':'),
                     pd.get_dummies(loan_data['home_ownership'], prefix = 'home_ownership', prefix_sep = ':'),
                     pd.get_dummies(loan_data['verification_status'], prefix = 'verification_status', prefix_sep = ':'),
                     pd.get_dummies(loan_data['loan_status'], prefix = 'loan_status', prefix_sep = ':'),
                     pd.get_dummies(loan_data['purpose'], prefix = 'purpose', prefix_sep = ':'),
                     pd.get_dummies(loan_data['addr_state'], prefix = 'addr_state', prefix_sep = ':'),
                     pd.get_dummies(loan_data['initial_list_status'], prefix = 'initial_list_status', prefix_sep = ':')]
loan_data_dummies = pd.concat(loan_data_dummies, axis = 1)

第十八集 预处理缺失值

第十九集 PD模型是什么样的

好坏定义(违约定义):一般定义为拖欠还款超过90天。 images/logistic0.png

images/logistic.png

监管者要求PD模型要有可解释性,所以它的输入变量都是dummy变量。

第二十集 根据好坏定义建立因变量

np.where() 类似于 if 语法。用 apply 也可以实现:

good = ['Fully Paid', 'Current', 'In Grace Period', 'Late (16-30 days)',
       'Does not meet the credit policy. Status:Fully Paid']
df['good_bad'] = df.loan_status.apply(lambda x: 1 if x in good else 0)

第二十一集 连续变量离散化,Fine classing, WOE和Coarse classing

先将连续变量进行初始离散,再计算每个离散区间的WoE。

WoE_i = ln(%goodi/%badi)

WoEi的绝对值越大,则这个离散区间区分好坏的能力越强。再根据初始的离散区间构造 新的区间,这个过程称为Coarse classing.

构造新区间的方法为将WoE值相近的区间合并,以减少区间数量。再将新的区间转化成dummy变量, 送入PD模型中。

第二十二集 信息值IV

反映自变量对因变量的预测能力,可以用来pre-selection,即特征选择。但是本视频不会用IV 值来选择特征,因为我们将用更高级的方法。但这是个很重要的量,经常用到。 images/iv.png

第二十三集 分离测试集

用sklearn的train_test_split

第二十四集 计算grade变量的WoE

# 计算每个grade的分立取值对应的因变量target的个数
df['good_bad'] = df.groupby('grade', as_index=false)['target'].count()

第二十五集 自动计算离散变量的WoE和IV值

定义函数来自动处理离散变量,函数原型为:

def woe_discrete(df, discrete_variable_name, target_variable_df):
    # 计算WoE
    df['WoE'] = #...
    # 计算IV
    df['IV'] = #...
    return df

DataFrame df中包含了以字符串命名的离散变量discrete_variable_name, 因变量单独存在以target_variable_df 命名的DataFrame中。

第二十六集 可视化离散变量的WoE

定义绘图函数 plot_woe(df_woe, rotation_x_label=0)

第二十七集 根据WoE合并离散变量的分立取值(一)

合并的依据:?

  • 样本数太少的应该合并到其他组
  • 样本数大的应该单独分为一组
  • WoE值相近的可以分为一个组

直接将需要合并的离散变量的分立取值对应的dummy变量相加!(不懂为什么?)

# 合并grade A和B
df['AB'] = sum(df['grade:A'], df['grade:B'])

第二十八集 根据WoE合并离散变量的分立取值(二)

风险管理的保守态度,缺失信息则假设为风险最高。将合并好的分组转化成dummy变量, 并将WoE最小的分组作为参考,以比较回归模型的能力。合并的方法和上节相同,用 sum

第二十九集 连续变量计算woe的方法(一)

离散变量定性不同,它们的顺序没有意义,所以我们之前按woe值大小排序,以进行Coarse classing. 连续变量定量不同,它们是有序的,不能按它们的woe值大小排序,而要按它 们本身的值排序,所以计算woe的函数只需要注释掉按woe排序即可,绘图函数不变。

第三十集 连续变量计算woe的方法:示例有序离散变量(当作连续值处理)(二)

在计算得到每个初始分组的woe后,用 np.where 将不同的分组合并。

df['emp_length_0'] = np.where(df.emp_length.isin([0]) 1, 0)
df['emp_length_3-6'] = np.where(df.emp_length.isin(range(3,7)) 1, 0)

第三十一集 连续变量计算woe的方法:连续变量示例(三)

先用qcut(df[‘mth_since_issue_d’], 50)成初始分组,再计算woe,并以此为 依据分组。同时考虑样本数量和woe值。

  • 观察woe时去掉两端极端的组,继续观察剩下的分组woe,以进一步分组。
  • 当出现锯齿状单调上长或下降的woe时,一般是由于样本数量太少引起的,可以将它们合并成一组。
  • 当出现锯齿状基本水平的woe时,一般是由于自变量对预测没用,可以将这个变量丢弃。
注意:可以在woe图中同时绘制样本数量的线,以方便Coarse classing。

第三十二集 连续变量计算woe的方法:有偏斜的自变量和有缺失值的变量(四)

先将收入变量初始分组100个,将收入高于某个阀值的组的样本数量很少,先不考虑, 对其余分组进行woe分析以合并分组。将大于阀值的组合并为一个分组。

df_temp = df.loc[df.income <= 140000, :] # 选择收入小于140000的行
df_target[df_temp.index] # 从因变量中选择出相应的行,df_target是个Series

对于有缺失值的自变量的处理也相似,先把缺失值的行去掉,分析合并有值的行,再将 有缺失 值的行划分到时一个分组中。

第三十三集 预处理测试集

处理测试集与训练集的步骤基本相同。对于测试集不需要计算woe和IV及可视化,也不用 Coarse classing,只需要保证也是相同的dummy变量即可。方便起见,可用相同的 代码运行测试集。

第三十四集 PD的逻辑回归模型

PD的逻辑回归模型特殊之处在于它的输入量都是dummpy变量。 线性回归的logistic函数就是逻辑回归。 y = ∑i βi xi

P(y) = sigmoid(y)

Y = 1, if P(y) > 0.5

Y = 0, if P(y) < 0.5

odds = P(Y=1)/P(Y=0) = eY

所以,

log(odds) = y = ∑i βi xi

PD模型中逻辑回归系数的解释如下:以高等教育变量为例。

y = -3.91 + 0.24x = log(odds)

则有高等教育经历(用x=1表示)与无高等教育经历(用x=0表示)的赔率比为:

odds(Y=1|x=1) / odds(Y=1|x=0) = eln(P(Y=1|x=1)) - ln(P(Y=1|x=0)) = e0.24 = 1.27

或者,

odds(Y=1|x=1) = 1.27 × odds(Y=1|x=0)

也就是说有高等教育经历的赔率比没有的赔率要高27%,这样逻辑回归的结果就具有可解释性了。

第三十五集 加载数据和选择特征

对于每个变量必须要删除一个dummy变量,以免陷入所谓的dummy variable trap。 因为n列的dummy变量可以由自由度为n-1的dummy变量表示,有一个冗余的dummy变量。 此处将每个变量woe最小的dummy丢弃,作为参考dummy。

选择特征用如下的方法:

filtered_col = ['grade:A',
'grade:B',
'grade:C',
'grade:D',
'grade:E',
'grade:F',
'grade:G',
'home_ownership:RENT_OTHER_NONE_ANY',
'home_ownership:OWN',
'home_ownership:MORTGAGE']
df_filtered  = df.reindex(columns=filtered_col)

丢弃特征用drop方法。

第三十六集 PD模型求解

用sklearn的 LogisticRegression() 拟合训练集。得到 reg.coef_reg.intercept_ 并将它们存在一个DataFrame里。

第三十七集 建立一个有P值的逻辑回归模型

重新定义逻辑回归,增加p值。p值的定义。此处p值计算代码如下:(没看懂!)

# P values for sklearn logistic regression.
# Class to display p-values for logistic regression in sklearn.
from sklearn import linear_model
import scipy.stats as stat

class LogisticRegression_with_p_values:
    def __init__(self,*args,**kwargs):#,**kwargs):
        self.model = linear_model.LogisticRegression(*args,**kwargs)#,**args)
    def fit(self,X,y):
        self.model.fit(X,y)
        #### Get p-values for the fitted model ####
        denom = (2.0 * (1.0 + np.cosh(self.model.decision_function(X))))
        denom = np.tile(denom,(X.shape[1],1)).T
        F_ij = np.dot((X / denom).T,X) ## Fisher Information Matrix
        Cramer_Rao = np.linalg.inv(F_ij) ## Inverse Information Matrix
        sigma_estimates = np.sqrt(np.diagonal(Cramer_Rao))
        z_scores = self.model.coef_[0] / sigma_estimates 
        # z-score for eaach model coefficient
        p_values = [stat.norm.sf(abs(x)) * 2 for x in z_scores] 
        ### two tailed test for p-values
        self.coef_ = self.model.coef_
        self.intercept_ = self.model.intercept_
        #self.z_scores = z_scores
        self.p_values = p_values
        #self.sigma_estimates = sigma_estimates
        #self.F_ij = F_ij

看p值来选择变量,只保留那些显著的变量。转化成dummy变量后,原来的一个变量由很多个dummy表示, 所以除非都不显著或绝大多数都不显著,否则都应该保留。如果p小于0.05,则保留这级dummy变量。

第三十八集 PD模型的系数解释

以之前预留的参考分组为对照,可以计算同一变量的不同分组的赔率比,如:

odds(Y=1|grade=D) / odds(Y=1|grade=G) = e β_{D }

我们假设参考组的拟合系数为0.

odds(Y=1|grade=B) / odds(Y=1|grade=D) = e β_{B - βD }

这种比较只能对同一变量的不同分组进行,不能对不同的两个变量进行。

第三十九集 PD模型的测试

将测试集转化成训练集相同的列(先fine classing,再coarse classing, 再丢弃参考分组, 再计算p值进行变量选择)。

再用逻辑回归来预测X_test

第四十集 计算模型的性能:精度和ROC AUC

概念及标准: images/ROCAUC.png

第四十一集 计算模型的性能:Gini系数和Kolmogorov-Smirnov

两个在风险建模领域广泛使用的分类衡量指标:Gini系数和Kolmogorov-Smirnov系数。

Gini系数一开始用于在经济学中衡量收入不平等性,此处它用于衡量好/坏借贷者的数量不 均衡性。

第四十三集 建立评分卡

images/card.png