def _serialize_struct_type(
    struct_typed_value: Any,
    type_spec: computation_types.StructType,
) -> computation_types.StructType:
    """Serializes a value of tuple type."""
    value_structure = structure.from_container(struct_typed_value)
    if len(value_structure) != len(type_spec):
        raise TypeError(
            'Cannot serialize a struct value of '
            f'{len(value_structure)} elements to a struct type '
            f'requiring {len(type_spec)} elements. Trying to serialize'
            f'\n{struct_typed_value!r}\nto\n{type_spec}.')
    type_elem_iter = structure.iter_elements(type_spec)
    val_elem_iter = structure.iter_elements(value_structure)
    elements = []
    for (e_name, e_type), (_, e_val) in zip(type_elem_iter, val_elem_iter):
        e_value, _ = serialize_value(e_val, e_type)
        if e_name:
            element = executor_pb2.Value.Struct.Element(name=e_name,
                                                        value=e_value)
        else:
            element = executor_pb2.Value.Struct.Element(value=e_value)
        elements.append(element)
    value_proto = executor_pb2.Value(struct=executor_pb2.Value.Struct(
        element=elements))
    return value_proto, type_spec
Beispiel #2
0
def serialize_value(value, type_spec=None):
    """Serializes a value into `executor_pb2.Value`.

  Args:
    value: A value to be serialized.
    type_spec: Optional type spec, a `tff.Type` or something convertible to it.

  Returns:
    An instance of `executor_pb2.Value` with the serialized content of `value`.

  Returns:
    TypeError: If the arguments are of the wrong types.
    ValueError: If the value is malformed.
  """
    type_spec = computation_types.to_type(type_spec)
    if isinstance(value, computation_pb2.Computation):
        if type_spec is not None:
            type_utils.reconcile_value_type_with_type_spec(
                type_serialization.deserialize_type(value.type), type_spec)
        return executor_pb2.Value(computation=value)
    elif isinstance(value, computation_impl.ComputationImpl):
        return serialize_value(
            computation_impl.ComputationImpl.get_proto(value),
            type_utils.reconcile_value_with_type_spec(value, type_spec))
    elif isinstance(type_spec, computation_types.TensorType):
        return serialize_tensor_value(value, type_spec)
    else:
        raise ValueError(
            'Unable to serialize value with Python type {} and {} TFF type.'.
            format(str(py_typecheck.type_string(type(value))),
                   str(type_spec) if type_spec is not None else 'unknown'))
Beispiel #3
0
    def test_create_tuple_of_value_sequence(self):
        datasets = (tf.data.Dataset.range(5), tf.data.Dataset.range(5))
        executor = executor_bindings.create_tensorflow_executor()
        struct_of_sequence_type = StructType([
            (None, SequenceType(datasets[0].element_spec)),
            (None, SequenceType(datasets[0].element_spec))
        ])
        arg_value_pb, _ = value_serialization.serialize_value(
            datasets, struct_of_sequence_type)
        arg = executor.create_value(arg_value_pb)

        @tensorflow_computation.tf_computation(struct_of_sequence_type)
        def preprocess(datasets):
            def double_value(x):
                return 2 * x

            @tf.function
            def add_preprocessing(ds1, ds2):
                return ds1.map(double_value), ds2.map(double_value)

            return add_preprocessing(*datasets)

        comp_pb = executor_pb2.Value(
            computation=preprocess.get_proto(preprocess))
        comp = executor.create_value(comp_pb)
        result = executor.create_call(comp.ref, arg.ref)
        output_pb = executor.materialize(result.ref)
        result, result_type_spec = value_serialization.deserialize_value(
            output_pb, type_hint=struct_of_sequence_type)
        type_test_utils.assert_types_identical(result_type_spec,
                                               struct_of_sequence_type)
