整理决定了训练能看到什么。整理算法读取一个数据集版本,对每个任务片段做出决定:去掉太短或质量差的、平衡各个任务、留出一部分做验证。平台把这些决定变成一个新的数据集版本,源版本始终不动。
整理算法每个数据集版本运行一次。它读取 version,并通过 out(一个 SelectionWriter)写出 selection:
| 方法 | 作用 |
|---|---|
out.keep(episode_id, split=None, task=None) | 保留一个任务片段,可以指定划分(train、val、test)。task 文本目前会被拒绝。 |
out.drop(episode_id, reason) | 丢弃一个任务片段,必须写原因。 |
version.members 列出各个任务片段,以及它们的任务、划分、标签、质量、会话、采集者、时长和任务片段级特征;喜欢表格的话,version.to_pandas() 会给你每个成员一行。没有做决定的任务片段原样保留。
示例:丢弃过短的任务片段
这个算法丢弃短于下限的任务片段,保留其余的,并把每第 5 个保留下来的交给验证集。文件是 packages/sdk-python/examples/v1/curate-min-duration/main.py。
"""Curate: drop episodes shorter than a minimum, keep the rest and give every 5th one to validation.
In: the dataset version: its episodes, with their length and task.
Out: a decision for every episode: keep (train or val) or drop with a reason.
Why: curation decides what a training run sees; dropping short episodes and holding some out for
validation are the two decisions almost every dataset needs.
"""
from dataclasses import dataclass
from embodiflow import DatasetVersion, SelectionWriter, algorithm, param
@dataclass
class Params:
min_duration_s: float = param(2.0, minimum=0.0, title="Shortest episode to keep (s)")
val_every: int = param(5, minimum=0, title="Every n-th kept episode goes to validation (0 = none)")
@algorithm.curate(name="min-duration", title="Drop short episodes", params=Params)
def run(version: DatasetVersion, out: SelectionWriter, ctx) -> None:
kept = 0
for member in version.members:
if member.duration_s < ctx.params.min_duration_s:
out.drop(member.episode_id, f"shorter than {ctx.params.min_duration_s} s ({member.duration_s:.2f} s)")
continue
kept += 1
validation = ctx.params.val_every and kept % ctx.params.val_every == 0
out.keep(member.episode_id, split="val" if validation else "train")它的测试是 packages/sdk-python/examples/v1/curate-min-duration/test_main.py:用一份很小的测试数据,通过真实的运行器运行这段代码,并检查写出的值。想从它开始,运行 embodiflow algorithm init my-algorithm --category curate,它会写出 main.py 和 test_main.py;再运行 embodiflow algorithm test my-algorithm(需要装有 pytest 和 SDK 的 Python)。
在数据集版本上试跑
在编辑器的「试跑」里,选择「数据集版本」而不是录制。试跑默认读取前 3 个任务片段,最多 50 个,然后列出每个任务片段的决定和原因,以及保留和丢弃的数量。和所有试跑一样,不会保存任何内容。
值得知道
每个任务片段最多决定一次,每次丢弃都要写原因,否则结果会被 SELECTION_INVALID 拒绝。设置划分可以正常使用,但设置任务文本会被 CURATE_TASK_CHANGE_UNSUPPORTED 拒绝:版本里的每个任务片段都保持冻结时的样子。
所有任务片段都被丢弃时,不会创建版本(CURATE_NOTHING_KEPT)。如果保留下来的任务片段恰好已经组成了一个版本,就直接返回那个版本,不会重复创建。新版本的归一化统计量由平台重新计算,新版本也会关联源版本和这次运行。已脱敏处理的版本不能整理(CURATE_SOURCE_VERSION_UNUSABLE)。
成员的字段还没有全部填上。session、operator 和任务片段级 features 目前为空;成员的质量取其录制已保存结果中最差的一条,没有结果时为未评估。暂时不要依据它们做决定。
一个整理工作流可以有多个整理步骤。只有每个步骤都保留的任务片段才会被保留;最多一个步骤设置划分,最多一个步骤设置任务文本,否则工作流会被 CURATE_SELECTION_CONFLICT 拒绝。