1. Proceso de construcción de modelos
1.1 Diseño experimental
El nuevo modelo debe compararse con el plan original, y se prueba mediante experimentos, y se debe prestar especial atención al modelo y la estrategia no se puede ajustar al mismo tiempo. El diseño experimental general incluye los siguientes procedimientos:
Pregunta: Después de que el negocio sea estable, ¿se puede eliminar la revisión manual?
Respuesta : No. Después de que se lanza el modelo general, el rendimiento de los segmentos alto y bajo es mejor, pero el segmento medio aún necesita revisión manual, e incluso después de perfeccionar el modelo, solo podemos reducir la revisión manual y es imposible abandonar por completo la revisión manual.
1.2 Diseño de la muestra
1.3 Capacitación y evaluación del modelo
Al realizar la selección y evaluación de modelos, evaluamos los modelos en el siguiente orden: Interpretabilidad > Estabilidad > Discriminación.
Índice de discriminación: AUC y KS
Índice de estabilidad: PSI
AUC: el área bajo la curva ROC, que refleja la capacidad de la probabilidad de salida del modelo para clasificar a los usuarios buenos y malos, y es el estado promedio de discriminación del modelo.
KS: Refleja la mayor diferencia en la distribución de buenos y malos usuarios, que es el mejor estado de discriminación del modelo.
Entre los indicadores de negocio, nos fijamos principalmente en la tasa de aprobación y la tasa de morosidad. Bajo la premisa de una tasa de atraso razonable, la tasa de aprobación debe incrementarse tanto como sea posible.
Una tarjeta: preste más atención a la tasa de aprobación, y la tasa de atraso puede ser ligeramente más baja;
Tarjeta B: encuentre formas de reducir la tasa de atraso y aumentar la cuota para buenos usuarios.
2. Construcción del modelo de regresión logística
La regresión logística es esencialmente un problema de regresión, y su salida está entre [0,1].Entonces, este resultado puede corresponder a la probabilidad de incumplimiento del usuario, y podemos asignar la probabilidad de incumplimiento a la puntuación.
Por ejemplo: puntuación
de fórmula de conversión de cuadro de mando estándar de la industria = 650 + 50 log 2 (P atrasado/ P no atrasado) puntuación = 650+50log_{2}(P_{atrasado}/P_{no atrasado})puntaje=650+50 log _ _2( PAGAtrasado/ pagno atrasado) , entonces, ¿cómo transformarlo aquí? Veamos la siguiente función sigmoidea:
y = 1 1 + e − z = 1 1 + e − ( w T x + b ) y = \frac{1}{1+e^{-z}} = \frac{ 1}{1+e^{-(w^Tx+b)}}y=1+mi− z1=1+mi− ( wT x+b)1
se puede transformar en la siguiente fórmula:
ln ( y 1 − y ) = w T x + b ln(\frac{y}{1-y})=w^Tx+ben ( _1−ytu)=wTX _+b
y nuestra fórmula de conversión de puntuación se puede transformar de la siguiente manera:
log 2 ( P atrasado / P no atrasado) = ln ( P atrasado 1 − P atrasado) / ln ( 2 ) = ( w T x + b ) / ln ( 2 ) log_ {2}(P_{vencido}/P_{no vencido}) = ln(\frac{P_{vencido}}{1-P_{vencido}})/ln(2) = (w^Tx+b)/ en (2)registro _ _2( PAGAtrasado/ pagno atrasado)=en ( _1−PAGAtrasadoPAGAtrasado) / n ( 2 ) _=( wTX _+b ) / l n ( 2 )
Entonces, solo necesitamos resolver el coeficiente de cada característica en la regresión logística, y luego ponderar y sumar cada valor de característica de la muestra para obtener el puntaje de crédito estandarizado actual del cliente. Entre ellos, 650 y 50 en la fórmula de conversión de puntuación son ejemplos y deben ajustarse de acuerdo con el negocio real.
Código de cuadro de mando de compilación de regresión logística
modelo de importación
# 导入所需要的模块
import pandas as pd
from sklearn.metrics import roc_auc_score,roc_curve,auc
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.linear_model import LogisticRegression
import numpy as np
import random
import math
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
Consultar la información básica de los datos
df = pd.read_csv('Bcard.txt', encoding='utf-8')
print(df.info())
df.head()
'''
bad_ind 为标签
外部评分数据:td_score,jxl_score,mj_score,rh_score,zzc_score,zcx_score
内部数据: person_info, finance_info, credit_info, act_info
obs_month: 申请日期所在月份的最后一天(数据经过处理,将日期都处理成当月最后一天)
'''
# 看一下申请日期的分布,我们将最后一个月作为测试集,其他作为训练集
print(df.obs_mth.unique())
print(df.bad_ind.describe())
Divida el conjunto de entrenamiento y el conjunto de prueba
train_df =df[df['obs_mth']!='2018-11-30'].reset_index()
test_df = df[df['obs_mth'] == '2018-11-30'].reset_index()
Todas las características se utilizan para el entrenamiento de modelos.
# 没有进行特征筛选的逻辑回归模型
feature_lst = df.columns.drop(['obs_mth','bad_ind','uid'])
train_X = train_df[feature_lst]
train_y = train_df['bad_ind']
test_X = test_df[feature_lst]
test_y = test_df['bad_ind']
lr_model = LogisticRegression(C=0.1)
lr_model.fit(train_X,train_y)
# 对模型进行评估,这里使用predict_proba返回概率值,左边为预测为0的概率,右边为预测为1的概率,我们取1的概率
# 测试集
y_prob = lr_model.predict_proba(test_X)[:,1]
auc = roc_auc_score(test_y,y_prob)
fpr_lr,tpr_lr,_ = roc_curve(test_y,y_prob)
test_KS = max(tpr_lr-fpr_lr)
# 训练集
y_prob_train = lr_model.predict_proba(train_X)[:,1]
auc_train = roc_auc_score(train_y,y_prob_train)
fpr_lr_train,tpr_lr_train,_ = roc_curve(train_y,y_prob_train)
train_KS = max(tpr_lr_train-fpr_lr_train)
plt.plot(fpr_lr,tpr_lr,label = 'test LR auc=%0.3f'%auc) #绘制训练集ROC
plt.plot(fpr_lr_train,tpr_lr_train,label = 'train LR auc=%0.3f'%auc_train) #绘制验证集ROC
plt.plot([0,1],[0,1],'k--')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC Curve')
plt.legend(loc = 'best')
plt.show()
print('训练集的KS:%0.3f'%train_KS)
print('测试集的KS:%0.3f'%test_KS)
Filtrar características con lightgbm
# 对特征进行筛选,让模型更准确
import lightgbm as lgb
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(train_X, train_y, random_state = 0, test_size=0.2)
lgb_clf = lgb.LGBMClassifier(boosting_type='gbdt',
objective = 'binary',
metric = 'auc',
learning_rate=0.1,
n_estimators=24,
max_depth=5,
num_leaves=20,
max_bin=45,
min_data_in_leaf = 6,
bagging_fraction = 0.6,
bagging_freq = 0,
feature_fraction = 0.8)
lgb_clf.fit(X_train, y_train,eval_set=[(X_train, y_train),(X_test, y_test)], eval_metric='auc')
lgb_auc = lgb_clf.best_score_['valid_1']['auc']
feature_importance = pd.DataFrame({
'name':lgb_clf.booster_.feature_name(),
'importance':lgb_clf.feature_importances_}).sort_values(by='importance', ascending=False)
feature_importance
Cree un modelo usando las cuatro características filtradas
# 使用排名靠前的四个特征进行新的模型构建
feature_lst = feature_importance['name'][0:4]
train_X = train_df[feature_lst]
train_y = train_df['bad_ind']
test_X = test_df[feature_lst]
test_y = test_df['bad_ind']
lr_model = LogisticRegression(C=0.1)
lr_model.fit(train_X,train_y)
# 对模型进行评估,这里使用predict_proba返回概率值,左边为预测为0的概率,右边为预测为1的概率,我们取1的概率
# 测试集
y_prob = lr_model.predict_proba(test_X)[:,1]
auc = roc_auc_score(test_y,y_prob)
fpr_lr,tpr_lr,_ = roc_curve(test_y,y_prob)
test_KS = max(tpr_lr-fpr_lr)
# 训练集
y_prob_train = lr_model.predict_proba(train_X)[:,1]
auc_train = roc_auc_score(train_y,y_prob_train)
fpr_lr_train,tpr_lr_train,_ = roc_curve(train_y,y_prob_train)
train_KS = max(tpr_lr_train-fpr_lr_train)
plt.plot(fpr_lr,tpr_lr,label = 'test LR auc=%0.3f'%auc) #绘制训练集ROC
plt.plot(fpr_lr_train,tpr_lr_train,label = 'train LR auc=%0.3f'%auc_train) #绘制验证集ROC
plt.plot([0,1],[0,1],'k--')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC Curve')
plt.legend(loc = 'best')
plt.show()
print('训练集的KS:%0.3f'%train_KS)
print('测试集的KS:%0.3f'%test_KS)
El modelo filtrado tiene KS y AUC más altos para los datos del conjunto de prueba y los resultados son más estables.
imprimir coeficientes de regresión
# 打印回归系数
print('变量名单:',feature_lst)
print('系数:',lr_model.coef_)
print('截距:',lr_model.intercept_)
generar informe
# 生成报告
# 计算出报告中所需要的字段:KS值、负样本个数、正样本个数、负样本累计个数、正样本累计个数、捕获率、负样本占比
temp_ = pd.DataFrame()
temp_['predict_bad_prob'] = lr_model.predict_proba(test_X)[:,1]
temp_['real_bad'] = test_y
temp_.sort_values('predict_bad_prob', ascending=False, inplace=True)
temp_['num'] = [i for i in range(temp_.shape[0])]
temp_['num'] = pd.cut(temp_.num, bins=20,labels=[i for i in range(20)])
temp_
report = pd.DataFrame()
report['BAD'] = temp_.groupby('num').real_bad.sum().astype(int)
report['GOOD'] = temp_.groupby('num').real_bad.count().astype(int) - report['BAD']
report['BAD_CNT'] = report['BAD'].cumsum()
report['GOOD_CNT'] = report['GOOD'].cumsum()
good_total = report['GOOD_CNT'].max()
bad_total = report['BAD_CNT'].max()
report['BAD_PECT'] = round(report.BAD_CNT/bad_total,3)
report['BAD_RATE'] = report.apply(lambda x:round(x.BAD/(x.BAD+x.GOOD),3), axis=1)
# 计算KS值
def cal_ks(x):
ks = (x.BAD_CNT/bad_total)-(x.GOOD_CNT/good_total)
return round(math.fabs(ks),3)
report['KS'] = report.apply(cal_ks,axis=1)
report
Trace un gráfico de líneas de BAD_RATE y KS
# 绘制出折线图badrate和ks图
fig = plt.figure(figsize=(16,10))
ax = fig.add_subplot(111)
ax.plot(report.index.values.to_list(), report.BAD_RATE, '-o', label='BAD_RATE')
ax2 = ax.twinx()
ax2.plot(report.index.values.to_list(), report.KS, '--o', color='red',label='KS')
ax.grid()
ax.set_xlim(-1,20,5)
ax.set_ylim(0,0.1)
ax2.set_ylim(0,0.5)
ax.legend(loc=2)
ax2.legend(loc=0)
Cree una fórmula de puntuación para puntuar a cada cliente
'''
6 person_info
8 credit_info
9 act_info
7 finance_info
Name: name, dtype: object
系数: [[ 2.48386162 1.88254182 -1.43356854 4.44901224]]
截距: [-3.90631899]
'''
# 计算每个客户的评分
def score(person_info,credit_info,act_info,finance_info):
xbeta = person_info*2.48386162+credit_info*1.88254182+act_info*(-1.43356854)+finance_info*4.44901224-3.90631899
score = 900+50*(xbeta)/(math.log(2))
return score
test_df['score'] = test_df.apply(lambda x:score(x.person_info,x.credit_info,x.act_info,x.finance_info), axis=1)
fpr_lr,tpr_lr,_ = roc_curve(test_y,test_df['score'])
print('val_ks:', abs(fpr_lr-tpr_lr).max())
De acuerdo a las calificaciones se puede obtener la tasa de morosidad de cada grupo
# 根据评分进行划分等级
def level(score):
level = ''
if score <= 600:
level = "D"
elif score <= 640 and score > 600 :
level = "C"
elif score <= 680 and score > 640:
level = "B"
elif score > 680 :
level = "A"
return level
test_df['level'] = test_df.score.map(lambda x:level(x))
test_df.level.groupby(test_df.level).count()/len(test_df)
en conclusión
- Del informe se puede ver que:
- El valor máximo de KS del modelo aparece en la sexta casilla (No. 5), si la caja se divide en partes más finas, el valor de KS seguirá aumentando, y el límite superior es el valor de KS calculado por la fórmula anterior.
- Las muestras en las primeras 4 cajas representaron el 20% de la población total, y las muestras negativas capturadas representaron el 56,4% de todas las muestras negativas.
- En el gráfico de líneas se puede ver que:
- El modelo fluctúa en la posición de la casilla 8, es decir, la proporción de muestras negativas en la casilla 8 es mayor que la de la casilla 7
- Aunque hay muchas fluctuaciones en el gráfico, el rango no es grande y la tendencia general es relativamente estable. Por lo tanto, la empresa aún puede aceptar la capacidad de clasificación del modelo.
- A juzgar por las tasas de morosidad de los cuatro grupos, las tasas de morosidad de C y D son similares.