Beispiel #4
0
def _serialize_tensor_value(
    value: Any,
    type_spec: computation_types.TensorType) -> _SerializeReturnType:
  """Serializes a tensor value into `executor_pb2.Value`.

  Args:
    value: A Numpy array or other object understood by `tf.make_tensor_proto`.
    type_spec: A `tff.TensorType`.

  Returns:
    A tuple `(value_proto, ret_type_spec)` in which `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`, and
    `ret_type_spec` is the type of the serialized value. The `ret_type_spec` is
    the same as the argument `type_spec` if that argument was not `None`. If
    the argument was `None`, `ret_type_spec` is a type determined from `value`.

  Raises:
    TypeError: If the arguments are of the wrong types.
    ValueError: If the value is malformed.
  """
  if isinstance(value, tf.Tensor):
    value = value.numpy()
  if isinstance(value, np.ndarray):
    tensor_proto = tf.make_tensor_proto(
        value, dtype=type_spec.dtype, verify_shape=False)
  else:
    tensor_proto = tf.make_tensor_proto(
        value, dtype=type_spec.dtype, shape=type_spec.shape, verify_shape=True)
  type_spec.check_assignable_from(
      computation_types.TensorType(
          dtype=tf.dtypes.as_dtype(tensor_proto.dtype),
          shape=tf.TensorShape(tensor_proto.tensor_shape)))
  any_pb = any_pb2.Any()
  any_pb.Pack(tensor_proto)
  return executor_pb2.Value(tensor=any_pb), type_spec
Beispiel #5
0
  def test_deserialize_federated_value_with_incompatible_member_types_raises(
      self):
    x = 10
    x_type = computation_types.to_type(tf.int32)
    int_member_proto, _ = executor_serialization.serialize_value(x, x_type)
    y = 10.
    y_type = computation_types.to_type(tf.float32)
    float_member_proto, _ = executor_serialization.serialize_value(y, y_type)
    fully_specified_type_at_clients = type_serialization.serialize_type(
        computation_types.at_clients(tf.int32))

    unspecified_member_federated_type = computation_pb2.FederatedType(
        placement=fully_specified_type_at_clients.federated.placement,
        all_equal=False)

    federated_proto = executor_pb2.Value.Federated(
        type=unspecified_member_federated_type,
        value=[int_member_proto, float_member_proto])
    federated_value_proto = executor_pb2.Value(federated=federated_proto)

    self.assertIsInstance(int_member_proto, executor_pb2.Value)
    self.assertIsInstance(float_member_proto, executor_pb2.Value)
    self.assertIsInstance(federated_value_proto, executor_pb2.Value)

    with self.assertRaises(TypeError):
      executor_serialization.deserialize_value(federated_value_proto)
Beispiel #6
0
def _serialize_computation(
        comp: computation_pb2.Computation,
        type_spec: Optional[computation_types.Type]) -> _SerializeReturnType:
    """Serializes a TFF computation."""
    type_spec = executor_utils.reconcile_value_type_with_type_spec(
        type_serialization.deserialize_type(comp.type), type_spec)
    return executor_pb2.Value(computation=comp), type_spec
Beispiel #7
0
def serialize_tensor_value(value, type_spec=None):
    """Serializes a tensor value into `executor_pb2.Value`.

  Args:
    value: A Numpy array or other object understood by `tf.make_tensor_proto`.
    type_spec: An optional type spec, a `tff.TensorType` or something
      convertible to it.

  Returns:
    An instance of `executor_pb2.Value` with the serialized content of `value`.

  Returns:
    TypeError: If the arguments are of the wrong types.
    ValueError: If the value is malformed.
  """
    if type_spec is not None:
        type_spec = computation_types.to_type(type_spec)
        py_typecheck.check_type(type_spec, computation_types.TensorType)
        tensor_proto = tf.make_tensor_proto(value,
                                            dtype=type_spec.dtype,
                                            shape=type_spec.shape,
                                            verify_shape=True)
    else:
        tensor_proto = tf.make_tensor_proto(value)
    any_pb = any_pb2.Any()
    any_pb.Pack(tensor_proto)
    return executor_pb2.Value(tensor=any_pb)
  def test_deserialize_federated_value_promotes_types(self):
    x = [10]
    smaller_type = computation_types.StructType([
        (None, computation_types.to_type(tf.int32))
    ])
    smaller_type_member_proto, _ = value_serialization.serialize_value(
        x, smaller_type)
    larger_type = computation_types.StructType([
        ('a', computation_types.to_type(tf.int32))
    ])
    larger_type_member_proto, _ = value_serialization.serialize_value(
        x, larger_type)
    type_at_clients = type_serialization.serialize_type(
        computation_types.at_clients(tf.int32))

    unspecified_member_federated_type = computation_pb2.FederatedType(
        placement=type_at_clients.federated.placement, all_equal=False)

    federated_proto = executor_pb2.Value.Federated(
        type=unspecified_member_federated_type,
        value=[larger_type_member_proto, smaller_type_member_proto])
    federated_value_proto = executor_pb2.Value(federated=federated_proto)

    _, deserialized_type_spec = value_serialization.deserialize_value(
        federated_value_proto)
    type_test_utils.assert_types_identical(
        deserialized_type_spec, computation_types.at_clients(larger_type))
