利用机器学习进行金融数据风险评估

需求

使用数据1,用python语言构建逻辑回归模型,分析预测目标人群发生风险交易的概率

(1)以 “python.txt”命名完整python执行代码,建模流程完整,主要步骤代码注释规范:有读入或导入样本、分析特征变量、查看数据维度、建立模型、测试模型相关步骤。

(2)能测试评估模型有效性。以“score_oos.xlsx”命名保存验证集OOS结果(素材有模板),结果文件字段内容完整,结论描述完整,计算正确,AUC评估值不小于0.5。
所需字段及相关说明:
uid(用户编号)
prob(风险交易概率,越大表示逾期风险越高)
target(实际风险交易标签)

(3)正确使用模型预测目标人群风险概率,以“score_sample_prob.xlsx”命名目标人群分析预测结果,输出文件字段内容完整,预测结果准确率高。
所需字段及相关说明:
uid(用户编号)
prob(风险交易概率,越大表示逾期风险越高)

数据1

https://gitee.com/pingfanrenbiji/resource/tree/master/%E9%87%91%E8%9E%8D%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/%E7%AC%AC%E4%B8%80%E9%A2%98/sucai1

需求分析

1、用python语言构建逻辑回归模型

2、代码关键步骤注释

有读入或导入样本、分析特征变量、查看数据维度、建立模型、测试模型相关步骤

3、结果文件字段完整(uid 用户编号、prob 风险交易概率 越大表示逾期风险越高 、target实际风险交易标签)

4、使用模型预测目标人群发生交易风险概率

Python代码

代码文件是ipynb格式 需要jupyter工具打开

Mac按照jupyter工具

  • 安装并启动
pip3 install jupyter
jupyter notebook
  • 访问页面
http://localhost:8888/
  • 设置密码
jupyter notebook password

Enter password: 
Verify password: 
[NotebookPasswordApp] Wrote hashed password to /Users/mengfanxiao/.jupyter/jupyter_notebook_config.json

上传代码到jupyter工具

源码文件

https://gitee.com/pingfanrenbiji/resource/blob/master/%E9%87%91%E8%9E%8D%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/%E7%AC%AC%E4%B8%80%E9%A2%98/task1.ipynb

代码逻辑分析

  • 导入python库 pandas和numpy
import pandas as pd
import numpy as np
  • 导入样本
model_vars = pd.read_csv('model_vars.csv')
transaction_risk_sample = pd.read_excel('transaction_risk_sample.xlsx')
transaction_risk_score_sample = pd.read_excel('transaction_risk_score_sample.xlsx')

执行之前 分别把这三个样本都上传上去

执行上面的python代码

若报错

则安装下这个包即可

pip3 install xlrd

分别查看下文件内容

样本特征表中字段:
uid time_sinc_login_sec timelong_lst_login log_from_lst_login city_lst_login result_lst_login type_lst_login scan_login_lst_login security_login_lst_login cnt_login ... cnt_sec1_login cnt_sec0_login rat_timelong_lst_avg rat_result1_login rat_type1_login rat_type2_login rat_type3_login rat_scan1_login rat_scan0_login rat_sec1_login
样本结果表中字段:
uid sample transaction_datetime target
预测集字段:
uid transaction_datetime
  • 查看数据的维度
model_vars.head(2)
  • 查看数据行列量
model_vars.shape

(24737, 32)

24737行,32列
  • 设置数据框展示列数
pd.set_option( 'display.max_columns' , 100)
  • 拼接样本特征和样本结果作为训练数据有 target(实际结果)
transaction_risk_sample = transaction_risk_sample.merge(model_vars, on = 'uid', how = 'left')

样本特征表model_vars 
样本结果表是transaction_risk_sample
两表以uid字段关联查询 并以左表(样本结果表transaction_risk_sample为基准)

查看拼接之后的样本结果表

字段信息:
uid sample transaction_datetime target time_sinc_login_sec timelong_lst_login log_from_lst_login city_lst_login result_lst_login type_lst_login scan_login_lst_login security_login_lst_login cnt_login sum_timelong avg_timelong cnt_log_from cnt_ip cnt_city cnt_result cnt_result1_login cnt_type1_login cnt_type2_login cnt_type3_login cnt_scan1_login cnt_scan0_login cnt_sec1_login cnt_sec0_login rat_timelong_lst_avg rat_result1_login rat_type1_login rat_type2_login rat_type3_login rat_scan1_login rat_scan0_login rat_sec1_login
  • 拼接样本预测表和样本特征表作为预测数据(没有target 就是要预测这个target)
