基于机器学习的办理银行贷款预测

该项目是补课班老师留的作业,比较简单,用来练手,熟悉流程

适合机器学习初学者来实践


#如何判断某些属性和特征与结果是否关联                
#首先通过相关人员进行简单筛选,也可以通过画图和求相关系数来发现
#例如,通过画age与最终贷款的柱状图,如果各个年龄下,差别不大,证明年龄关系不大,可以去掉。
#某个特征如果单独来看,和最终结果关系不大,它与其他的特征组合也不会有影响,因此可以不用考虑这种情况
#关于one-hot编码,当离散特征的大小没有做特殊要求时,即做范式平方差的时候不会有差异。
#本例中,暂不认为教育之间有差距,所以采用one-hot编码映射各个教育程度。
#利用one-hot处理后维度会变多,即本来为一个housing特征变成housing-yes,housing-no,housing-unknown三个特征。
#注,logistic回归不是利用距离计算,所以其实可以采用1,2,3数值去表示,只是习惯上在不确定的条件下采用one-hot编码去做。
#数值之间的比例无法确定。只能通过业务确定,或者自己摸索着去调。(其他维度相同,只有待测特征不同,看差距)
#关于连续数据离散化:一般情况下,原数据什么样就是什么样,不用转化成离散型。
#例如年龄特征一般就是连续型,不用再多加处理变成离散型;除非是有些算法不支持连续型(如决策树)。
#导入包
import pandas as pd
import numpy as np
from sklearn import preprocessing      #数据预处理
import matplotlib.pyplot as plt        #做图工具
from sklearn.linear_model import LogisticRegression  #logisticregression 算法
from sklearn.cross_validation import train_test_split  #交叉验证,随机选取训练集和测试集
# 读入数据,做数据分析,CSV格式用的最多,非常适合存储数据。
#pandas.read_csv,读取CSV(逗号分割)文件到DataFrame
#常用的函数只有两个,sep(表示指定分割符)和header(表示数据表头,默认是0)。
#sep : str, default ‘,’;指定分隔符,如果不指定参数,则会尝试使用逗号分隔。
#header:指定行数用来作为列名,数据开始行数。如果文件中有列名,则默认为0,否则设置为None,表示不要把第一行作为header。
data = pd.read_csv('banking.csv', header=0)
# 去掉缺失数据,.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)[source]
#主要看axis和how。#一般情况下,先进性填充,再采用dropna,否则删除样本过多   
#0表示删除行,1表示删除列(一般不会,因为会删除掉一个属性);
#how默认any,any-有一个缺失,则丢掉,all-全部缺失才丢掉。
data = data.dropna()
print(data.shape)
print(list(data.columns))   #输出各个列的名字
# 预览数据,前五行;与之对应的是tail(x)函数,预览后x行
data.head()
# 探索数据情况,利用unique看离散数据有哪些可选值。
data['education'].unique()
# 把所有的 "basic.*" 归结为 "Basic", 离散型的取值越少越好,差距小的可以合并。
#result = np.where(cond,xarr,yarr)  当符合条件时是x,不符合是y,常用于根据一个数组产生另一个新的数组。         
data['education'] = np.where(data['education'] == 'basic.9y', 'Basic', data['education'])
data['education'] = np.where(data['education'] == 'basic.6y', 'Basic', data['education'])
data['education'] = np.where(data['education'] == 'basic.4y', 'Basic', data['education'])
data['education'].unique()
# 看目标变量的比例
data['y'].value_counts()
# 利用groupby可以查看数据的分布情况,先按照参数可能的取值进行分类,再进行操作。
# 这个的mean表示的是取均值操作
data.groupby('y').mean()
data.groupby('job').mean()
data.groupby('marital').mean()
data.groupby('education').mean()
# 对分类数据进行One-Hot编码,连续型不变,离散型改动
#给编码取名,一般为原名字_新名字
#把没改变的连续型的加进去
#疑问:
#1.两个cat_list代码什么意思?执行后的效果是什么?
#2,cat_list最后的结果是1000这种编码还是'job_admin‘这种文字?
#3.join()函数在这里是如何运作的?
#4,我怎么看这个循环里每一步都发生啥了?
#5,data.columns与data.columns.values输出的一样,有什么区别?  好像对最终结果没影响。   下面data_final与data_final.columns.values处同理。
#get_dummies函数,将分类变量(categorical variable)转换为“哑变量矩阵”(dummy matrix)或“指标矩阵”(indicator matrix)
#即如果DataFrame的某一列中含有k个不同的值,则可以派生出一个k列矩阵或DataFrame(其值全为1和0)
#prefix 给所有的列索引上加个前缀。
#.join()函数  语法:'sep'.join(seq):参数说明--sep:分隔符。可以为空;seq:要连接的元素序列、字符串、元组、字典
#上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串
#返回值:返回一个以分隔符sep连接各个元素后生成的字符串
#tolist() 将数组或者矩阵转换成列表
cat_vars=['job','marital','education','default','housing','loan','contact','month','day_of_week','poutcome']
for var in cat_vars:
    cat_list='var'+'_'+var
    cat_list = pd.get_dummies(data[var], prefix=var)    
    data1=data.join(cat_list)
    data=data1
