news 2026/10/13 7:43:51

SQLFlow 信用卡欺诈检测实战:用 SQL 完成 DNN 分类的完整流程(训练 · 预测 · 解释)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQLFlow 信用卡欺诈检测实战:用 SQL 完成 DNN 分类的完整流程(训练 · 预测 · 解释)
  • 人工智能
  • 机器学习
  • 后端
  • 编译器

【免费下载链接】sqlflow

Brings SQL and AI together.

项目地址:https://gitcode.com/gh_mirrors/sq/sqlflow
点击查看免费下载

本篇教程以 Kaggle 信用卡欺诈数据集为例,演示如何使用 SQLFlow 的扩展 SQL 语法(TO TRAIN/TO PREDICT/TO EXPLAIN)在 MySQL 上完成"数据导入 → 不平衡处理 → 深度分类器训练 → 预测 → 可解释性分析"的端到端流程。读完本文,你将掌握 SQLFlow 训练语句中WITH子句各参数(model.n_classes、model.hidden_units、model.batch_norm、train.batch_size、train.epoch、optimizer.learning_rate等)的实际语义与调参思路,并能复现一套完整的欺诈检测建模方案。

数据集简介

对银行来说,能够识别欺诈性的信用卡交易至关重要,它可以帮助客户避免不必要的经济损失。本教程使用的 Kaggle 信用卡欺诈数据集包含 2013 年 9 月欧洲持卡人通过信用卡进行的交易:在两天内发生的 284807 笔交易中,共有 492 笔盗刷。该数据集高度不平衡,正例(发生盗刷)仅占全部交易的 0.172%,这一比例甚至低于常见点击率预估数据集中正例约 1% 的占比,因此非常适合用来演示类别不平衡场景下的建模方法。

由于信用卡真实数据涉及用户隐私、属于公司或银行的高度机密,该数据集并未提供原始特征和更多背景信息。几乎所有特征都是 PCA 变换之后的数值:

  • 特征V1、V2……V28是通过 PCA 得到的主成分;
  • 只有time和amount两个特征没有被 PCA 转化:time表示每笔交易与数据集中第一笔交易之间经过的时长(秒),amount是交易金额,此特征可用于设置样本权重;
  • 字段class是标签,如果存在盗刷则该字段值为 1,否则为 0。

准备数据:从 CSV 到 MySQL 数据表

仓库在 doc/datasets/popularize_creditcardfraud.sql 中提供了信用卡欺诈数据集的建表与灌数脚本,可直接用于复现本教程的数据环境。如果你想从原始 CSV 从头导入一次,可以按下面的步骤操作。

下载并解压

Kaggle 信用卡欺诈数据集以压缩包形式提供,需注册账户方能下载。下载完成后通过以下命令解压,压缩包中只有一个文件creditcard.csv:

unzip creditcard.csv.zip

建表

在 SQLFlow command-line 上用以下语句建立数据表:

CREATE DATABASE IF NOT EXISTS creditcard; CREATE TABLE creditcard.creditcard( time int,v1 FLOAT,v2 FLOAT,v3 FLOAT, v4 FLOAT,v5 FLOAT,v6 FLOAT,v7 FLOAT, v8 FLOAT,v9 FLOAT,v10 FLOAT,v11 FLOAT, v12 FLOAT,v13 FLOAT,v14 FLOAT,v15 FLOAT, v16 FLOAT,v17 FLOAT,v18 FLOAT,v19 FLOAT, v20 FLOAT,v21 FLOAT,v22 FLOAT,v23 FLOAT, v24 FLOAT,v25 FLOAT,v26 FLOAT,v27 FLOAT, v28 FLOAT,amount FLOAT, class int);

仓库中的 popularize_creditcardfraud.sql 使用CREATE TABLE IF NOT EXISTS创建了完全相同结构的creditcard.creditcard表,并直接以INSERT INTO ... VALUES形式插入了带真实 PCA 特征数值的样本行(例如某条盗刷记录形如(46057,-1.30944,1.78649,...,0.293426,1,1)),可作为你校验导入结果的参照。

导入 CSV

建表完成后,将creditcard.csv的内容导入数据表。导入时请指定csv文件的绝对路径,你可以通过mysql client来执行以下语句。通常你需要先通过设置local_infile配置来允许 MySQL 加载本地文件:

-- 允许从本地记载数据 set global local_infile = 1; LOAD DATA LOCAL INFILE '/path/to/creditcard.csv' INTO TABLE creditcard.creditcard CHARACTER SET 'utf8' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"';

数据分析与预处理

查看正负类分布

我们使用如下的 SQL 语句来查看正负类数据的总条数:

