大数据分析案例-基于随机森林算法构建银行贷款审批预测模型

🤵‍♂️ 个人主页:@艾派森的个人主页

✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+


喜欢大数据分析项目的小伙伴,希望可以多多支持该系列的其他文章

大数据分析案例合集
大数据分析案例-基于随机森林算法预测人类预期寿命
大数据分析案例-基于随机森林算法的商品评价情感分析
大数据分析案例-用RFM模型对客户价值分析(聚类)
大数据分析案例-对电信客户流失分析预警预测
大数据分析案例-基于随机森林模型对北京房价进行预测
大数据分析案例-基于RFM模型对电商客户价值分析
大数据分析案例-基于逻辑回归算法构建垃圾邮件分类器模型
大数据分析案例-基于决策树算法构建员工离职预测模型

大数据分析案例-基于KNN算法对茅台股票进行预测

大数据分析案例-基于多元线性回归算法构建广告投放收益模型
大数据分析案例-基于随机森林算法构建返乡人群预测模型
大数据分析案例-基于决策树算法构建金融反欺诈分类模型

目录

1.项目背景

2.项目简介

2.1项目说明

2.2数据说明

2.3技术工具

3.算法原理

4.项目实施步骤

4.1理解数据

4.2数据预处理

4.3探索性数据分析

4.4特征工程

4.5模型构建

4.6模型评估

5.实验总结

源代码


1.项目背景

        随着金融科技的发展和数字化浪潮的推进,银行和其他金融机构越来越依赖数据分析来做出决策,特别是在贷款审批领域。传统的贷款审批过程往往依赖于人工审核和有限的信用评分系统,这种方法不仅效率低下,而且可能受到主观偏见和人为错误的影响。因此,开发一种能够自动、准确并高效地评估贷款申请人信用风险的模型变得至关重要。

        近年来,机器学习算法,特别是随机森林算法,在信用风险评估领域的应用逐渐受到关注。随机森林算法是一种集成学习方法,它通过构建多个决策树并结合它们的输出来提高预测精度和稳定性。该算法能够处理大量高维数据,自动捕捉数据中的非线性关系,并且对噪声和异常值具有较强的鲁棒性。       

        本研究不仅有助于推动银行贷款审批流程的数字化转型,还可为其他金融领域的风险管理提供有益的参考和借鉴。随着数据科学和人工智能技术的不断发展,未来贷款审批预测模型将更加精准、高效,为金融业的稳定发展提供有力支持。

2.项目简介

2.1项目说明

        本项目旨在利用借款人的历史信用记录、财务状况、个人背景等多维度信息,通过机器学习和数据分析技术,构建一个自动化的贷款审批流程。该模型能够快速、准确地评估申请人的信用风险,帮助银行做出更加明智的贷款决策,减少坏账风险,提高贷款业务的盈利能力。

        此外,该模型还有助于银行实现客户细分和个性化服务。通过对不同申请人群体进行特征分析和风险预测,银行可以更加精准地满足不同客户群体的需求,优化贷款产品设计和定价策略,提升客户满意度和忠诚度。因此,基于随机森林算法的银行贷款审批模型不仅具有重要的理论价值,还具有广阔的应用前景和巨大的市场潜力。

2.2数据说明

        本数据集来源于Kaggle,在这个贷款状态预测数据集中,我们有以前根据property Loan的属性申请贷款的申请人的数据。银行将根据申请人的收入、贷款金额、以前的信用记录、共同申请人的收入等因素来决定是否向申请人提供贷款。我们的目标是建立一个机器学习模型来预测申请人的贷款被批准或被拒绝。原始数据集共有381条,13个变量。各变量含义如下:

Loan_ID:唯一的贷款ID。

Gender:男性或女性。

Married:天气结婚(是)或不结婚(否)。

Dependents:依赖于客户端的人数。

Education   :申请人学历(研究生或本科)。

Self_Employed:自雇(是/否)。

ApplicantIncome:申请人收入。

CoapplicantIncome:共同申请人收入。

LoanAmount:以千为单位的贷款金额。

Loan_Amount_Term:以月为单位的贷款期限。

Credit_History:信用记录符合指导原则。

Property_Area:申请人居住在城市、半城市或农村。

Loan_Status:贷款批准(Y/N)。

2.3技术工具

Python版本:3.9

代码编辑器:jupyter notebook

3.算法原理

        随机森林是一种有监督学习算法。就像它的名字一样,它创建了一个森林,并使它拥有某种方式随机性。所构建的“森林”是决策树的集成,大部分时候都是用“bagging”方法训练的。bagging 方法,即 bootstrapaggregating,采用的是随机有放回的选择训练数据然后构造分类器,最后组合学习到的模型来增加整体的效果。简而言之,随机森林建立了多个决策树,并将它们合并在一起以获得更准确和稳定的预测。其一大优势在于它既可用于分类,也可用于回归问题,这两类问题恰好构成了当前的大多数机器学习系统所需要面对的。

        随机森林分类器使用所有的决策树分类器以及 bagging 分类器的超参数来控制整体结构。与其先构建 bagging分类器,并将其传递给决策树分类器,我们可以直接使用随机森林分类器类,这样对于决策树而言,更加方便和优化。要注意的是,回归问题同样有一个随机森林回归器与之相对应。

        随机森林算法中树的增长会给模型带来额外的随机性。与决策树不同的是,每个节点被分割成最小化误差的最佳指标,在随机森林中我们选择随机选择的指标来构建最佳分割。因此,在随机森林中,仅考虑用于分割节点的随机子集,甚至可以通过在每个指标上使用随机阈值来使树更加随机,而不是如正常的决策树一样搜索最佳阈值。这个过程产生了广泛的多样性,通常可以得到更好的模型。