Beispiel #9
0
def serialize_value(value, type_spec=None):
    """Serializes a value into `executor_pb2.Value`.

  Args:
    value: A value to be serialized.
    type_spec: Optional type spec, a `tff.Type` or something convertible to it.

  Returns:
    A tuple `(value_proto, ret_type_spec)` where `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`, and the
    returned `ret_type_spec` is an instance of `tff.Type` that represents the
    TFF type of the serialized value.

  Raises:
    TypeError: If the arguments are of the wrong types.
    ValueError: If the value is malformed.
  """
    type_spec = computation_types.to_type(type_spec)
    if isinstance(value, computation_pb2.Computation):
        type_spec = type_utils.reconcile_value_type_with_type_spec(
            type_serialization.deserialize_type(value.type), type_spec)
        return executor_pb2.Value(computation=value), type_spec
    elif isinstance(value, computation_impl.ComputationImpl):
        return serialize_value(
            computation_impl.ComputationImpl.get_proto(value),
            type_utils.reconcile_value_with_type_spec(value, type_spec))
    elif isinstance(type_spec, computation_types.TensorType):
        return serialize_tensor_value(value, type_spec)
    elif isinstance(type_spec, computation_types.NamedTupleType):
        type_elements = anonymous_tuple.to_elements(type_spec)
        val_elements = anonymous_tuple.to_elements(
            anonymous_tuple.from_container(value))
        tup_elems = []
        for (e_name, e_type), (_, e_val) in zip(type_elements, val_elements):
            e_proto, _ = serialize_value(e_val, e_type)
            tup_elems.append(
                executor_pb2.Value.Tuple.Element(
                    name=e_name if e_name else None, value=e_proto))
        result_proto = (executor_pb2.Value(tuple=executor_pb2.Value.Tuple(
            element=tup_elems)))
        return result_proto, type_spec
    else:
        raise ValueError(
            'Unable to serialize value with Python type {} and {} TFF type.'.
            format(str(py_typecheck.type_string(type(value))),
                   str(type_spec) if type_spec is not None else 'unknown'))
def _value_proto_for_np_array(
        value, type_spec: computation_types.Type) -> executor_pb2.Value:
    """Creates value proto for np array, assumed to be assignable to type_spec."""
    tensor_proto = tf.make_tensor_proto(value,
                                        dtype=type_spec.dtype,
                                        verify_shape=True)
    any_pb = any_pb2.Any()
    any_pb.Pack(tensor_proto)
    return executor_pb2.Value(tensor=any_pb)
Beispiel #11
0
    def test_call_no_arg(self):
        executor = executor_bindings.create_tensorflow_executor()

        @tensorflow_computation.tf_computation
        def foo():
            return tf.constant(123.0)

        comp_pb = executor_pb2.Value(computation=foo.get_proto(foo))
        comp = executor.create_value(comp_pb)
        result = executor.create_call(comp.ref, None)
        result_value_pb = executor.materialize(result.ref)
        result_tensor, _ = value_serialization.deserialize_value(
            result_value_pb)
        self.assertEqual(result_tensor, 123.0)
Beispiel #12
0
def _serialize_struct_type(
        struct_typed_value: Any,
        type_spec: computation_types.StructType) -> _SerializeReturnType:
    """Serializes a value of tuple type."""
    type_elem_iter = structure.iter_elements(type_spec)
    val_elem_iter = structure.iter_elements(
        structure.from_container(struct_typed_value))
    tup_elems = []
    for (e_name, e_type), (_, e_val) in zip(type_elem_iter, val_elem_iter):
        e_proto, _ = serialize_value(e_val, e_type)
        tup_elems.append(
            executor_pb2.Value.Struct.Element(name=e_name if e_name else None,
                                              value=e_proto))
    result_proto = (executor_pb2.Value(struct=executor_pb2.Value.Struct(
        element=tup_elems)))
    return result_proto, type_spec
