需求
使用数据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)