使用 DuckDB 进行基本特征工程

在这篇文章中,我们将展示如何直接在 DuckDB 中使用 SQL 来完成机器学习数据预处理中的关键任务,例如缺失值填补、类别编码以及特征缩放。这样的方式不仅简化了工作流程,还能充分利用 DuckDB 高性能的进程内执行引擎,实现快速高效的数据准备。

使用 DuckDB 进行基本特征工程

引言

数据预处理是任何机器学习流程中必不可少的一步,它既影响模型的有效性,也关系到后续维护的便利性。虽然 scikit-learn 因与更广泛的 Python 生态系统集成而被广泛应用于预处理,但 DuckDB 提供了一种切实可行的替代方案——允许在 Python 中通过 SQL 来进行数据转换。DuckDB 的声明式语法支持模块化工作流,使预处理步骤更容易拆解、检查和调试。此外,DuckDB 对列式数据格式的高效查询支持,以及将预处理逻辑持久化为 SQL 脚本的能力,都有助于构建更具可复现性和透明度的处理流程。

数据准备

我们将使用一个来自 Kaggle 的合成金融交易数据集,其中包含一些通用的金融交易信息,主要用于金融欺诈检测。

使用 DuckDB 进行基本特征工程

我们第一通过执行 SUMMARIZE 来分析数据。

使用 DuckDB 进行基本特征工程

特征编码

从上面的数据统计中可以看到,数据聚焦包含一些类别型字段,例如 transaction_type、merchant_category 和 payment_channel。由于大多数机器学习模型都需要数值型输入,这类数据需要被转换为数值表明。这个过程称为编码,可以通过多种方式实现。下面我们将展示几种常见的 SQL 编码方法。

在本文中,我们会使用 DuckDB 的一些“友善 SQL”特性,包括 FROM 优先语法前缀别名

独热编码(One-Hot Encoding)

当对某个类别字段应用独热编码时,每个不同的取值都会被转化为单独的一列;若该行匹配该取值,则该列取值为 1,否则为 0

使用 DuckDB 进行基本特征工程

另一种实现独热编码的方法是使用 PIVOT 语句:

使用 DuckDB 进行基本特征工程

在上述语句中,我们完成了以下操作:

  • 以类别字段 transaction_type 作为透视的依据;
  • 透视条件是 transaction_type 是否与其各个取值相匹配;
  • 将布尔值转换为整数,并在匹配结果上应用 max
  • 将转置后的列命名为对应的 transaction_type 值并加上后缀 _onehot。

如果有更多的类别字段需要进行独热编码,可以在 子查询WITH 子句 中使用 PIVOT

使用 DuckDB 进行基本特征工程

序数编码(Ordinal Encoding)

序数编码为每个类别取值分配一个唯一的标识符,一般在类别值之间存在某种顺序或层级关系时使用。

例如,我们可以通过 row_number 函数并按 transaction_type 排序来分配标识符:

使用 DuckDB 进行基本特征工程

标签编码(Label Encoding)

与序数编码类似,标签编码也为每个类别值分配一个唯一的标识符,但它不思考顺序。这种方法一般用于输出数据

使用 DuckDB 进行基本特征工程

另一种实现上述方法的方式是使用 列表函数,例如通过 array_agg 创建包含所有不同取值的数组,再利用 list_position 提取每个取值在数组中的位置:

使用 DuckDB 进行基本特征工程

特征缩放(Feature Scaling)

机器学习中另一个常见的数据预处理步骤是对数值型特征进行缩放,使得不同特征的数值处于类似的范围或分布。缩放,也称为特征归一化标准化,通过对特征进行变换,使它们具有可比的量级;一般方法包括将数值重新缩放到固定范围(如 0 到 1)或调整为零均值、单位方差。这个过程是必要的,由于许多算法依赖于距离计算或梯度更新,如果特征尺度差异过大,会导致结果偏差。

如果编码是在初始原始数据上进行的(需要知道整个类别取值列表),则缩放需要先将数据划分为训练集和测试集,以避免数据泄漏。在 DuckDB 中,我们可以通过采样的方式来划分数据:

使用 DuckDB 进行基本特征工程

标准缩放(Standard Scaling)

标准缩放是一种预处理技术,通过对数值型特征减去均值再除以标准差,将每个特征转换为均值为 0、标准差为 1 的分布。

例如,要对 velocity_score 进行标准缩放,我们可以执行:

使用 DuckDB 进行基本特征工程

最小-最大缩放(Min-Max Scaling)

最小-最大缩放是一种归一化技术,通过减去最小值并除以范围(最大值 − 最小值),将特征转换到固定范围,一般是 0 到 1。这样既保留了原始分布的形状,又确保所有特征在一样的尺度上。

为了对特征进行最小-最大缩放,我们可以在 scaling_params 宏中扩展,对输入列列表计算最小值和最大值:

使用 DuckDB 进行基本特征工程

然后我们为最小-最大计算定义一个宏定义:

使用 DuckDB 进行基本特征工程

最后,我们提取值:

使用 DuckDB 进行基本特征工程

稳健/鲁棒缩放(Robust Scaling)

稳健缩放是一种数据归一化技术,通过减去中位数并除以四分位距(IQR)来转换数值型特征。与使用均值和标准差的标准缩放不同,稳健缩放通过关注数据的中间 50% 来降低异常值的影响,因此超级适合分布偏斜或存在极端值的数据集。

在 DuckDB 中,我们可以使用 quantile_cont 统计聚合函数来计算分位数范围:

使用 DuckDB 进行基本特征工程

我们为鲁棒缩放计算定义标量宏:

使用 DuckDB 进行基本特征工程

并且,与其他缩放转换类似,我们直接在 SQL 中调用它:

使用 DuckDB 进行基本特征工程

处理缺失值(Handling Missing Values)

在实际数据处理中,输入数据往往存在不完整的情况,即包含缺失值。根据具体应用场景,这类数据可以被排除、直接使用,或者用一个常数填充。在 DuckDB 中,我们可以使用 coalesce 函数来获取列的值,如果列为 NULL,则返回默认值。

一些常用的缺失值处理方法包括:

  • 用常数替换缺失值;
  • 用平均值替换缺失值;
  • 用中位数替换缺失值。

我们可以通过在 scaling_params 宏中加入中位数计算来扩展处理方法:

使用 DuckDB 进行基本特征工程

我们根据用例应用合并来处理缺失值:

使用 DuckDB 进行基本特征工程

在特征缩放之前应该填充缺失数据。

在本文中,我们演示了 DuckDB 如何为机器学习工作流提供高性能且 SQL 原生的数据预处理方法。通过直接在数据库引擎内部处理缺失值插补、分类编码和特征缩放等任务,可以消除不必要的数据移动并减少预处理延迟。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
文哥的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容