def _serialize_federated_value(
    federated_value: Any, type_spec: computation_types.FederatedType
) -> computation_types.FederatedType:
    """Serializes a value of federated type."""
    if type_spec.all_equal:
        value = [federated_value]
    else:
        value = federated_value
    py_typecheck.check_type(value, list)
    value_proto = executor_pb2.Value()
    for v in value:
        federated_value_proto, it_type = serialize_value(v, type_spec.member)
        type_spec.member.check_assignable_from(it_type)
        value_proto.federated.value.append(federated_value_proto)
    value_proto.federated.type.CopyFrom(
        type_serialization.serialize_type(type_spec).federated)
    return value_proto, type_spec
 def test_deserialize_federated_all_equal_value_takes_first_element(self):
   tensor_value_pb, _ = value_serialization.serialize_value(
       10, TensorType(tf.int32))
   num_clients = 5
   value_pb = executor_pb2.Value(
       federated=executor_pb2.Value.Federated(
           value=[tensor_value_pb] * num_clients,
           type=computation_pb2.FederatedType(
               placement=computation_pb2.PlacementSpec(
                   value=computation_pb2.Placement(
                       uri=placements.CLIENTS.uri)))))
   all_equal_clients_type_hint = computation_types.FederatedType(
       tf.int32, placements.CLIENTS, all_equal=True)
   deserialized_value, deserialized_type = value_serialization.deserialize_value(
       value_pb, all_equal_clients_type_hint)
   type_test_utils.assert_types_identical(deserialized_type,
                                          all_equal_clients_type_hint)
   self.assertAllEqual(deserialized_value, 10)
Beispiel #15
0
    def test_call_with_arg(self):
        executor = executor_bindings.create_tensorflow_executor()
        value_pb, _ = value_serialization.serialize_value(
            tf.constant([1, 2, 3]), TensorType(shape=[3], dtype=tf.int64))
        value_ref = executor.create_value(value_pb)
        arg = executor.create_struct((value_ref.ref, value_ref.ref))

        @tensorflow_computation.tf_computation(tf.int64, tf.int64)
        def foo(a, b):
            return tf.add(a, b)

        comp_pb = executor_pb2.Value(computation=foo.get_proto(foo))
        comp = executor.create_value(comp_pb)
        result = executor.create_call(comp.ref, arg.ref)
        result_value_pb = executor.materialize(result.ref)
        result_tensor, _ = value_serialization.deserialize_value(
            result_value_pb)
        self.assertAllEqual(result_tensor, [2, 4, 6])
Beispiel #16
0
    def test_compute_returns_result(self, mock_stub):
        tensor_proto = tf.make_tensor_proto(1)
        any_pb = any_pb2.Any()
        any_pb.Pack(tensor_proto)
        value = executor_pb2.Value(tensor=any_pb)
        response = executor_pb2.ComputeResponse(value=value)
        instance = mock_stub.return_value
        instance.Compute = mock.Mock(side_effect=[response])
        loop = asyncio.get_event_loop()
        executor = create_remote_executor()
        type_signature = computation_types.FunctionType(None, tf.int32)
        comp = remote_executor.RemoteValue(executor_pb2.ValueRef(),
                                           type_signature, executor)

        result = loop.run_until_complete(comp.compute())

        instance.Compute.assert_called_once()
        self.assertEqual(result, 1)
    def test_compute_returns_result(self, mock_stub):
        tensor_proto = tf.make_tensor_proto(1)
        any_pb = any_pb2.Any()
        any_pb.Pack(tensor_proto)
        value = executor_pb2.Value(tensor=any_pb)
        mock_stub.compute.return_value = executor_pb2.ComputeResponse(
            value=value)
        executor = remote_executor.RemoteExecutor(mock_stub)
        _set_cardinalities_with_mock(executor, mock_stub)
        executor.set_cardinalities({placements.CLIENTS: 3})
        type_signature = computation_types.FunctionType(None, tf.int32)
        comp = remote_executor.RemoteValue(executor_pb2.ValueRef(),
                                           type_signature, executor)

        result = asyncio.run(comp.compute())

        mock_stub.compute.assert_called_once()
        self.assertEqual(result, 1)
