Pysyft: Asynchronous FL on MNIST: call WebsocketClientWorker evaluate() method causes error

Created on 18 Feb 2020  路  12Comments  路  Source: OpenMined/PySyft

Hello!
I am trying to run the example from tutorials. Everything works great until the models' evaluation. The script crashes with the error:

Client message

RuntimeError Traceback (most recent call last)
in async-def-wrapper()
37 )
38
---> 39 # Federate models (note that this will also change the model in models[0]
40 for worker_id, worker_model, worker_loss in results:
41 if worker_model is not None:

in evaluate_model_on_worker(model_identifier, worker, dataset_key, model, nr_bins, batch_size, print_target_hist)
67 nr_bins=nr_bins,
68 return_loss=True,
---> 69 return_raw_accuracy=True
70 )
71 test_loss = result["loss"]

~/Library/Python/3.7/lib/python/site-packages/syft/workers/websocket_client.py in evaluate(self, dataset_key, return_histograms, nr_bins, return_loss, return_raw_accuracy)
221 nr_bins=nr_bins,
222 return_loss=return_loss,
--> 223 return_raw_accuracy=return_raw_accuracy,
224 )
225

~/Library/Python/3.7/lib/python/site-packages/syft/workers/websocket_client.py in _send_msg_and_deserialize(self, command_name, args, *kwargs)
113 # Send the message and return the deserialized response.
114 serialized_message = sy.serde.serialize(message)
--> 115 response = self._send_msg(serialized_message)
116 return sy.serde.deserialize(response)
117

~/Library/Python/3.7/lib/python/site-packages/syft/workers/websocket_client.py in _send_msg(self, message, location)
81
82 def _send_msg(self, message: bin, location=None) -> bin:
---> 83 return self._recv_msg(message)
84
85 def _forward_to_websocket_server_worker(self, message: bin) -> bin:

~/Library/Python/3.7/lib/python/site-packages/syft/workers/websocket_client.py in _recv_msg(self, message)
102 if not self.ws.connected:
103 raise RuntimeError(
--> 104 "Websocket connection closed and creation of new connection failed."
105 )
106 return response

RuntimeError: Websocket connection closed and creation of new connection failed.

Server message:

2020-02-18 17:54:56,388 | Task exception was never retrieved
future: exception=AttributeError("'dict' object has no attribute 'owner'",)>
Traceback (most recent call last):
File "/opt/conda/lib/python3.6/site-packages/syft/workers/websocket_server.py", line 113, in _producer_handler
response = self._recv_msg(message)
File "/opt/conda/lib/python3.6/site-packages/syft/workers/websocket_server.py", line 124, in _recv_msg
return self.recv_msg(message)
File "/opt/conda/lib/python3.6/site-packages/syft/workers/base.py", line 310, in recv_msg
response = self._message_routertype(msg)
File "/opt/conda/lib/python3.6/site-packages/syft/workers/base.py", line 457, in execute_command
command_name, response, list(return_ids), self
File "/opt/conda/lib/python3.6/site-packages/syft/generic/frameworks/hook/hook_args.py", line 665, in register_response
new_response = register_response_function(response, response_ids=response_ids, owner=owner)
File "/opt/conda/lib/python3.6/site-packages/syft/generic/frameworks/hook/hook_args.py", line 766, in
return lambda x, *kwargs: f(lambdas, x, *kwargs)
File "/opt/conda/lib/python3.6/site-packages/syft/generic/frameworks/hook/hook_args.py", line 522, in two_fold
return lambdas0, lambdas1
File "/opt/conda/lib/python3.6/site-packages/syft/generic/frameworks/hook/hook_args.py", line 744, in
else lambda i, *kwargs: register_tensor(i, *kwargs)
File "/opt/conda/lib/python3.6/site-packages/syft/generic/frameworks/hook/hook_args.py", line 712, in register_tensor
tensor.owner = owner
AttributeError: 'dict' object has no attribute 'owner'

Exactly the same issue is described here

Version of the lib is '0.2.3a1'

Most helpful comment

I'm in the process of doing some clean-up deep in the guts of Plans and Operations, starting with #3078. It may take a while to resolve this issue; not sure if making the output type more flexible or adding separate messages to the Syft protocol will turn out to be a preferable approach. Will keep this issue in mind as we sort through issues with the core abstractions.

All 12 comments

See #2948

Sounds like we might need to release a new version with recent fixes.

Wait, #2948 was included in 0.2.3.a1...

I checked 2948. It is not the source of the problem.

The source of the problem is incorrect type of the function output. According to Operation class (from syft/messaging/message.py) the output must be Tensor. But evaluate() function (from syft/federated/federated_client.py) returns dictionary of floats.

Facing the same Issue with recently published docker image also @karlhigley

@karlhigley I have more or less the same problem running the same tutorial. @9sashafr could you find any workaround?

I'm in the process of doing some clean-up deep in the guts of Plans and Operations, starting with #3078. It may take a while to resolve this issue; not sure if making the output type more flexible or adding separate messages to the Syft protocol will turn out to be a preferable approach. Will keep this issue in mind as we sort through issues with the core abstractions.

I was able to workaround by changing the generic/frameworks/hook/hook_args.py file so the register_tensor function is:

def register_tensor(
    tensor: FrameworkTensorType, owner: AbstractWorker, response_ids: List = list()
):
    """
    Registers a tensor.

    Args:
        tensor: A tensor.
        owner: The owner that makes the registration.
        response_ids: List of ids where the tensor should be stored
            and each id is pop out when needed.
    """

    #tensor.owner = owner
    #try:
    #    tensor.id = response_ids.pop(-1)
    #except IndexError:
    #    raise exceptions.ResponseSignatureError

    owner.register_obj(tensor, response_ids.pop(-1))

@brandonhee After doing, what you suggested I got another error saying dict object has no attribute 'id'.

Any ideas?

@Dhrumilsoni I have tried with the master and I think the bug has been fixed and it works now.

Fixed in master and should work in the next release.

Was this page helpful?
0 / 5 - 0 ratings