transaction_risk_score_sample = transaction_risk_score_sample.merge(model_vars, on = 'uid', how = 'left')
uid transaction_datetime time_sinc_login_sec timelong_lst_login log_from_lst_login city_lst_login result_lst_login type_lst_login scan_login_lst_login security_login_lst_login cnt_login sum_timelong avg_timelong cnt_log_from cnt_ip cnt_city cnt_result cnt_result1_login cnt_type1_login cnt_type2_login cnt_type3_login cnt_scan1_login cnt_scan0_login cnt_sec1_login cnt_sec0_login rat_timelong_lst_avg rat_result1_login rat_type1_login rat_type2_login rat_type3_login rat_scan1_login rat_scan0_login rat_sec1_login
  • 为了保持训练样本和预测样本数据格式一致 做增删操作

此处预测样本中没有sample列 故将此从训练样本中删除

del transaction_risk_sample['sample']
  • 观察训练样本中0/1分布情况
transaction_risk_sample['target'].value_counts()

0有19133条数据
1有657行数据
  • 查看数据集格式
transaction_risk_sample.describe()

object为字符串类型
  • 分析特征变量

将变量名转换为列表 便于后续的循环遍历

var_all = transaction_risk_sample.columns.tolist()
  • 检查是否有空值
for col in var_all:
    x = transaction_risk_sample[col].isnull().sum()
    if x != 0:
        print(col, x)
        
循环遍历每一个列
统计当前列的空值数据

得到rat_timelong_lst_avg这个列有47个空值
  • 填充空值 用均值填充 训练和预测样本集都需要做处理
rat_timelong_lst_avg_mean = np.mean(transaction_risk_sample['rat_timelong_lst_avg'])#获取该列的均值
transaction_risk_sample['rat_timelong_lst_avg'].fillna(rat_timelong_lst_avg_mean, inplace = True) #对训练集补充空值
transaction_risk_score_sample['rat_timelong_lst_avg'].fillna(rat_timelong_lst_avg_mean, inplace = True) #对训练集补充空值
  • 异常值处理
观察到所有的变量都是数值型(原数据未给出具体变量信息,只能从数据类型上判断)
由于未给出具体变量信息,无法判断是否异常值,故此处不做异常值处理
  • 分组操作
transaction_risk_sample.groupby(['cnt_result''target']).size()

先以cnt_result字段分组 再根据target字段分组 最后统计每一组的大小
和数据库分组的概念是一样的
  • 导入画图的库
import matplotlib.pyplot as plt
import seaborn as sns

如果报错

ImportError: No module named 'seaborn'

安装此库

pip3 install seaborn
  • 画图探索每组违约率差异
