- 人工智能
- 大模型
- 数据工程
- 数据清洗
- 数据增强
- 数据质检
【免费下载链接】data-juicer
Data processing for and with foundation models! 🍎 🍋 🌽 ➡️ ➡️🍸 🍹 🍷
本指南深入讲解 Data-Juicer 中的specified_numeric_field_filter过滤算子:如何根据样本中指定字段(支持点分隔的多级字段)的数值是否落在[min_value, max_value]区间内来决定样本去留,并完整还原官方文档中的参数表格与效果演示,结合仓库源码(算子实现、单元测试)剖析其两阶段执行原理、字符串数字兼容逻辑与边界行为,帮助读者在真实数据清洗流水线中正确配置和使用该算子。
算子概述与适用场景
specified_numeric_field_filter是 Data-Juicer 的filter(过滤)类算子,标签为cpu(无需 GPU,纯 CPU 逻辑执行)。它的核心能力是:
- 以样本中某个字段的数值为判据,仅保留数值落在给定闭区间
[min_value, max_value]内的样本; - 字段支持多级嵌套结构,各级键之间用点号
.分隔(例如meta.star、meta.key1.key2.count); - 若未提供
field_key,则保留所有样本; - 算子在进行比较前会先确保字段存在于样本中且其值可被解析为数值。
典型应用场景包括:按元数据(如文档评分meta.star、下载量、统计计数等)筛选语料、剔除数值异常或超出业务阈值的样本、对多级 JSON 结构中的深层数值字段做质量门槛控制等。
参数配置说明
官方文档给出的参数表如下,实际取值与源码签名(见 specified_numeric_field_filter.py)一致:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
field_key | str | '' | 参与过滤的目标键对应的数值字段;多级字段信息对应的目标键需要用.分隔 |
min_value | float | -9223372036854775807(即-sys.maxsize) | SpecifiedNumericField 算子的最小过滤值,指定数值字段低于该参数时样本将被过滤 |
max_value | float | 9223372036854775807(即sys.maxsize) | SpecifiedNumericField 算子的最大过滤值,指定数值字段超过该参数时样本将被过滤 |
args | — | '' | 额外参数 |
kwargs | — | '' | 额外参数 |
几点补充说明:
- 默认值取自 Python 的
sys.maxsize(约9.22e18),因此只设置min_value或只设置max_value的单侧过滤是常见用法:例如min_value=10表示只过滤掉数值小于 10 的样本,上界保持默认极大值; - 区间为闭区间:数值等于
min_value或max_value的样本会被保留; - 在完整配置模板 config_all.yaml 中,该算子给出的参考示例为
field_key: ''、min_value: 0、max_value: 10000,实际使用时应按业务数据替换; - 除上表参数外,算子还继承自
Filter基类,可透传诸如min_closed_interval、max_closed_interval、reversed_range等通用过滤参数(详见下文“底层实现原理”),它们通过kwargs接收。
底层实现原理
从源码结构看,该算子遵循 Data-Juicer 过滤算子的两阶段模式:先compute_stats计算统计量,再process依据统计量决定去留。
阶段一:compute_stats_single 提取字段值
def compute_stats_single(self, sample): # get the value from the original field field_value = sample for key in self.field_key.split("."): assert key in field_value.keys(), "'{}' not in {}".format(key, field_value.keys()) field_value = field_value[key] # copy it into the stats field if self.field_key not in sample[Fields.stats]: sample[Fields.stats][self.field_key] = field_value return sample关键点:
- 按点号切分
field_key后逐层下钻取值,因此天然支持任意深度的嵌套字典; - 若某层键不存在,会触发断言
'{}' not in {}报错,说明配置的field_key必须与样本实际结构严格对应; - 提取出的原始值被拷贝到样本的 stats 字段(
Fields.stats,定义于 constant.py,值为__dj__stats__)中,供下一阶段读取,实现统计与决策解耦。
阶段二:process_single 区间判定
def process_single(self, sample): if not self.field_key: return True field_value = sample[Fields.stats][self.field_key] if is_number(field_value): field_value = float(field_value) return self.get_keep_boolean(field_value, self.min_value, self.max_value) else: return False关键点:
field_key为空时直接返回True,即所有样本都被保留,与文档描述一致;- 取值后先经过模块级辅助函数
is_number校验:它尝试float(s)转换,成功返回True,否则返回False; - 非数值一律返回
False被过滤,包括None、无法解析为数字的字符串(如'asdkc')等; - 可解析为数字的值统一转为
float后交给基类方法get_keep_boolean判定。
基类区间判定:get_keep_boolean
最终比较逻辑位于 base_op.py:
def get_keep_boolean(self, val, min_val=None, max_val=None): res_bool = True if min_val is not None: res_bool = res_bool and (val >= min_val if self.min_closed_interval else val > min_val) if max_val is not None: res_bool = res_bool and (val <= max_val if self.max_closed_interval else val < max_val) if self.reversed_range: res_bool = not res_bool return res_bool基类还通过kwargs提供了三个通用调节项(base_op.py):
min_closed_interval(默认True):下界是否闭区间,为False时改为严格大于>;max_closed_interval(默认True):上界是否闭区间,为False时改为严格小于<;reversed_range(默认False):为True时整体取反,将保留区间翻转为(-∞, min_val) ∪ (max_val, +∞),即保留区间之外的样本。
也就是说,specified_numeric_field_filter默认是闭区间过滤,但可以通过继承自基类的这些通用参数扩展出开区间、反向过滤等变体行为。
效果演示:官方 test_case
官方文档给出的第一个示例构造如下(源码对应 test_case):
SpecifiedNumericFieldFilter(field_key='meta.star', min_value=10, max_value=70)输入数据
| Sample | text | meta.suffix | meta.star |
|---|---|---|---|
| 1 | Today is Sun | 50 | |
| 2 | a v s e c s f e f g a a a | .docx | 6 |
| 3 | 中文也是一个字算一个长度 | .txt | 100 |
| 4 | ,。、„”“«»1」「《》´∶:?! | .html | 12.51 |
| 5 | dasdasdasdasdasdasdasd | None | (无该字段) |
输出数据
| Sample | text | meta.suffix | meta.star |
|---|---|---|---|
| 1 | Today is Sun | 50 | |
| 4 | ,。、„”“«»1」「《》´∶:?! | .html | 12.51 |
解释:算子根据meta.star字段过滤样本,仅保留该字段值在 10 到 70(含端点)之间的样本。Sample 2(6)与 Sample 3(100)超出范围被移除;Sample 5 缺少meta.star字段、无数值可判,同样被过滤。范围外的样本被移除。注意 Sample 4 的12.51是浮点数,同样正常参与比较。
效果演示:官方 test_str_case(字符串数字)
官方文档给出的第二个示例验证了字段值为数字字符串时的行为(源码对应 test_str_case):
SpecifiedNumericFieldFilter(field_key='meta.star', min_value=10, max_value=70)输入数据
| Sample | text | meta.suffix | meta.star |
|---|---|---|---|
| 1 | Today is Sun | '36' | |
| 2 | a v s e c s f e f g a a a | .docx | '13.5' |
| 3 | 中文也是一个字算一个长度 | .txt | 'asdkc' |
| 4 | ,。、„”“«»1」「《》´∶:?! | .html | '441' |
| 5 | dasdasdasdasdasdasdasd | None | (无该字段) |
输出数据
| Sample | text | meta.suffix | meta.star |
|---|---|---|---|
| 1 | Today is Sun | '36' | |
| 2 | a v s e c s f e f g a a a | .docx | '13.5' |
解释:此案例说明当指定数值字段是数字的字符串表示时,算子同样能工作。'36'、'13.5'可被float解析并落入[10, 70]而被保留;'asdkc'无法解析为非数值字符串被过滤;'441'虽可解析但超出上界 70 被过滤;缺少字段的 Sample 5 被过滤。整个流程由is_number完成字符串校验、再由float()统一转数值后比较。
多级嵌套字段实战:test_multi_case
官方文档未单独展示、但单元测试中专门覆盖的多层字段场景(test_multi_case)是理解点分隔键的关键:
SpecifiedNumericFieldFilter(field_key='meta.key1.key2.count', min_value=10, max_value=70)输入样本中meta.key1.key2.count分别取值34、243、None、18,输出仅保留34与18两条。该用例验证了三件事:
- 点号分隔键可穿透任意层级的嵌套字典(
compute_stats_single中逐层split('.')下钻); None作为深层字段值会被判为非数值而过滤;- 同一样本中即使存在同名的其他字段(如顶层
count为101或None),也只以field_key指向的那条路径为准,各字段互不干扰。
在数据流水线中配置使用
YAML 配置方式
在 Data-Juicer 的 processing 配置文件中,将该算子加入process列表即可:
process: - specified_numeric_field_filter: field_key: 'meta.star' # 目标数值字段,多级用 '.' 分隔 min_value: 10 # 下界(含),低于该值的样本被过滤 max_value: 70 # 上界(含),高于该值的样本被过滤更完整的模板可参考 config_all.yaml 中给出的示例参数。
命令行运行
配置好 YAML 后,通过 Data-Juicer 的process_data.py工具执行:
python tools/process_data.py --config <your_config>.yaml代码直接调用
也可以在 Python 脚本中直接构造算子并作用于数据集(与单元测试 test_specified_numeric_field_filter.py 的执行模式一致):
from data_juicer.core.data import NestedDataset as Dataset from data_juicer.ops.filter.specified_numeric_field_filter import \ SpecifiedNumericFieldFilter from data_juicer.utils.constant import Fields ds_list = [{'text': 'Today is Sun', 'meta': {'star': 50}}, {'text': 'bad sample', 'meta': {'star': 6}}] dataset = Dataset.from_list(ds_list) # 补充 stats 列(过滤算子依赖该列存放中间统计量) if Fields.stats not in dataset.features: dataset = dataset.add_column(name=Fields.stats, column=[{}] * dataset.num_rows) op = SpecifiedNumericFieldFilter(field_key='meta.star', min_value=10, max_value=70) dataset = dataset.map(op.compute_stats) # 阶段一:提取并缓存字段值 dataset = dataset.filter(op.process) # 阶段二:按区间过滤 dataset = dataset.remove_columns(Fields.stats) # 清理中间统计列需要说明的是:常规流水线中上述map/filter调用由 Data-Juicer 的 executor 自动编排,用户只需在配置中声明算子;此处仅用于展示算子的两阶段调用契约。
边界情况与注意事项
- 字段缺失:
compute_stats_single会因断言失败而报错,因此field_key必须存在于所有样本中;若某些样本缺少该字段但希望保留,应先用其他算子补全或使用空field_key(保留全部样本); - 非数值值:
None、不可解析字符串等一律被过滤,这保证了区间比较永远发生在合法的float上; - 浮点精度:比较前统一
float()转换,整数、浮点数、数字字符串均可处理,但超大整数在转为float后可能引入精度损失,对精度敏感的字段需自行评估; - 闭区间语义:默认
min_value/max_value端点均含,需要开区间或反向保留时可利用基类透传的min_closed_interval、max_closed_interval、reversed_range参数(见 base_op.py); - 与
specified_field_filter的区分:仓库中还提供了按字段值精确匹配/多值集合保留的 specified_field_filter(参数为field_key+target_value列表),而本算子专用于数值区间过滤,二者配置方式不同,可按需选用。
相关资源
- 算子源代码:包含
is_number校验、两阶段实现与参数签名 - 单元测试:覆盖基础区间、多级嵌套、字符串数字三类场景
- 基类区间判定逻辑:
get_keep_boolean与区间开关参数 - 完整配置模板:流水线 YAML 中的参考写法
- 返回算子列表:查看全部 filter 类算子
- 人工智能
- 大模型
- 数据工程
- 数据清洗
- 数据增强
- 数据质检
【免费下载链接】data-juicer
Data processing for and with foundation models! 🍎 🍋 🌽 ➡️ ➡️🍸 🍹 🍷
相关推荐
data-juicer 指定字段过滤算子 SpecifiedFieldFilter 详解:按元数据字段值精准筛选样本
data juicer 指定字段过滤算子 SpecifiedFieldFilter 详解:按元数据字段值精准筛选样本 data juicer 是面向大模型的数据
人工智能大模型数据工程数据清洗数据增强数据质检data-juicer 停用词过滤算子 stopwords_filter 完全指南:原理、参数与实战
data juicer 停用词过滤算子 stopwords_filter 完全指南:原理、参数与实战 本文围绕 data juicer 的文本过滤算子 stop
人工智能大模型数据工程数据清洗数据增强数据质检Data-Juicer general_field_filter 通用字段过滤算子:表达式语法、AST 求值原理与实战配置
Data Juicer general_field_filter 通用字段过滤算子:表达式语法、AST 求值原理与实战配置 导读 general_field_f
人工智能大模型数据工程数据清洗数据增强数据质检
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考