Skip to content

Issue with Encrypted Aggregation #3001

@stefano555

Description

@stefano555

Tutorial Part 10, when I call

# iterate through each parameter
for param_i in range(len(params[0])):

    # for each worker
    spdz_params = list()
    for remote_index in range(len(compute_nodes)):
        
        # select the identical parameter from each worker and copy it
        copy_of_parameter = params[remote_index][param_i].copy()
        
        # since SMPC can only work with integers (not floats), we need
        # to use Integers to store decimal information. In other words,
        # we need to use "Fixed Precision" encoding.
        fixed_precision_param = copy_of_parameter.fix_precision()
        
        # now we encrypt it on the remote machine. Note that 
        # fixed_precision_param is ALREADY a pointer. Thus, when
        # we call share, it actually encrypts the data that the
        # data is pointing TO. This returns a POINTER to the 
        # MPC secret shared object, which we need to fetch.
        encrypted_param = fixed_precision_param.share(bob, alice, crypto_provider=james)
        
        # now we fetch the pointer to the MPC shared value
        param = encrypted_param.get()
        
        # save the parameter so we can average it with the same parameter
        # from the other workers
        spdz_params.append(param)

    # average params from multiple workers, fetch them to the local machine
    # decrypt and decode (from fixed precision) back into a floating point number
    new_param = (spdz_params[0] + spdz_params[1]).get().float_precision()/2
    
    # save the new averaged parameter
    new_params.append(new_param)

I get this error:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook_args.py in register_response(attr, response, response_ids, owner)
    662         # Load the utility function to register the response and transform tensors with pointers
--> 663         register_response_function = register_response_functions[attr_id]
    664         # Try running it

KeyError: 'numpy'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-15-34467fe3bdcd> in <module>
     12         # to use Integers to store decimal information. In other words,
     13         # we need to use "Fixed Precision" encoding.
---> 14         fixed_precision_param = copy_of_parameter.fix_precision()
     15 
     16         # now we encrypt it on the remote machine. Note that

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/frameworks/torch/tensors/interpreters/native.py in fix_prec(self, storage, field_type, no_wrap, *args, **kwargs)
    765 
    766         max_precision = _get_maximum_precision()
--> 767         need_large_prec = self._requires_large_precision(max_precision, base, prec_fractional)
    768 
    769         if storage == "crt":

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/frameworks/torch/tensors/interpreters/native.py in _requires_large_precision(self, max_precision, base, precision_fractional)
    837         # We need to use NumPy here as log2 is not yet implemented for LongTensor PyTorch objects
    838         return np.any(
--> 839             np.log2(np.abs(self.clone().detach().numpy()) + 1) + base_fractional > max_precision
    840         )
    841 

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/trace.py in trace_wrapper(*args, **kwargs)
     81                 syft.hook.trace.logs.append((command, response))
     82             else:
---> 83                 response = func(*args, **kwargs)
     84 
     85             return response

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook.py in overloaded_native_method(self, *args, **kwargs)
    475                 # Send the new command to the appropriate class and get the response
    476                 method = getattr(new_self, method_name)
--> 477                 response = method(*new_args, **new_kwargs)
    478 
    479                 # For inplace methods, just directly return self

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook.py in overloaded_pointer_method(self, *args, **kwargs)
    638             command = (attr, self, args, kwargs)
    639 
--> 640             response = owner.send_command(location, command)
    641 
    642             # For inplace methods, just directly return self

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/workers/base.py in send_command(self, recipient, message, return_ids)
    510         try:
    511             ret_val = self.send_msg(
--> 512                 Operation(cmd_name, cmd_owner, cmd_args, cmd_kwargs, return_ids), location=recipient
    513             )
    514         except ResponseSignatureError as e:

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/workers/base.py in send_msg(self, message, location)
    275 
    276         # Step 2: send the message and wait for a response
--> 277         bin_response = self._send_msg(bin_message, location)
    278 
    279         # Step 3: deserialize the response

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/workers/virtual.py in _send_msg(self, message, location)
      5 class VirtualWorker(BaseWorker, FederatedClient):
      6     def _send_msg(self, message: bin, location: BaseWorker) -> bin:
----> 7         return location._recv_msg(message)
      8 
      9     def _recv_msg(self, message: bin) -> bin:

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/workers/virtual.py in _recv_msg(self, message)
      8 
      9     def _recv_msg(self, message: bin) -> bin:
---> 10         return self.recv_msg(message)

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/workers/base.py in recv_msg(self, bin_message)
    308 
    309         # Step 1: route message to appropriate function
--> 310         response = self._message_router[type(msg)](msg.contents)
    311 
    312         # Step 2: Serialize the message to simple python objects

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/workers/base.py in execute_command(self, message)
    455             try:
    456                 response = hook_args.register_response(
--> 457                     command_name, response, list(return_ids), self
    458                 )
    459                 return response

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook_args.py in register_response(attr, response, response_ids, owner)
    670         register_response_functions[attr_id] = register_response_function
    671         # Run it
--> 672         new_response = register_response_function(response, response_ids=response_ids, owner=owner)
    673 
    674     # Remove the artificial tuple

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook_args.py in <lambda>(x, **kwargs)
    764         f = many_fold
    765 
--> 766     return lambda x, **kwargs: f(lambdas, x, **kwargs)

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook_args.py in two_fold(lambdas, args, **kwargs)
    520 
    521 def two_fold(lambdas, args, **kwargs):
--> 522     return lambdas[0](args[0], **kwargs), lambdas[1](args[1], **kwargs)
    523 
    524 

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook_args.py in <lambda>(i, **kwargs)
    742         if isinstance(r, (list, tuple))  # if the rule is a list or tuple.
    743         # Last if not, rule is probably == 1 so use type to return the right transformation.
--> 744         else lambda i, **kwargs: register_tensor(i, **kwargs)
    745         for a, r in zip(response, rules)  # And do this for all the responses / rules provided
    746     ]

~/anaconda3/lib/python3.7/site-packages/syft-0.2.2a1-py3.7.egg/syft/generic/frameworks/hook/hook_args.py in register_tensor(tensor, owner, response_ids)
    710             and each id is pop out when needed.
    711     """
--> 712     tensor.owner = owner
    713     try:
    714         tensor.id = response_ids.pop(-1)

AttributeError: 'numpy.ndarray' object has no attribute 'owner'

OS: Ubuntu 18.04.3 LTS
Python 3.7
PyTorch 1.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: Stale 🍞Been open for a while with no activityType: Bug 🐛Some functionality not working in the codebase as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions