def comp():
     value = intrinsics.federated_value(10, placements.CLIENTS)
     return intrinsics.federated_sum(value)
Ejemplo n.º 2
0
def _empty_state():
    return intrinsics.federated_value((), placements.SERVER)
Ejemplo n.º 3
0
 def test_init_state_not_assignable(self):
   float_initialize_fn = federated_computation.federated_computation()(
       lambda: intrinsics.federated_value(0.0, placements.SERVER))
   with self.assertRaises(errors.TemplateStateNotAssignableError):
     finalizers.FinalizerProcess(float_initialize_fn, test_next_fn)
Ejemplo n.º 4
0
def unsecure_aggregation():
    data_at_clients = intrinsics.federated_value(1, placements.CLIENTS)
    return intrinsics.federated_sum(data_at_clients)
Ejemplo n.º 5
0
 def stateless_broadcast(state, value):
     empty_metrics = intrinsics.federated_value((), placements.SERVER)
     return measured_process.MeasuredProcessOutput(
         state=state,
         result=intrinsics.federated_broadcast(value),
         measurements=empty_metrics)
Ejemplo n.º 6
0
def _test_init_fn():
    return intrinsics.federated_value(0, placements.SERVER)
Ejemplo n.º 7
0
def _test_evaluation_fn(state, client_data):
    del state, client_data  # Unused
    metrics = collections.OrderedDict([('metric', 2.0)])
    output = intrinsics.federated_value(metrics, placements.SERVER)
    return output
Ejemplo n.º 8
0
 def init_fn():
     # Empty/null state, nothing is tracked across invocations.
     return intrinsics.federated_value((), placements.SERVER)
 def float_next_fn(state, val):
   del state
   return MeasuredProcessOutput(
       intrinsics.federated_value(0.0, placements.SERVER),
       intrinsics.federated_sum(val), server_zero())
Ejemplo n.º 10
0
 def next_fn(state, datasets):
   del datasets  # Unused.
   return LearningProcessOutput(
       state, intrinsics.federated_value((), placements.SERVER))
Ejemplo n.º 11
0
 def init_fn():
   return intrinsics.federated_value(0, placements.CLIENTS)
Ejemplo n.º 12
0
 def next_fn(state, value):
   del value  # Unused.
   return LearningProcessOutput(
       state=state,
       metrics=intrinsics.federated_value(empty_tuple, placements.SERVER))
Ejemplo n.º 13
0
 def initialize_comp():
     return intrinsics.federated_value(0, placements.SERVER)
Ejemplo n.º 14
0
 def get_bounds(state):
   del state  # Unused.
   return (intrinsics.federated_value(upper_bound, placements.SERVER),
           intrinsics.federated_value(lower_bound, placements.SERVER))
 def next_fn(_, client_data):
     return one_round_computation(client_data), intrinsics.federated_value(
         (), placements.SERVER)
 def weighted_next_fn(state, value, weight):
   del weight
   return MeasuredProcessOutput(
       state, intrinsics.federated_sum(value),
       intrinsics.federated_value(1, placements.SERVER))
 def test_server_initialization():
   return intrinsics.federated_value(2.0, placements.SERVER)
def server_zero():
  """Returns zero integer placed at SERVER."""
  return intrinsics.federated_value(0, placements.SERVER)
Ejemplo n.º 19
0
def _test_next_fn(state, client_data):
    del state, client_data  # Unused
    updated_state = intrinsics.federated_value(1, placements.SERVER)
    metrics = collections.OrderedDict([('metric', 1.0)])
    output = intrinsics.federated_value(metrics, placements.SERVER)
    return updated_state, output
 def next_fn(state, val):
   return MeasuredProcessOutput(
       state, intrinsics.federated_sum(val),
       intrinsics.federated_value(1, placements.SERVER))
Ejemplo n.º 21
0
def secure_aggregation():
    data_at_clients = intrinsics.federated_value(1, placements.CLIENTS)
    bitwidth = 1
    return intrinsics.federated_secure_sum(data_at_clients, bitwidth)
Ejemplo n.º 22
0
 def stateless_mean(state, value, weight):
     empty_metrics = intrinsics.federated_value((), placements.SERVER)
     return measured_process.MeasuredProcessOutput(
         state=state,
         result=intrinsics.federated_mean(value, weight=weight),
         measurements=empty_metrics)
Ejemplo n.º 23
0
def _empty_server_initialization():
    return intrinsics.federated_value((), placements.SERVER)
