当我们对联合训练数据调用 IterativeProcess.next 时到底发生了什么?

What exactly happens when we call IterativeProcess.next on federated training data?

我完成了联邦学习教程。当我们在迭代过程中调用它时,我想知道 .next 函数是如何工作的。 假设我们有火车数据,这是一个列表列表。外部列表是客户端列表,内部列表是每个客户端的批量数据。然后,我们创建一个迭代过程,例如联合平均过程,并初始化状态。 当我们对该训练数据调用 IterativeProcess.next 时究竟发生了什么。每一轮都是从这些数据中随机取的吗?还是一次只从每个客户端获取一批数据?

假设我有一个 tf.data.Datasets 列表,每个列表代表一个客户端数据。如何为下一次联合学习迭代从该列表中抽样添加一些随机性?

我的数据集长度不一定相同。当其中一个完全迭代时,这个数据集是否等待所有其他数据集完全迭代它们的数据?

任何 tff.Computation(如 next)将始终 运行 整个 指定的计算。例如,如果您的 tff.templates.IterativeProcesstff.learning.build_federated_averaging_process 的结果,则其 next 函数将代表一轮联合平均算法。

联合平均算法 运行s 在每个本地数据集上训练固定数量的 epochs(为简单起见假设为 1),并对模型更新进行平均服务器上的数据加权方式以完成一轮——请参阅 Algorithm 1 in the original federated averaging paper 了解算法规范。

现在,关于 TFF 如何表示和执行该算法。从 build_federated_averaging_process 的文档中,next 函数具有类型签名:

(<S@SERVER, {B*}@CLIENTS> -> <S@SERVER, T@SERVER>)

TFF的类型系统将一个数据集表示为一个tff.SequenceType(这是上面*的意思),所以类型签名的参数中的第二个元素表示一个集合(技术上是一个multiset) 具有 B 类型元素的数据集,放置在客户端。

这在您的示例中的含义如下。您有一个 tf.data.Datasets 列表,每个列表代表每个客户端上的本地数据——您可以认为该列表代表联合放置。在这种情况下,TFF 执行整个指定的计算意味着:TFF 会将列表中的每个项目视为要在这一轮中进行训练的客户端。根据上面链接的算法,您的数据集列表表示集合 S_t.

TFF 将忠实地执行一轮联合平均算法,列表中的 Dataset 元素代表为这一轮 select 编辑的客户。每个客户端的单个时期的训练将是 运行(并行);如果数据集有不同数量的数据,那么你是正确的,每个客户端的训练很可能在不同的时间完成。然而,这是单轮联合平均算法的正确语义,与 Reptile 等类似算法的参数化相反,运行 用于每个客户端的固定步数。

如果您希望 select 一部分客户进行 运行 一轮训练,这应该在 Python 中完成,在调用 TFF 之前,例如:

state = iterative_process.initialize()

# ls is list of datasets
sampled_clients = random.sample(ls, N_CLIENTS)

state = iterative_process.next(state, sampled_clients)

通常,您可以将 Python 运行 时间视为“实验驱动程序”层——例如,任何 select 客户端都应该发生在这一层.有关详细信息,请参阅 this answer 的开头。

每一轮(迭代过程)是否随机取这些数据?还是一次只从每个客户端获取一批数据?

TFF 教程全部使用 tff.learning.build_federated_averaging_process which constructs a tff.templates.IterativeProcess that implements the Federated Averaging algorithm (McMahan et al. 2017). In this algorithm each "round" (one invocation of IterativePocess.next()) processes as many batches of examples on each client as the tf.data.Dataset is setup to produce in one iteration. tf.data: Build TensorFlow input pipelinestf.data.Dataset 的绝佳指南。

处理示例的顺序取决于 tf.data.Datasets that were passed into the next() method as arguments were constructed. For example, in the Federated Learning for Text Generation tutorial's section titled Load and Preprocess the Federated Shakespeare Data 每个客户端数据集是如何设置预处理管道的:

def preprocess(dataset):
  return (
      # Map ASCII chars to int64 indexes using the vocab
      dataset.map(to_ids)
      # Split into individual chars
      .unbatch()
      # Form example sequences of SEQ_LENGTH +1
      .batch(SEQ_LENGTH + 1, drop_remainder=True)
      # Shuffle and form minibatches
      .shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)
      # And finally split into (input, target) tuples,
      # each of length SEQ_LENGTH.
      .map(split_input_target))

下一个函数将在每次调用 next() 时完整地迭代这些数据集,在这种情况下,由于没有调用 tf.data.Dataset.repeat()next() 将让每个客户端一次查看其所有示例。

假设我有一个 tf.data.Datasets 列表,每个列表代表一个客户端数据。我怎样才能为联邦学习的下一次迭代从这个列表中抽样添加一些随机性?

要为每个客户的数据集添加随机性,可以使用 tf.data.Dataset.shuffle() to first randomize the order of yielded examples, and then tf.data.Dataset.take() 仅获取新随机排序的样本。这可以添加到上面的 preprocess() 方法中。

或者,客户选择的随机性(例如,随机选择每轮参与的客户)可以使用任何 Python 库对列表进行子抽样来完成数据集,例如Python 的 random.sample.

我的数据集长度不一定相同。当其中一个完全迭代时,这个数据集是否等待所有其他数据集完全迭代它们的数据?

每个数据集在每次调用 .next() 时仅迭代一次。这符合 McMahan et al. 2017 中的同步通信“回合”。从某种意义上说,是的,数据集相互“等待”。