4.项目实施步骤

4.1理解数据

导入本次实验的第三方库

import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt
import seaborn as sns 
import warnings
from sklearn.metrics import accuracy_score, confusion_matrix, roc_curve, auc
from sklearn.preprocessing import MinMaxScaler
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.linear_model import LogisticRegression
import xgboost as xgb
from xgboost import XGBClassifier
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
import plotly.express as px
warnings.simplefilter(action='ignore', category=FutureWarning)

接着加载数据集

data = pd.read_csv("loan_data.csv")
data.head()

查看数据大小 

查看数据基本信息

查看数值型变量的描述性统计

查看非数值型变量的描述性统计

4.2数据预处理

查看缺失值情况

发现数据存在缺失值,需要进行处理

处理缺失值

# 处理分类列中缺失的值
for col in categorical_columns:
    data[col].fillna(data[col].mode()[0], inplace=True)

# 处理数值列中的缺失值
data['Loan_Amount_Term'].fillna(data['Loan_Amount_Term'].median(), inplace=True)
data['Credit_History'].fillna(data['Credit_History'].mode()[0], inplace=True)
data.isnull().sum() 

编码处理

# 编码处理
data['Dependents'] = data['Dependents'].replace(['0', '1', '2', '3+'], [0,1,2,3])
data['Credit_History'] = data['Credit_History'].astype(int)
label_encoder_columns = ['Gender', 'Married', 'Education', 'Self_Employed','Property_Area', 'Loan_Status']

label_encoder = LabelEncoder()
for col in label_encoder_columns:
    data[col] = label_encoder.fit_transform(data[col])

data.head()

4.3探索性数据分析

相关系数热力图

plt.figure(figsize=(10,8))
corr_df = data.corr()
sns.heatmap(corr_df,annot=True)
plt.show()

自定义两个绘图函数

# 自定义绘图函数
def violin(col):
    fig = px.violin(data, y=col, x="Loan_Status", color="Loan_Status", box=True)
    return fig.show()

def kde_plot(feature):
    grid = sns.FacetGrid(data, hue="Loan_Status",aspect=2)
    grid.map(sns.kdeplot, feature)
    grid.add_legend()
violin('LoanAmount')

kde_plot('LoanAmount')

categorical_columns = ['Gender', 'Married', 'Education','Self_Employed', 'Loan_Status']

fig, ax = plt.subplots(3, 2, figsize=(12, 15))
for index, cat_col in enumerate(categorical_columns):
    row, col = index // 2, index % 2
    sns.countplot(x=cat_col, data=data, hue='Loan_Status', ax=ax[row, col], palette='Set2')
    ax[row, col].set_title(f'Distribution of Loan Approval by {cat_col}', fontsize=14)

    for p in ax[row, col].patches:
        ax[row, col].annotate(f'{p.get_height()}', (p.get_x() + p.get_width() / 2., p.get_height()),
                              ha='center', va='center', xytext=(0, 10), textcoords='offset points', fontsize=10)

plt.subplots_adjust(hspace=0.5, wspace=0.3)
plt.suptitle('Loan Approval Distribution Across Categorical Variables', fontsize=16, y=1.02)
plt.show()

numerical_columns = ['ApplicantIncome', 'CoapplicantIncome', 'LoanAmount', 'Loan_Amount_Term']

fig, axes = plt.subplots(1, 4, figsize=(25, 7))

for idx, num_col in enumerate(numerical_columns):
    sns.boxplot(x='Loan_Status', y=num_col, data=data, ax=axes[idx], palette='Set2')
    axes[idx].set_title(f'Distribution of {num_col} by Loan Approval', fontsize=14)
    axes[idx].set_ylabel(num_col, fontsize=12)

plt.suptitle('Distribution of Numerical Variables by Loan Approval', fontsize=16, y=1.02)
plt.subplots_adjust(wspace=0.4)
print(data[numerical_columns].describe())
plt.show()

4.4特征工程

准备建模数据

# 准备建模数据
ind_col = [col for col in data.columns if col != 'Loan_Status']
dep_col = 'Loan_Status'
X = data[ind_col]
y = data[dep_col]

特征筛选 

# 应用SelectKBest类提取前8个最佳特征
bestfeatures = SelectKBest(score_func=chi2, k=8)
fit = bestfeatures.fit(X, y)
# 创建一个DataFrame来显示所选的特性及其分数
featureScores = pd.DataFrame({'Specs': X.columns, 'Score': fit.scores_})
# 打印10个最佳特征
print(featureScores.nlargest(10, 'Score'))

