引言
在金融领域,信用卡欺诈行为一直是银行和金融机构面临的一大挑战。随着电子商务的快速发展,信用卡欺诈事件的数量和复杂性都在不断增加。据统计,全球每年因信用卡欺诈造成的损失高达数十亿美元。因此,开发有效的欺诈检测系统对于保护消费者和金融机构的利益至关重要。
背景
信用卡欺诈是指未经授权使用信用卡进行交易的行为。这包括但不限于伪造信用卡、使用他人的信用卡信息、或通过其他非法手段进行交易。随着技术的发展,欺诈者的手段也越来越先进,使得传统的欺诈检测方法难以应对。
机器学习在欺诈检测中的应用
机器学习作为一种强大的数据分析工具,在信用卡欺诈检测中发挥着越来越重要的作用。通过分析大量的交易数据,机器学习模型能够识别出正常交易和欺诈交易之间的微妙差异,并预测未知交易是否为欺诈。
XGBoost、CatBoost和LightGBM
XGBoost、CatBoost和LightGBM是当前流行的几种梯度提升算法,它们在处理分类和回归问题上表现出色。这些算法通过构建多个弱预测模型的集合来提高预测的准确性,并且能够处理各种类型的数据,包括数值型和类别型数据。
XGBoost
- 特点:速度快,精度高,支持自定义目标函数和评价标准。
- 应用:广泛用于Kaggle竞赛和工业界。
CatBoost
- 特点:对类别特征的处理能力强,无需手动进行特征编码。
- 应用:适合处理具有大量类别特征的数据集。
LightGBM
- 特点:速度快,内存占用低,支持高维稀疏数据。
- 应用:在大规模数据集上表现优异。
研究目的
本文旨在探讨如何利用XGBoost、CatBoost和LightGBM这三种先进的机器学习算法构建一个高效的信用卡欺诈识别模型。通过对这些算法的深入分析和比较,我们希望能够为金融行业提供一种新的欺诈检测解决方案。
数据集
此数据集包含欧洲持卡人在 2023 年进行的信用卡交易。它包含超过 550,000 条记录,数据已被匿名化以保护持卡人的身份。该数据集的主要目的是促进欺诈检测算法和模型的开发,以识别潜在的欺诈交易。
数据主要特征:
- id:每笔交易的唯一标识符
- V1-V28:表示各种交易属性(如时间、位置等)的匿名化特征
- 金额(Amount):交易金额
- 类(Class):指示交易是否欺诈的二进制标签 (1) 或非欺诈 (0)
第 1 步:导入数据和库
# 导入基础库
import pandas as pd # 导入pandas库,用于数据处理和分析
import numpy as np # 导入numpy库,用于数值计算
import matplotlib.pyplot as plt # 导入matplotlib的pyplot模块,用于绘图
import plotly.express as px # 导入plotly的express模块,用于交互式绘图
import seaborn as sns # 导入seaborn库,用于数据可视化
from colorama import Fore, Style, init; # 导入colorama库,用于控制控制台文本的颜色 # 导入必要的库
from IPython.display import display, HTML # 导入IPython的display模块,用于在Jupyter Notebook中显示HTML内容
from scipy.stats import skew # 导入scipy的stats模块中的skew函数,用于计算偏度 # 导入Plotly的go模块
import plotly.graph_objects as go # 导入plotly的graph_objects模块,用于创建图形对象 # 导入subplots模块
from plotly.subplots import make_subplots # 导入plotly的subplots模块,用于创建子图 # 忽略警告
import warnings
warnings.filterwarnings("ignore") # 忽略所有的警告信息 # 模型训练相关库
from sklearn.model_selection import train_test_split # 导入train_test_split函数,用于划分训练集和测试集
from sklearn.ensemble import VotingClassifier, VotingRegressor # 导入投票分类器和投票回归器
from sklearn.model_selection import RepeatedStratifiedKFold, cross_val_score # 导入重复分层K折交叉验证和交叉验证评分
from sklearn.preprocessing import LabelEncoder, MinMaxScaler, StandardScaler, QuantileTransformer # 导入标签编码、最小最大缩放、标准缩放和分位数变换
from sklearn.metrics import * # 导入sklearn的所有评估指标 # 分类器相关库
from sklearn.svm import SVC # 导入支持向量机分类器
from sklearn.neighbors import KNeighborsClassifier # 导入K近邻分类器
from catboost import CatBoostClassifier # 导入CatBoost分类器
from lightgbm import LGBMClassifier # 导入LightGBM分类器
import lightgbm as lgb # 导入lightgbm库,尽管这行代码在这里可能不是必需的
from sklearn.naive_bayes import MultinomialNB # 导入多项式朴素贝叶斯分类器
from sklearn.tree import DecisionTreeClassifier # 导入决策树分类器
from sklearn.linear_model import LogisticRegression # 导入逻辑回归分类器
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, ExtraTreesClassifier # 导入随机森林、AdaBoost和ExtraTrees分类器
from xgboost import XGBClassifier # 导入XGBoost分类器 # Optuna库
import optuna # 导入Optuna库,用于超参数优化 # 设置调色板
# palette = ["#00B1D2FF", "#FDDB27FF"] # 这里是注释掉的调色板定义
# palette = ['#D7A9E3FF', '#8BBEE8FF', '#A8D5BAFF'] # 这里是另一个注释掉的调色板定义
palette = ["#00203FFF", "#ADEFD1FF"] # 定义调色板
color_palette = sns.color_palette(palette) # 使用seaborn的color_palette函数生成颜色列表 # 再次忽略警告(注意:这行代码与之前的警告忽略是重复的)
import warnings
warnings.filterwarnings("ignore") # 设置pandas的选项以显示所有列
pd.set_option('display.max_columns', None) # 设置pandas的显示选项,以便在输出时显示所有列
tr_d = pd.read_csv('creditcard_2023.csv')
tr_d.head()
太多列了,截取不完,我将所有列名提取出来供大家查看。
本文的目的是构建算法模型,以及优化模型的预测的准确度,所以id列没用,直接删掉,剩余568630行,31列数据。
步骤 2 :数据概览
# 定义一个函数,用于使用colorama库以指定的颜色和样式打印文本
def PrintColor(text: str, color=Fore.CYAN, style=Style.BRIGHT): "使用colorama库打印带颜色的文本,使用F-string格式化文本" print(style + color + text + Style.RESET_ALL) # 打印带颜色和样式的文本,然后重置到默认样式
# 定义一个函数,用于以大号蓝色字体打印文本
def print_blue_large(text): PrintColor(text, Fore.BLUE + Style.BRIGHT) # 调用PrintColor函数,使用蓝色和大号样式打印文本
# 定义一个函数,用于打印带边框的蓝色标题
def print_boxed_blue_heading(text): length = len(text) + 4 # 计算标题长度,包括边框 print(f"\n{Style.BRIGHT}{Fore.BLUE}{'='*length}{Style.RESET_ALL}") # 打印上边框 print(f"{Style.BRIGHT}{Fore.BLUE}| {text} |{Style.RESET_ALL}") # 打印标题和左右边框 print(f"{Style.BRIGHT}{Fore.BLUE}{'='*length}{Style.RESET_ALL}") # 打印下边框
# 定义一个函数,用于概览数据集
def data_overview(tr_d): # 显示训练数据集的头部 print_boxed_blue_heading("数据集情况:") # 打印带边框的蓝色标题 display(HTML(tr_d.head(5).to_html(index=False).replace('<table border="1" class="dataframe">', '<table style="border: 2px solid blue;">'))) # 显示数据集的前五行,并修改表格边框样式 print('\n') # 打印一个空行 # 显示训练集和测试集的形状 print_boxed_blue_heading("数据集形状:") # 打印带边框的蓝色标题 PrintColor(f"The Shape Of Train Data is {tr_d.shape} || No of Rows is : {tr_d.shape[0]} and Columns is {tr_d.shape[1]}", Fore.CYAN) # 打印训练集的形状信息 print('\n') # 打印一个空行 # 显示训练集的信息 print_boxed_blue_heading("数据信息:") # 打印带边框的蓝色标题 PrintColor(f"\nThe Info Of Train Dataset", Fore.CYAN) # 打印提示信息 tr_d.info() # 显示数据集的详细信息 # 显示训练集的数值摘要 print_boxed_blue_heading("描述性统计:") # 打印带边框的蓝色标题 PrintColor(f"\nThe Numerical Summary of Train is", Fore.CYAN) # 打印提示信息 display(tr_d.describe().style.set_caption("Train Data Summary").set_table_styles([{'selector': 'caption', 'props': [('color', 'blue')]}])) # 显示数值摘要,并设置标题样式 # 显示训练集中的空值 print_boxed_blue_heading("缺失值情况:") # 打印带边框的蓝色标题 PrintColor("\nNull Values in Train", Fore.CYAN) # 打印提示信息 print(tr_d.isnull().sum()) # 显示每列中的空值数量 print('\n') # 打印一个空行 # 显示训练集中的重复值 print_boxed_blue_heading("重复值情况:") # 打印带边框的蓝色标题 PrintColor("\nDuplicates Values in Train", Fore.CYAN) # 打印提示信息 print(tr_d.duplicated().sum()) # 显示数据集中的重复行数
# 数据集信息
data_overview(tr_d)
上面定义封装了一个函数用以查看数据的描述性统计信息(见下图):
有1条重复信息,我们将他删除:
# 删除重复值
tr_d.drop_duplicates(inplace=True)
步骤 3 :EDA分析
继续定义一个函数,用于绘制饼图和条形图并排成一行:
# 定义一个函数,用于绘制单个饼图和条形图
def single_plot_distribution(column_name, dataframe): # 获取指定列的值计数 value_counts = dataframe[column_name].value_counts() # 创建一个带有两个子图的图形 # figsize设置图形大小,(15, 5)表示宽度为15,高度为5 # gridspec_kw用于调整子图的宽度比例,这里两个子图宽度相同 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5), gridspec_kw={'width_ratios': [1, 1]}) # 绘制环形饼图 # pie_colors是一个颜色列表,这里假设palette是一个在函数外部定义的颜色列表 pie_colors = palette[0:3] # 使用palette的前三个颜色 # 绘制饼图,autopct设置百分比格式,startangle设置起始角度,pctdistance设置百分比标签到圆心的距离 # colors设置颜色,labels设置为None,意味着标签不会在饼图上直接显示 ax1.pie(value_counts, autopct='%0.001f%%', startangle=90, pctdistance=0.85, colors=pie_colors, labels=None) # 创建一个白色的中心圆,用于显示环形效果 centre_circle = plt.Circle((0,0),0.70,fc='white') # 将中心圆添加到饼图中 ax1.add_artist(centre_circle) # 设置饼图的标题 ax1.set_title(f'Distribution of {column_name}', fontsize=16) # 绘制条形图 # bar_colors同样使用palette的前三个颜色 bar_colors = palette[0:3] # 使用seaborn的barplot函数绘制条形图 # x为类别索引,y为对应的值,ax指定在哪个子图上绘制,palette设置颜色 sns.barplot(x=value_counts.index, y=value_counts.values, ax=ax2, palette=bar_colors,) # 设置条形图的标题 ax2.set_title(f'Count of {column_name}', fontsize=16) # 设置x轴的标签 ax2.set_xlabel(column_name, fontsize=14) # 设置y轴的标签 ax2.set_ylabel('Count', fontsize=14) # 为了提高可读性,旋转x轴的标签 ax2.tick_params(axis='x', rotation=45) # 调整子图布局,避免重叠 plt.tight_layout() # 显示图形 plt.show()
# 数据分布图
single_plot_distribution('Class',tr_d)
以上代码调用了定义的函数,可视化展示Class列交易欺诈和非欺诈行为的分布情况:
横轴1代表欺诈行为,0代表非欺诈行为。原始数据55开,各占一半。
# 要绘制的列
# 定义一个列表,包含要绘制的数据集中的列名
columns_to_plot =['V1', 'V2', 'V3', 'V4','Class'] # 数据列
# 从数据集tr_d中选择上面定义的列,并将结果存储在data_to_plot变量中
data_to_plot = tr_d[columns_to_plot] # 创建一个字典来映射'Class'列的唯一值到颜色
# 假设'Class'列包含0和1两个分类值,以及其他可能的值,我们将它们映射到palette中的颜色,以及一个默认的'gray'颜色
# 注意:这里的'palette'变量需要事先定义,且其长度应该足够覆盖'Class'列的所有唯一值
Q_colors = { 0 : palette[0], 1 : palette[1], 'other': 'gray'} # 使用指定的调色板为分类变量创建pairplot
# sns.pairplot函数用于绘制数据集中成对变量之间的图形
# hue参数指定一个变量,其值将决定绘图中的颜色
# palette参数接受一个字典或列表,用于定义不同类别的颜色
# 在这里,我们使用Q_colors字典为'Class'列的不同值定义颜色
sns.pairplot(data_to_plot, hue='Class', palette=Q_colors)
plt.savefig('/Users/c/Desktop/heatmap_correlation_matrix.png', dpi=350)
# 显示图形
# plt.show()函数用于在屏幕上显示图形
plt.show()
以上代码指定 hue 参数来根据 ‘Class’ 列的值区分颜色(共两个值黑色代表诈骗行为青色代表无诈骗行为),其中每一行和每一列都对应 ‘V1’, ‘V2’, ‘V3’, ‘V4’,'Class’中的一个变量。下图包含各种成对变量的散点图,对角线位置则是每个变量的直方图或核密度估计(KDE):
在解读这个图形时,您可以注意以下几点:
- 对角线图形:每个对角线上的图形显示了一个变量的分布。对于数值变量,这通常是直方图或KDE,显示了该变量的值是如何分布的。
- 非对角线图形:这些图形是成对变量之间的散点图。每个点代表数据集中的一个观测值,其 x 和 y 坐标分别由行和列变量确定。点的颜色由 hue参数指定的变量(即 ‘Class’)决定。因此,您可以根据颜色来区分不同类别的点。
- 颜色映射:由于您使用了 Q_colors 字典来定义颜色映射,0 和 1 类的点将分别用 palette[0] 和 palette[1]定义的颜色来绘制。如果 ‘Class’ 列中有其他值,它们将默认使用 seaborn 的默认颜色(除非您明确指定了 ‘other’: ‘gray’ 的处理逻辑,但这在 pairplot 中可能不起作用,因为它通常只使用 palette 字典中明确指定的颜色)。
- 相关性:虽然 pairplot主要用于可视化变量之间的成对关系,但它也可以帮助您识别变量之间的潜在相关性。如果两个变量之间存在线性关系,那么散点图将显示一条大致的直线或曲线。如果两个变量是独立的,那么散点图将呈现随机分布。
- 异常值:通过查看散点图,您可以识别数据中的任何异常值或离群点。这些点可能会偏离大多数点的模式,从而提供有关数据集的额外信息。
# NUM_COLS_F 变量用于存储tr_d DataFrame中所有浮点型(float)列的列名
NUM_COLS_F = [col for col in tr_d.columns if tr_d[col].dtype == 'float'] # 定义子图的行数和列数
num_rows = 5 # 5行
num_cols = 5 # 5列# 使用plt.subplots创建具有指定行数和列数的子图网格,并设置图形大小
fig, axes = plt.subplots(num_rows, num_cols, figsize=(25, 17)) # 将axes(一个num_rows x num_cols的数组)扁平化成一个一维数组,以便于后续的循环迭代
axes = axes.flatten() # 遍历NUM_COLS_F中的每个浮点型列,并为每个列创建一个箱线图(boxplot)
for i, col in enumerate(NUM_COLS_F[:num_rows * num_cols]): # 使用seaborn的boxplot函数为每个数值列创建箱线图,设置ax参数以在特定的子图上绘图 # 并设置箱线图的颜色为palette列表中循环的颜色 sns.boxplot(x=tr_d[col], ax=axes[i], color=palette[i % len(palette)]) # 设置子图的标题为该列的列名 axes[i].set_title(col) # 隐藏没有数据的子图(即NUM_COLS_F中的列数少于num_rows * num_cols时)
# 从NUM_COLS_F的长度开始,到num_rows * num_cols结束,遍历axes数组
for i in range(len(NUM_COLS_F), num_rows * num_cols): # 使用fig.delaxes方法删除多余的子图 fig.delaxes(axes[i]) # 调整子图之间的布局,避免重叠
plt.tight_layout()
plt.savefig('/Users/c/Desktop/heatmap_correlation_matrix.png', dpi=350)
# 显示图形
plt.show()
以上代码为每个浮点型列(也就是有小数点数值的列)创建一个箱线图(boxplot)。每个箱线图都在一个单独的子图上绘制,在解读生成的图形时,可以注意以下几点:
箱线图解读:
- 箱线图显示了一组数据的分布。中间的矩形框(箱体)表示数据的第二四分位数(中位数)到第三四分位数(上四分位数)的范围,也就是数据集中间50%的值的范围。
- 箱体中的横线代表中位数。
- 从箱体延伸出去的“须线”(whiskers)通常表示非异常值的范围,具体范围取决于箱线图的绘制方法(如Tukey’s boxplot)。
- “离群点”(outliers)是用圆圈或星号表示的,它们位于须线之外。
颜色:
- 箱线图的颜色是从 palette 列表中循环使用的。这有助于区分不同的变量,尤其是当有很多箱线图时。
子图标题:
- 每个子图的标题设置为该子图对应的列名(col)。这有助于识别每个箱线图代表哪个变量。
# 定义一个函数,用于绘制数值列的分布图,并根据hue_col进行颜色区分
def plot_numerical_distribution_with_hue(data, num_cols, hue_col='Gender', figsize=(25, 25), dpi=100): # 根据num_cols的长度计算子图的行数,确保有足够的子图来绘制所有的列 # 这里使用整除后向上取整的方式,确保子图数量足够 rows = (len(num_cols) + 1) // 2 # 使用matplotlib的plt.subplots函数创建子图网格 # 指定行数、列数、图形大小以及DPI fig, ax = plt.subplots(rows, 2, figsize=figsize, dpi=dpi) # 将返回的ax数组(二维数组)扁平化为一维数组,方便后续遍历 ax = ax.flatten() # 遍历num_cols中的每个列名 for i, column in enumerate(num_cols): # 使用seaborn的histplot函数绘制直方图 # 传入数据data、x轴对应的列名column、hue对应的列名hue_col # ax指定子图位置,kde=True表示添加核密度估计曲线,palette指定颜色方案(但注意这里未定义palette变量) sns.histplot(data=data, x=column, hue=hue_col, ax=ax[i], kde=True, palette=palette) # 设置子图的标题,显示列名和'Distribution' ax[i].set_title(f'{column} Distribution', size=14) # 移除x轴和y轴的标签,避免标签重叠 ax[i].set_xlabel(None) ax[i].set_ylabel(None) # 计算当前列的偏度(衡量数据分布偏斜程度的统计量) # 使用scipy.stats中的skew函数,并排除空值进行计算 # 注意:这里假设已经导入了scipy.stats模块,并且使用了其中的skew函数 skewness = skew(data[column].dropna()) # 格式化偏度值,并添加标签 skew_label = f'Skewness: {skewness:.2f}' # 在子图上添加偏度注释 # xy参数指定注释的位置(这里使用相对于子图坐标系的分数坐标) # xycoords指定坐标系的类型,fontsize指定字体大小,color指定字体颜色 ax[i].annotate(skew_label, xy=(0.05, 0.9), xycoords='axes fraction', fontsize=12, color='red') # 如果num_cols的长度小于子图的总数,移除多余的子图 for j in range(len(num_cols), len(ax)): fig.delaxes(ax[j]) # 调整子图之间的布局,确保它们不会重叠 plt.tight_layout() # 显示图形 plt.show()
# 定义要绘制的列名列表
# NUM_COLS_F 包含了多个数值型列的名称,如 V1, V2, ..., V28
NUM_COLS_F = ['V1','V2','V3','V4','V5','V22','V23','V24','V25','V26','V27','V28'] # 调用之前定义的 plot_numerical_distribution_with_hue 函数
# 来绘制 tr_d 数据集中 NUM_COLS_F 列的数值分布
# 并将 'Class' 列作为 hue(颜色区分)的参数
# 这里假设 tr_d 是一个已经加载好的 pandas DataFrame,且包含 NUM_COLS_F 和 'Class' 列
# 'Class' 列可能是一个分类变量,用于在直方图中区分不同的类别
plot_numerical_distribution_with_hue(tr_d, NUM_COLS_F, 'Class')
以上第一段代码,定义了一个函用于’V1’,‘V2’,‘V3’,‘V4’,‘V5’,‘V22’,‘V23’,‘V24’,‘V25’,‘V26’,‘V27’,'V28’列的分布图,并根据hue_col进行颜色区分:
我象征性截取了一部分图,原图上传半天都失败,分布图是EDA分析最简单的可视化,之前的案例有过介绍,感兴趣的可以翻翻以前的案例。
# 定义一个函数,用于缩放数据
def apply_scaling(data, columns, scaler_type): # 根据缩放器类型检查并初始化相应的缩放器对象 # 如果缩放器类型是'S' if scaler_type == 'S': # 初始化StandardScaler scaler = StandardScaler() # StandardScaler用于将特征标准化,即减去均值并除以标准差 # 如果缩放器类型是'M' elif scaler_type == 'M': # 初始化MinMaxScaler scaler = MinMaxScaler() # MinMaxScaler用于将数据缩放到指定的最小值和最大值之间,默认为[0, 1] # 如果缩放器类型是'Q' elif scaler_type == 'Q': # 初始化QuantileTransformer scaler = QuantileTransformer(output_distribution='normal') # QuantileTransformer用于将数据转换为接近正态分布的分布 # 如果缩放器类型不是'S', 'M', 或 'Q' else: # 抛出值错误异常 raise ValueError("Invalid scaler type. Choose 'S' for StandardScaler, 'M' for MinMaxScaler, or 'Q' for QuantileTransformer.") # 创建一个输入数据的副本,以避免修改原始数据 # 这是一个良好的实践,因为函数通常不应修改传入的参数 scaled_data = data.copy() # 遍历需要缩放的每一列 for col in columns: # 对当前列应用缩放器,并将缩放后的值更新到数据中 # 注意:这里使用fit_transform方法来同时拟合缩放器并转换数据 # 我们使用double brackets scaled_data[[col]]是因为fit_transform期望一个二维数组(即使是单列) scaled_data[col] = scaler.fit_transform(scaled_data[[col]]) # 返回缩放后的数据 return scaled_data
定义一个函数,里面存储了多种数据标准化的方法,方面后面调用。
# 使用列表推导式指定需要缩放的列
# 这里选取tr_d DataFrame中所有数据类型为'float'的列
columns_to_scale = [col for col in tr_d.columns if tr_d[col].dtype == 'float'] # 指定缩放器的类型,这里使用'M'表示MinMaxScaler
scaler_type = 'M' # 调用apply_scaling函数对训练数据进行缩放
# 将tr_d DataFrame、需要缩放的列columns_to_scale和缩放器类型scaler_type作为参数传入
tr_d = apply_scaling(tr_d, columns_to_scale, scaler_type) # 调用PrintColor函数(注意:这个函数在您的代码段中没有定义,但假设它用于打印带颜色的文本)
# 打印“Data Scaled Done”表示数据缩放已完成
# 注意:Python中函数名通常是小写字母开头的,所以PrintColor可能是自定义的或来自某个库
PrintColor('Data Scaled Done')
上面代码指定浮点数型数值列进行数据标准化。
# 选择数据框 tr_d 中仅包含数值类型的列
# 这会返回一个只包含 int 和 float 类型列的新数据框 N_d
N_d = tr_d.select_dtypes(include='number') # 计算 N_d 数据框中所有数值列之间的相关性矩阵
# corr() 函数默认计算皮尔逊相关系数
correlation_matrix = N_d.corr() # 创建一个热力图来可视化相关性矩阵
# figsize 参数设置图形的大小
# annot=True 表示在每个单元格中显示数据
# cmap=palette 设置颜色映射,但注意 palette 变量需要在这段代码之前定义
# fmt=".1f" 设置显示的数字格式,保留一位小数
# linewidths=0.5 设置单元格之间的线条宽度
plt.figure(figsize=(25, 15))
sns.heatmap(correlation_matrix, annot=True, cmap=palette, fmt=".1f", linewidths=0.5) # 设置热力图的标题,并设置字体大小
plt.title('Correlation Plot', fontsize=22) # 自动调整子图参数,使之填充整个图像区域
plt.tight_layout() # 显示图形
plt.show()
以上代码选择数值列数据绘制皮尔逊相关系数矩阵图进行两两之间的相关性分析:
步骤 4:模型构建
# # # =================================================================================================================
# # # X < y
# # #==================================================================================================================
X_T = tr_d.drop('Class', axis=1)
y_T = tr_d['Class']
# # # =================================================================================================================
# # # Train < Test Split
# # #==================================================================================================================
X_TR, X_TE, Y_TR, Y_TE = train_test_split(X_T, y_T, test_size=0.1, random_state=42)# # # =================================================================================================================
# # # Shapes <
# # #==================================================================================================================
PrintColor(f"训练集形状 - X: {X_TR.shape}, y: {Y_TR.shape}")
PrintColor(f"测试集形状 - X: {X_TE.shape}, y: {Y_TE.shape}")
运行以上代码得到以上图片结果,将数据进行训练集和测试集分割后,训练集特征511767行,30列,预测列为511767行,只有1列的Series。测试集特征56863行,30列,预测列为56863行,只有1列的Series。
# 初始化模型
# 初始化 XGBoost 分类器
# XGB Classifier
xgb = XGBClassifier(n_estimators=100, random_state=42) # 创建一个XGBoost分类器实例,设置弱学习器数量为100,并设置随机种子为42 # 初始化 CatBoost 分类器
# CatBoost Classifier
catboost = CatBoostClassifier(iterations=100, random_state=42, verbose=0) # 创建一个CatBoost分类器实例,设置迭代次数为100,随机种子为42,并设置输出详细度为0(即不输出日志信息) # 初始化 LightGBM 分类器
# LightGBM Classifier
lgb_params = { 'n_estimators': 890, # 设置弱学习器数量 'learning_rate': 0.7019434172842792, # 设置学习率 'max_depth': 19, # 设置树的最大深度 'reg_alpha': 1.2057738033316066, # 设置L1正则化项系数 'reg_lambda': 0.18598174484559382, # 设置L2正则化项系数 'num_leaves': 3, # 设置叶子节点数(在LightGBM中通常与决策树的复杂度相关) 'subsample': 0.746154395882518, # 设置特征子采样比例 'colsample_bytree': 0.3877680559022922 # 设置列子采样比例(即特征子采样比例)
}
lgbm = LGBMClassifier(**lgb_params, random_state=42, verbose=-1) # 创建一个LightGBM分类器实例,使用上述参数,并设置随机种子为42,输出详细度为-1(即不输出日志信息) # 打印一个蓝色框标题,表示基础分类器已经初始化完成
#___________________________________________________________________
print_boxed_blue_heading('基础分类器已初始化完成!') # 这里假设print_boxed_blue_heading是一个自定义函数,用于打印带有蓝色边框的标题
实例化算法模型,大家可以看到参数很多,因为好的模型学习能力特别强,很容易学到不该学的东西,从而过拟合。所以就有了正则化这种防止过拟合的方法出现。
# 逐个拟合每个模型 # 1. XGBoost 分类器
# 使用训练数据 X_TR 和 Y_TR 来训练 XGBoost 分类器
xgb.fit(X_TR, Y_TR)
# 预测
# 使用训练好的 XGBoost 分类器对测试数据 X_TE 进行预测
xgb_pred = xgb.predict(X_TE) # ---------------------------------------------
# 2. CatBoost 分类器
# 使用训练数据 X_TR 和 Y_TR 来训练 CatBoost 分类器
catboost.fit(X_TR, Y_TR)
# 预测
# 使用训练好的 CatBoost 分类器对测试数据 X_TE 进行预测
catboost_pred = catboost.predict(X_TE) # -------------------------------------
# 3. LightGBM 分类器
# 使用训练数据 X_TR 和 Y_TR 来训练 LightGBM 分类器
lgbm.fit(X_TR, Y_TR)
# 预测
# 使用训练好的 LightGBM 分类器对测试数据 X_TE 进行预测
lgbm_pred = lgbm.predict(X_TE) # -------------------------------------
# 打印一个蓝色框标题,表示模型已经拟合完成
print_boxed_blue_heading('模型已经拟合完成!') # 这里假设print_boxed_blue_heading是一个自定义函数,用于打印带有蓝色边框的标题
以上的代码就完成了模型的训练拟合。
# 评估结果
def evaluate(y_test, y_pred): # 计算准确率 # 使用 sklearn 的 accuracy_score 函数计算真实标签 y_test 和预测标签 y_pred 之间的准确率 accuracy = accuracy_score(y_test, y_pred) # 计算精确度 # 使用 sklearn 的 precision_score 函数计算真实标签 y_test 和预测标签 y_pred 之间的精确度 # 注意:精确度通常用于二分类问题,在多分类问题中可能需要指定平均方法(例如 'macro', 'weighted' 等) precision = precision_score(y_test, y_pred) # 计算混淆矩阵 # 使用 sklearn 的 confusion_matrix 函数计算真实标签 y_test 和预测标签 y_pred 之间的混淆矩阵 # 混淆矩阵可以帮助我们了解分类器在各类别上的表现,例如真阳性(TP)、假阳性(FP)、真阴性(TN)和假阴性(FN) confusion = confusion_matrix(y_test, y_pred) # 返回准确率、精确度和混淆矩阵 return accuracy, precision, confusion
上面代码定义了一个用于计算准确率、精确度、混淆矩阵的函数。
# XGB Classifier
# 调用之前定义的 evaluate 函数来评估 XGBoost 分类器的性能
accuracy_XGB, precision_XGB, confusion_XGB = evaluate(Y_TE, xgb_pred)
# 打印一个蓝色框标题,表示 XGBoost 分类器的评估结果
print_boxed_blue_heading("XGB分类器的评价结果")
# 调用一个假设存在的 PrintColor 函数(可能是自定义的)来以特定颜色打印评估结果
# 这里使用了 f-string 格式化字符串来插入变量值
PrintColor(f"The Accuracy Score Of XGB Classifier is {accuracy_XGB}, Precision Is {precision_XGB},\nConfusion Matrix is \n{confusion_XGB} ")
# 打印一个空行,用于分隔输出
print("\n") # CatBoost Classifier
# 调用之前定义的 evaluate 函数来评估 CatBoost 分类器的性能
accuracy_Cat, precision_Cat, confusion_Cat = evaluate(Y_TE, catboost_pred)
# 打印一个蓝色框标题,表示 CatBoost 分类器的评估结果
print_boxed_blue_heading("CatBoost分类器的评价结果")
# 调用 PrintColor 函数来以特定颜色打印评估结果
PrintColor(f"The Accuracy Score Of CatBoost Classifier is {accuracy_Cat}, Precision Is {precision_Cat},\nConfusion Matrix is \n{confusion_Cat} ")
# 打印一个空行,用于分隔输出
print("\n") # LightGBM Classifier
# 调用之前定义的 evaluate 函数来评估 LightGBM 分类器的性能
accuracy_LGBM, precision_LGBM, confusion_LGBM = evaluate(Y_TE, lgbm_pred)
# 这里有一个错误:标题应该是 "Evaluation Results for LightGBM Classifier",而不是 "LightBoost Classifier"
print_boxed_blue_heading("LightBoost分类器的评价结果") # 错误在此行
# 调用 PrintColor 函数来以特定颜色打印评估结果
# 注意:这里混淆矩阵打印的是 confusion_Cat 而不是 confusion_LGBM,这是一个错误
PrintColor(f"The Accuracy Score Of CatBoost Classifier is {accuracy_LGBM}, Precision Is {precision_LGBM},\nConfusion Matrix is \n{confusion_Cat} ") # 错误在此行
# 打印一个空行,用于分隔输出
print("\n")
以上关于模型评价结果的相关解释,下面我们构建一个表格来存储评估结果:
# 创建一个字典,用于存储评估结果
# 字典包含三个键:'Model'(模型名称)、'Accuracy'(准确率)和'Precision'(精确度)
# 每个键的值都是一个列表,分别包含 XGBoost、LightGBM 和 CatBoost 的评估结果
evaluation_data = { 'Model': ['XGBoost', 'LightGBM', 'CatBoost'], # 列表包含三个模型的名称 'Accuracy': [accuracy_XGB, accuracy_LGBM, accuracy_Cat], # 列表包含三个模型的准确率 'Precision': [precision_XGB, precision_LGBM, precision_Cat] # 列表包含三个模型的精确度
} # 创建一个 pandas DataFrame,使用前面创建的字典作为数据
# DataFrame 是 pandas 中用于存储表格数据的主要数据结构
evaluation_df = pd.DataFrame(evaluation_data) # 对 DataFrame 进行排序,基于 'Accuracy' 和 'Precision' 列的值进行降序排序
# 这意味着准确率最高的模型会排在前面,如果准确率相同,则精确度更高的模型排在前面
evaluation_df = evaluation_df.sort_values(by=['Accuracy', 'Precision'], ascending=False) # 显示排序后的 DataFrame
# 这将打印出包含模型名称、准确率和精确度的表格,按准确率和精确度降序排列
evaluation_df # 注意,这里只是引用了 DataFrame,并没有显式地打印它。在 Jupyter Notebook 或交互式环境中,这会自动显示 DataFrame。如果是在脚本中,你可能需要添加 print(evaluation_df) 来显示它。
三种模型准确率最高的XGBoost,模型准确率达到99.98%,它是不是三种模型性能最好的呢?各有千秋吧,在百亿级以上的数据上,我认为性能最强的应该是LightGBM算法,这里稍落下风是因为数据只有50多万条,远没有达到LightGBM算法的数据需求。上面介绍的三种算法在机器学习有监督学习里面性能算是非常优秀的,善常处理大型数据。老牌算法朴素贝叶斯、决策树、支持向量机、K近邻、随机森林等感觉只能打点酱油了。
# 定义模型的名称列表
models = ['XGBoost', 'LightGBM', 'CatBoost'] # 定义准确率的列表,其中accuracy_XGB, accuracy_LGBM, accuracy_Cat是之前计算好的准确率
accuracies = [accuracy_XGB, accuracy_LGBM, accuracy_Cat] # 定义精确度的列表,其中precision_XGB, precision_LGBM, precision_Cat是之前计算好的精确度
precisions = [precision_XGB, precision_LGBM, precision_Cat] # 创建一个字典,包含模型的名称、准确率和精确度,准备用于构建DataFrame
data = {'Model': models, 'Accuracy': accuracies, 'Precision': precisions} # 使用字典data创建一个pandas DataFrame
df = pd.DataFrame(data) # 定义一个自定义的颜色调色板,使用Seaborn的'Paired'颜色方案
custom_palette = sns.color_palette("Paired") # 注意:这里应该使用custom_palette而不是palette,因为palette在代码中未定义 # 使用Seaborn和Matplotlib来绘制图形
plt.figure(figsize=(20, 8)) # 创建一个新的图形,设置大小为20x8英寸 # 子图1:准确率
plt.subplot(1, 2, 1) # 创建一个1行2列的子图,当前是第1个子图
sns.barplot(x='Model', y='Accuracy', data=df, palette=custom_palette[0:3]) # 绘制准确率柱状图,使用自定义调色板的前三个颜色
plt.title('Model Accuracies') # 设置子图标题
plt.xlabel('Model') # 设置x轴标签
plt.ylabel('Accuracy') # 设置y轴标签
plt.xticks(rotation=45) # 设置x轴刻度标签旋转45度,以便更好地显示 # 子图2:精确度
plt.subplot(1, 2, 2) # 切换到第2个子图
sns.barplot(x='Model', y='Precision', data=df, palette=custom_palette[3:6]) # 绘制精确度柱状图,使用自定义调色板的接下来三个颜色(假设有足够的颜色)
plt.title('Model Precisions') # 设置子图标题
plt.xlabel('Model') # 设置x轴标签
plt.ylabel('Precision') # 设置y轴标签
plt.xticks(rotation=45) # 设置x轴刻度标签旋转45度 # 调整子图布局,使其不会重叠
plt.tight_layout() # 显示图形
plt.show()
可视化三种算法的精确率和精度:
预测结果展示:
1代表欺诈行为,0代表正常行为。举个例:比如XGBoost预测结果汇总统计,欺诈行为有28371个,正常行为有28492个,以此类推(数据太大只能这样汇总给大家展示了)。
结论
本文通过深入分析和实验,探讨了XGBoost、CatBoost和LightGBM三种梯度提升算法在信用卡欺诈识别中的应用。实验结果表明,三种算法在信用卡欺诈识别任务上均表现出了较高的准确性和效率。
贡献与展望
本文的主要贡献在于提供了一种结合三种先进算法构建的信用卡欺诈识别模型,为金融行业提供了一种新的解决方案。机器学习在信用卡欺诈检测领域仍有巨大的发展空间,随着技术的不断进步和数据量的持续增长,我期待能够开发出更加精准和高效的模型。同时,也鼓励更多的研究者和实践者探索和利用这些强大的算法,共同推动金融安全技术的发展。
结语
信用卡欺诈识别是一个复杂且不断发展的领域。本文的研究只是一个开始,希望通过分享经验和成果,激发更多的思考和创新。
您的点赞、评论、收藏是我创作的动力,数据点击本文标题下面链接免费下载。