十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flower Datasets 与 PyTorch 集成指南:从 FederatedDataset 到 DataLoader 的完整实战

Flower Datasets 与 PyTorch 集成指南:从 FederatedDataset 到 DataLoader 的完整实战 Flower Datasets 与 PyTorch 集成指南从 FederatedDataset 到 DataLoader 的完整实战【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower本文讲解如何在 Flower 联邦学习框架中将flwr-datasetsFlower Datasets下载与划分好的联邦数据集无缝接入 PyTorch 的DataLoader并保留你惯用的 PyTorch Transform 流水线。读完本文你将掌握FederatedDataset的标准用法、特征名检查、with_transform与map两种数据转换方式、多种数据二次划分方案以及联邦训练循环中字典型 batch 的正确取数方式可直接用于联邦学习项目的客户端数据准备。前置准备安装与背景flwr-datasets是 Flower 生态中负责数据集下载与划分的库它基于 Hugging Face 的datasets实现因此天然支持 Hugging Face、PyTorch、TensorFlow、NumPy、Pandas、JAX、Arrow 等多种格式。在 PyTorch 场景下建议安装带视觉扩展的版本以便处理图像数据集python -m pip install flwr-datasets[vision]详细安装方式可参考 如何安装 flwr-datasets。本文的所有示例均以 CIFAR-10 为例但流程适用于 Hugging Face Hub 上的任意数据集。标准流程创建 FederatedDataset 并加载分区使用FederatedDataset完成下载数据集 按客户端划分 保留集中式评估集三件事是使用flwr-datasets的标准起点from flwr_datasets import FederatedDataset fds FederatedDataset(datasetcifar10, partitioners{train: 10}) partition fds.load_partition(0, train) centralized_dataset fds.load_split(test)逐行解读FederatedDataset(datasetcifar10, partitioners{train: 10})指定数据集名称为cifar10并将trainsplit 划分为 10 份IID 划分对应 10 个联邦客户端fds.load_partition(0, train)取出编号为 0 的客户端分区partition_id取值范围为0到num_partitions - 1用于本地训练fds.load_split(test)加载完整的testsplit不参与划分通常用于服务端的集中式评估。从源码federated_dataset.py可以看到FederatedDataset的完整构造参数还包括subset数据子集/版本、preprocessor重划分等预处理、shuffle默认True划分前随机打乱样本顺序、seed默认42控制打乱的随机性以及load_dataset_kwargs透传给datasets.load_dataset的额外参数如num_proc4、trust_remote_codeTrue。此外partitioners的值除了整数代表 IID 划分为多少份外也可以是Partitioner对象——例如用DirichletPartitioner模拟非独立同分布non-IID场景此时可传入num_partitions、partition_by、alpha等参数。值得注意的底层行为数据集的下载是**惰性lazy**的即只有在第一次调用load_partition或load_split时才真正触发datasets.load_dataset随后依次执行打乱shuffle、预处理preprocessor与分区分配见源码中的_prepare_dataset方法。这意味着你可以在创建FederatedDataset后立即返回给各个客户端由各客户端按需触发下载。确认特征名partition.featuresload_partition返回的是 Hugging Face 的Dataset对象数据以列feature组织。在写转换代码前务必先确认特征名——不同数据集的命名习惯不同可能是img或image、label或labelspartition.featuresCIFAR-10 的输出如下{img: Image(decodeTrue, idNone), label: ClassLabel(names[airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck], idNone)}即该数据集的特征名为img图像和label类别标签共 10 类。后续所有转换和取数都要用这两个 key。方式一with_transform 实时应用 PyTorch Transformdatasets.Dataset.with_transform()是推荐的第一种转换方式它最大的特点是**按需on-the-fly**执行你指定的转换只在你真正访问数据时才生效这与 PyTorch 生态中 Transform 的工作方式一致不会预先物化整个数据集。需要特别留意的是with_transform中的函数作用在批量batch数据上——即使你只取一个元素它也会被表示为一个大小为 1 的 batch。因此需要在函数内遍历该批次的每个样本并逐一应用转换from torch.utils.data import DataLoader from torchvision.transforms import ToTensor transforms ToTensor() def apply_transforms(batch): batch[img] [transforms(img) for img in batch[img]] return batch partition_torch partition.with_transform(apply_transforms) # 可选先通过 partition_torch[0] 检查转换是否有误 dataloader DataLoader(partition_torch, batch_size64)完成with_transform之后partition_torch直接就是一个符合 PyTorchDataset协议的datasets.Dataset可以直接交给torch.utils.data.DataLoader。建议在正式训练前先执行一次partition_torch[0]做冒烟测试确认转换逻辑没有书写错误。仓库中的 PyTorch 端到端测试pytorch_test.py完整验证了这条链路它使用FederatedDataset(datasetcifar10, partitioners{train: 100})加载分区后用with_transform应用ToTensor()或Compose([ToTensor(), Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])并断言DataLoader 产出的 batch 是dict类型、batch[img]是Tensor且形状为(batch_size, 3, 32, 32)同时用一轮训练验证 loss 不为 NaN/Inf。这说明分区 → 实时转换 → DataLoader → 训练的完整流程是被官方测试覆盖的可靠实践。方式二map 即时转换并配合 with_format(torch)如果你希望转换立即执行而不是访问时触发可以使用map()函数。它与with_transform/set_transform不同操作是即时完成的同时要注意map返回的字典中如果 key 已存在会就地修改该特征若 key 不存在则会新增一个特征。下面把数据集的img特征直接转换为 PyTorch Tensorfrom torch.utils.data import DataLoader from torchvision.transforms import ToTensor transforms ToTensor() partition_torch partition.map( lambda img: {img: transforms(img)}, input_columnsimg ).with_format(torch) dataloader DataLoader(partition_torch, batch_size64)这里map对每条样本执行{img: transforms(img)}使用input_columnsimg指定输入列随后调用.with_format(torch)让数据在访问时以 PyTorch Tensor 格式返回再交给DataLoader。两种方式如何取舍简单说with_transform是转换随取随用适合希望在训练循环里保留完整 PyTorch 语义、避免重复转换开销的场景map是转换立即落盘适合希望一次性完成预处理、后续只做格式切换的场景。对于小数据集两者性能差异很小可按个人习惯选择。为什么建议保留 ToTensor()官方文档特别建议保留ToTensor()尤其是你的 PyTorch 代码原本就使用它时原因在于它完成了通道维度的交换将形状从(H x W x C)变为(C x H x W)。这种通道在前的顺序正是带卷积层Conv2D的模型所期望的输入布局。跳过这一步直接喂入原始图像会因维度顺序不符而导致模型无法正确训练。数据二次划分训练/验证/测试子集联邦场景中经常需要把某个客户端的分区再拆成训练集、验证集、测试集。flwr-datasets提供了三种方案可在把数据集交给DataLoader之前的任意时刻使用。方案一Hugging Face 原生的 train_test_splitpartition_train_test partition.train_test_split(test_size0.2, seed42) partition_train partition_train_test[train] partition_test partition_train_test[test]这是最简方案按 80:20 拆分为训练与测试seed42保证可复现。缺点是一次只能拆成两份。方案二divide_dataset 按比例拆成多份如果你需要保持样本顺序不变并且要拆成 2 份或更多份可以使用flwr_datasets.utils中的divide_datasetfrom flwr_datasets.utils import divide_dataset train, valid, test divide_dataset(partition, [0.6, 0.2, 0.2])从实现utils.py来看divide_dataset按给定比例从数据集开头依次切分division可以是一个list/tuple如[0.6, 0.2, 0.2]返回list[Dataset]也可以是一个dict如{train: 0.6, valid: 0.2, test: 0.2}返回带名字的DatasetDict。源码中的校验逻辑要求每个比例必须大于 0 且小于等于 1各比例之和不能超过 1若总和小于 1会给出警告提示部分数据未被使用。方案三手动计算索引最简单的就是自己计算索引范围然后借助select切片partition_len len(partition) # 将 partition 按 80:20 拆分 num_train_examples int(0.8 * partition_len) # 使用前 80% partition_train partition.select(range(num_train_examples)) # 使用后 20% partition_test partition.select(range(num_train_examples, partition_len))这种方法自由度最高适合需要完全自定义划分边界的场景。训练循环字典型 batch 的取数方式最后训练循环里需要做一处关键调整。普通的 PyTorch DataLoader 每次迭代返回一个列表for batch in all_from_pytorch_dataloader: images, labels batch # 或者 # images, labels batch[0], batch[1]而flwr-datasets产出的数据集返回的是字典需要通过 key 而不是下标取数for batch in dataloader: images, labels batch[img], batch[label]在端到端测试pytorch_test.py中训练循环正是按此模式编写inputs, labels data[img].to(device), data[label].to(device)随后执行optimizer.zero_grad()、前向、loss.backward()与optimizer.step()与标准 PyTorch 训练完全兼容。完整示例联邦客户端数据准备 PyTorch 训练将上述要点串起来一个典型的客户端侧数据准备与训练代码结构如下from flwr_datasets import FederatedDataset from torch.utils.data import DataLoader from torchvision.transforms import ToTensor # 1. 下载并划分数据集10 个客户端test 用于集中式评估 fds FederatedDataset(datasetcifar10, partitioners{train: 10}) partition fds.load_partition(0, train) centralized_dataset fds.load_split(test) # 2. 确认特征名partition.features 输出 img / label # 3. 实时应用 Transform transforms ToTensor() def apply_transforms(batch): batch[img] [transforms(img) for img in batch[img]] return batch # 4.可选本地二次划分为 train / valid / test train, valid, test divide_dataset(partition, [0.8, 0.1, 0.1]) # 5. 构建 DataLoader trainloader DataLoader(train.with_transform(apply_transforms), batch_size64) # 6. 训练循环按 key 取数 for batch in trainloader: images, labels batch[img], batch[label] # 前向、反向、更新……这套流程可以与 Flower 联邦学习框架的客户端实现直接衔接每个客户端用自己的partition_id调用load_partition获取专属分区再经由上述转换与 DataLoader 封装后进入本地训练服务端则通过load_split(test)获取完整测试集进行集中式评估。相关的 NumPy 与 TensorFlow 集成方式可分别参考 如何与 NumPy 一起使用 与 如何与 TensorFlow 一起使用两篇文档共享同一套FederatedDataset加载逻辑仅在数据格式转换环节有所不同。【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表