def to_representation_for_type(value, type_spec, backend=None): """Verifies or converts the `value` to executor payload matching `type_spec`. The following kinds of `value` are supported: * Computations, either `pb.Computation` or `computation_impl.ComputationImpl`. * Numpy arrays and scalars, or Python scalars that are converted to Numpy. * Nested structures of the above. Args: value: The raw representation of a value to compare against `type_spec` and potentially to be converted. type_spec: An instance of `tff.Type`. Can be `None` for values that derive from `typed_object.TypedObject`. backend: The backend to use; an instance of `xla_client.Client`. Only used for functional types. Can be `None` if unused. Returns: Either `value` itself, or a modified version of it. Raises: TypeError: If the `value` is not compatible with `type_spec`. ValueError: If the arguments are incorrect. """ if backend is not None: py_typecheck.check_type(backend, xla_client.Client) if type_spec is not None: type_spec = computation_types.to_type(type_spec) type_spec = type_utils.reconcile_value_with_type_spec(value, type_spec) if isinstance(value, computation_base.Computation): return to_representation_for_type( computation_impl.ComputationImpl.get_proto(value), type_spec, backend) if isinstance(value, pb.Computation): comp_type = type_serialization.deserialize_type(value.type) if type_spec is not None: comp_type.check_equivalent_to(type_spec) return _ComputationCallable(value, comp_type, backend) if isinstance(type_spec, computation_types.StructType): return structure.map_structure( lambda v, t: to_representation_for_type(v, t, backend), structure.from_container(value, recursive=True), type_spec) if isinstance(type_spec, computation_types.TensorType): type_spec.shape.assert_is_fully_defined() type_analysis.check_type(value, type_spec) if type_spec.shape.rank == 0: return np.dtype(type_spec.dtype.as_numpy_dtype).type(value) if type_spec.shape.rank > 0: return np.array(value, dtype=type_spec.dtype.as_numpy_dtype) raise TypeError('Unsupported tensor shape {}.'.format(type_spec.shape)) raise TypeError('Unexpected type {}.'.format(type_spec))
def to_representation_for_type(value, type_spec=None, backend=None): """Verifies or converts the `value` to executor payload matching `type_spec`. The following kinds of `value` are supported: * Computations, either `pb.Computation` or `computation_impl.ComputationImpl`. These are compiled and converted into `runtime.ComputationCallable`. * Numpy arrays and scalars, or Python scalars that are converted to Numpy. Args: value: The raw representation of a value to compare against `type_spec` and potentially to be converted. type_spec: An instance of `tff.Type`. Can be `None` for values that derive from `typed_object.TypedObject`. backend: Optional information about the backend, only required for computations. Must be `None` or an instance of `backend_info.BackendInfo`. Returns: Either `value` itself, or a modified version of it. Raises: TypeError: If the `value` is not compatible with `type_spec`. ValueError: If the arguments are incorrect (e.g., missing `backend` for a computation-typed `value`). """ type_spec = type_utils.reconcile_value_with_type_spec(value, type_spec) if backend is not None: py_typecheck.check_type(backend, backend_info.BackendInfo) if isinstance(value, computation_base.Computation): return to_representation_for_type( computation_impl.ComputationImpl.get_proto(value), type_spec=type_spec, backend=backend) elif isinstance(value, pb.Computation): if backend is None: raise ValueError('Missing backend info for a computation.') module = compiler.import_tensorflow_computation(value) return runtime.ComputationCallable(module, backend) elif isinstance(type_spec, computation_types.TensorType): type_spec.shape.assert_is_fully_defined() type_analysis.check_type(value, type_spec) if type_spec.shape.rank == 0: return np.dtype(type_spec.dtype.as_numpy_dtype).type(value) elif type_spec.shape.rank > 0: return np.array(value, dtype=type_spec.dtype.as_numpy_dtype) else: raise TypeError('Unsupported tensor shape {}.'.format( type_spec.shape)) else: raise TypeError('Unexpected type {}.'.format(type_spec))
def invoke(self, comp, arg): fn = value_impl.to_value(comp, None, self._context_stack) tys = fn.type_signature py_typecheck.check_type(tys, computation_types.FunctionType) if arg is not None: if tys.parameter is None: raise ValueError( 'A computation of type {} does not expect any arguments, but got ' 'an argument {}.'.format(tys, arg)) type_analysis.check_type(arg, tys.parameter) ret_val = fn(arg) else: if tys.parameter is not None: raise ValueError( 'A computation of type {} expects an argument of type {}, but got ' ' no argument.'.format(tys, tys.parameter)) ret_val = fn() type_analysis.check_type(ret_val, tys.result) return ret_val
def invoke(self, comp: computation_impl.ConcreteComputation, arg): if arg is not None: type_analysis.check_type(arg, comp.type_signature.parameter) # We are invoking a tff.tf_computation inside of another # tf_computation. py_typecheck.check_type(comp, computation_impl.ConcreteComputation) computation_proto = computation_impl.ConcreteComputation.get_proto(comp) computation_oneof = computation_proto.WhichOneof('computation') if computation_oneof != 'tensorflow': raise ValueError( 'Can only invoke TensorFlow in the body of a TensorFlow ' 'computation; got computation of type {}'.format(computation_oneof)) shared_name_suffix = f'_tffshared_{self._shared_name_index}' self._shared_name_index += 1 init_op, result = ( tensorflow_utils.deserialize_and_call_tf_computation( computation_proto, arg, self._graph, shared_name_suffix, self.session_token)) if init_op: self._init_ops.append(init_op) return type_conversions.type_to_py_container(result, comp.type_signature.result)
def normalize_tensor_representation(value, type_spec): """Normalizes the representation of a tensor `value` of a given `type_spec`. This converts vairous sorts of constants into a numpy representation. Args: value: The value whose representation to normalize. type_spec: An instance of `computation_types.TensorType` for this value. Returns: A normalized representation of `value` in numpy. Raises: TypeError: if the arguments are of the wrong types. """ py_typecheck.check_type(type_spec, computation_types.TensorType) type_spec.shape.assert_is_fully_defined() type_analysis.check_type(value, type_spec) if type_spec.shape.rank == 0: return np.dtype(type_spec.dtype.as_numpy_dtype).type(value) if type_spec.shape.rank > 0: return np.array(value, dtype=type_spec.dtype.as_numpy_dtype) raise TypeError('Unsupported tensor shape {}.'.format(type_spec.shape))
def test_raises_type_error(self): type_analysis.check_type(10, tf.int32) self.assertRaises(TypeError, type_analysis.check_type, 10, tf.bool)
def test_raises_type_error(self): type_analysis.check_type(10, computation_types.TensorType(tf.int32)) self.assertRaises(TypeError, type_analysis.check_type, 10, tf.bool)
def ingest(self, val, type_spec): val = value_impl.to_value(val, type_spec, self._context_stack) type_analysis.check_type(val, type_spec) return val
def ingest(self, val, type_spec): type_analysis.check_type(val, type_spec) return val