Beispiel #18
0
def _serialize_federated_value(
        federated_value: Any,
        type_spec: computation_types.FederatedType) -> _SerializeReturnType:
    """Serializes a value of federated type."""
    if type_spec.all_equal:
        value = [federated_value]
    else:
        value = federated_value
    py_typecheck.check_type(value, list)
    items = []
    for v in value:
        it, it_type = serialize_value(v, type_spec.member)
        type_spec.member.check_assignable_from(it_type)
        items.append(it)
    result_proto = executor_pb2.Value(federated=executor_pb2.Value.Federated(
        type=type_serialization.serialize_type(type_spec).federated,
        value=items))
    return result_proto, type_spec
def _serialize_sequence_value(
    value: Union[Union[type_conversions.TF_DATASET_REPRESENTATION_TYPES],
                 List[Any]], type_spec: computation_types.SequenceType
) -> computation_types.SequenceType:
    """Serializes a `tf.data.Dataset` value into `executor_pb2.Value`.

  Args:
    value: A `tf.data.Dataset`, or equivalent list of values convertible to
      (potentially structures of) tensors.
    type_spec: A `computation_types.Type` specifying the TFF sequence type of
      `value.`

  Returns:
    A tuple `(value_proto, type_spec)` in which `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`,
    and `type_spec` is the type of the serialized value.
  """
    if isinstance(value, list):
        value = tensorflow_utils.make_data_set_from_elements(
            None, value, type_spec.element)
    if not isinstance(value, type_conversions.TF_DATASET_REPRESENTATION_TYPES):
        raise TypeError(
            'Cannot serialize Python type {!s} as TFF type {!s}.'.format(
                py_typecheck.type_string(type(value)),
                type_spec if type_spec is not None else 'unknown'))
    element_type = computation_types.to_type(value.element_spec)
    _check_container_compat_with_tf_nest(element_type)
    value_type = computation_types.SequenceType(element_type)
    if not type_spec.is_assignable_from(value_type):
        raise TypeError(
            'Cannot serialize dataset with elements of type {!s} as TFF type {!s}.'
            .format(value_type,
                    type_spec if type_spec is not None else 'unknown'))
    value_proto = executor_pb2.Value()
    # TFF must store the type spec here because TF will lose the ordering of the
    # names for `tf.data.Dataset` that return elements of
    # `collections.abc.Mapping` type. This allows TFF to preserve and restore the
    # key ordering upon deserialization.
    value_proto.sequence.serialized_graph_def = _serialize_dataset(value)
    value_proto.sequence.element_type.CopyFrom(
        type_serialization.serialize_type(element_type))
    return value_proto, type_spec
    def test_compute_returns_result(self, mock_executor_grpc_stub):
        tensor_proto = tf.make_tensor_proto(1)
        any_pb = any_pb2.Any()
        any_pb.Pack(tensor_proto)
        value = executor_pb2.Value(tensor=any_pb)
        response = executor_pb2.ComputeResponse(value=value)
        instance = mock_executor_grpc_stub.return_value
        instance.Compute = mock.Mock(side_effect=[response])

        request = executor_pb2.ComputeRequest(
            executor=executor_pb2.ExecutorId(),
            value_ref=executor_pb2.ValueRef())

        stub = create_stub()
        result = stub.compute(request)

        instance.Compute.assert_called_once()

        value, _ = value_serialization.deserialize_value(result.value)
        self.assertEqual(value, 1)
  def test_deserialize_federated_value_with_unset_member_type(self):
    x = 10
    x_type = computation_types.to_type(tf.int32)
    member_proto, _ = value_serialization.serialize_value(x, x_type)
    fully_specified_type_at_clients = type_serialization.serialize_type(
        computation_types.at_clients(tf.int32))

    unspecified_member_federated_type = computation_pb2.FederatedType(
        placement=fully_specified_type_at_clients.federated.placement,
        all_equal=fully_specified_type_at_clients.federated.all_equal)

    federated_proto = executor_pb2.Value.Federated(
        type=unspecified_member_federated_type, value=[member_proto])
    federated_value_proto = executor_pb2.Value(federated=federated_proto)

    deserialized_federated_value, deserialized_type_spec = value_serialization.deserialize_value(
        federated_value_proto)
    type_test_utils.assert_types_identical(
        deserialized_type_spec, computation_types.at_clients(tf.int32))
    self.assertEqual(deserialized_federated_value, [10])
