BasicAI 标注数据质检实现方案

BasicAI 标注数据质检实现方案

BasicAI 是全球首个开源多模态训练数据平台,通过提供 AI 赋能的软件工具、数万项目提炼的本体中心和丰富的数据治理特性,来加速多模态训练数据的处理效率,进而提高 AI 工程师的建模效率。

业务背景

在现今 AI 大模型流行的时代,大部分算法都是开源的,用于训练模型的标注数据的质量变得尤为重要。要想得到高质量的人工标注数据,需要对标注数据进行全方位质检,比如检查标注对象属性是否缺失、标注对象大小是否满足需求、标注对象重叠程度等。标注对象数据量非常大,一个包含 100 万个 Data 的数据集,假设每个 Data 标注出 30 个对象,那么就会产生 3000 万个对象,对于拥有成千上万数据集的 BasicAI SaaS,很容易就会达到百亿,甚至千亿级别。要对这么大的数据量进行分析,只能求助于大数据系统,然而传统的基于 Hadoop 生态的大数据系统过于复杂,不适合小团队和简单业务场景,经过调研分析,最终我们选择了 Doris 这款 OLAP 分析型数据库,主要基于以下原因:

简单

使用简单:Doris 兼容 MySQL 协议,支持标准 SQL,上手门槛低。Doris 的 ETL 编写脚本主要使用 SQL 进行开发,使用 MySQL 协议登陆使用,兼容多数 MySQL 语法,提供了丰富的数据分析函数,省去了许多 UDF 开发工作。

架构简单:Doris 组件只包含 FE 和 BE 两类进程,不依赖其它系统,升级扩容非常方便,故障排查链路很清晰,有利于降低运维成本。

高性能

依托于列式存储引擎、自动分区分桶、向量计算、多方面 Join 优化和物化视图等功能,Doris 可以覆盖众多场景的查询需求,海量数据查询也能保证低延迟,实现秒级或分钟级响应。

低成本

Doris 免费开源,其简洁的架构、协议的兼容、丰富的生态都能够为使用者节省不少资源和人力投入。

社区活跃

Doris 已开源数年,超千家企业在使用,社区也非常活跃,使用起来没有后顾之忧。

Doris 介绍

不同于 MySQL、TiDB 这样的面向小批量频繁读写的事务型数据库(OLTP),Doris 适用于需要大批量读写数据,并且读多写少的分析型场景(OLAP)。两者设计理念相左,一个采用行式存储,一个采用列式存储,虽然说 Doris 也使用 MySQL 协议,但其使用方式更接近于数据仓库,许多公司都将其用于构建实时数仓。

查询 & 分析

  1. 查询时指定尽可能多的前缀 Key 列来利用前缀索引;
  2. 不能用到前缀索引时可为条件列创建倒排索引(2.0 支持)或 BloomFilter 索引;
  3. 只读取需要的列而不是读取整行,如果确实需要高并发整行读取可对表开启行存(2.0 支持),以空间换时间;

插入 & 更新 & 删除

  1. 只有 Unique 模型才支持更新和删除;
  2. 避免使用 Delete 语句来删除数据;
  3. 使用 Stream LoadBroker LoadRoutine Load 来批量删除数据,也可以用于追加数据,或者两者同时进行;
  4. 不推荐使用 Update 语句来更新数据,尤其是查询条件里使用 Value 列;
  5. 避免并发执行 DeleteUpdate 等 DML 语句,否则可能会出现脏数据;

技术方案

为了加速针对整个数据集或任务的全量质检,将预先计算好每个标注对象的各项指标(缺失属性数、最近距离、最远距离等),质检时基于这些指标来快速完成计算,同时还能够在多次质检之间复用大量中间计算结果。考虑到影响指标结果的源数据种类很多并且更新频繁,指标难以做到实时更新且保持口径统一,定期全量计算的代价又非常大,所以需要用户自行判断是否及何时更新指标库,比如选择在团队休息时间段进行。由于指标很难做到实时更新,因此无法用于工具里针对单个数据的实时质检,实时质检需要在应用内实时计算,前端工具提交结果的同时把相关指标预计算好,以便加速服务端计算。考虑到数据导入场景,服务端需要实现所有指标计算(不能依赖前端工具),其中涉及到边框、位置、大小等信息的交由算法完成(最近距离、最远距离、是否重叠等),其余的由应用负责(属性缺失数量等)。算法服务以 Sidecar 形式集成到应用服务 Pod 中,这样可以通过本地网络调用和文件共享来提升调用性能。

库表设计

