def test_federated_mean_masked(self): value_type = tff.StructType([('a', tff.TensorType(tf.float32, shape=[3])), ('b', tff.TensorType(tf.float32, shape=[2, 1]))]) weight_type = tff.TensorType(tf.float32) federated_mean_masked_fn = fed_pa_schedule.build_federated_mean_masked( value_type, weight_type) # Check type signature. expected_type = tff.FunctionType( parameter=collections.OrderedDict( value=tff.FederatedType(value_type, tff.CLIENTS), weight=tff.FederatedType(weight_type, tff.CLIENTS)), result=tff.FederatedType(value_type, tff.SERVER)) self.assertTrue( federated_mean_masked_fn.type_signature.is_equivalent_to(expected_type), msg='{s}\n!={t}'.format( s=federated_mean_masked_fn.type_signature, t=expected_type)) # Check correctness of zero masking in the mean. values = [ collections.OrderedDict( a=tf.constant([0.0, 1.0, 1.0]), b=tf.constant([[1.0], [2.0]])), collections.OrderedDict( a=tf.constant([1.0, 3.0, 0.0]), b=tf.constant([[3.0], [0.0]])) ] weights = [tf.constant(1.0), tf.constant(3.0)] output = federated_mean_masked_fn(values, weights) expected_output = collections.OrderedDict( a=tf.constant([1.0, 2.5, 1.0]), b=tf.constant([[2.5], [2.0]])) self.assertAllClose(output, expected_output)
def test_clip_by_global_norm(self): clip_norm = 20.0 aggregate_fn = aggregate_fns.build_clip_norm_aggregate_fn(clip_norm) # Global l2 norms [17.74824, 53.99074]. deltas = [create_weights_delta(), create_weights_delta(constant=10)] deltas_type = tff.framework.type_from_tensors(deltas[0]) weights = [1., 1.] @tff.federated_computation(tff.FederatedType(deltas_type, tff.CLIENTS), tff.FederatedType(tf.float32, tff.CLIENTS)) def federated_aggregate_test(deltas, weights): state = tff.federated_value(aggregate_fn.initialize(), tff.SERVER) return aggregate_fn(state, deltas, weights) federated_aggregate_test.type_signature.result.check_equivalent_to( tff.StructType(( tff.FederatedType( aggregate_fns.ClipNormAggregateState(clip_norm=tf.float32, max_norm=tf.float32), tff.SERVER), tff.FederatedType(deltas_type, tff.SERVER), ))) state, mean = federated_aggregate_test(deltas, weights) expected_clipped = [] for delta in deltas: flat = tf.nest.flatten(delta) clipped, _ = tf.clip_by_global_norm(flat, clip_norm) expected_clipped.append(tf.nest.pack_sequence_as(delta, clipped)) expected_mean = tf.nest.map_structure(lambda a, b: (a + b) / 2, *expected_clipped) self.assertEqual(state.clip_norm, tf.constant(20.0, tf.float32)) self.assertEqual(state.max_norm, tf.constant(53.99074, tf.float32)) tf.nest.map_structure(self.assertAllEqual, expected_mean, mean)
async def _decrypt_values_on_singleton(self, val, sender, receiver): ### Check proper key placement pk_sender = self.key_references.get_public_key(sender) sk_receiver = self.key_references.get_secret_key(receiver) type_analysis.check_federated_type(pk_sender.type_signature, placement=receiver) type_analysis.check_federated_type(sk_receiver.type_signature, placement=receiver) pk_snd_type = pk_sender.type_signature.member sk_rcv_type = sk_receiver.type_signature.member ### Check placement cardinalities snd_children = self.strategy._get_child_executors(sender) rcv_children = self.strategy._get_child_executors(receiver) py_typecheck.check_len(rcv_children, 1) rcv_child = rcv_children[0] ### Check value cardinalities py_typecheck.check_len(pk_sender.internal_representation, len(snd_children)) py_typecheck.check_len(sk_receiver.internal_representation, 1) ### Materialize decryptor type_spec & function definition py_typecheck.check_type(val.type_signature, tff.StructType) type_analysis.check_federated_type(val.type_signature[0], placement=receiver, all_equal=True) input_type = val.type_signature[0].member # each input_type is a tuple needed for one value to be decrypted py_typecheck.check_type(input_type, tff.StructType) py_typecheck.check_type(pk_snd_type, tff.StructType) py_typecheck.check_len(val.type_signature, len(pk_snd_type)) input_element_type = input_type pk_element_type = pk_snd_type[0] decryptor_arg_spec = (input_element_type, pk_element_type, sk_rcv_type) decryptor_proto, decryptor_type = utils.materialize_computation_from_cache( sodium_comp.make_decryptor, self._decryptor_cache, decryptor_arg_spec, orig_tensor_dtype=self._input_type_cache.dtype) ### Decrypt values and return them vals = val.internal_representation sk = sk_receiver.internal_representation[0] decryptor_fn = await rcv_child.create_value(decryptor_proto, decryptor_type) decryptor_args = await asyncio.gather(*[ rcv_child.create_struct([v, pk, sk]) for v, pk in zip(vals, pk_sender.internal_representation) ]) decrypted_values = await asyncio.gather(*[ rcv_child.create_call(decryptor_fn, arg) for arg in decryptor_args ]) decrypted_value_types = [decryptor_type.result] * len(decrypted_values) return federated_resolving_strategy.FederatedResolvingStrategyValue( structure.from_container(decrypted_values), tff.StructType([ tff.FederatedType(dvt, receiver, all_equal=True) for dvt in decrypted_value_types ]))
async def _compute_paillier_sum( self, encryption_key: federated_resolving_strategy. FederatedResolvingStrategyValue, values: federated_resolving_strategy. FederatedResolvingStrategyValue): paillier_child = self._get_child_executors( paillier_placement.AGGREGATOR, index=0) sum_proto, sum_type = utils.lift_to_computation_spec( self._paillier_sequence_sum, input_arg_type=tff.StructType( (encryption_key.type_signature.member, tff.StructType([vt.member for vt in values.type_signature])))) sum_fn = paillier_child.create_value(sum_proto, sum_type) sum_arg = paillier_child.create_struct( (encryption_key.internal_representation, await paillier_child.create_struct(values.internal_representation))) sum_fn, sum_arg = await asyncio.gather(sum_fn, sum_arg) encrypted_sum = await paillier_child.create_call(sum_fn, sum_arg) return federated_resolving_strategy.FederatedResolvingStrategyValue( encrypted_sum, tff.FederatedType(sum_type.result, paillier_placement.AGGREGATOR, True))
def test_build_with_preprocess_function(self): test_dataset = tf.data.Dataset.range(5) client_datasets_type = tff.FederatedType( tff.SequenceType(test_dataset.element_spec), tff.CLIENTS) @tff.tf_computation(tff.SequenceType(test_dataset.element_spec)) def preprocess_dataset(ds): def to_batch(x): return _Batch( tf.fill(dims=(784,), value=float(x) * 2.0), tf.expand_dims(tf.cast(x + 1, dtype=tf.int64), axis=0)) return ds.map(to_batch).batch(2) iterproc = _build_simple_fed_pa_process( _uncompiled_model_builder, client_optimizer_fn=tf.keras.optimizers.SGD, server_optimizer_fn=tf.keras.optimizers.SGD) iterproc = tff.simulation.compose_dataset_computation_with_iterative_process( preprocess_dataset, iterproc) with tf.Graph().as_default(): test_model_for_types = _uncompiled_model_builder() server_state_type = tff.FederatedType( fed_pa_schedule.ServerState( model=tff.framework.type_from_tensors( tff.learning.ModelWeights( test_model_for_types.trainable_variables, test_model_for_types.non_trainable_variables)), optimizer_state=(tf.int64,), round_num=tf.float32), tff.SERVER) metrics_type = tff.FederatedType( tff.StructType([('loss', tf.float32), ('model_delta_zeros_percent', tf.float32), ('model_delta_correction_l2_norm', tf.float32)]), tff.SERVER) expected_parameter_type = collections.OrderedDict( server_state=server_state_type, federated_dataset=client_datasets_type, ) expected_result_type = (server_state_type, metrics_type) expected_type = tff.FunctionType( parameter=expected_parameter_type, result=expected_result_type) self.assertTrue( iterproc.next.type_signature.is_equivalent_to(expected_type), msg='{s}\n!={t}'.format( s=iterproc.next.type_signature, t=expected_type))
async def transfer(self, value): _check_value_placement(value, self.placements) sender_placement = value.type_signature.placement receiver_placement = _get_other_placement(sender_placement, self.placements) sent = await self.send(value, sender_placement, receiver_placement) rcv_children = self.strategy._get_child_executors(receiver_placement) message = await sent.compute() message_type = type_conversions.infer_type(message) if receiver_placement is tff.CLIENTS: if isinstance(message_type, tff.StructType): iterator = zip(rcv_children, message, message_type) member_type = message_type[0] all_equal = False else: iterator = zip(rcv_children, itertools.repeat(message), itertools.repeat(message_type)) member_type = message_type all_equal = True message_value = federated_resolving_strategy.FederatedResolvingStrategyValue( await asyncio.gather(*[c.create_value(m, t) for c, m, t in iterator]), tff.FederatedType(member_type, receiver_placement, all_equal)) else: rcv_child = rcv_children[0] if isinstance(message_type, tff.StructType): message_value = federated_resolving_strategy.FederatedResolvingStrategyValue( structure.from_container(await asyncio.gather(*[ rcv_child.create_value(m, t) for m, t in zip(message, message_type) ])), tff.StructType([ tff.FederatedType(mt, receiver_placement, True) for mt in message_type ])) else: message_value = federated_resolving_strategy.FederatedResolvingStrategyValue( await rcv_child.create_value(message, message_type), tff.FederatedType(message_type, receiver_placement, value.type_signature.all_equal)) return await self.receive(message_value, sender_placement, receiver_placement)
def materialize_computation_from_cache(factory_func, cache, arg_spec, **factory_kwargs): """Materialize a tf_computation generated by factory_func. If this function has already been called with a given combination of factory_func, arg_spec, and factory_kwargs, the resulting function proto & type spec will be retreived from cache instead of re-tracing. """ hashable_arg_spec = tuple( (*(repr(arg) for _, arg in factory_kwargs.items()), *(x.compact_representation() for x in arg_spec))) fn_proto, fn_type = cache.get(hashable_arg_spec, (None, None)) if fn_proto is None: func = factory_func(*arg_spec, **factory_kwargs) if len(arg_spec) > 1: arg_spec = tff.StructType(arg_spec) else: arg_spec = arg_spec[0] fn_proto, fn_type = lift_to_computation_spec(func, input_arg_type=arg_spec) cache[hashable_arg_spec] = (fn_proto, fn_type) return fn_proto, fn_type
async def _compute_paillier_encryption( self, client_encryption_keys: federated_resolving_strategy. FederatedResolvingStrategyValue, clients_value: federated_resolving_strategy. FederatedResolvingStrategyValue): client_children = self._get_child_executors(tff.CLIENTS) num_clients = len(client_children) py_typecheck.check_len(client_encryption_keys.internal_representation, num_clients) py_typecheck.check_len(clients_value.internal_representation, num_clients) encryptor_proto, encryptor_type = utils.lift_to_computation_spec( self._paillier_encryptor, input_arg_type=tff.StructType( (client_encryption_keys.type_signature.member, clients_value.type_signature.member))) encryptor_fns = asyncio.gather(*[ c.create_value(encryptor_proto, encryptor_type) for c in client_children ]) encryptor_args = asyncio.gather(*[ c.create_struct((ek, v)) for c, ek, v in zip(client_children, client_encryption_keys.internal_representation, clients_value.internal_representation) ]) encryptor_fns, encryptor_args = await asyncio.gather( encryptor_fns, encryptor_args) encrypted_values = await asyncio.gather(*[ c.create_call(fn, arg) for c, fn, arg in zip( client_children, encryptor_fns, encryptor_args) ]) return federated_resolving_strategy.FederatedResolvingStrategyValue( encrypted_values, tff.FederatedType(encryptor_type.result, tff.CLIENTS, clients_value.type_signature.all_equal))
return (X_test, y_test) np.random.seed(0) nest_asyncio.apply() np.random.seed(0) federated_float_on_clients = tff.type_at_clients(tf.float32) print(str(federated_float_on_clients.member)) print(str(federated_float_on_clients.placement)) federated_float_on_clients.all_equal print(str(tff.type_at_clients(tf.float32, all_equal=True))) simple_regression_model_type = (tff.StructType([('a', tf.float32), ('b', tf.float32)])) print(str(simple_regression_model_type)) train_set = 'UNSW_NB15_training-set.csv' test_set = 'UNSW_NB15_testing-set.csv' training = pd.read_csv(train_set, index_col='id') test = pd.read_csv(test_set, index_col='id') data = pd.concat([training, test]) # Just merging the sets for now NUM_CLIENTS = 10 BATCH_SIZE = 20 ROUNDS = 10
federated_float_on_clients = tff.type_at_clients(tf.float32) #完整显示联邦数据类型 # print( str(federated_float_on_clients) , '\n') #第一个参数表示联邦数据成员类型 , 第二个参数表示联邦数据部署位置 # print( str(federated_float_on_clients.member),'\n' , str(federated_float_on_clients.check_placement)) #联邦数据有两种定义方式,第一种已知分布式设备上的所有数据都相同 #第二种分布式设备上数据不全相同(默认)federated_float_on_clients.all_equal = False # print(str(federated_float_on_clients.all_equal)) #创建本地设备不全相同的联邦数据表示类型 #以y = ax+b为例 differ_simple_regression_model_type = ( #类型不一定要是数值类型 tff.StructType([('a', tf.float32), ('b', tf.string), ('c', tf.float64)])) # print(str(differ_simple_regression_model_type)) #当联邦数据类型全都一致时,可以表示为 #该联邦数据类型具有对称性,因此通常使用术语xyz联邦来指成员组成类似于xyz的联邦值 same_simple_regression_model_type = (tff.StructType([('a', tf.float32), ('b', tf.float32)])) # print(str(tff.type_at_clients(differ_simple_regression_model_type , all_equal=True))) ''' 联邦计算(关键单元) ''' #TFF是一种强类型的函数式编程 #可以使用联邦数据作为输入,同时使用联邦数据作为输出 #示例:读取所有温度传感器进行计算 #温度传感器就是客户端,将传感器读取的温度构造成联邦数据进行输入 #指定联邦计算输入类型
async def _encrypt_values_on_singleton(self, val, sender, receiver): ### # we can safely assume sender has cardinality=1 when receiver is CLIENTS ### # Case 1: receiver=CLIENTS # plaintext: Fed(Tensor, sender, all_equal=True) # pk_receiver: Fed(Tuple(Tensor), sender, all_equal=True) # sk_sender: Fed(Tensor, sender, all_equal=True) # Returns: # encrypted_values: Tuple(Fed(Tensor, sender, all_equal=True)) ### ### Check proper key placement sk_sender = self.key_references.get_secret_key(sender) pk_receiver = self.key_references.get_public_key(receiver) type_analysis.check_federated_type(sk_sender.type_signature, placement=sender) assert sk_sender.type_signature.placement is sender assert pk_receiver.type_signature.placement is sender ### Check placement cardinalities rcv_children = self.strategy._get_child_executors(receiver) snd_children = self.strategy._get_child_executors(sender) py_typecheck.check_len(snd_children, 1) snd_child = snd_children[0] ### Check value cardinalities type_analysis.check_federated_type(val.type_signature, placement=sender) py_typecheck.check_len(val.internal_representation, 1) py_typecheck.check_type(pk_receiver.type_signature.member, tff.StructType) py_typecheck.check_len(pk_receiver.internal_representation, len(rcv_children)) py_typecheck.check_len(sk_sender.internal_representation, 1) ### Materialize encryptor function definition & type spec input_type = val.type_signature.member self._input_type_cache = input_type pk_rcv_type = pk_receiver.type_signature.member sk_snd_type = sk_sender.type_signature.member pk_element_type = pk_rcv_type[0] encryptor_arg_spec = (input_type, pk_element_type, sk_snd_type) encryptor_proto, encryptor_type = utils.materialize_computation_from_cache( sodium_comp.make_encryptor, self._encryptor_cache, encryptor_arg_spec) ### Prepare encryption arguments v = val.internal_representation[0] sk = sk_sender.internal_representation[0] ### Encrypt values and return them encryptor_fn = await snd_child.create_value(encryptor_proto, encryptor_type) encryptor_args = await asyncio.gather(*[ snd_child.create_struct([v, this_pk, sk]) for this_pk in pk_receiver.internal_representation ]) encrypted_values = await asyncio.gather(*[ snd_child.create_call(encryptor_fn, arg) for arg in encryptor_args ]) encrypted_value_types = [encryptor_type.result] * len(encrypted_values) return federated_resolving_strategy.FederatedResolvingStrategyValue( structure.from_container(encrypted_values), tff.StructType([ tff.FederatedType(evt, sender, all_equal=False) for evt in encrypted_value_types ]))