def serialize_sequence_value(value):
    """Serializes a `tf.data.Dataset` value into `executor_pb2.Value`.

  Args:
    value: A `tf.data.Dataset`, or equivalent.

  Returns:
    A tuple `(value_proto, type_spec)` in which `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`, and
    `type_spec` is the type of the serialized value.
  """
    py_typecheck.check_type(value, type_utils.TF_DATASET_REPRESENTATION_TYPES)
    # TFF must store the type spec here because TF will lose the ordering of the
    # names for `tf.data.Dataset` that return elements of `collections.Mapping`
    # type. This allows TFF to preserve and restore the key ordering upon
    # deserialization.
    element_type = computation_types.to_type(value.element_spec)
    return executor_pb2.Value(sequence=executor_pb2.Value.Sequence(
        zipped_saved_model=tensorflow_serialization.serialize_dataset(value),
        element_type=type_serialization.serialize_type(element_type)))
Beispiel #23
0
    def test_create_value_sequence(self, dataset):
        executor = executor_bindings.create_tensorflow_executor()
        sequence_type = SequenceType(dataset.element_spec)
        arg_value_pb, _ = value_serialization.serialize_value(
            dataset, sequence_type)
        arg = executor.create_value(arg_value_pb)

        @tensorflow_computation.tf_computation(sequence_type)
        def sum_examples(ds):
            return ds.reduce(tf.constant(0, ds.element_spec.dtype),
                             lambda s, x: s + tf.reduce_sum(x))

        comp_pb = executor_pb2.Value(
            computation=sum_examples.get_proto(sum_examples))
        comp = executor.create_value(comp_pb)
        result = executor.create_call(comp.ref, arg.ref)
        output_pb = executor.materialize(result.ref)
        result, result_type_spec = value_serialization.deserialize_value(
            output_pb)
        type_test_utils.assert_types_identical(
            result_type_spec, TensorType(sequence_type.element.dtype))
        self.assertEqual(result, sum(range(5)))
Beispiel #24
0
def _serialize_sequence_value(
    value: Union[type_conversions.TF_DATASET_REPRESENTATION_TYPES],
    type_spec: computation_types.SequenceType) -> _SerializeReturnType:
  """Serializes a `tf.data.Dataset` value into `executor_pb2.Value`.

  Args:
    value: A `tf.data.Dataset`, or equivalent.
    type_spec: A `computation_types.Type` specifying the TFF sequence type of
      `value.`

  Returns:
    A tuple `(value_proto, type_spec)` in which `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`, and
    `type_spec` is the type of the serialized value.
  """
  if not isinstance(value, type_conversions.TF_DATASET_REPRESENTATION_TYPES):
    raise TypeError(
        'Cannot serialize Python type {!s} as TFF type {!s}.'.format(
            py_typecheck.type_string(type(value)),
            type_spec if type_spec is not None else 'unknown'))

  value_type = computation_types.SequenceType(
      computation_types.to_type(value.element_spec))
  if not type_spec.is_assignable_from(value_type):
    raise TypeError(
        'Cannot serialize dataset with elements of type {!s} as TFF type {!s}.'
        .format(value_type, type_spec if type_spec is not None else 'unknown'))

  # TFF must store the type spec here because TF will lose the ordering of the
  # names for `tf.data.Dataset` that return elements of
  # `collections.abc.Mapping` type. This allows TFF to preserve and restore the
  # key ordering upon deserialization.
  element_type = computation_types.to_type(value.element_spec)
  return executor_pb2.Value(
      sequence=executor_pb2.Value.Sequence(
          zipped_saved_model=_serialize_dataset(value),
          element_type=type_serialization.serialize_type(
              element_type))), type_spec