# 拟合ExtraTreesClassifier模型
model = ExtraTreesClassifier()
model.fit(X, y)

# 特征重要性
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(8).plot(kind='barh')
plt.show()

# 特征挑选
selected_features = feat_importances.nlargest(8).index
X_new = data.loc[:, selected_features].copy()
X_new.head()

数据标准化

# 数据标准化
scaler = MinMaxScaler()
for column in numerical_columns:
    X_new[column] = scaler.fit_transform(X_new[[column]])
X_new.head()

拆分数据集

# 拆分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_new,y,train_size=0.8,random_state=0)
print(X_train.shape)
print(X_test.shape)

4.5模型构建

确定各模型最优参数

## 关于XGBoost的超参数优化

XGBoost_params={
 "learning_rate"    : [0.05, 0.20, 0.25 ] ,
 "max_depth"        : [ 5, 8, 10, 12],
 "min_child_weight" : [ 1, 3, 5, 7 ],
 "gamma"            : [ 0.0, 0.1, 0.2 , 0.4 ],
 "colsample_bytree" : [ 0.3, 0.4, 0.7 ]
    
}

## 关于随机森林的超参数优化
RF_params = {
    'n_estimators': [50, 100, 200, 300],  # Number of trees in the forest
    'max_depth': [None, 10, 20, 30],  # Maximum depth of the tree
    'min_samples_split': [2, 5, 10],  # Minimum number of samples required to split an internal node
    'min_samples_leaf': [1, 2, 4],  # Minimum number of samples required to be at a leaf node
    'max_features': ['sqrt', 'log2', None],  # Number of features to consider at every split
    'bootstrap': [True, False]  # Method of selecting samples for training each tree
}

## 关于决策树的超参数优化
DT_params = {
    'criterion': ['gini', 'entropy','log_loss'],  # Measure of impurity
    'splitter': ['best', 'random'],  # Strategy to choose the split at each node
    'max_depth': [None, 10, 20, 30],  # Maximum depth of the tree
    'min_samples_split': [2, 5, 10],  # Minimum number of samples required to split an internal node
    'min_samples_leaf': [1, 2, 4],  # Minimum number of samples required to be at a leaf node
    'max_features': [None, 'sqrt', 'log2'],  # Number of features to consider at every split
}

初始化模型

# XGBoost 
xgboost = XGBClassifier()
# Random Forest
random_forest = RandomForestClassifier()
# Decision Tree
decision_tree = DecisionTreeClassifier()

XGBoost模型的随机搜索

# RandomizedSearchCV for XGBoost
XGBoost_random_search = RandomizedSearchCV(xgboost,param_distributions=XGBoost_params,n_iter=5,scoring='roc_auc',n_jobs=-1,cv=5,verbose=3)
XGBoost_random_search.fit(X_train, y_train)

随机森林模型的随机搜索

# RandomizedSearchCV for Random Forest
RF_random_search = RandomizedSearchCV(random_forest, param_distributions=RF_params, n_iter=5, scoring='roc_auc', n_jobs=-1, cv=5, verbose=3)
RF_random_search.fit(X_train, y_train)

决策树模型的随机搜索

# RandomizedSearchCV for Decision Tree
DT_random_search = RandomizedSearchCV(decision_tree, param_distributions=DT_params, n_iter=5, scoring='roc_auc', n_jobs=-1, cv=5, verbose=3)
DT_random_search.fit(X_train, y_train)

打印模型的最佳参数

# 打印每个模型的最佳参数
print("Best Parameters for XGBoost:")
print(XGBoost_random_search.best_params_)

print("\nBest Parameters for Random Forest:")
print(RF_random_search.best_params_)

print("\nBest Parameters for Decision Tree:")
print(DT_random_search.best_params_)

定义模型 

# Define final XGBoost Classifier 
xgboost_classifier = XGBClassifier(min_child_weight = 1, max_depth = 5, learning_rate = 0.2, gamma = 0.2, colsample_bytree  = 0.7)

# Define final Random Forest Classifier
rf_classifier = RandomForestClassifier(n_estimators = 50, min_samples_split = 10, min_samples_leaf = 4, max_features = 'sqrt', max_depth = 30, bootstrap = True)

# Define final Decision Tree Classifier
dt_classifier = DecisionTreeClassifier(splitter =  'best', min_samples_split = 10, min_samples_leaf = 4, max_features = None, max_depth = 10, criterion = 'log_loss')

# Define Logistic Regression Classifier
lr_classifier = LogisticRegression()

训练模型

# Train XGBoost Classifier
xgboost_classifier.fit(X_train, y_train)

# Train Random Forest Classifier
rf_classifier.fit(X_train, y_train)

# Train Decision Tree Classifier
dt_classifier.fit(X_train, y_train)

# Train Logistic Regression Classifier 
lr_classifier.fit(X_train, y_train)

4.6模型评估

打印模型混淆矩阵

