使用逻辑回归构建信用评分卡全流程python脚本包含:导入包、 导入数据、 EDA、 数据分箱 、特征筛选 、woe转化 、逻辑回归建模 、评分卡转换 、输出每个特征分箱对应的评分、同时包含oot也计算计算psi并详细解释每一个步骤
- 导入包
首先,需要导入需要的包,如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
- 导入数据
接下来,需要导入需要使用的数据集。可以使用 pandas 中的 read_csv 方法读取 csv 文件。
data = pd.read_csv('credit.csv')
- EDA
进行数据探索性分析(EDA),可以使用 pandas 中的 head、info、describe 等方法查看数据的基本信息,并通过 matplotlib 和 seaborn 等库进行可视化分析。
data.head()
data.info()
data.describe()
sns.countplot(x='credit', data=data)
- 数据分箱
数据分箱是信用评分卡模型中的重要步骤,可以使用 pandas 中的 cut 和 qcut 方法对数据进行分箱。
data['age_bin'] = pd.cut(data['age'], bins=[0, 20, 30, 40, 50, 60, 70, 80, 90, 100])
data['income_bin'] = pd.qcut(data['income'], q=4)
- 特征筛选
特征筛选是信用评分卡模型中的重要步骤,可以使用相关性、IV 值等方法进行筛选。可以使用 pandas 和 scipy 库中的相关性分析方法、IV 值计算方法。
corr = data.corr()
sns.heatmap(corr, annot=True)
from scipy.stats import chi2_contingency
def calc_iv(df, feature, target):
lst = []
for i in range(df[feature].nunique()):
val = list(df[feature].unique())[i]
lst.append([feature, val, df[df[feature] == val].count()[feature], df[(df[feature] == val) & (df[target] == 0)].count()[feature], df[(df[feature] == val) & (df[target] == 1)].count()[feature]])
data = pd.DataFrame(lst, columns=['Variable', 'Value', 'All', 'Good', 'Bad'])
data['Share'] = data['All'] / data['All'].sum()
data['Bad Rate'] = data['Bad'] / data['All']
data['Distribution Good'] = (data['All'] - data['Bad']) / (data['All'].sum() - data['Bad'].sum())
data['Distribution Bad'] = data['Bad'] / data['Bad'].sum()
data['WoE'] = np.log(data['Distribution Good'] / data['Distribution Bad'])
data['IV'] = (data['WoE'] * (data['Distribution Good'] - data['Distribution Bad'])).sum()
data = data.sort_values(by=['Variable', 'Value'], ascending=True)
return data['IV'].values[0]
for col in data.columns.tolist():
if col not in ['credit', 'age_bin', 'income_bin']:
iv = calc_iv(data, col, 'credit')
if iv < 0.1:
data.drop(col, axis=1, inplace=True)
- WOE 转化
WOE 转化是信用评分卡模型中的重要步骤,可以使用 pandas 中的 groupby 和 transform 方法进行转化。
def woe_transformation(df, col, target):
total = df.groupby([col])[target].count()
bad = df.groupby([col])[target].sum()
good = total - bad
woe = np.log((good / good.sum()) / (bad / bad.sum()))
return woe
for col in data.columns.tolist():
if col not in ['credit', 'age_bin', 'income_bin']:
woe = woe_transformation(data, col, 'credit')
data[col] = data[col].map(woe)
- 逻辑回归建模
逻辑回归建模是信用评分卡模型中的重要步骤,可以使用 sklearn 中的 LogisticRegression 方法进行建模。
X = data.drop(['credit'], axis=1)
y = data['credit']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
model = LogisticRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
- 评分卡转换
评分卡转换是信用评分卡模型中的重要步骤,可以使用自定义函数进行转换。
def score_conversion(df, odds, pdo):
factor = pdo / np.log(2)
offset = odds / factor
df['score'] = df['woe'] * (-factor) + offset
df['score'] = df['score'].astype(int)
return df
- 输出每个特征分箱对应的评分
输出每个特征分箱对应的评分,可以使用 pandas 中的 apply 和 groupby 方法进行计算。
bins = {}
for col in data.columns.tolist():
if col not in ['credit', 'age_bin', 'income_bin']:
bins[col] = pd.DataFrame(data.groupby(col, as_index=True).apply(lambda x: x.name))
bins[col].reset_index(inplace=True)
bins[col].columns = [col, 'bin']
bins[col] = pd.merge(bins[col], data[[col, 'woe']].drop_duplicates(), on=col, how='left')
bins[col] = score_conversion(bins[col], odds=1.5, pdo=50)
- 同时包含 oot 也计算,计算 psi
同时包含 oot 也计算,计算 psi,可以使用自定义函数进行计算。
def calc_psi(expected, actual, bins=10):
breakpoints = np.arange(1, bins + 1) / bins
expected_percents = np.histogram(expected, breakpoints)[0] / len(expected)
actual_percents = np.histogram(actual, breakpoints)[0] / len(actual)
psi_value = np.sum((expected_percents - actual_percents) * np.log(expected_percents / actual_percents))
return psi_value
oot = pd.read_csv('oot.csv')
oot['age_bin'] = pd.cut(oot['age'], bins=[0, 20, 30, 40, 50, 60, 70, 80, 90, 100])
oot['income_bin'] = pd.qcut(oot['income'], q=4)
for col in data.columns.tolist():
if col not in ['credit', 'age_bin', 'income_bin']:
bins_oot = pd.DataFrame(oot.groupby(col, as_index=True).apply(lambda x: x.name))
bins_oot.reset_index(inplace=True)
bins_oot.columns = [col, 'bin']
bins_oot = pd.merge(bins_oot, data[[col, 'woe']].drop_duplicates(), on=col, how='left')
bins_oot = score_conversion(bins_oot, odds=1.5, pdo=50)
psi = calc_psi(data[col], oot[col])
print(col, psi)
``
原文地址: https://www.cveoy.top/t/topic/ddLB 著作权归作者所有。请勿转载和采集!