df = pd.DataFrame() #创建一个新的表
df['total'] = transaction_risk_sample.groupby(['type_lst_login'])['target'].count() #计算每组的总数
df['bad'] = transaction_risk_sample.groupby(['type_lst_login'])['target'].sum() #计算每组违约总数
df['default_rate'] = df['bad']/df['total'#计算每组违约率
df = df.reset_index()
sns.barplot(data = df, x = 'type_lst_login', y = 'default_rate')

简单分析下这个逻辑

1、对样本结果表 transaction_risk_sample 先按照type_lst_login最后登陆时间分组 再按照target(是否违约 1违约0没有违约)进行分组

得到每一个登陆时间用户是否违约的情况

2、count()是包含target为0和1的情况 即每一个登陆时间内访问的用户数(总数)

3、sum() 仅包含target=1的情况 对所有的1进行求和 得到的是每一个登陆时间内 违约的用户数

4、每组违约的用户数 / 总数 得到每组的违约率

5、reset_index 设置索引 加快数据处理速度

6、barplot画图  x轴是登陆时间 y轴是每个登陆时间的违约率
  • 对于连续型变量做箱线图 观察数据分布
var_num = []
for col in transaction_risk_sample.columns:
    x =  transaction_risk_sample[].nunique() #观察每个变量里有多少个不同的值
    print(col, x)
    var_num.append(col)

代码分析

训练遍历每一个列
获取当前列的不同值个数
  • 箱线图
plt.boxplot(transaction_risk_sample['city_lst_login'])

获取city_lst_login最后的登陆城市这一列数据画箱线图

  • 删除无用的变量
var_num.remove('uid')
var_num.remove('transaction_datetime')
var_num.remove('target')

用户编号和是否违约对于判断是否违约没有意义 所以去掉
交易日期是离散型变量即字符串 不是连续型变量(数值)
  • 导入机器学习库
from sklearn.preprocessing import StandardScaler
  • 将连续型变量标准化
for col in var_num:
    print(col)
    SSL = StandardScaler().fit(transaction_risk_sample[col].values.reshape(-1,1))
    transaction_risk_sample[col] = SSL.transform(transaction_risk_sample[col].values.reshape(-1,1))
    transaction_risk_score_sample[col] = SSL.transform(transaction_risk_score_sample[col].values.reshape(-1,1))
    #transaction_risk_sample[col] = StandardScaler().fit_transform(all_data[col].values.reshape(-1,1))

代码分析

1、循环遍历var_num列
2、获取这个列中的数据量 
3、reshape(-1,1)的意思是转换成一列
将一个数组中的每一个数值元素都作为一个数组

4、特征变量标准化处理方式

a SSL=StandardScaler().fit
b SSL.transform

即 StandardScaler().fit_transform

特征变量标准化之后 开始进行选择

  • 特征选择

导入库

from sklearn.feature_selection import RFE
#导入逻辑回归模型
from sklearn.linear_model import LogisticRegression

降维之前的特征变量

len(var_num)
31

创建一个逻辑回归模型对象

model = LogisticRegression()

期望降维到15个变量

rfe = RFE(model, 15)

把表格中的一行数据转换成list数组中的一个元素

X = transaction_risk_sample[var_num].values.tolist()

获取target列数据 并转换为列数据

y = transaction_risk_sample['target'].values.tolist()

特征选择计算

rfe = rfe.fit(X, y)

print(rfe.support_)

打印出所有变量

如果变量计算结果为true的话 则是被选中的变量

var_model = []
for i in range(len(rfe.support_)):
    if rfe.support_[i]:
        var_model.append(var_num[i])
        
len(var_model)
15
  • 建立模型

导入库

# 导入训练、测试数据集分割库
from sklearn.model_selection import train_test_split
# 导入逻辑回归
from sklearn.linear_model import LogisticRegression as LR
# 导入f1、recall、roc等库
from sklearn.metrics import confusion_matrix, f1_score, precision_score, recall_score, roc_auc_score
  • 分割测试、训练集
train, test = train_test_split(transaction_risk_sample, test_size=0.4, random_state=22)

test_size=0.4 训练集是60% 测试集40%
random_state 随机种子是22 即每次分割训练、测试集都是一样的 因为随机种子一样
  • 分割完之后 打印出来
#剥离给出的训练集,分成因变量,自变量,必要
X_train = train[var_model]
y_train = train['target']

X_test = test[var_model]
y_test = test['target']
  • 创建逻辑回归
model = LogisticRegression()
  • 模型训练
lgr = model.fit(X_train, y_train)
  • 测试模型
y_pred = lgr.predict_proba(X_test)[:, 1]

第一列是0的概率 第二列是1的概率
  • 计算AUC
roc_auc_score(y_test ,y_pred)

y_test 真实数据
y_pred 预测数据
  • 导入库
from sklearn.metrics import roc_curve, auc
  • 计算预测模型的ks和auc
def ks_perf(actuals, predictions):
    fpr, tpr, threshold = roc_curve(actuals, predictions)
    auc_ = auc(fpr, tpr)
    ks_ = max(tpr-fpr)
    print(auc_, ks_)

代码分析

ks曲线 fpr 假正例率 , tpr 真正例率, threshold阈值
(0,0)是阈值最大的点
横坐标是阈值 纵坐标是fpr和tpr

tpr在fpr上面
tpr-fpr为ks值
ks越大 风险区分能力越强


auc曲线
横坐标是 fpr
纵坐标是 tpr
auc曲线和横坐标轴之间的面积 为auc面积
  • 调用计算ks/auc方法
ks_perf(y_test ,y_pred)
  • 将预测值放入测试集表中
test['prob'] = y_pred
  • 获取测试集test表中的三个字段形成一个新表
test_oos = test[['uid''prob''target']]
  • 到处excel表 不加序号
test_oos.to_excel('test_oos.xlsx', index = False)

对预测集进行预测

  • 获取预测集
x_inference = transaction_risk_score_sample[var_model]
  • 调用模型进行预测并获取违约的概率
y_inference = lgr.predict_proba(x_inference)[:, 1]
  • 将数据导出
pip3 install openpyxl
transaction_risk_score_sample['prob'] = y_inference
result = transaction_risk_score_sample[['uid''prob']]
result.to_excel('score_sample_prob.xlsx', index = False)
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值