xgboost_pred = xgboost_classifier.predict(X_test)
rf_pred = rf_classifier.predict(X_test)
dt_pred = dt_classifier.predict(X_test) 
lr_pred = lr_classifier.predict(X_test)
# Confusion Matrix for XGBoost
confusion_xgboost = confusion_matrix(y_test, xgboost_pred)
print('Confusion Matrix for XGBoost:')
print(confusion_xgboost)

# Confusion Matrix for Random Forest
confusion_rf = confusion_matrix(y_test, rf_pred)
print('\nConfusion Matrix for Random Forest:')
print(confusion_rf)

# Confusion Matrix for Decision Tree
confusion_dt = confusion_matrix(y_test, dt_pred)
print('\nConfusion Matrix for Decision Tree:')
print(confusion_dt)

# Confusion Matrix for Logistic Regression
confusion_lr = confusion_matrix(y_test, lr_pred)
print('\nConfusion Matrix for Logistic Regression:')
print(confusion_lr)

打印模型准确率

# Accuracy of XGBoost 
xgboost_accuracy = accuracy_score(y_test, xgboost_pred)
print("Accuracy of XGBoost:")
print(xgboost_accuracy)

# Accuracy of Random Forest
RF_accuracy = accuracy_score(y_test, rf_pred)
print("Accuracy of Random Forest:")
print(RF_accuracy)

# Accuracy of Decision Tree
DT_accuracy = accuracy_score(y_test, dt_pred)
print("Accuracy of Decision Tree:")
print(DT_accuracy)

# Accuracy of Logistic Regression
LR_accuracy = accuracy_score(y_test, lr_pred)
print("Accuracy of Logistic Regression:")
print(LR_accuracy)

ROC曲线 

# XGBoost
y_prob_xgb = xgboost_classifier.predict_proba(X_test)[:, 1]
fpr_xgb, tpr_xgb, thresholds_xgb = roc_curve(y_test, y_prob_xgb)
roc_auc_xgb = auc(fpr_xgb, tpr_xgb)

# RandomForestClassifier
y_prob_rf = rf_classifier.predict_proba(X_test)[:, 1]
fpr_rf, tpr_rf, thresholds_rf = roc_curve(y_test, y_prob_rf)
roc_auc_rf = auc(fpr_rf, tpr_rf)

# Decision Tree Classifier
y_prob_dt = dt_classifier.predict_proba(X_test)[:, 1]
fpr_dt, tpr_dt, thresholds_dt = roc_curve(y_test, y_prob_dt)
roc_auc_dt = auc(fpr_dt, tpr_dt)

# Logistic Regression
y_prob_lr = lr_classifier.predict_proba(X_test)[:, 1]
fpr_lr, tpr_lr, thresholds_lr = roc_curve(y_test, y_prob_lr)
roc_auc_lr = auc(fpr_lr, tpr_lr)

# Create a subplot with 2 rows and 2 columns
plt.figure(figsize=(15, 10))

# Plot for XGBoost
plt.subplot(2, 2, 1)
plt.plot(fpr_xgb, tpr_xgb, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_xgb))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('XGBoost\nAccuracy: {:.2f}%'.format(xgboost_accuracy * 100))
plt.legend(loc="lower right")

# Plot for RandomForestClassifier
plt.subplot(2, 2, 2)
plt.plot(fpr_rf, tpr_rf, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_rf))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Random Forest\nAccuracy: {:.2f}%'.format(RF_accuracy * 100))
plt.legend(loc="lower right")

# Plot for Decision Tree
plt.subplot(2, 2, 3)
plt.plot(fpr_dt, tpr_dt, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_dt))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Decision Tree\nAccuracy: {:.2f}%'.format(DT_accuracy * 100))
plt.legend(loc="lower right")

# Plot for Logistic Regression
plt.subplot(2, 2, 4)
plt.plot(fpr_lr, tpr_lr, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_lr))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Logistic Regression\nAccuracy: {:.2f}%'.format(LR_accuracy * 100))
plt.legend(loc="lower right")

# Adjust layout to prevent overlap
plt.tight_layout()

# Show the plots
plt.show()

5.实验总结

心得与体会:

通过这次Python项目实战,我学到了许多新的知识,这是一个让我把书本上的理论知识运用于实践中的好机会。原先,学的时候感叹学的资料太难懂,此刻想来,有些其实并不难,关键在于理解。

在这次实战中还锻炼了我其他方面的潜力,提高了我的综合素质。首先,它锻炼了我做项目的潜力,提高了独立思考问题、自我动手操作的潜力,在工作的过程中,复习了以前学习过的知识,并掌握了一些应用知识的技巧等

在此次实战中,我还学会了下面几点工作学习心态:

1)继续学习,不断提升理论涵养。在信息时代,学习是不断地汲取新信息,获得事业进步的动力。作为一名青年学子更就应把学习作为持续工作

用心性的重要途径。走上工作岗位后,我会用心响应单位号召,结合工作实际,不断学习理论、业务知识和社会知识,用先进的理论武装头脑,用精良的业务知识提升潜力,以广博的社会知识拓展视野。

2)努力实践,自觉进行主角转化。只有将理论付诸于实践才能实现理论自身的价值,也只有将理论付诸于实践才能使理论得以检验。同样,一个人的价值也是透过实践活动来实现的,也只有透过实践才能锻炼人的品质,彰显人的意志。

3)提高工作用心性和主动性。实习,是开端也是结束。展此刻自我面前的是一片任自我驰骋的沃土,也分明感受到了沉甸甸的职责。在今后的工作和生活中,我将继续学习,深入实践,不断提升自我,努力创造业绩,继续创造更多的价值。

这次Python实战不仅仅使我学到了知识,丰富了经验。也帮忙我缩小了实践和理论的差距。在未来的工作中我会把学到的理论知识和实践经验不断的应用到实际工作中,为实现理想而努力。

源代码

import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt
import seaborn as sns 
import warnings
from sklearn.metrics import accuracy_score, confusion_matrix, roc_curve, auc
from sklearn.preprocessing import MinMaxScaler
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.linear_model import LogisticRegression
import xgboost as xgb
from xgboost import XGBClassifier
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
import plotly.express as px
warnings.simplefilter(action='ignore', category=FutureWarning)
data = pd.read_csv("loan_data.csv")
data.head()
data.shape
data.info()
data.describe()
data.describe(include='O')
data.isnull().sum()
categorical_columns=[col for col in data.columns if data[col].dtype=='O']
categorical_columns
# 处理分类列中缺失的值
for col in categorical_columns:
    data[col].fillna(data[col].mode()[0], inplace=True)

# 处理数值列中的缺失值
data['Loan_Amount_Term'].fillna(data['Loan_Amount_Term'].median(), inplace=True)
data['Credit_History'].fillna(data['Credit_History'].mode()[0], inplace=True)
data.isnull().sum() 
# 删除不相关的列
data.drop('Loan_ID', axis=1, inplace=True)
# 编码处理
data['Dependents'] = data['Dependents'].replace(['0', '1', '2', '3+'], [0,1,2,3])
data['Credit_History'] = data['Credit_History'].astype(int)
label_encoder_columns = ['Gender', 'Married', 'Education', 'Self_Employed','Property_Area', 'Loan_Status']

label_encoder = LabelEncoder()
for col in label_encoder_columns:
    data[col] = label_encoder.fit_transform(data[col])

data.head()
plt.figure(figsize=(10,8))
corr_df = data.corr()
sns.heatmap(corr_df,annot=True)
plt.show()
# 自定义绘图函数
def violin(col):
    fig = px.violin(data, y=col, x="Loan_Status", color="Loan_Status", box=True)
    return fig.show()

def kde_plot(feature):
    grid = sns.FacetGrid(data, hue="Loan_Status",aspect=2)
    grid.map(sns.kdeplot, feature)
    grid.add_legend()
violin('LoanAmount')
kde_plot('LoanAmount')
categorical_columns = ['Gender', 'Married', 'Education','Self_Employed', 'Loan_Status']

fig, ax = plt.subplots(3, 2, figsize=(12, 15))
for index, cat_col in enumerate(categorical_columns):
    row, col = index // 2, index % 2
    sns.countplot(x=cat_col, data=data, hue='Loan_Status', ax=ax[row, col], palette='Set2')
    ax[row, col].set_title(f'Distribution of Loan Approval by {cat_col}', fontsize=14)

    for p in ax[row, col].patches:
        ax[row, col].annotate(f'{p.get_height()}', (p.get_x() + p.get_width() / 2., p.get_height()),
                              ha='center', va='center', xytext=(0, 10), textcoords='offset points', fontsize=10)

plt.subplots_adjust(hspace=0.5, wspace=0.3)
plt.suptitle('Loan Approval Distribution Across Categorical Variables', fontsize=16, y=1.02)
plt.show()
numerical_columns = ['ApplicantIncome', 'CoapplicantIncome', 'LoanAmount', 'Loan_Amount_Term']

fig, axes = plt.subplots(1, 4, figsize=(25, 7))

for idx, num_col in enumerate(numerical_columns):
    sns.boxplot(x='Loan_Status', y=num_col, data=data, ax=axes[idx], palette='Set2')
    axes[idx].set_title(f'Distribution of {num_col} by Loan Approval', fontsize=14)
    axes[idx].set_ylabel(num_col, fontsize=12)

plt.suptitle('Distribution of Numerical Variables by Loan Approval', fontsize=16, y=1.02)
plt.subplots_adjust(wspace=0.4)
print(data[numerical_columns].describe())
plt.show()
# 准备建模数据
ind_col = [col for col in data.columns if col != 'Loan_Status']
dep_col = 'Loan_Status'
X = data[ind_col]
y = data[dep_col]
# 应用SelectKBest类提取前8个最佳特征
bestfeatures = SelectKBest(score_func=chi2, k=8)
fit = bestfeatures.fit(X, y)
# 创建一个DataFrame来显示所选的特性及其分数
featureScores = pd.DataFrame({'Specs': X.columns, 'Score': fit.scores_})
# 打印10个最佳特征
print(featureScores.nlargest(10, 'Score'))
# 拟合ExtraTreesClassifier模型
model = ExtraTreesClassifier()
model.fit(X, y)

