贷款利润最大化——利用随机森林和逻辑回归

文章目录

  • 分析目的
  • 一、数据采集
    • 1、数据来源
    • 2、数据说明
  • 二、数据传输
  • 三、数据处理
    • 1、查看数据
    • 2、清理无用特征值
    • 3、标签列分析
    • 4、清理只单一值的列
    • 5、空值处理
    • 6、数据类型转换
  • 四、数据挖掘
    • 1、构建模型
    • 2、导入算法
  • 五、总结

分析目的

本文针对某信贷网站提供的2007-2011年贷款申请人的各项评估指标,建立关于信贷审批达到利润最大化模型,即对贷款人借贷状态(全额借贷、不予借贷)进行分类,从而实现贷款利润最大化,并采用不同算法进行评估。

一、数据采集

1、数据来源

数据来源,这个要注册登录,也可以直接点击下载数据链接下载。下载链接,提取码:nkvk

2、数据说明

本数据集共有四万多头数据,包含52个特征值,其中数据类型分别是 float64型30个, object型22个。本次数据分析主要是实现贷款利润最大化,所以不需这么多特征量,需要对其进行舍弃处理。

二、数据传输

将数据导入到PYTHON软件:

import pandas as pd
loans = pd.read_csv('LoanStats3a.csv', skiprows=1)
half_count = len(loans) / 2
loans = loans.dropna(thresh=half_count, axis=1)
loans = loans.drop(['desc', 'url'],axis=1)
loans.to_csv('loans_2007.csv', index=False)
loans = pd.read_csv("loans_2007.csv")
loans.info()

三、数据处理

1、查看数据

#loans.iloc[0]
loans.head(1)

在这里插入图片描述

2、清理无用特征值

了解各数据特征在业务中的含义。观察数据特征,主要清理与业务相关性不大的内容,重复特征值(等级下的另一个等级)以及预测后的特征值(批出的额度),此处的相关性大小凭业务知识进行粗略判断,如申请人的id,member_id,url,公司名emp_title等。

loans = loans.drop(["id", "member_id", "funded_amnt", "funded_amnt_inv", "grade", "sub_grade", "emp_title", "issue_d"], axis=1)
loans = loans.drop(["zip_code", "out_prncp", "out_prncp_inv", "total_pymnt", "total_pymnt_inv", "total_rec_prncp"], axis=1)
loans = loans.drop(["total_rec_int", "total_rec_late_fee", "recoveries", "collection_recovery_fee", "last_pymnt_d", "last_pymnt_amnt"], axis=1)
loans.head(1)

在这里插入图片描述
删除无关字段后,剩余32个字段

3、标签列分析

#统计不同还款状态对应的样本数量——标签类分析
loans['loan_status'].value_counts()

在这里插入图片描述
统计结果显示,共有9种借贷状态,其中我们仅分析"Fully Paid"(全额借款)和"Charged Off"(不借款)这两种状态。“Fully paid”和“Charged Off”(其他取值样本较少,是否贷款含义不明,直接舍弃),表示同意贷款和不同意贷款,将此特征作为及其学习的标签列,由于sklearn中各及其学习模型值接受数值类型的数据类型,所以我们将“loan_status”映射为数值类型。
将“loan_status”映射为数值类型:

loans = loans[(loans['loan_status'] == "Fully Paid") | (loans['loan_status'] == "Charged Off")]
status_replace = {"loan_status" : {"Fully Paid": 1,"Charged Off": 0,}
}
loans= loans.replace(status_replace)
loans.loan_status

4、清理只单一值的列

在进行数据分析时,部分字段对应的值只有一个,应删除这些无关字段

#查找只包含一个惟一值的列并删除
orig_columns = loans.columns
drop_columns = []
for col in orig_columns:col_series = loans[col].dropna().unique()#如果字段值都一样,删除该字段if len(col_series) == 1:drop_columns.append(col)
loans= loans.drop(drop_columns, axis=1)
print(drop_columns)
#将清洗后数据存入一个新的文件中
loans.to_csv('filtered_loans_2007.csv', index=False)

在这里插入图片描述

5、空值处理

本文的处理原则是:对于某一特征,如果出现空值的样本较少,则删除在此特征商为空值的样本;如果去空值的样本数量较多,则选择删除该特征。有上述原则知,我们需要对各特征出现空值的数量进行统计。

loans = pd.read_csv('filtered_loans_2007.csv')
null_counts = loans.isnull().sum()
null_counts

在这里插入图片描述
发现有四个特征有取空值的情况,其中三个空值数量较少,我们删除对应的样本,另外一个特征“pub_rec_bankruptcies”,空值数量较多,我们删除该特征。

loans = loans.drop("pub_rec_bankruptcies", axis=1)
loans = loans.dropna(axis=0)

6、数据类型转换

#统计不同数据类型下的字段总和
print(loans.dtypes.value_counts())

输出结果如下图,12个列所对应的数据类型为字符型,应转化为数值型。
在这里插入图片描述

#输出数据类型为字符型的字段
object_columns_df = loans.select_dtypes(include=["object"])
print(object_columns_df.iloc[0])
#对字符型数据进行分组计数
cols = ['home_ownership', 'verification_status', 'emp_length', 'term', 'addr_state']
for c in cols:print(loans[c].value_counts())
print(loans["purpose"].value_counts())
print(loans["title"].value_counts())

在这里插入图片描述
“emp_length”可以直接映射为数值型 ,对于“int_rate”,“revol_util”可以去掉百分号,然后转换为数值型,对于含义重复的特征,如“purpose”和“title”,都表示贷款意图,可选择删除一个,其他与模型训练无关的特征选择删除。剩余的其他字符型特征,此处选择使用pandas的get_dummies()函数,直接映射为数值型。

#将"emp_length"字段转化为字符型数据
mapping_dict = {"emp_length": {"10+ years": 10,"9 years": 9,"8 years": 8,"7 years": 7,"6 years": 6,"5 years": 5,"4 years": 4,"3 years": 3,"2 years": 2,"1 year": 1,"< 1 year": 0,"n/a": 0}
}
loans = loans.drop(["last_credit_pull_d", "earliest_cr_line", "addr_state", "title"], axis=1)
#将百分比类型转化为浮点型(小数类型)
loans["int_rate"] = loans["int_rate"].str.rstrip("%").astype("float")
loans["revol_util"] = loans["revol_util"].str.rstrip("%").astype("float")
loans = loans.replace(mapping_dict)
cat_columns = ["home_ownership", "verification_status", "emp_length", "purpose", "term"]
dummy_df = pd.get_dummies(loans[cat_columns])
loans = pd.concat([loans, dummy_df], axis=1)
loans = loans.drop(cat_columns, axis=1)
loans = loans.drop("pymnt_plan", axis=1)
loans.to_csv('cleaned_loans2007.csv', index=False)
import pandas as pd
#读取最终清洗的数据
loans = pd.read_csv("cleaned_loans2007.csv")
print(loans.info())

在这里插入图片描述

四、数据挖掘

1、构建模型

对于二分类问题,一般情况下,首选逻辑回归,这里我们引用sklearn库。首先定义模型效果的评判标准。根据贷款行业的实际情况,为了实现利润最大化,我们不仅要求模型预测正确率较高,同时还要尽可能的让错误率较低,这里采用两个指标tpr和fpr。同时该模型采用交叉验证(KFold,分组数采用默认的最好的分组方式)进行学习。为了比较不同模型的训练效果,建立三个模型。

2、导入算法

初始化处理

#负例预测为正例
fp_filter = (predictions == 1) & (loans["loan_status"] == 0)
fp = len(predictions[fp_filter])
# 正例预测为正例
tp_filter = (predictions == 1) & (loans["loan_status"] == 1)
tp = len(predictions[tp_filter])
# 负例预测为正例
fn_filter = (predictions == 0) & (loans["loan_status"] == 1)
fn = len(predictions[fn_filter])
# 负例预测为负例
tn_filter = (predictions == 0) & (loans["loan_status"] == 0)
tn = len(predictions[tn_filter])

逻辑回归:

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
cols = loans.columns
train_cols = cols.drop("loan_status")
features = loans[train_cols]
target = loans["loan_status"]
lr.fit(features, target)
predictions = lr.predict(features)
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
lr = LogisticRegression()
kf = KFold(features.shape[0], random_state=1)
predictions = cross_val_predict(lr, features, target, cv=kf)
predictions = pd.Series(predictions)
# False positives.
fp_filter = (predictions == 1) & (loans["loan_status"] == 0)
fp = len(predictions[fp_filter])
# True positives.
tp_filter = (predictions == 1) & (loans["loan_status"] == 1)
tp = len(predictions[tp_filter])
# False negatives.
fn_filter = (predictions == 0) & (loans["loan_status"] == 1)
fn = len(predictions[fn_filter])
# True negatives
tn_filter = (predictions == 0) & (loans["loan_status"] == 0)
tn = len(predictions[tn_filter])
# Rates
tpr = tp / float((tp + fn))
fpr = fp / float((fp + tn))
print(tpr)
print(fpr)
print predictions[:20]

在这里插入图片描述
错误率和正确率都达到99.9%,错误率太高,通过观察预测结果发现,模型几乎将所有的样本都判断为正例,通过对原始数据的了解,分析造成该现象的原因是由于政府样本数量相差太大,即样本不均衡造成模型对正例样本有所偏重,大家可以通过下采样或上采用对数据进行处理,这里采用对样本添加权重值的方式进行调整。
逻辑回归balanced处理不均衡:

from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import cross_val_predict
lr = LogisticRegression(class_weight="balanced")
kf = KFold(features.shape[0], random_state=1)
predictions = cross_val_predict(lr, features, target, cv=kf)
predictions = pd.Series(predictions)
# False positives.
fp_filter = (predictions == 1) & (loans["loan_status"] == 0)
fp = len(predictions[fp_filter])
# True positives.
tp_filter = (predictions == 1) & (loans["loan_status"] == 1)
tp = len(predictions[tp_filter])
# False negatives.
fn_filter = (predictions == 0) & (loans["loan_status"] == 1)
fn = len(predictions[fn_filter])
# True negatives
tn_filter = (predictions == 0) & (loans["loan_status"] == 0)
tn = len(predictions[tn_filter])
# Rates
tpr = tp / float((tp + fn))
fpr = fp / float((fp + tn))
print(tpr)
print(fpr)
print predictions[:20]

在这里插入图片描述
新的结果降低了错误率约为40%,但正确率也下降约为65%,因此有必要再次尝试,可以采取自定义权重值的方式。
逻辑回归penalty处理不均衡:

from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import cross_val_predict
penalty = {0: 5,1: 1}
lr = LogisticRegression(class_weight=penalty)
kf = KFold(features.shape[0], random_state=1)
predictions = cross_val_predict(lr, features, target, cv=kf)
predictions = pd.Series(predictions)
# False positives.
fp_filter = (predictions == 1) & (loans["loan_status"] == 0)
fp = len(predictions[fp_filter])
# True positives.
tp_filter = (predictions == 1) & (loans["loan_status"] == 1)
tp = len(predictions[tp_filter])
# False negatives.
fn_filter = (predictions == 0) & (loans["loan_status"] == 1)
fn = len(predictions[fn_filter])
# True negatives
tn_filter = (predictions == 0) & (loans["loan_status"] == 0)
tn = len(predictions[tn_filter])
# Rates
tpr = tp / float((tp + fn))
fpr = fp / float((fp + tn))
print(tpr)
print(fpr)

在这里插入图片描述
新的结果错误率约为47%,正确率约为73%,可根据需要继续调整,但调整策略并不限于样本权重值这一种,下面使用随机森林建立模型。
随机森林balanced处理不均衡:

from sklearn.ensemble import RandomForestClassifier
from sklearn.cross_validation import cross_val_predict
rf = RandomForestClassifier(n_estimators=10,class_weight="balanced", random_state=1)
#print help(RandomForestClassifier)
kf = KFold(features.shape[0], random_state=1)
predictions = cross_val_predict(rf, features, target, cv=kf)
predictions = pd.Series(predictions)
# False positives.
fp_filter = (predictions == 1) & (loans["loan_status"] == 0)
fp = len(predictions[fp_filter])
# True positives.
tp_filter = (predictions == 1) & (loans["loan_status"] == 1)
tp = len(predictions[tp_filter])
# False negatives.
fn_filter = (predictions == 0) & (loans["loan_status"] == 1)
fn = len(predictions[fn_filter])
# True negatives
tn_filter = (predictions == 0) & (loans["loan_status"] == 0)
tn = len(predictions[tn_filter])
# Rates
tpr = tp / float((tp + fn))
fpr = fp / float((fp + tn))
print(tpr)
print(fpr)

在这里插入图片描述
在这里错误率约为97%,正确率约为94%,错误率太高,同时可得到本次分析随机森林模型效果劣于逻辑回归模型的效果

五、总结

当模型效果不理想时,可以考虑的调整策略:
1.调节正负样本的权重参数。
2.更换模型算法。
3.同时几个使用模型进行预测,然后取去测的最终结果。
4.使用原数据,生成新特征。
5.调整模型参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/474918.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ios学习之UITabBar(标签栏)

自定义TabBar的高度&#xff1a;&#xff08;无论横屏还是竖屏都以竖屏为准&#xff0c;之前就改为横屏的设置出错&#xff0c;找了好久才找到这个问题&#xff09; tabBar [[UITabBarController alloc] init];// 改变tabBarController高度 tabBar.tabBar.frameCGRectMake(0,…

LeetCode MySQL 512. 游戏玩法分析 II