%%sqlflow select class, count(*) from creditcard.creditcard group by class;

从结果可以看出,负类(无盗刷)的样例远远多于正类(有盗刷)的样例。针对这种数据不平衡的情况,可以用重采样等方式来做预处理。

下采样平衡正负例

下面我们用一种非常简单的下采样来使训练数据中的正负例数量保持一致。下面的 SQL 语句将数据库中的正例和负例进行打乱,然后把全部正例和等量的负例筛选到creditcard.train表中:

%%sqlflow DROP TABLE IF EXISTS creditcard.train; CREATE TABLE creditcard.train AS SELECT amount, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, class FROM ( SELECT * FROM ( SELECT rand() as r, creditcard.creditcard.* FROM creditcard.creditcard ORDER BY class DESC, r LIMIT 984 ) t ORDER BY r ) tmp

上述 SQL 运行之后,我们可以查看train表中的数据分布,结果表明我们选取了等量的正负例:

%%sqlflow select class, count(*) from creditcard.train group by class;
+-------+----------+ | class | count(*) | +-------+----------+ | 0 | 492 | | 1 | 492 | +-------+----------+

对 amount 字段做归一化

深度模型对数值范围比较敏感。该数据集中v开头的列数据范围都较小,而amount的数据范围较大,我们可以对其进行归一化(读者也可以尝试对其他字段进行归一化):

SELECT MIN(amount), MAX(amount) FROM creditcard.creditcard;
+-------------+-------------+ | MIN(amount) | MAX(amount) | +-------------+-------------+ | 0 | 25691.2 | +-------------+-------------+

注意到amount范围在 0 ~ 25691.2 之间,我们将每条数据的amount字段都除以 25691.2 即可:

%%sqlflow UPDATE creditcard.train SET amount = amount / 25691.2;

训练 DNNClassifier

执行如下语句,我们选取大约 80% 的数据(表中前 780 条)来训练一个深度分类器,然后将训练好的模型存储在creditcard.my_fraud_dnn_model表中:

%%sqlflow SELECT * FROM creditcard.train limit 780 TO TRAIN DNNClassifier WITH train.batch_size=128, model.n_classes=2, model.batch_norm=True, model.hidden_units=[64, 32], optimizer.learning_rate=0.1, train.epoch=20, validation.select="select * from creditcard.train limit 780, 200" LABEL class INTO creditcard.my_fraud_dnn_model;

我们可以从日志链接中看到训练效果。由于训练集数据具有一定随机性,你所看到的结果可能稍有不同:

{'accuracy': 0.86764705, 'accuracy_baseline': 0.51960784, 'auc': 0.9389199, 'auc_precision_recall': 0.9131467, 'average_loss': 0.43539605, 'label/mean': 0.51960784, 'loss': 0.42728242, 'precision': 0.816, 'prediction/mean': 0.6484489, 'recall': 0.9622642, 'global_step': 500}

语法简介

在 SQLFlow 中,SQL 语句以标准 SQL 中的SELECT开始,以TO为界,TO之后就是 SQLFlow 的扩展 SQL 语法。在上面的例子中:

  • TO TRAIN表示这是一条训练语句;
  • DNNClassifier表示我们使用 TensorFlow canned estimators 中的DNNClassifier来针对信用卡欺诈检测数据集进行模型训练;
  • LABEL关键字指定标签字段为class;
  • INTO关键字指定最终构建的模型的名称,同时也是模型存储的表名,这里指定的是my_fraud_dnn_model。训练完成之后,我们可以在该表中查询到以 Base64 格式保存的模型数据。

从源码结构看,SQLFlow 的训练语句最终会经由 go/codegen/tensorflow/template_train.go 中的模板生成一段 Python 训练程序:模板会从tensorflow.estimator导入DNNClassifier、DNNRegressor、LinearClassifier、LinearRegressor、BoostedTreesClassifier等内置 estimator,把WITH子句中model.前缀的参数写入model_params,把train.前缀的参数写入train_params,再调用 python/runtime/tensorflow/train.py 中定义的train()入口完成训练、评估与模型保存。

WITH 子句

WITH子句用于指定模型参数。在上面的例子中我们指定了六个参数,分别介绍如下。

model.n_classes

该参数指定DNNClassifier这样的分类模型的类目数量。由于信用卡欺诈数据集的标签class只有盗刷/正常两种情况,所以我们指定类目数量为 2。实际上,2 是DNNClassifier默认的类目数量,因此例子中的model.n_classes=2,是可以省略的。仓库 go/attribute/model_parameters.go 中DNNClassifier的参数文档也印证了这一点:"Number of label classes. Defaults to 2, namely binary classification. Must be > 1."。