# 特征重要性
feat_importances = pd.Series(model.feature_importances_, index=X.columns)
feat_importances.nlargest(8).plot(kind='barh')
plt.show()
# 特征挑选
selected_features = feat_importances.nlargest(8).index
X_new = data.loc[:, selected_features].copy()
X_new.head()
# 数据标准化
scaler = MinMaxScaler()
for column in numerical_columns:
    X_new[column] = scaler.fit_transform(X_new[[column]])
X_new.head()
# 拆分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_new,y,train_size=0.8,random_state=0)
print(X_train.shape)
print(X_test.shape)
## 关于XGBoost的超参数优化

XGBoost_params={
 "learning_rate"    : [0.05, 0.20, 0.25 ] ,
 "max_depth"        : [ 5, 8, 10, 12],
 "min_child_weight" : [ 1, 3, 5, 7 ],
 "gamma"            : [ 0.0, 0.1, 0.2 , 0.4 ],
 "colsample_bytree" : [ 0.3, 0.4, 0.7 ]
    
}

## 关于随机森林的超参数优化
RF_params = {
    'n_estimators': [50, 100, 200, 300],  # Number of trees in the forest
    'max_depth': [None, 10, 20, 30],  # Maximum depth of the tree
    'min_samples_split': [2, 5, 10],  # Minimum number of samples required to split an internal node
    'min_samples_leaf': [1, 2, 4],  # Minimum number of samples required to be at a leaf node
    'max_features': ['sqrt', 'log2', None],  # Number of features to consider at every split
    'bootstrap': [True, False]  # Method of selecting samples for training each tree
}

## 关于决策树的超参数优化
DT_params = {
    'criterion': ['gini', 'entropy','log_loss'],  # Measure of impurity
    'splitter': ['best', 'random'],  # Strategy to choose the split at each node
    'max_depth': [None, 10, 20, 30],  # Maximum depth of the tree
    'min_samples_split': [2, 5, 10],  # Minimum number of samples required to split an internal node
    'min_samples_leaf': [1, 2, 4],  # Minimum number of samples required to be at a leaf node
    'max_features': [None, 'sqrt', 'log2'],  # Number of features to consider at every split
}
# XGBoost 
xgboost = XGBClassifier()
# Random Forest
random_forest = RandomForestClassifier()
# Decision Tree
decision_tree = DecisionTreeClassifier()
# RandomizedSearchCV for XGBoost
XGBoost_random_search = RandomizedSearchCV(xgboost,param_distributions=XGBoost_params,n_iter=5,scoring='roc_auc',n_jobs=-1,cv=5,verbose=3)
XGBoost_random_search.fit(X_train, y_train)
# RandomizedSearchCV for Random Forest
RF_random_search = RandomizedSearchCV(random_forest, param_distributions=RF_params, n_iter=5, scoring='roc_auc', n_jobs=-1, cv=5, verbose=3)
RF_random_search.fit(X_train, y_train)
# RandomizedSearchCV for Decision Tree
DT_random_search = RandomizedSearchCV(decision_tree, param_distributions=DT_params, n_iter=5, scoring='roc_auc', n_jobs=-1, cv=5, verbose=3)
DT_random_search.fit(X_train, y_train)
# 打印每个模型的最佳参数
print("Best Parameters for XGBoost:")
print(XGBoost_random_search.best_params_)

print("\nBest Parameters for Random Forest:")
print(RF_random_search.best_params_)

print("\nBest Parameters for Decision Tree:")
print(DT_random_search.best_params_)
# Define final XGBoost Classifier 
xgboost_classifier = XGBClassifier(min_child_weight = 1, max_depth = 5, learning_rate = 0.2, gamma = 0.2, colsample_bytree  = 0.7)

# Define final Random Forest Classifier
rf_classifier = RandomForestClassifier(n_estimators = 50, min_samples_split = 10, min_samples_leaf = 4, max_features = 'sqrt', max_depth = 30, bootstrap = True)

# Define final Decision Tree Classifier
dt_classifier = DecisionTreeClassifier(splitter =  'best', min_samples_split = 10, min_samples_leaf = 4, max_features = None, max_depth = 10, criterion = 'log_loss')

# Define Logistic Regression Classifier
lr_classifier = LogisticRegression()
# Train XGBoost Classifier
xgboost_classifier.fit(X_train, y_train)

# Train Random Forest Classifier
rf_classifier.fit(X_train, y_train)

# Train Decision Tree Classifier
dt_classifier.fit(X_train, y_train)

# Train Logistic Regression Classifier 
lr_classifier.fit(X_train, y_train)
xgboost_pred = xgboost_classifier.predict(X_test)
rf_pred = rf_classifier.predict(X_test)
dt_pred = dt_classifier.predict(X_test) 
lr_pred = lr_classifier.predict(X_test)
# Confusion Matrix for XGBoost
confusion_xgboost = confusion_matrix(y_test, xgboost_pred)
print('Confusion Matrix for XGBoost:')
print(confusion_xgboost)