cat_vars=['job','marital','education','default','housing','loan','contact','month','day_of_week','poutcome']
data_vars=data.columns.values.tolist()
to_keep=[i for i in data_vars if i not in cat_vars]
data_final=data[to_keep]
data_final.columns.values
#疑问:
#1,这段代码是干啥的?这里的x和y是啥?      
#答:这段代码是用来删除掉属性中的y这一列。
data_final_vars=data_final.columns.values.tolist()
y=['y']
X=[i for i in data_final_vars if i not in y]
# 利用Recursive Feature Elimination (RFE)选择最佳特征,即给特征进行排序
#RFE()两个重要参数,estimator是选择的一个模型,这里是logisticregression, 18表示选取的特征数,默认不填时是总数一半
#这里留下的特征值的数目没有明确的规定,一般由相关人员去确定,这里one-hot扩充之后留下了18个
#这里记住rfe的用法即可,在上述网址的说明中有例子
from sklearn import datasets          #sklearn中的数据集
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression()
rfe = RFE(logreg, 18)    
rfe = rfe.fit(data_final[X], data_final[y] ) #rfe.fit()参数--fit)(X,y);X为训练数据,y为目标结果  
print(rfe.support_)     #support 中有false和ture分别表示这个特征不留与留
print(rfe.ranking_)     #ranking 表示重要性,1最大
# 整理上一步选出来的特征数据
cols=["previous", "euribor3m", "job_blue-collar", "job_retired", "job_services", "job_student", "default_no",
      "month_aug", "month_dec", "month_jul", "month_nov", "month_oct", "month_sep", "day_of_week_fri", "day_of_week_wed",
      "poutcome_failure", "poutcome_nonexistent", "poutcome_success"]