标注对象表

保存所有标注对象(包括实例和分割)的详情,可用于对象检索。

表名:annotation_object

模型:Unique(写时合并)

分区:以 Dataset 创建时间按月分区

分桶:按 Data ID Hash 分桶,单桶大小控制在 1GB ~ 10GB,可基于历史分区来决定当前分区的桶数

列名
类型
聚合类型
评论
dataset_id
INT

数据集 ID,用于分桶
dateset_create_date
DATEV2

数据集创建日期,用于分区
source_type
TINYINT

来源类型,0 数据集,1 任务
source_id
INT

来源 ID,对于数据集为来源 ID,对于任务为任务 ID
data_id
BIGINT

数据 ID
track_id
VARCHAR

追踪对象 ID,只对实例对象有用
object_id
CHAR(36)

对象 ID
track_name
VARCHAR
NONE
追踪对象名
annotation_type

VARCHAR

NONE

标注类型,INSTANCE 实例标注,SEGMENTATION 分割标注
object_type
VARCHAR
NONE
对象类型,比如 3D_BOX
class_id
INT
NONE
分类 ID
class_name
VARCHAR
NONE
分类名
class_values
JSONB
NONE
分类属性值
instance_contour
JSONB
NONE
实例对象轮廓信息
segment_device_name
VARCHAR
NONE
分割对象设备名
segment_no
SMALLINT
NONE
分割对象编号
create_at
DATATIMEV2
NONE
创建时间
  1. 如果需要按追踪对象粒度聚合,可使用 Group By,通过 ANY_VALUE 函数从多个值中任意取一个;

标注对象指标表

保存所有标注对象(包括实例和分割)的指标,比如用于质检。

表名:annotation_object_index

模型:Unique(写时合并)

分区:以 Dataset 创建时间按月分区

分桶:按 Data ID Hash 分桶,单桶大小控制在 1GB ~ 10GB,可基于历史分区来决定当前分区的桶数

列名
类型
聚合类型
评论
dataset_id
INT

数据集 ID,用于分桶
dateset_create_date
DATEV2

数据集创建日期,用于分区
source_type
TINYINT

来源类型,0 数据集,1 任务
source_id
INT

来源 ID,对于数据集为来源 ID,对于任务为任务 ID
data_id
BIGINT

数据 ID
track_id
VARCHAR

追踪对象 ID,只对实例对象有用
object_id
CHAR(36)

对象 ID
annotation_type

VARCHAR

NONE
标注类型,INSTANCE 实例标注,SEGMENTATION 分割标注
object_type
VARCHAR
NONE
对象类型,比如 3D_BOX
class_attr_missing_count
SMALLINT
NONE
分类属性缺失计数
class_attr_required_missing_count
SMALLINT
NONE
分类必需属性缺失计数
min_distance

FLOAT

NONE

XY 平面上距离原点的最近距离,只对点云标注有用,对于实例标注只考虑关键点,对于分割标注需考虑所有点
max_distance
FLOAT
NONE
XY 平面上距离原点的最远距离
min_height

FLOAT

NONE
Z 轴上的最低高度,只对点云标注有用,对于实例标注只考虑关键点,对于分割标注需考虑所有点
max_height
FLOAT
NONE
Z 轴上的最高高度
is_overlapped
BOOLEAN
NONE
是否跟其它对象重叠
is_match_fixed_size_constraint
BOOLEAN
NONE
是否符合固定大小限制
is_match_ontology_constraint
BOOLEAN
NONE
是否符合本体约束
create_at
DATATIMEV2
NONE
创建时间

标注对象质检结果表

记录违反每条质检规则的标注对象。

表名:annotation_object_qa_result

模型:Unique(写时合并)

分区:以 Dataset 创建时间按月分区

分桶:按 Data ID Hash 分桶,单桶大小控制在 1GB ~ 10GB,可基于历史分区来决定当前分区的桶数

列名
类型
聚合类型
评论
dataset_id
INT

数据集 ID
dateset_create_date
DATEV2

数据集创建日期,用于分区
job_type
TINYINT

任务类型,0 数据集,1 任务
job_id
INT

任务 ID,对于数据集为 Job ID,对于任务为任务 ID
violation_rule_id
INT

违反规则 ID
data_id
BIGINT

数据 ID
track_id
VARCHAR

追踪对象 ID,只对实例对象有用
object_id
CHAR(36)

对象 ID
create_at
DATATIMEV2
NONE
创建时间

以数据为粒度上卷

列名
dataset_id
job_type
job_id
data_id