Construcción de modelos: use la regresión logística para construir modelos, lightGBM para la detección de características

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:
inserte la descripción de la imagen aquí

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+miz1=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 ( _1ytu)=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 ( _1PAGAtrasadoPAGAtrasado) / 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()

inserte la descripción de la imagen aquí

'''
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())

inserte la descripción de la imagen aquí
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)

inserte la descripción de la imagen aquí
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

inserte la descripción de la imagen aquí
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)

inserte la descripción de la imagen aquí
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_)

inserte la descripción de la imagen aquí
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

inserte la descripción de la imagen aquí

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)

inserte la descripción de la imagen aquí
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())

inserte la descripción de la imagen aquí

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)

inserte la descripción de la imagen aquí

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.

Supongo que te gusta

Origin blog.csdn.net/gjinc/article/details/131852206
Recomendado
Clasificación