# Confusion Matrix for Random Forest
confusion_rf = confusion_matrix(y_test, rf_pred)
print('\nConfusion Matrix for Random Forest:')
print(confusion_rf)

# Confusion Matrix for Decision Tree
confusion_dt = confusion_matrix(y_test, dt_pred)
print('\nConfusion Matrix for Decision Tree:')
print(confusion_dt)

# Confusion Matrix for Logistic Regression
confusion_lr = confusion_matrix(y_test, lr_pred)
print('\nConfusion Matrix for Logistic Regression:')
print(confusion_lr)
# Accuracy of XGBoost 
xgboost_accuracy = accuracy_score(y_test, xgboost_pred)
print("Accuracy of XGBoost:")
print(xgboost_accuracy)

# Accuracy of Random Forest
RF_accuracy = accuracy_score(y_test, rf_pred)
print("Accuracy of Random Forest:")
print(RF_accuracy)

# Accuracy of Decision Tree
DT_accuracy = accuracy_score(y_test, dt_pred)
print("Accuracy of Decision Tree:")
print(DT_accuracy)

# Accuracy of Logistic Regression
LR_accuracy = accuracy_score(y_test, lr_pred)
print("Accuracy of Logistic Regression:")
print(LR_accuracy)
# XGBoost
y_prob_xgb = xgboost_classifier.predict_proba(X_test)[:, 1]
fpr_xgb, tpr_xgb, thresholds_xgb = roc_curve(y_test, y_prob_xgb)
roc_auc_xgb = auc(fpr_xgb, tpr_xgb)

# RandomForestClassifier
y_prob_rf = rf_classifier.predict_proba(X_test)[:, 1]
fpr_rf, tpr_rf, thresholds_rf = roc_curve(y_test, y_prob_rf)
roc_auc_rf = auc(fpr_rf, tpr_rf)

# Decision Tree Classifier
y_prob_dt = dt_classifier.predict_proba(X_test)[:, 1]
fpr_dt, tpr_dt, thresholds_dt = roc_curve(y_test, y_prob_dt)
roc_auc_dt = auc(fpr_dt, tpr_dt)

# Logistic Regression
y_prob_lr = lr_classifier.predict_proba(X_test)[:, 1]
fpr_lr, tpr_lr, thresholds_lr = roc_curve(y_test, y_prob_lr)
roc_auc_lr = auc(fpr_lr, tpr_lr)

# Create a subplot with 2 rows and 2 columns
plt.figure(figsize=(15, 10))

# Plot for XGBoost
plt.subplot(2, 2, 1)
plt.plot(fpr_xgb, tpr_xgb, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_xgb))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('XGBoost\nAccuracy: {:.2f}%'.format(xgboost_accuracy * 100))
plt.legend(loc="lower right")

# Plot for RandomForestClassifier
plt.subplot(2, 2, 2)
plt.plot(fpr_rf, tpr_rf, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_rf))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Random Forest\nAccuracy: {:.2f}%'.format(RF_accuracy * 100))
plt.legend(loc="lower right")

# Plot for Decision Tree
plt.subplot(2, 2, 3)
plt.plot(fpr_dt, tpr_dt, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_dt))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Decision Tree\nAccuracy: {:.2f}%'.format(DT_accuracy * 100))
plt.legend(loc="lower right")

# Plot for Logistic Regression
plt.subplot(2, 2, 4)
plt.plot(fpr_lr, tpr_lr, color='darkorange', lw=2, label='ROC curve (AUC = {:.2f})'.format(roc_auc_lr))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Logistic Regression\nAccuracy: {:.2f}%'.format(LR_accuracy * 100))
plt.legend(loc="lower right")

# Adjust layout to prevent overlap
plt.tight_layout()

# Show the plots
plt.show()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#之partial关键字

在C#中,partial关键字用于声明一个类、结构体、接口或方法的分部定义。这意味着可以将一个类或其他类型的定义分成多个部分,这些部分可以在同一个命名空间或程序集中的多个源文件中进行定义。当编译器编译这些部分时,会将它们合并成一个单独的…

【RAG 论文】BGM:为 LLM 和 Retriever 的偏好 gap 搭建一个 Bridge

论文:Bridging the Preference Gap between Retrievers and LLMs ⭐⭐⭐ Google Research, arXiv:2401.06954 论文速读 LLM 与 Retriever 之间存在一个 preference gap:大多数 retriever 被设计为 human-friendly,但是 LLM 的偏好与人类的却…

网络配置的加密存储

随着数据泄露事件的增加,扰乱了公司的正常工作周期,企业遭受了损失。事实上,数据泄露可以通过存储加密来控制,存储加密是防止黑客对网络数据库造成严重破坏的最有效方法之一。在网络配置管理器中,存储加密可用于存储设…

C++数据结构——AVL树

目录 一、引言 1.1 二叉搜索树 1.2 二叉搜索树的缺陷 1.3 AVL数的引入 二、AVL树结点的定义 三、AVL树的操作 3.1 插入 3.1.1 基本步骤 3.1.2 平衡因子的调整 3.2 旋转操作(重点!) 3.2.1 右单旋 3.2.2 左单旋 3.2.3 左右双旋 3.2.4 右左双旋 3.3 插入…