model.hidden_units

该参数指定DNNClassifier中神经网络的结构。[200, 100, 50]表示这个DNNClassifier具有三个隐藏神经元层,各层的节点数分别为 200、100 和 50。本例使用[64, 32],即两层全连接网络,第一层 64 个节点、第二层 32 个节点。参数文档对它的描述是"每个隐藏层的神经元数量组成的可迭代对象,所有层都是全连接的"。

model.batch_norm

该参数设置为 True 的话,DNNClassifier中神经网络的每个隐藏层后会增加一个 batch normalization 层。上文中提过,V1、V2…V28取值范围较小,但仍然远大于 [-1, 1] 这个范围;既然我们没有针对数据本身做归一化,则开启 batch normalization 对效果和训练的稳定性会有很大帮助。

train.batch_size

该参数指定DNNClassifier训练的 batch 大小。神经网络一般都采用随机梯度下降算法,每从数据中读取一个 batch 的大小,就更新一次模型。前面提到,信用卡欺诈数据集的正负例很不均衡,这个参数需要设置得较大,以此来保障每个 batch 在概率上至少有一条正例,从而保证训练过程能正常执行。从运行时实现看,python/runtime/tensorflow/input_fn.py 中数据管道会执行dataset.batch(batch_size),而 python/runtime/tensorflow/train.py 的train()签名中batch_size=1、epoch=1是默认值,训练数据管道默认还会以shuffle_size=1000进行打乱。通过对负例进行采样可以在一定程度上解决正负例不均衡的问题,我们把这个练习留给读者。

train.epoch

该参数控制模型训练的轮数。在本例中train.epoch=20表示训练数据将被完整使用 20 轮;从 input_fn.py 的实现看,当epochs > 1时数据管道会执行dataset.repeat(epochs)来重复遍历数据。

optimizer.learning_rate

optimizer 指定 TensorFlow 的随机梯度下降算法类别。对 DNN 来说,一般默认为Adagrad算法(在 model_parameters.go 的DNNClassifier.optimizer文档中写明 "Defaults to Adagrad optimizer")。learning_rate控制算法的学习率,大部分情况下,这是 DNN 中最重要的超参数。一般来说,较大的 batch_size 和 batch normalization 都有助于设置更大的 learning_rate。

AdaGrad 的默认学习率为 0.001。从理论上讲,AdaGrad 的学习率应该尽可能的大,但不能太大。实际上,可以将学习率逐步调大来尝试得到更好的性能。在这个例子中,为了讲述方便,我们并不遵循这个原则,而是把学习率直接提高 100 倍(设为 0.1)。

validation.select

该参数指定训练过程中的验证数据集。本例用"select * from creditcard.train limit 780, 200"选取训练集后 200 条样本作为验证集,SQLFlow 在训练过程中会周期性在该数据集上评估模型指标(accuracy、auc、precision、recall 等),并输出到日志中。

预测

我们可以通过下面的 SQL 语句来对数据进行预测,这里我们将数据中后 20% 的样本用于预测:

%%sqlflow SELECT * from creditcard.train limit 780, 1000 TO PREDICT creditcard.predict.class USING creditcard.my_fraud_dnn_model;

该语句的含义是:取creditcard.train中第 781 条起的样本,加载USING指定的已训练模型creditcard.my_fraud_dnn_model,把预测出的类别写入creditcard.predict表的class字段。我们可以通过下面的语句来查看预测结果:

%%sqlflow SELECT * from creditcard.predict limit 5

解释:分析模型学到了什么

在处理实际问题的时候,并不是用机器学习技术训练出一个效果良好的模型、预测出结果就万事大吉。我们经常需要分析模型学到了什么,以确定模型是如何决策的、模型的预测结果是不是合理的,等等。下面,我们将通过TO EXPLAIN语句来解释当前数据集中各个字段对于最终分类结果的影响:

%%sqlflow SELECT * FROM creditcard.train WHERE class=1 limit 10 TO EXPLAIN creditcard.my_fraud_dnn_model WITH summary.plot_type="bar";

经过几分钟的运行,你将看到如本节开头所示的结果图,图中将显示各个特征在所选样例分类中的重要性。

从实现层面看,TO EXPLAIN语句由 go/codegen/tensorflow/template_explain.go 生成解释程序,运行时调用 python/runtime/tensorflow/explain.py 中的explain()函数:对于DNNClassifier这类深度模型,SQLFlow 使用 SHAP 的KernelExplainer计算每个样本各特征的 SHAP 值(当样本超过 100 条时会先用shap.kmeans压缩为 16 个加权样本以加速),再通过shap.summary_plot按summary.plot_type指定的"bar"类型绘制特征重要性图,最终由 python/runtime/explainer.py 的plot_and_save()保存成图片返回给用户。此外,如果指定了结果表,SHAP 值还可以逐行写回数据库表,便于后续量化分析。