Ejemplo n.º 24
0
def _normalize_secure_quantized_sum_args(client_value, lower_bound,
                                         upper_bound):
    """Normalizes inputs to `secure_quantized_sum` method.

  Validates the epxected structure of arguments, as documented in the docstring
  of `secure_quantized_sum` method. The arguments provided are also returned,
  possibly normalized to meet those expectations. In particular, if
  `lower_bound` and `upper_bound` are Python constants, these are converted to
  `tff.SERVER`-placed federated values.

  Args:
    client_value: A `tff.Value` placed at `tff.CLIENTS`.
    lower_bound: The smallest possible value for `client_value` (inclusive).
      Values smaller than this bound will be clipped. Must be either a scalar or
      a nested structure of scalars, matching the structure of `client_value`.
      Must be either a Python constant or a `tff.Value` placed at `tff.SERVER`,
      with dtype matching that of `client_value`.
    upper_bound: The largest possible value for `client_value` (inclusive).
      Values greater than this bound will be clipped. Must be either a scalar or
      a nested structure of scalars, matching the structure of `client_value`.
      Must be either a Python constant or a `tff.Value` placed at `tff.SERVER`,
      with dtype matching that of `client_value`.

  Returns:
    Normalized `(client_value, lower_bound, upper_bound)` tuple.
  """
    # Validation of client_value.
    _validate_value_on_clients(client_value)
    client_value_member = client_value.type_signature.member
    if client_value.type_signature.member.is_struct():
        dtypes = [v.dtype for v in structure.flatten(client_value_member)]
        for dtype in dtypes:
            _check_secure_quantized_sum_dtype(dtype)
    else:
        dtypes = client_value_member.dtype
        _check_secure_quantized_sum_dtype(dtypes)

    # Validation of bounds.
    if isinstance(lower_bound, value_impl.Value) != isinstance(
            upper_bound, value_impl.Value):
        raise BoundsDifferentTypesError(lower_bound, upper_bound)
    elif not isinstance(lower_bound, value_impl.Value):
        # Normalization of bounds to federated values.
        lower_bound = intrinsics.federated_value(lower_bound,
                                                 placements.SERVER)
        upper_bound = intrinsics.federated_value(upper_bound,
                                                 placements.SERVER)

    if lower_bound.type_signature != upper_bound.type_signature:
        raise BoundsDifferentSignaturesError(lower_bound, upper_bound)
    # The remaining type checks only use lower_bound as the upper_bound has
    # itendical type_signature.
    if lower_bound.type_signature.placement != placements.SERVER:
        raise BoundsNotPlacedAtServerError(
            lower_bound.type_signature.placement)

    # Validation of client_value and bounds compatibility.
    bound_member = lower_bound.type_signature.member
    if bound_member.is_struct():
        if not client_value_member.is_struct() or (structure.map_structure(
                lambda v: v.dtype, bound_member) != structure.map_structure(
                    lambda v: v.dtype, client_value_member)):
            raise StructuredBoundsTypeMismatchError(client_value_member,
                                                    bound_member)
    else:
        # If bounds are scalar, must be compatible with all tensors in client_value.
        if client_value_member.is_struct():
            if len(set(dtypes)) > 1 or (bound_member.dtype != dtypes[0]):
                raise ScalarBoundStructValueDTypeError(client_value_member,
                                                       bound_member)
        else:
            if bound_member.dtype != client_value_member.dtype:
                raise ScalarBoundSimpleValueDTypeError(client_value_member,
                                                       bound_member)

    return client_value, lower_bound, upper_bound
Ejemplo n.º 25
0
 def init_fn():
     return intrinsics.federated_value((), placements.SERVER)
