如何在TensorFlow联合SGD中操纵客户端梯度

问题描述

我正在关注this tutorial,以开始使用tensorflow联合。我的目标是在将客户端梯度值发送到服务器之前对其进行一些操作来运行联邦sgd(而非联邦avg)。

在继续操作之前,为简要地重申联邦sgd流程,客户端每转一圈,客户端会将其计算出的梯度(未更新的权重)发送到服务器,服务器将其汇总并向客户端广播更新的模型。

现在,到目前为止,我可以使用上述教程中的函数build_federated_sgd_process代替build_federated_averaging_process来以上述方式执行联合sgd。

我迷路的地方是,在将渐变发送到服务器之前,我需要裁剪客户端渐变并为其添加一些噪音(针对每个渐变值独立生成),我不确定该怎么做。生成噪声足够简单,但是我应该修改/实现哪个函数才能将噪声应用于梯度?

解决方法

build_federated_sgd_process已完全罐装;它实际上是设计为参考实现,而不是可扩展性。

我相信您正在寻找的是build_federated_sgd_process在“ tff.learning.framework.build_model_delta_optimizer_process”下调用的函数。此函数使您可以提供自己的从模型函数(即,一个可返回tff.learning.Model的零参数可调用对象,返回tff.learning.framework.ClientDeltaFn)的映射。

您的ClientDeltaFn类似于:

@tf.function
def _clip_and_noise(grads):
  return ...

class ClippedGradClientDeltaFn(tff.learning.framework.ClientDeltaFn)

def __init__(self,model,...):
  self._model = model
  ...

@tf.function
def __call__(dataset,weights):
  # Compute gradients grads
  return _clip_and_noise(grads)

您将可以通过调用以下命令来构建tff.templates.IterativeProcess

def clipped_sgd(model_fn: Callable[[],model_lib.Model]) -> ClippedGradClientDeltaFn:
    return ClippedGradClientDeltaFn(
        model_fn(),...)

iterproc = optimizer_utils.build_model_delta_optimizer_process(
      model_fn,model_to_client_delta_fn=clipped_sgd,...)

build_federated_sgd_process的正文中或多或少。

在我看来,您对差异化隐私感兴趣;实际上,TFF的设计通常是通过聚合过程而不是编写不同的客户端更新来实现差异性隐私,尽管这当然是一种方法。请参见TFF for research documentation的指针,以了解将差异隐私连接到TFF的惯用方法。