总结

在这篇文章中,我们介绍了 Kaggle 信用卡欺诈数据集,并以DNNClassifier为例,介绍了如何使用 SQLFlow 完成机器学习的主要任务:

  1. 训练:如何根据数据构建模型

    • SELECT ... TO TRAIN语法
  2. 调参:如何设置不同模型的不同参数

    • WITH子句用于设置训练参数
    • model.hidden_units参数用于控制 DNN 模型的结构
    • model.n_classes参数用于指定分类类别数量(默认 2,可省略)
    • model.batch_norm参数用于开启隐藏层后的 batch normalization
    • optimizer.learning_rate参数用于控制 DNN 模型的学习速率
    • train.batch_size参数用于控制模型批次使用数据时的分批大小
    • train.epoch参数用于控制模型的训练轮数
    • validation.select参数用于指定训练过程中的验证数据集
  3. 预测:在新数据集上应用训练好的模型

    • SELECT ... TO PREDICT语法
  4. 解释:分析各特征对分类结果的影响

    • SELECT ... TO EXPLAIN语法,底层基于 SHAP 计算特征重要性

SQLFlow 让"用 SQL 完成机器学习建模"成为可能:数据预处理、模型训练、预测与解释全部以 SQL 语句的形式串联执行,模型与特征信息一并落库管理,非常适合数据团队在已有数据库基础设施上快速开展分类、回归等常规建模任务。

  • 人工智能
  • 机器学习
  • 后端
  • 编译器

【免费下载链接】sqlflow

Brings SQL and AI together.

项目地址:https://gitcode.com/gh_mirrors/sq/sqlflow
点击查看免费下载

相关推荐

上一篇:Jellium Desktop播放速度基础教程:掌握倍速播放的简单方法
下一篇:探索开源虚拟桌宠模拟器:如何打造个性化的桌面陪伴伙伴

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 7:43:39

Blend If + AI语义分割:素颜照秒变高定妆容的修图流水线

拿到一张光线还凑合但完全素颜的照片,能不能在一分钟内做出秀场后台那种高定妆容感?我试了很多偏方之后发现,最稳的答案其实是两个听着有年代感的东西:修图软件里的 Blend If 混合选项,加上一个能识别五官区域的 AI 模…

作者头像 李华
网站建设 2026/10/13 7:43:15

基于SSM的学生设计作品交流网站毕设实战指南

又到了毕业设计的高峰期,这两年被问得最多的课题类型之一,就是这种“某某学院某某系统/网站”的经典组合。好几个同学来问同一个题目:基于SSM的学生设计作品交流网站。这确实是个很典型的Java Web毕设选题,它覆盖了SSM框架的核心开…

作者头像 李华
网站建设 2026/10/13 7:42:32

非刚性图像配准源代码实战:从VoxelMorph训练到ONNX部署

简介:本资源是一套完整的非刚性图像配准开源实现,面向计算机视觉、医学影像分析方向的研究生、算法工程师及科研人员,聚焦解决跨模态、跨时相图像的像素级形变对齐问题,尤其适用于器官运动建模、肿瘤动态监测等临床研究场景。压缩…

作者头像 李华
网站建设 2026/10/13 7:41:54

二级注册计量师实务案例分析:六大场景串起计量工作链

二级注册计量师《专业实务与案例分析》这个系列写到第六篇,我反而觉得越往后越接近这门课的本质:它考的不是记忆,而是一条完整的计量工作链条。前面五篇我们把法律法规、测量数据处理、不确定度基础、计量标准的运行逻辑、比对和能力验证的底…

作者头像 李华
网站建设 2026/10/13 7:41:19

UNB3M三维重建工具实战:管线部署、参数调优与避坑指南

简介:这是一份基于C实现的UNB3M对流层延迟模型计算程序,面向GNSS精密定位、大地测量和气象学应用人员,主要解决天顶对流层延迟(ZTD)的快速估算问题。程序对应加拿大新不伦瑞克大学提出的UNB3M模型,利用多项…

作者头像 李华
网站建设 2026/10/13 7:41:17

鸿蒙UA适配:Flutter random_user_agents改造实践

接手鸿蒙设备适配时,我第一个碰到的硬骨头就是第三方 Flutter 库random_user_agents。这个库在 Android 和 iOS 上用得挺顺手,一换到鸿蒙系统就露馅了:应用里 WebView 打开页面时服务端能精准识别出这不是鸿蒙设备,接口返回的页面…

作者头像 李华