Ejemplo n.º 26
0
def secure_quantized_sum(client_value, lower_bound, upper_bound):
    """Quantizes and sums values securely.

  Provided `client_value` can be either a Tensor or a nested structure of
  Tensors. If it is a nested structure, `lower_bound` and `upper_bound` must be
  either both scalars, or both have the same structure as `client_value`, with
  each element being a scalar, representing the bounds to be used for each
  corresponding Tensor in `client_value`.

  This method converts each Tensor in provided `client_value` to appropriate
  format and uses the `tff.federated_secure_sum_bitwidth` operator to realize
  the sum.

  The dtype of Tensors in provided `client_value` can be one of `[tf.int32,
  tf.int64, tf.float32, tf.float64]`.

  If the dtype of `client_value` is `tf.int32` or `tf.int64`, the summation is
  possibly exact, depending on `lower_bound` and `upper_bound`: In the case that
  `upper_bound - lower_bound < 2**32`, the summation will be exact. If it is
  not, `client_value` will be quantized to precision of 32 bits, so the worst
  case error introduced for the value of each client will be approximately
  `(upper_bound - lower_bound) / 2**32`. Deterministic rounding to nearest value
  is used in such cases.

  If the dtype of `client_value` is `tf.float32` or `tf.float64`, the summation
  is generally *not* accurate up to full floating point precision. Instead, the
  values are first clipped to the `[lower_bound, upper_bound]` range. These
  values are then uniformly quantized to 32 bit resolution, using deterministic
  rounding to round the values to the quantization points. Rounding happens
  roughly as follows (implementation is a bit more complex to mitigate numerical
  stability issues):

  ```
  values = tf.round(
      (client_value - lower_bound) * ((2**32 - 1) / (upper_bound - lower_bound))
  ```

  After summation, the inverse operation if performed, so the return value
  is of the same dtype as the input `client_value`.

  In terms of accuracy, it is safe to assume accuracy within 7-8 significant
  digits for `tf.float32` inputs, and 8-9 significant digits for `tf.float64`
  inputs, where the significant digits refer to precision relative to the range
  of the provided bounds. Thus, these bounds should not be set extremely wide.
  Accuracy losses arise due to (1) quantization within the given clipping range,
  (2) float precision of final outputs (e.g. `tf.float32` has 23 bits in its
  mantissa), and (3) precision losses that arise in doing math on `tf.float32`
  and `tf.float64` inputs.

  As a concrete example, if the range is `+/- 1000`, errors up to `1e-4` per
  element should be expected for `tf.float32` and up to `1e-5` for `tf.float64`.

  Args:
    client_value: A `tff.Value` placed at `tff.CLIENTS`.
    lower_bound: The smallest possible value for `client_value` (inclusive).
      Values smaller than this bound will be clipped. Must be either a scalar or
      a nested structure of scalars, matching the structure of `client_value`.
      Must be either a Python constant or a `tff.Value` placed at `tff.SERVER`,
      with dtype matching that of `client_value`.
    upper_bound: The largest possible value for `client_value` (inclusive).
      Values greater than this bound will be clipped. Must be either a scalar or
      a nested structure of scalars, matching the structure of `client_value`.
      Must be either a Python constant or a `tff.Value` placed at `tff.SERVER`,
      with dtype matching that of `client_value`.

  Returns:
    Summed `client_value` placed at `tff.SERVER`, of the same dtype as
    `client_value`.

  Raises:
    TypeError (or its subclasses): If input arguments do not satisfy the type
      constraints specified above.
  """

    # Possibly converts Python constants to federated values.
    client_value, lower_bound, upper_bound = _normalize_secure_quantized_sum_args(
        client_value, lower_bound, upper_bound)

    # This object is used during decoration of the `client_shift` method, and the
    # value stored in this mutable container is used during decoration of the
    # `server_shift` method. The reason for this is that we cannot currently get
    # the needed information out of `client_value.type_signature.member` as we
    # need both the `TensorType` information as well as the Python container
    # attached to them.
    temp_box = []

    # These tf_computations assume the inputs were already validated. In
    # particular, that lower_bnd and upper_bnd have the same structure, and if not
    # scalar, the structure matches the structure of value.
    @computations.tf_computation()
    def client_shift(value, lower_bnd, upper_bnd):
        assert not temp_box
        temp_box.append(tf.nest.map_structure(lambda v: v.dtype, value))
        fn = _client_tensor_shift_for_secure_sum
        if tf.is_tensor(lower_bnd):
            return tf.nest.map_structure(lambda v: fn(v, lower_bnd, upper_bnd),
                                         value)
        else:
            return tf.nest.map_structure(fn, value, lower_bnd, upper_bnd)

    @computations.tf_computation()
    def server_shift(value, lower_bnd, upper_bnd, summands):
        fn = _server_tensor_shift_for_secure_sum
        if tf.is_tensor(lower_bnd):
            return tf.nest.map_structure(
                lambda v, dtype: fn(summands, v, lower_bnd, upper_bnd, dtype),
                value, temp_box[0])
        else:
            return tf.nest.map_structure(lambda *args: fn(summands, *args),
                                         value, lower_bnd, upper_bnd,
                                         temp_box[0])

    client_one = intrinsics.federated_value(1, placements.CLIENTS)

    # Orchestration.
    client_lower_bound = intrinsics.federated_broadcast(lower_bound)
    client_upper_bound = intrinsics.federated_broadcast(upper_bound)

    value = intrinsics.federated_map(
        client_shift, (client_value, client_lower_bound, client_upper_bound))
    num_summands = intrinsics.federated_sum(client_one)

    secagg_value_type = value.type_signature.member
    assert secagg_value_type.is_tensor() or secagg_value_type.is_struct()
    if secagg_value_type.is_tensor():
        bitwidths = 32
    else:
        bitwidths = structure.map_structure(lambda t: 32, secagg_value_type)

    value = intrinsics.federated_secure_sum_bitwidth(value, bitwidth=bitwidths)
    value = intrinsics.federated_map(
        server_shift, (value, lower_bound, upper_bound, num_summands))
    return value
Ejemplo n.º 27
0
 def init_fn():
     return intrinsics.federated_value(
         collections.OrderedDict(num_clients=0), placements.SERVER)
Ejemplo n.º 28
0
 def empty_initialize_fn():
     return intrinsics.federated_value((), placements.SERVER)
Ejemplo n.º 29
0
 def float_next_fn(state, weights, update):
   del state
   return MeasuredProcessOutput(
       intrinsics.federated_value(0.0, placements.SERVER),
       test_finalizer_result(weights, update),
       intrinsics.federated_value(1, placements.SERVER))
 def comp():
     return intrinsics.federated_zip(
         collections.OrderedDict([
             ('A', intrinsics.federated_value(10, placements.CLIENTS)),
             ('B', intrinsics.federated_value(20, placements.CLIENTS)),
         ]))