X=data_final[cols]
y=data_final['y']
# 构建模型,功能是从样本中随机的按比例选取train data和testdata
#X_train,X_test, y_train, y_test =train_test_split(train_data,train_target,test_size=0.4, random_state=0)
#train_data:所要划分的样本特征集 train_target:所要划分的样本结果
#test_size:样本占比,如果是整数的话就是样本的数量 random_state:是随机数的种子。
#随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。
#比如你每次都填1,其他参数一样的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。
#调用sklearn逻辑回归算法十分简单:1.导入;2.fit()训练;3.predic()预测
#其中参数设置才是关键,sklearn.linear_model中LogisticRegression类的参数。默认参数如下:
#LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,intercept_scaling=1, max_iter=100,
#multi_class='ovr', n_jobs=1,penalty='l2', random_state=None, solver='liblinear', tol=0.0001,verbose=0, warm_start=False)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
# 查看模型性能
#LogisticRegression().score()返回测试数据上的平均正确率。
#format是python新增的一个格式化字符串的方法。 .xf转化为小数点后x位,默认是2位
y_pred = logreg.predict(X_test)
print('Accuracy of logistic regression classifier on test set: {:.2f}'.format(logreg.score(X_test, y_test)))
# cross validation 交叉验证
# https://zhuanlan.zhihu.com/p/24825503   交叉验证的讲解
#交叉验证尽量保证所使用的数据不带有偏向性。   KFold只是交叉验证中的一种
#本例中acc相差不大,若相差较大,以交叉认证为主,交叉认证取得是均值。
#n_splits默认为3,最小为2,是K折验证的的K值,即将数据分成K份
#random_state表示的是随机种子
#sklearn.model_selection.cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None, n_jobs=1,
#                                        verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’)
#返回值 就是对于每次不同的的划分raw data时,在test data上得到的分类的准确率。
#estimator:是不同的分类器,可以是任何的分类器。比如支持向量机分类器:estimator = svm.SVC(kernel='linear', C=1)
#cv:代表不同的cross validation的方法
#scoring:默认Nnoe,准确率的算法,可以通过score_func参数指定;如果不指定的话,是用estimator默认自带的准确率算法。
from sklearn import model_selection
from sklearn.model_selection import cross_val_score
kfold = model_selection.KFold(n_splits=10, random_state=7)
modelCV = LogisticRegression()
scoring = 'accuracy'
results = model_selection.cross_val_score(modelCV, X_train, y_train, cv=kfold, scoring=scoring)
print("10-fold cross validation average accuracy: %.3f" % (results.mean()))
# confusion matrix
#函数confusion_matrix(y_true, y_pred, labels=None, sample_weight=None)
#通过计算混淆矩阵来计算一个分类的准确性
from sklearn.metrics import confusion_matrix
confusion_matrix = confusion_matrix(y_test, y_pred)
print(confusion_matrix)
#sklearn中的classification_report函数用于显示主要分类指标的文本报告.在报告中显示每个类的精确度,召回率,F1值等信息。
#其中列表左边的一列为分类的标签名,右边support列为每个标签的出现次数.avg / total行为各列的均值(support列为总和).
#precision recall f1-score三列分别为各个类别的精确度/召回率及 F1值.
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
#ROC曲线
#roc_auc_score 直接根据真实值(必须是二值)、预测值(可以是0/1,也可以是proba值)计算出auc值,中间过程的roc计算省略。
#roc_curve 该函数返回这三个变量:fpr,tpr,和阈值thresholds;
#sklearn.metrics.roc_curve(y_true,y_score, pos_label=None, sample_weight=None, drop_intermediate=True)
#“Score”表示每个测试样本属于正样本的概率。
#FPR = FP /(FP + TN) (被预测为正的负样本结果数 /负样本实际数),为横坐标:假正率(False Positive Rate , FPR)
#TPR = TP /(TP + FN)  (正样本预测结果数 / 正样本实际数),为纵坐标:真正率(True Positive Rate , TPR)或灵敏度(sensitivity)
#这里理解thresholds:分类器的一个重要功能“概率输出”,即表示分类器认为某个样本具有多大的概率属于正样本(或负样本)
#疑问:
#1。predict和predict_proba是啥意思?
#答:#predict是返回预测标签,predict_proba是返回预测属于某个标签的概率。
    #返回你测试集中每个测试样例,分类为每个类的概率;第一列为标签为0的概率,第二列为标签为1的概率
#2.为什么要[:,1]?
#答:取标签为1的那一列。那是不是都一定是第二列,因为score是属于正样本的概率。
#legend显示图例,参数loc,设置图例显示的位置
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
logit_roc_auc = roc_auc_score(y_test, logreg.predict(X_test))
fpr, tpr, thresholds = roc_curve(y_test, logreg.predict_proba(X_test)[:,1])
plt.figure()
plt.plot(fpr, tpr, label='Logistic Regression (area = %0.2f)' % logit_roc_auc)
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")     
plt.savefig('Log_ROC')     #保存图
plt.show()
#本例子中没有做归一化,因为lg算法不是基于距离的,所以不需要做归一化,但是在不知道的情况下,做归一化肯定是没有错的
#归一化一般服从高斯分布,用均值归一化。  在不确定的情况下,不推荐使用零均值归一化,用普通归一化。
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值