【算法】滑动窗口——最小覆盖子串

本节博客是对“最小覆盖子串”题目由暴力求解到滑动窗口的思路解析,有需要借鉴即可。 目录 1.题目2.滑动窗口解法3.总结 1.题目 题目链接:LINK 这个题目是困难难度,感觉是一个中等题目的感觉。 首先我肯定想到的是暴力求解的方法&#xff…

大模型微调方法汇总

微调方法 Freeze方法P-tuning方法 prefix-tuningPrompt TuningP-tuning v1P-tuning v2Lora方法 重要相关参数LoRA 的优势Qlora方法 相关参数微调经验 模型选择模型大小选择数据处理微调方案英文模型需要做词表扩充吗?如何避免灾难遗忘大模型的幻觉问题微调后的输出…

MySQL表的增删查改【基础部分】

数据表的操作 新增 普通插入 insert into 表名 values(值,值...)注意: 此处的值要和表中的列相匹配 使用’‘单引号或者”“双引号来表示字符串 mysql> insert into student values(123,zhangsan); Query OK, 1 row affected (0.02 sec)指定列插入 insert …

搜索引擎的设计与实现(二)

目录 3 搜索引擎的基本原理 3.1搜索引擎的基本组成及其功能 l.搜索器 (Crawler) 2.索引器(Indexer) 3.检索器(Searcher) 4.用户接口(UserInterface) 3.2搜索引擎的详细工作流程 4 系统分析与设计 4.1系统分析 4.2系统概要设计 4.2系统实现目标 前面内容请移步 搜索引…

苍穹外卖Day06笔记(复习了jwt的加密解密和传递)

疯玩了一个月,效率好低,今天开始捡起来苍穹外卖~ 1. 为什么不需要单独引入HttpClient的dependency? 因为我们在sky-common的pom.xml中已经引入了aliyun-sdk-oss的依赖,而这个依赖低层就引入了httpclinet的依赖,根据依…

06、SpringBoot 源码分析 - SpringApplication启动流程六

SpringBoot 源码分析 - SpringApplication启动流程六 初始化基本流程SpringApplication的prepareEnvironment准备环境SpringApplication的getOrCreateEnvironment创建环境configureEnvironment配置环境ApplicationConversionService的getSharedInstance配置转换器 SpringApplic…

LLVM中期报告

1.主要开展的工作 研究对LLVM IR层面进行代码混淆,分析IR的指令 ,并且实现混淆 从LLVM代码混淆的角度出发,函数之间的正常调用构成了待混淆程序的原始控制流,不同的基础代码块构成了一个个的函数,每个基础…

PyQt6--Python桌面开发(12.QpushButton按钮控件)

一.按钮类控件 二.QpushButton按钮控件 2.1QAbstractButton类属性 2.2QpushButton类属性

Git系列:Git Stash临时保存与恢复工作进度

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

ncs sdk nrf5340 运行DFU

nrf5340 运行DFU 1. dfu介绍 Nordic 的 DFU(Device Firmware Update)是一种用于更新设备固件的技术和协议。Nordic Semiconductor 是一家专门设计和制造无线芯片的公司,他们的产品主要用于物联网(IoT)和无线连接应用…

无线网卡网络老断网

无线网卡网络老断网 设置 Intel AX210 无线网卡 路由器华为 AX3 问题及解决 问题 无线网卡连接到 wifi ,连接不通,或者连接上后网络很慢,延时大,掉包。 解决方案 调整如下界面,调整信道后,连接正常。…

Springboot HelloWorld

新建一个maven工程 引入依赖项 <modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.11.RELEASE</version><…

armbian 安装libreoffice 转换word为PDF

安装libreoffice sudo apt-get install libreoffice安装JVM sudo apt-get install default-jre #验证 java -version尝试转换&#xff1a; libreoffice --convert-to pdf /root/printFiles/f.docx发现问题乱码 从Windows 拷贝字体到debian上&#xff0c;windows字体路径是&a…

Postman基础功能-断言与日志

若能脱颖而出&#xff0c;何必苦苦融入。大家好&#xff0c;在 API 测试的领域中&#xff0c;Postman 是一款极为强大且广泛使用的工具。其中&#xff0c;断言和日志调试功能扮演着至关重要的角色。 一、介绍 断言允许我们在测试过程中验证 API 的响应是否符合预期。通过设定各…

vue从入门到精通(一):初始Vue

一&#xff0c;Vue是什么 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。另一方面&#xff0c;当与现代…

基于SpringBoot+Vue的教师个人成果管理系统

初衷 在后台收到很多私信是咨询毕业设计怎么做的&#xff1f;有没有好的毕业设计参考? 能感觉到现在的毕业生和当时的我有着同样的问题&#xff0c;但是当时的我没有被骗&#xff0c; 因为现在很多人是被骗的&#xff0c;还没有出学校还是社会经验少&#xff0c;容易相信别人…