def serialize_tensor_value(value, type_spec=None):
  """Serializes a tensor value into `executor_pb2.Value`.

  Args:
    value: A Numpy array or other object understood by `tf.make_tensor_proto`.
    type_spec: An optional type spec, a `tff.TensorType` or something
      convertible to it.

  Returns:
    A tuple `(value_proto, ret_type_spec)` in which `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`, and
    `ret_type_spec` is the type of the serialized value. The `ret_type_spec` is
    the same as the argument `type_spec` if that argument was not `None`. If
    the argument was `None`, `ret_type_spec` is a type determined from `value`.

  Raises:
    TypeError: If the arguments are of the wrong types.
    ValueError: If the value is malformed.
  """
  if isinstance(value, tf.Tensor):
    if type_spec is None:
      type_spec = computation_types.TensorType(
          dtype=tf.DType(value.dtype), shape=tf.TensorShape(value.shape))
    value = value.numpy()
  if type_spec is not None:
    type_spec = computation_types.to_type(type_spec)
    py_typecheck.check_type(type_spec, computation_types.TensorType)
    tensor_proto = tf.make_tensor_proto(
        value, dtype=type_spec.dtype, shape=type_spec.shape, verify_shape=True)
  else:
    tensor_proto = tf.make_tensor_proto(value)
    type_spec = computation_types.TensorType(
        dtype=tf.DType(tensor_proto.dtype),
        shape=tf.TensorShape(tensor_proto.tensor_shape))
  any_pb = any_pb2.Any()
  any_pb.Pack(tensor_proto)
  return executor_pb2.Value(tensor=any_pb), type_spec
Beispiel #26
0
def serialize_value(value, type_spec=None):
    """Serializes a value into `executor_pb2.Value`.

  Args:
    value: A value to be serialized.
    type_spec: Optional type spec, a `tff.Type` or something convertible to it.

  Returns:
    A tuple `(value_proto, ret_type_spec)` where `value_proto` is an instance
    of `executor_pb2.Value` with the serialized content of `value`, and the
    returned `ret_type_spec` is an instance of `tff.Type` that represents the
    TFF type of the serialized value.

  Raises:
    TypeError: If the arguments are of the wrong types.
    ValueError: If the value is malformed.
  """
    type_spec = computation_types.to_type(type_spec)
    if isinstance(value, computation_pb2.Computation):
        type_spec = type_utils.reconcile_value_type_with_type_spec(
            type_serialization.deserialize_type(value.type), type_spec)
        return executor_pb2.Value(computation=value), type_spec
    elif isinstance(value, computation_impl.ComputationImpl):
        return serialize_value(
            computation_impl.ComputationImpl.get_proto(value),
            type_utils.reconcile_value_with_type_spec(value, type_spec))
    elif isinstance(type_spec, computation_types.TensorType):
        return serialize_tensor_value(value, type_spec)
    elif isinstance(type_spec, computation_types.NamedTupleType):
        type_elements = anonymous_tuple.to_elements(type_spec)
        val_elements = anonymous_tuple.to_elements(
            anonymous_tuple.from_container(value))
        tup_elems = []
        for (e_name, e_type), (_, e_val) in zip(type_elements, val_elements):
            e_proto, _ = serialize_value(e_val, e_type)
            tup_elems.append(
                executor_pb2.Value.Tuple.Element(
                    name=e_name if e_name else None, value=e_proto))
        result_proto = (executor_pb2.Value(tuple=executor_pb2.Value.Tuple(
            element=tup_elems)))
        return result_proto, type_spec
    elif isinstance(type_spec, computation_types.SequenceType):
        if not isinstance(value,
                          type_conversions.TF_DATASET_REPRESENTATION_TYPES):
            raise TypeError(
                'Cannot serialize Python type {!s} as TFF type {!s}.'.format(
                    py_typecheck.type_string(type(value)),
                    type_spec if type_spec is not None else 'unknown'))

        value_type = computation_types.SequenceType(
            computation_types.to_type(value.element_spec))
        if not type_analysis.is_assignable_from(type_spec, value_type):
            raise TypeError(
                'Cannot serialize dataset with elements of type {!s} as TFF type {!s}.'
                .format(value_type,
                        type_spec if type_spec is not None else 'unknown'))

        return serialize_sequence_value(value), type_spec
    elif isinstance(type_spec, computation_types.FederatedType):
        if type_spec.all_equal:
            value = [value]
        else:
            py_typecheck.check_type(value, list)
        items = []
        for v in value:
            it, it_type = serialize_value(v, type_spec.member)
            type_analysis.check_assignable_from(type_spec.member, it_type)
            items.append(it)
        result_proto = executor_pb2.Value(
            federated=executor_pb2.Value.Federated(
                type=type_serialization.serialize_type(type_spec).federated,
                value=items))
        return result_proto, type_spec
    else:
        raise ValueError(
            'Unable to serialize value with Python type {} and {} TFF type.'.
            format(str(py_typecheck.type_string(type(value))),
                   str(type_spec) if type_spec is not None else 'unknown'))