• 数据挖掘案列分析---LightGBM实战贷款违约预测


    在今天的机器学习时代,各种算法和工具层出不穷,其中LightGBM凭借其出色的性能和速度,在众多机器学习算法中脱颖而出。本次实战项目,将通过一个简单但不简约的案例,展示如何使用LightGBM进行建模,并通过网格搜索进行模型优化。整个流程将包含数据探索性分析(EDA)、建模和模型优化三个主要部分。

    一、数据探索性分析(EDA)

    首先,我们需要对数据进行探索性分析,以了解数据的分布、特征之间的相关性以及目标变量的趋势。这一步骤对于后续的建模至关重要,因为只有深入了解数据,我们才能选择合适的特征和算法进行建模。

    • 数据加载与预处理
      使用Python的pandas库加载数据,并进行必要的预处理,如缺失值填充、异常值处理等。

    • 数据描述性分析
      通过绘制直方图、箱线图等可视化图表,我们可以直观地了解每个特征的分布情况。同时,计算特征的均值、中位数、标准差等统计量,有助于我们进一步了解数据的整体情况。

    • 特征相关性分析
      利用热力图或相关矩阵,我们可以分析特征之间的相关性。这对于后续的特征选择和模型构建具有重要的指导意义。

    二、基于LightGBM的建模

    在完成数据探索性分析后,我们将使用LightGBM进行建模。LightGBM是一种基于决策树算法的梯度提升框架,具有高效、快速、准确等优点。

    • 数据划分
      将数据集划分为训练集和测试集,以便在训练模型时评估其性能。

    • 模型训练
      使用LightGBM的API进行模型训练。我们可以调整LightGBM的参数,如学习率、树的数量、叶子节点的最小样本数等,以寻找最佳模型。

    • 模型评估
      通过计算准确率、召回率、F1值等指标,评估模型在测试集上的性能。同时,绘制ROC曲线和AUC值,进一步了解模型的分类性能。

    三、基于网格搜索的模型优化

    虽然LightGBM具有许多优秀的默认参数,但针对不同的问题和数据集,我们仍然需要调整参数以获得更好的性能。网格搜索是一种常用的参数优化方法,它通过遍历所有可能的参数组合来找到最优参数。

    • 参数空间定义
      根据LightGBM的文档和经验,我们定义一个包含多个参数的参数空间。这些参数可能包括学习率、树的数量、最大深度、叶子节点的最小样本数等。

    • 网格搜索执行
      使用scikit-learn的GridSearchCV函数进行网格搜索。该函数将自动遍历参数空间中的所有组合,并使用交叉验证评估每个组合的性能。最终,它将返回具有最佳性能的参数组合。

    • 最优模型构建与评估
      使用网格搜索找到的最优参数组合构建新的LightGBM模型,并在测试集上进行评估。与之前的模型相比,优化后的模型应该具有更好的性能。

    四、基于LIghtGBM的贷款违约预测

    实战项目使用的数据集,具体的实现代码如下:

    4.1、导入相应的python库
    import pandas as pd 
    import numpy as np 
    pd.set_option('display.max_columns', 100)
    from IPython.display import display_html
    
    import plotly_express as px 
    import plotly.graph_objects as go 
    
    import matplotlib
    import matplotlib.pyplot as plt 
    plt.rcParams["font.sans-serif"] = ["SimHei"]    #设置字体
    plt.rcParams["axes.unicode_minus"] = False      #解决“-”负号乱码问题
    import seaborn as sns 
    %matplotlib inline
    
    import missingno as ms 
    import gc 
    
    from datetime import datetime
    from sklearn.model_selection import train_test_split, StartifiedKFold, Gr 
    from sklearn.preprocessing import StandardScaler, MinMaxScaler
    from sklearn.decomposition import PCA
    from imblearn.under_sampling import ClusterCentroids
    from imblearn.over_sampling import KMeansSMOTE, SMOTE 
    from sklearn.model_selection import KFold 
    
    from sklearn.metrics import accuracy_score, recall_score, precision_sco
    from sklearn.metrics import roc_auc_score, precision_recall_curve, confu
    
    # Classifiers
    from sklearn.linear_model import LogisticRegression 
    from sklearn.svm import SVC 
    from sklearn import tree
    from pydotplus import graph_from_dot_data
    from sklearn.tree import DecisionTreeClassifier 
    from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier 
    from catboost import CatBoostClassifier 
    import lightgbm as lgb 
    import xgboost as xgb 
    
    from scipy import stats
    
    import warnings
    warnings.filterwarnings("ignore")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    4.2 导入数据查看数据情况
    df = pd.read_csv("random_data.csv")
    df.columns 
    # 缺省值情况
    df.isnull().sum()
    df["History_Default_Times"].value_counts()  # 历史违约次数统计:
    
    df["Sex"].value_counts()                    # 男女人数几乎相同,很均衡。  
    
    df["Default"].value_counts()                # 目标变量是否违约的人数对比
    
    df[df["History_Default_Times"] == 2]        # 需要注意的是:历史违约次数大于0,不代表一定是违约客户。比如历史违约次数为2,最终是否违约的客户两种情况都有。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    4.3 数据简单的可视化
    # 是否违约的客户收入存在差异:
    fig = px.violin(df, x="Default",y="Income")
    fig.show()
    # 基于seaborn绘制密度图:
    
    sns.displot(data=df,x="Income",hue="Default",kind="kde")
    plt.show()                                  # 可以看到在低收入和高收入人群中容易发生违约。
    
    
    fig = px.violin(df, x="Default",y="Age")
    fig.show()
    sns.displot(data=df,x="Age",hue="Default",kind="kde")
    plt.show()                                  # 可以看到是是否违约客户的年龄段分布是一致的。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    4.4 数据集合切分
    #  提取特征和目标变量
    X = df.drop(columns="Default")
    Y = df["Default"]
    
    # 划分训练集和测试集数据
    from sklearn.model_selection import train_test_split
    
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    4.5 模型训练
    from lightgbm import LGBMClassifier
    
    model = LGBMClassifier()
    model.fit(X_train, y_train)  # 模型训练 
    
    • 1
    • 2
    • 3
    • 4
    4.6 模型预测
    y_pred = model.predict(X_test)
    y_pred
    
    • 1
    • 2
    4.7 模型评估
    ### 1、对比测试集中的实际值和预测值:
    predict_true = pd.DataFrame()
    
    predict_true["预测值"] = list(y_pred)
    predict_true["实际值"] = list(y_test)
    predict_true
    
    # 模型在测试集上的准确率
    
    from sklearn.metrics import accuracy_score
    accuracy = accuracy_score(y_pred, y_test)
    accuracy
    
    # ROC-AUC曲线的绘制:
    y_pred_proba = model.predict_proba(X_test)
    y_pred_proba[:5]
    
    from sklearn.metrics import roc_curve  # ROC-AUC曲线
    fpr, tpr, thres = roc_curve(y_test, y_pred_proba[:,1])
    plt.plot(fpr, tpr)
    plt.title("ROC_AUC Curve of Default")
    plt.show()
    
    # 3、查看具体的AUC值:
    from sklearn.metrics import roc_auc_score
    score = roc_auc_score(y_test, y_pred_proba[:,1])
    
    score
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    4.8 特征重要度
    model.feature_importances_
    model.feature_name_
    
    features_df = pd.DataFrame({"features": model.feature_name_,"importances": model.feature_importances_})
    features_df
    
    • 1
    • 2
    • 3
    • 4
    • 5
    4.9 模型调优
    # 基于网格搜索的模型调优:
    from sklearn.model_selection import GridSearchCV
    
    # 设定待搜索的参数及其取值范围:
    parameters = {"num_leaves": [10, 15, 13],
                  "n_estimators":[10,20,30],
                  "learning_rate":[0.05,0.1,0.2]
                 }
    
    model = LGBMClassifier()  #  基础模型实例化
    
    # 定义搜索实例化对象
    grid_search = GridSearchCV(model, # 基础模型
                               parameters,  # 搜索参数
                               scoring="roc_auc", # 评价指标
                               cv=5  # 交叉验证5次
                              )
    
    grid_search.fit(X_train, y_train)  # 模型训练
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    4.10 K折交叉验证
    import os
    import gc
    import math
    
    import pandas as pd
    import numpy as np
    
    import lightgbm as lgb
    import xgboost as xgb
    from catboost import CatBoostRegressor
    from sklearn.linear_model import SGDRegressor, LinearRegression, Ridge
    from sklearn.preprocessing import MinMaxScaler
    
    
    from sklearn.model_selection import StratifiedKFold, KFold
    from sklearn.metrics import log_loss
    from sklearn.model_selection import train_test_split
    
    from tqdm import tqdm
    import matplotlib.pyplot as plt
    import time
    import warnings
    warnings.filterwarnings('ignore')
    
    
    def cv_model(clf, train_x, train_y, test_x, seed=2024):
        # 使用K折交叉验证训练和验证模型
        folds = 5
        kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
        
        # 初始化oof预测和测试集预测
        oof = np.zeros(train_x.shape[0])
        test_predict = np.zeros(test_x.shape[0])
        cv_scores = []
        
        # KFold交叉验证
        for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
            print('************************************ {} ************************************'.format(str(i+1)))
            trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], train_y[valid_index]
            
            # 转换数据为lightgbm数据格式
            train_matrix = clf.Dataset(trn_x, label=trn_y)
            valid_matrix = clf.Dataset(val_x, label=val_y)
            
            # 定义lightgbm参数
            params = {
                    'boosting_type': 'gbdt', # GBDT算法为基础
                    'objective': 'multiclass', # 多分类任务
                    'num_class': 4,          # 设置多分类问题的类别个数
                    'num_leaves': 2 ** 5,    # 指定叶子的个数,默认值为31,大会更准,但可能过拟合。最大不能超过2^max_depth
                    # 构建弱学习器,对特征随机采样的比例,默认值为1,可以防止过拟合,每次迭代中随机选择80%的参数来建树
                    'feature_fraction': 0.8,   
                    'bagging_fraction': 0.8, # 每次迭代时用的数据比例,用于加快训练速度和减小过拟合
                    'bagging_freq': 4,   # 表示bagging(采样)的频率,0意味着没有使用bagging ,k意味着每k轮迭代进行一次bagging
                    'learning_rate': 0.025,
                    'seed': seed,
                    # 使用线程数,一般设置成-1,使用所有线程。这个参数用来控制最大并行的线程数,如果你希望取得所有CPU的核,那么你就不用管它。
                    'nthread': 28,  
                    'n_jobs':24, # 使用多少个线性并构造模型
                    'verbose': -1,
                    'lambda_l1': 0.4,   # L1正则化权重项,增加此值将使模型更加保守。
                    'lambda_l2': 0.5,   # L2正则化权重项,增加此值将使模型更加保守
                    # 'device' : 'gpu'
                }
    
            # 使用训练集数据进行模型训练
            model = clf.train(params, 
                    train_set=train_matrix, 
                    valid_sets=valid_matrix, 
                    num_boost_round=2000, 
                    verbose_eval=100, 
                    early_stopping_rounds=200)
            
            # 对验证集进行预测
            val_pred = model.predict(val_x, num_iteration=model.best_iteration)
            test_pred = model.predict(test_x, num_iteration=model.best_iteration) 
            
            oof[valid_index] = val_pred
            test_predict += test_pred / kf.n_splits
            
            # 计算打印当前折的分数
            score = np.sqrt(mean_squared_erroe(vale_pred, val_y))
            cv_scores.apped(score)
            print(cv_scores)
            
        return oof, test_predict
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    4.11 输出最优的参数,并在最优的参数上进行lightgbm模型的训练
    # 输出最佳的参数组合:
    dict_params = grid_search.best_params_  
    
    dict_params
    
    # 基于最佳的参数组合建立新模型:
    new_model = LGBMClassifier(num_leaves=10, # 使用最佳参数
                               n_estimators=30,
                               learning_rate=0.05
                              )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    MinIO - 站点复制 Site Replication
    linux 内核协助的探测
    华为机试:单词搜索(找到它)
    深度学习+opencv+python实现昆虫识别 -图像识别 昆虫识别 计算机竞赛
    凌恩客户文章|菜豆“不菜”——浙江省农科院新发现:菜用大豆和粮用大豆可能是独立训驯化
    LeetCode 5. 最长回文子串(C++)
    用于发票处理的 DocuWare,摆脱纸张和数据输入的束缚,自动处理所有收到的发票
    【muduo源码剖析】Poller/EPollPoller设计分析
    Linux环境搭建与登陆
    NoveAI本地环境搭建、AI作画
  • 原文地址:https://blog.csdn.net/qq_38614074/article/details/136560062