Creates a TFF computation that aggregates metrics using secure summation.

The returned federated TFF computation has the following type signature:

(local_unfinalized_metrics@CLIENTS ->
 <aggregated_metrics@SERVER, secure_sum_measurements@SERVER)

where the input is given by tff.learning.models.VariableModel.report_local_unfinalized_metrics() at CLIENTS, and the first output (aggregated_metrics) is computed by first securely summing the unfinalized metrics from CLIENTS, followed by applying the finalizers at SERVER. The second output (secure_sum_measurements) is an OrderedDict that maps from factory_keys to the secure summation measurements (e.g. the number of clients gets clipped. See tff.aggregators.SecureSumFactory for details). A factory_key is uniquely defined by three scalars: lower bound, upper bound, and tensor dtype (denoted as datatype enum). Metric values of the same factory_key are grouped and aggegrated together (and hence, the secure_sum_measurements are also computed at a group level).

Since secure summation works in fixed-point arithmetic space, floating point numbers must be encoding using integer quantization. By default, each tensor in local_unfinalized_metrics_type will be clipped to [0, 2**20 - 1] and encoded to integers inside tff.aggregators.SecureSumFactory. Callers can change this range by setting metric_value_ranges, which may be a partial tree matching the structure of local_unfinalized_metrics_type.

Example partial value range specification:

finalizers = ...
metrics_type = tff.to_type(collections.OrderedDict(
    c=[tff.types.TensorType(tf.float32), tff.types.TensorType(tf.float32)])
value_ranges = collections.OrderedDict(
    b=(0.0, 1.0),
    c=[None, (0.0, 1.0)])
aggregator = tff.learning.metrics.secure_sum_then_finalize(
    finalizers, metrics_type, value_ranges)

This sets the range of the second tensor of b in the dictionary, using the range for the first tensor, and the a tensor.

metric_finalizers Either the result of tff.learning.models.VariableModel.metric_finalizers (an OrderedDict of callables) or the tff.learning.models.FunctionalModel.finalize_metrics method (a callable that takes an OrderedDict argument). If the former, the keys must be the same as the OrderedDict returned by tff.learning.models.VariableModel.report_local_unfinalized_metrics. If the later, the callable must compute over the same keyspace of the result returned by tff.learning.models.FunctionalModel.update_metrics_state.
local_unfinalized_metrics_type A tff.types.StructWithPythonType (with OrderedDict as the Python container) of a client's local unfinalized metrics. Let local_unfinalized_metrics be the output of tff.learning.models.VariableModel.report_local_unfinalized_metrics(). Its type can be obtained by tff.types.type_from_tensors(local_unfinalized_metrics).
metric_value_ranges A collections.OrderedDict that matches the structure of local_unfinalized_metrics_type (a value for each tff.types.TensorType in the type tree). Each leaf in the tree should have a 2-tuple that defines the range of expected values for that variable in the metric. If the entire structure is None, a default range of [0.0, 2.0**20 - 1] will be applied to all variables. Each leaf may also be None, which will also get the default range; allowing partial user sepcialization. At runtime, values that fall outside the ranges specified at the leaves, those values will be clipped to within the range.

A federated TFF computation that securely sums the unfinalized metrics from CLIENTS, and applies the correponding finalizers at SERVER.

TypeError If the inputs are of the wrong types.
ValueError If the keys (i.e., metric names) in metric_finalizers are not the same as those expected by local_unfinalized_metrics_type.