文章目录1. 题目2. 解题1. 题目 Table: Activity ----------------------- | Column Name | Type | ----------------------- | player_id | int | | device_id | int | | event_date | date | | games_played | int | ----------------------- (…

Gtk-WARNING **: 无法在模块路径中找到主题引擎:“pixmap”(转)

Gtk-WARNING**:无法在模块路径中找到主题引擎:“pixmap”的解决如果终端中提示&#xff1a;(gvim:2353): Gtk-WARNING **: 无法在模块路径中找到主题引擎&#xff1a;“pixmap”解决方法是运行&#xff1a; sudo apt-get install gtk2-engines-pixbuf 转载于:https://www.cnbl…

机器学习算法优缺点对比及选择

文章目录偏差&方差常见算法优缺点朴素贝叶斯Logistic Regression&#xff08;逻辑回归&#xff09;线性回归最近邻算法——KNN决策树ID3、C4.5算法CART分类与回归树AdaboostingSVM支持向量机人工神经网络K-Means聚类EM最大期望算法集成算法&#xff08;AdaBoost算法&#x…

LeetCode MySQL 1076. 项目员工II

文章目录1. 题目2. 解题1. 题目 Table: Project ---------------------- | Column Name | Type | ---------------------- | project_id | int | | employee_id | int | ---------------------- 主键为 (project_id, employee_id)。 employee_id 是员工表 Employ…

CouchDB与Couchbase:区别何在,Membase又将如何?

CouchDB与Couchbase&#xff1a;区别何在&#xff0c;Membase又将如何&#xff1f; 2012-05-23 02:05 682人阅读 评论(1) 收藏 举报 本文来源于我在InfoQ中文站翻译的文章&#xff0c;原文地址是&#xff1a;http://www.infoq.com/cn/news/2012/05/couchdb-vs-couchbase-memba…

Sklearn.metrics评估方法

文章目录混淆矩阵分类准确率 accuracy精确率Precision召回率 recallF1值Roc曲线、AUC混淆矩阵 混淆矩阵又称误差矩阵&#xff0c;针对预测值和真实值之间的关系&#xff0c;我们可以将样本分为四个部分&#xff0c;分别是&#xff1a; 真正例&#xff08;True Positive&#x…

HDU 1492 The number of divisors(约数) about Humble Numbers

The number of divisors(约数) about Humble Numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1741 Accepted Submission(s): 852 Problem DescriptionA number whose only prime factors are 2,3,5 or …

LeetCode MySQL 1083. 销售分析 II

文章目录1. 题目2. 解题1. 题目 Table: Product ----------------------- | Column Name | Type | ----------------------- | product_id | int | | product_name | varchar | | unit_price | int | ----------------------- product_id 是这张表的主键Tabl…

常见的几种流失预警模型

建立预警模型的目的是提前识别潜在流失用户&#xff0c;为挽留用户赢得时间。 流失预警模型&#xff0c;不应该只是单一的模型&#xff0c;而应该是一系列模型。预警模型的优劣通常用准确率、召回率来衡量。准确率&#xff1a;预测为流失的用户中&#xff0c;有多少真的流失。召…

WP7 网络请求之WebClient

WebClient运行于UI线程&#xff0c;支持编码方式的设定、支持POST/GET方式提交、不支持同步请求、不支持超时设定。WP7会缓存URL链 接&#xff0c;所以两次请求&#xff0c;尽管网络端数据发生了变化&#xff0c;得到的还会是同样的数据&#xff0c;这点要特别注意&#xff0c;…

Jupyter Notebook安装 nbextensions 插件

安装 nbextensions 插件 一、打开Anaconda Prompt窗口&#xff0c;执行第一个命令&#xff0c;用于安装nbextensions&#xff1a; pip install jupyter_contrib_nbextensions 二、再执行第二个命令&#xff0c;用于安装 javascript and css files jupyter contrib nbextens…

LeetCode MySQL 1084. 销售分析III

文章目录1. 题目2. 解题1. 题目 Table: Product ----------------------- | Column Name | Type | ----------------------- | product_id | int | | product_name | varchar | | unit_price | int | ----------------------- product_id 是这个表的主键Tabl…

15.使用using和try/finally来做资源清理

只有是实现了IDispose接口的类型的调用都应使用using 或者try/finally释放对象。转载于:https://www.cnblogs.com/movemoon/archive/2012/10/24/2736571.html

数据分析常用Python库:数值计算、可视化、机器学习等领域

镜像pip安装 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣(douban) http://pypi.douban.com/simple/ 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/ 中国科学技术大学 http://pypi.mirrors.ustc.edu.cn…

LeetCode MySQL 1322. 广告效果

文章目录1. 题目2. 解题1. 题目 表: Ads ------------------------ | Column Name | Type | ------------------------ | ad_id | int | | user_id | int | | action | enum | ------------------------ (ad_id, user_id) 是该表的主键…

linux下练习 c++ 容器set、multimset的特性

print.h //print.h#include <iostream>using namespace std;#ifndef print_fun#define print_funtemplate<typename T>///显示序列数据void print(T b,T e,char c ){bool isExitfalse;while (b!e){cout<<*b<<c;isExittrue;}if(isExit) cout<<end…

Python数据预处理数据的方法总结(使用sklearn-preprocessing)

文章目录数据预处理思路数据预处理方法1 标准化&#xff1a;去均值&#xff0c;方差规模化2 规模化稀疏数据3 规模化有异常值的数据4 正则化Normalization5 二值化–特征的二值化6 类别特征编码7 弥补缺失数据7 创建多项式特征数据预处理思路 1.首先要明确有多少特征&#xff…

LeetCode MySQL 1179. 重新格式化部门表

文章目录1. 题目2. 解题1. 题目 部门表 Department&#xff1a; ------------------------ | Column Name | Type | ------------------------ | id | int | | revenue | int | | month | varchar | ------------------------ (id, mo…

消息推送生命周期_一套完整的APP推送体系方案|附思维导图

写这篇文章的初衷是前几天在脉脉上看到一个问题&#xff1a;线上app push故障&#xff0c;该不该给用户发送补救推送信息&#xff1f;联想到自己当初作为实习菜鸟也犯过类似的推送事故&#xff0c;好在补救处理尚可&#xff0c;最终结果不错。这次仔细看了问题下的每一条回答&a…