def _SliceShape(op): """Shape function for array_ops.slice.""" input_shape = op.inputs[0].get_shape() begin_shape = op.inputs[1].get_shape().with_rank(1) sizes_shape = op.inputs[2].get_shape().with_rank(1) ndims = begin_shape.merge_with(sizes_shape)[0].value if ndims is not None: input_shape.assert_has_rank(ndims) begin_value = tensor_util.constant_value(op.inputs[1]) sizes_value = tensor_util.constant_value(op.inputs[2]) if sizes_value is not None: returned_dims = [] for i, slice_size in enumerate(sizes_value.ravel()): if slice_size != -1: returned_dims.append(slice_size) elif begin_value is not None: returned_dims.append(input_shape[i] - begin_value[i]) else: returned_dims.append(None) return [tensor_shape.TensorShape(returned_dims)] else: if input_shape.ndims is not None: return [tensor_shape.unknown_shape(ndims=input_shape.ndims)] elif ndims is not None: return [tensor_shape.unknown_shape(ndims=ndims)] else: return [tensor_shape.unknown_shape()]
def _split_batch_beams(self, t, s=None): """Splits the tensor from a batch by beams into a batch of beams. More exactly, t is a tensor of dimension [batch_size*beam_width, s]. We reshape this into [batch_size, beam_width, s] Args: t: Tensor of dimension [batch_size*beam_width, s]. s: (Possibly known) depth shape. Returns: A reshaped version of t with dimension [batch_size, beam_width, s]. Raises: ValueError: If, after reshaping, the new tensor is not shaped `[batch_size, beam_width, s]` (assuming batch_size and beam_width are known statically). """ if isinstance(s, ops.Tensor): s = tensor_shape.TensorShape(tensor_util.constant_value(s)) else: s = tensor_shape.TensorShape(s) t_shape = tf.shape(t) reshaped_t = tf.reshape( t, tf.concat( ([self._batch_size, self._beam_width], t_shape[1:]), 0)) static_batch_size = tensor_util.constant_value(self._batch_size) expected_reshaped_shape = tensor_shape.TensorShape( [static_batch_size, self._beam_width]).concatenate(s) if not reshaped_t.shape.is_compatible_with(expected_reshaped_shape): raise ValueError("Unexpected behavior when reshaping between beam width " "and batch size. The reshaped tensor has shape: %s. " "We expected it to have shape " "(batch_size, beam_width, depth) == %s. Perhaps you " "forgot to create a zero_state with " "batch_size=encoder_batch_size * beam_width?" % (reshaped_t.shape, expected_reshaped_shape)) reshaped_t.set_shape(expected_reshaped_shape) return reshaped_t
def _merge_batch_beams(self, t, s=None): """Merges the tensor from a batch of beams into a batch by beams. More exactly, t is a tensor of dimension [batch_size, beam_width, s]. We reshape this into [batch_size*beam_width, s] Args: t: Tensor of dimension [batch_size, beam_width, s] s: (Possibly known) depth shape. Returns: A reshaped version of t with dimension [batch_size * beam_width, s]. """ if isinstance(s, ops.Tensor): s = tensor_shape.as_shape(tensor_util.constant_value(s)) else: s = tensor_shape.TensorShape(s) t_shape = tf.shape(t) static_batch_size = tensor_util.constant_value(self._batch_size) batch_size_beam_width = ( None if static_batch_size is None else static_batch_size * self._beam_width) reshaped_t = tf.reshape( t, tf.concat( ([self._batch_size * self._beam_width], t_shape[2:]), 0)) reshaped_t.set_shape( (tensor_shape.TensorShape([batch_size_beam_width]).concatenate(s))) return reshaped_t
def _test(self, input_shape, block_shape, base_paddings): input_shape = np.array(input_shape) block_shape = np.array(block_shape) if base_paddings is not None: base_paddings = np.array(base_paddings) # Check with constants. paddings, crops = tf.required_space_to_batch_paddings( input_shape, block_shape, base_paddings) paddings_const = tensor_util.constant_value(paddings) crops_const = tensor_util.constant_value(crops) self.assertIsNotNone(paddings_const) self.assertIsNotNone(crops_const) self._checkProperties(input_shape, block_shape, base_paddings, paddings_const, crops_const) # Check with non-constants. assignments = {} input_shape_placeholder = tf.placeholder(tf.int32) assignments[input_shape_placeholder] = input_shape block_shape_placeholder = tf.placeholder(tf.int32, [len(block_shape)]) assignments[block_shape_placeholder] = block_shape if base_paddings is not None: base_paddings_placeholder = tf.placeholder(tf.int32, [len(block_shape), 2]) assignments[base_paddings_placeholder] = base_paddings else: base_paddings_placeholder = None t_paddings, t_crops = tf.required_space_to_batch_paddings( input_shape_placeholder, block_shape_placeholder, base_paddings_placeholder) with self.test_session(): paddings_result = t_paddings.eval(assignments) crops_result = t_crops.eval(assignments) self.assertAllEqual(paddings_result, paddings_const) self.assertAllEqual(crops_result, crops_const)
def __init__(self, input_dataset, map_func, batch_size, num_parallel_calls, drop_remainder, use_legacy_function=False): """See `Dataset.map()` for details.""" self._input_dataset = input_dataset self._map_func = dataset_ops.StructuredFunctionWrapper( map_func, "tf.data.experimental.map_and_batch()", dataset=input_dataset, use_legacy_function=use_legacy_function) self._batch_size_t = ops.convert_to_tensor( batch_size, dtype=dtypes.int64, name="batch_size") self._num_parallel_calls_t = ops.convert_to_tensor( num_parallel_calls, dtype=dtypes.int64, name="num_parallel_calls") self._drop_remainder_t = ops.convert_to_tensor( drop_remainder, dtype=dtypes.bool, name="drop_remainder") constant_drop_remainder = tensor_util.constant_value(self._drop_remainder_t) if constant_drop_remainder: # NOTE(mrry): `constant_drop_remainder` may be `None` (unknown statically) # or `False` (explicitly retaining the remainder). self._structure = self._map_func.output_structure._batch( # pylint: disable=protected-access tensor_util.constant_value(self._batch_size_t)) else: self._structure = self._map_func.output_structure._batch(None) # pylint: disable=protected-access variant_tensor = ged_ops.experimental_map_and_batch_dataset( self._input_dataset._variant_tensor, # pylint: disable=protected-access self._map_func.function.captured_inputs, f=self._map_func.function, batch_size=self._batch_size_t, num_parallel_calls=self._num_parallel_calls_t, drop_remainder=self._drop_remainder_t, preserve_cardinality=True, **dataset_ops.flat_structure(self)) super(_MapAndBatchDataset, self).__init__(input_dataset, variant_tensor)
def testConstant(self): np_val = np.random.rand(3, 4, 7).astype(np.float32) tf_val = constant_op.constant(np_val) self.assertAllClose(np_val, tensor_util.constant_value(tf_val)) np_val = np.random.rand(3, 0, 7).astype(np.float32) tf_val = constant_op.constant(np_val) self.assertAllClose(np_val, tensor_util.constant_value(tf_val))
def _RangeShape(op): start_value = tensor_util.constant_value(op.inputs[0]) limit_value = tensor_util.constant_value(op.inputs[1]) delta_value = tensor_util.constant_value(op.inputs[2]) if start_value is None or limit_value is None or delta_value is None: return [tensor_shape.vector(None)] else: return [tensor_shape.vector((limit_value - start_value + delta_value - 1) // delta_value)]
def _broadcast_shape(shape1, shape2): """Convenience function which statically broadcasts shape when possible.""" if (tensor_util.constant_value(shape1) is not None and tensor_util.constant_value(shape2) is not None): return array_ops.broadcast_static_shape( tensor_shape.TensorShape(tensor_util.constant_value(shape1)), tensor_shape.TensorShape(tensor_util.constant_value(shape2))) return array_ops.broadcast_dynamic_shape(shape1, shape2)
def _concat(prefix, suffix, static=False): """Concat that enables int, Tensor, or TensorShape values. This function takes a size specification, which can be an integer, a TensorShape, or a Tensor, and converts it into a concatenated Tensor (if static = False) or a list of integers (if static = True). Args: prefix: The prefix; usually the batch size (and/or time step size). (TensorShape, int, or Tensor.) suffix: TensorShape, int, or Tensor. static: If `True`, return a python list with possibly unknown dimensions. Otherwise return a `Tensor`. Returns: shape: the concatenation of prefix and suffix. Raises: ValueError: if `suffix` is not a scalar or vector (or TensorShape). ValueError: if prefix or suffix was `None` and asked for dynamic Tensors out. """ if isinstance(prefix, ops.Tensor): p = prefix p_static = tensor_util.constant_value(prefix) if p.shape.ndims == 0: p = array_ops.expand_dims(p, 0) elif p.shape.ndims != 1: raise ValueError("prefix tensor must be either a scalar or vector, " "but saw tensor: %s" % p) else: p = tensor_shape.as_shape(prefix) p_static = p.as_list() if p.ndims is not None else None p = (constant_op.constant(p.as_list(), dtype=dtypes.int32) if p.is_fully_defined() else None) if isinstance(suffix, ops.Tensor): s = suffix s_static = tensor_util.constant_value(suffix) if s.shape.ndims == 0: s = array_ops.expand_dims(s, 0) elif s.shape.ndims != 1: raise ValueError("suffix tensor must be either a scalar or vector, " "but saw tensor: %s" % s) else: s = tensor_shape.as_shape(suffix) s_static = s.as_list() if s.ndims is not None else None s = (constant_op.constant(s.as_list(), dtype=dtypes.int32) if s.is_fully_defined() else None) if static: shape = tensor_shape.as_shape(p_static).concatenate(s_static) shape = shape.as_list() if shape.ndims is not None else None else: if p is None or s is None: raise ValueError("Provided a prefix or suffix of None: %s and %s" % (prefix, suffix)) shape = array_ops.concat((p, s), 0) return shape
def make_dims(start_sum, size, name): """Closure to make dims range.""" start_sum = start_sum if start_sum else (array_ops.zeros((), dtype=dtypes.int32, name="zero"),) if self._is_all_constant_helper(size, *start_sum): start = sum([tensor_util.constant_value(s) for s in start_sum]) stop = start + tensor_util.constant_value(size) return ops.convert_to_tensor(list(range(start, stop)), dtype=dtypes.int32, name=name) else: start = sum(start_sum) return math_ops.range(start, start + size)
def testPack_Axis1(self): inputs = [np.random.rand(4, 7) for _ in range(3)] tf_val = array_ops.stack(inputs, axis=1) c_val = tensor_util.constant_value(tf_val) self.assertIsNone(c_val) tf_val = array_ops.stack( [inputs[0], array_ops.placeholder(dtypes.float32), inputs[2]], axis=1) c_val = tensor_util.constant_value(tf_val) self.assertIs(None, c_val)
def testCast(self): np_val = np.random.rand(3, 4, 7).astype(np.float32) tf_val = math_ops.cast(constant_op.constant(np_val), dtypes.float64) c_val = tensor_util.constant_value(tf_val) self.assertAllClose(np_val.astype(np.float64), c_val) np_val = np.random.rand(3, 0, 7).astype(np.float32) tf_val = math_ops.cast(constant_op.constant(np_val), dtypes.float64) c_val = tensor_util.constant_value(tf_val) self.assertAllClose(np_val.astype(np.float64), c_val)
def slice_shape(start_sum, size, name): """Closure to slice out shape.""" start_sum = start_sum if start_sum else (array_ops.zeros((), dtype=dtypes.int32, name="zero"),) if x.get_shape().ndims is not None and self._is_all_constant_helper(size, *start_sum): start = sum([tensor_util.constant_value(s) for s in start_sum]) stop = start + tensor_util.constant_value(size) slice_ = x.get_shape()[start:stop].as_list() if all(s is not None for s in slice_): return ops.convert_to_tensor(slice_, dtype=dtypes.int32, name=name) # Fall-through intended. return array_ops.slice(array_ops.shape(x), (sum(start_sum),), (size,))
def testPack_Axis0(self): inputs = [np.random.rand(4, 7) for _ in range(3)] np_val = np.array(inputs) tf_val = array_ops.stack(inputs) c_val = tensor_util.constant_value(tf_val) self.assertAllClose(np_val, c_val) tf_val = array_ops.stack( [inputs[0], array_ops.placeholder(dtypes.float32), inputs[2]]) c_val = tensor_util.constant_value(tf_val) self.assertIs(None, c_val)
def _get_event_reduce_dims(self, min_event_ndims, event_ndims): """Compute the reduction dimensions given event_ndims.""" min_event_ndims_ = (min_event_ndims if isinstance(min_event_ndims, int) else tensor_util.constant_value(min_event_ndims)) event_ndims_ = (event_ndims if isinstance(event_ndims, int) else tensor_util.constant_value(event_ndims)) if min_event_ndims_ is not None and event_ndims_ is not None: return [-index for index in range(1, event_ndims_ - min_event_ndims_ + 1)] else: reduce_ndims = event_ndims - min_event_ndims return math_ops.range(-reduce_ndims, 0)
def slice_shape(start_sum, size, name): """Closure to slice out shape.""" start_sum = start_sum if start_sum else [ array_ops.zeros([], dtype=dtypes.int32, name="zero")] if (x.get_shape().ndims is not None and self._is_all_constant_helper(size, *start_sum)): start = sum(tensor_util.constant_value(s) for s in start_sum) stop = start + tensor_util.constant_value(size) slice_ = x.get_shape()[start:stop].as_list() if all(s is not None for s in slice_): return ops.convert_to_tensor(slice_, dtype=dtypes.int32, name=name) return array_ops.slice(array_ops.shape(x), [sum(start_sum)], [size])
def _EditDistanceShape(op): """Shape function for the EditDistance op.""" hypothesis_shape = tensor_util.constant_value(op.inputs[2]) truth_shape = tensor_util.constant_value(op.inputs[5]) if hypothesis_shape is not None and truth_shape is not None: if len(hypothesis_shape) != len(truth_shape): raise ValueError( "Inconsistent ranks in hypothesis and truth. Saw shapes: %s and %s" % (str(hypothesis_shape), str(truth_shape))) return [tensor_shape.TensorShape( [max(h, t) for h, t in zip(hypothesis_shape[:-1], truth_shape[:-1])])] return [tensor_shape.unknown_shape()]
def make_dims(start_sum, size, name): """Closure to make dims range.""" start_sum = start_sum if start_sum else [ tf.zeros([], dtype=tf.int32, name="zero") ] if self._is_all_constant_helper(size, *start_sum): start = sum(tensor_util.constant_value(s) for s in start_sum) stop = start + tensor_util.constant_value(size) return tf.convert_to_tensor( list(range(start, stop)), dtype=tf.int32, name=name) else: start = sum(start_sum) return tf.range(start, start + size)
def testEqual(self): # Scalar inputs. tf_val = math_ops.equal(constant_op.constant(1), constant_op.constant(1)) self.assertEqual(tensor_util.constant_value(tf_val), True) tf_val = math_ops.equal(constant_op.constant(1), constant_op.constant(0)) self.assertEqual(tensor_util.constant_value(tf_val), False) # Shaped inputs with broadcast semantics. tf_val = math_ops.equal(constant_op.constant([[0, 1]]), constant_op.constant([[0], [1]])) c_val = tensor_util.constant_value(tf_val) self.assertAllEqual(c_val, [[True, False], [False, True]])
def _split_dataset_batch(dataset, split_batch_by): """Divide a batch-ed dataset's batches into smaller batches.""" # TODO(sourabhbajaj): Remove this in lieu of distributed datasets # pylint: disable=protected-access def _get_batch_dataset(d): """Get the underlying batch dataset from the dataset object.""" if isinstance(d, dataset_ops.DatasetV1Adapter): d = d._dataset if isinstance(d, (dataset_ops.BatchDataset, batching._MapAndBatchDataset)): return d elif isinstance(d, dataset_ops.PrefetchDataset): return _get_batch_dataset(d._input_dataset) raise ValueError( "Unable to get batched dataset from the input dataset. `batch` " "`map_and_batch` need to be the last operations on the dataset. " "The batch operations can be followed by a prefetch.") batched_dataset = _get_batch_dataset(dataset) if isinstance(batched_dataset, dataset_ops.BatchDataset): batch_size = batched_dataset._batch_size drop_remainder = batched_dataset._drop_remainder elif isinstance(batched_dataset, batching._MapAndBatchDataset): batch_size = batched_dataset._batch_size_t drop_remainder = batched_dataset._drop_remainder_t prefetch_buffer = None if isinstance(dataset, dataset_ops.PrefetchDataset): prefetch_buffer = dataset._buffer_size elif (isinstance(dataset, dataset_ops.DatasetV1Adapter) and isinstance(dataset._dataset, dataset_ops.PrefetchDataset)): prefetch_buffer = dataset._dataset._buffer_size # pylint: enable=protected-access if tensor_util.is_tensor(batch_size): batch_size = tensor_util.constant_value(batch_size) if tensor_util.is_tensor(drop_remainder): drop_remainder = tensor_util.constant_value(drop_remainder) if batch_size % split_batch_by: raise ValueError( "Batch size %s cannot be sharded evenly across replicas %s" % ( batch_size, split_batch_by)) new_batch_size = batch_size // split_batch_by dataset = dataset.apply(batching.unbatch()) dataset = dataset.batch(new_batch_size, drop_remainder=drop_remainder) if prefetch_buffer is not None: dataset = dataset.prefetch(prefetch_buffer) return dataset
def _maybe_validate_shape_override(self, override_shape, base_is_scalar, validate_args, name): """Helper to __init__ which ensures override batch/event_shape are valid.""" if override_shape is None: override_shape = [] override_shape = ops.convert_to_tensor(override_shape, dtype=dtypes.int32, name=name) if not override_shape.dtype.is_integer: raise TypeError("shape override must be an integer") override_is_scalar = _is_scalar_from_shape(override_shape) if tensor_util.constant_value(override_is_scalar): return self._empty dynamic_assertions = [] if override_shape.get_shape().ndims is not None: if override_shape.get_shape().ndims != 1: raise ValueError("shape override must be a vector") elif validate_args: dynamic_assertions += [check_ops.assert_rank( override_shape, 1, message="shape override must be a vector")] if tensor_util.constant_value(override_shape) is not None: if any(s <= 0 for s in tensor_util.constant_value(override_shape)): raise ValueError("shape override must have positive elements") elif validate_args: dynamic_assertions += [check_ops.assert_positive( override_shape, message="shape override must have positive elements")] is_both_nonscalar = _logical_and(_logical_not(base_is_scalar), _logical_not(override_is_scalar)) if tensor_util.constant_value(is_both_nonscalar) is not None: if tensor_util.constant_value(is_both_nonscalar): raise ValueError("base distribution not scalar") elif validate_args: dynamic_assertions += [check_ops.assert_equal( is_both_nonscalar, False, message="base distribution not scalar")] if not dynamic_assertions: return override_shape return control_flow_ops.with_dependencies( dynamic_assertions, override_shape)
def constant_value(value_or_tensor_or_var, dtype=None): """Returns value if value_or_tensor_or_var has a constant value. Args: value_or_tensor_or_var: A value, a `Tensor` or a `Variable`. dtype: Optional `tf.dtype`, if set it would check it has the right dtype. Returns: The constant value or None if it not constant. Raises: ValueError: if value_or_tensor_or_var is None or the tensor_variable has the wrong dtype. """ if value_or_tensor_or_var is None: raise ValueError('value_or_tensor_or_var cannot be None') value = value_or_tensor_or_var if isinstance(value_or_tensor_or_var, (ops.Tensor, variables.Variable)): if dtype and value_or_tensor_or_var.dtype != dtype: raise ValueError('It has the wrong type %s instead of %s' % ( value_or_tensor_or_var.dtype, dtype)) if isinstance(value_or_tensor_or_var, variables.Variable): value = None else: value = tensor_util.constant_value(value_or_tensor_or_var) return value
def __init__(self, event_ndims=2, validate_args=False, name="cholesky_outer_product"): """Instantiates the `CholeskyOuterProduct` bijector. Args: event_ndims: `constant` `int32` scalar `Tensor` indicating the number of dimensions associated with a particular draw from the distribution. Must be 0 or 2. validate_args: Python `bool` indicating whether arguments should be checked for correctness. name: Python `str` name given to ops managed by this object. Raises: ValueError: if event_ndims is neither 0 or 2. """ self._graph_parents = [] self._name = name with self._name_scope("init", values=[event_ndims]): event_ndims = ops.convert_to_tensor(event_ndims, name="event_ndims") event_ndims = tensor_util.constant_value(event_ndims) if event_ndims is None or event_ndims not in [0, 2]: raise ValueError("`event_ndims` must be a TF constant which is 0 or 2") self._static_event_ndims = event_ndims super(CholeskyOuterProduct, self).__init__( event_ndims=event_ndims, validate_args=validate_args, name=name)
def _SumGrad(op, grad): """Gradient for Sum.""" # Fast path for when reducing to a scalar and ndims is known: adds only # Reshape and Tile ops (and possibly a Shape). input_0_shape = op.inputs[0]._shape_tuple() # pylint: disable=protected-access if input_0_shape is not None: axes = tensor_util.constant_value(op.inputs[1]) if axes is not None: rank = len(input_0_shape) if np.array_equal(axes, np.arange(rank)): # Reduce all dims. grad = array_ops.reshape(grad, [1] * rank) # If shape is not fully defined (but rank is), we use Shape. if None not in input_0_shape: input_shape = input_0_shape else: input_shape = array_ops.shape(op.inputs[0]) return [array_ops.tile(grad, input_shape), None] input_shape = array_ops.shape(op.inputs[0]) # TODO(apassos) remove this once device placement for eager ops makes more # sense. with ops.colocate_with(input_shape): output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1]) tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims) grad = array_ops.reshape(grad, output_shape_kept_dims) return [array_ops.tile(grad, tile_scaling), None]
def split(self, value, lengths, name=None): """See TensorArray.""" with ops.name_scope(name, "TensorArraySplit", [self._handle, value, lengths]): value = ops.convert_to_tensor(value, name="value") with self._maybe_colocate_with(value): lengths_64 = math_ops.to_int64(lengths) if self._infer_shape and context.in_graph_mode(): clengths = tensor_util.constant_value(lengths_64) if value.shape.dims is not None: if clengths is not None and clengths.max() == clengths.min(): self._merge_element_shape( tensor_shape.TensorShape([clengths[0]]).concatenate( value.shape[1:])) flow_out = gen_data_flow_ops._tensor_array_split_v3( handle=self._handle, value=value, lengths=lengths_64, flow_in=self._flow, name=name) ta = TensorArray( dtype=self._dtype, handle=self._handle, flow=flow_out, colocate_with_first_write_call=self._colocate_with_first_write_call) ta._infer_shape = self._infer_shape ta._element_shape = self._element_shape ta._colocate_with = self._colocate_with return ta
def _ReductionShape(op): """Common shape function for reduction ops.""" input_shape = op.inputs[0].get_shape() reduction_indices = tensor_util.constant_value(op.inputs[1]) keep_dims = op.get_attr("keep_dims") if reduction_indices is None or input_shape.ndims is None: if keep_dims: return [tensor_shape.unknown_shape(ndims=input_shape.ndims)] else: return [tensor_shape.unknown_shape()] # Turn reduction_indices from scalar to vector if necessary reduction_indices = np.ravel(reduction_indices) for reduction_index in reduction_indices: if reduction_index < 0 or reduction_index >= input_shape.ndims: raise ValueError("Invalid reduction dimension %d for input with %d " "dimensions" % (reduction_index, input_shape.ndims)) returned_dims = [] if keep_dims: for i, dim in enumerate(input_shape.dims): if i in reduction_indices: returned_dims.append(1) else: returned_dims.append(dim) else: for i, dim in enumerate(input_shape.dims): if i not in reduction_indices: returned_dims.append(dim) return [tensor_shape.TensorShape(returned_dims)]
def _maybe_set_maximum_iterations_attr(op, maximum_iterations): if maximum_iterations is not None and control_flow_util.IsInXLAContext(op): # Store the maximum_iterations to use in the gradient pass. op._set_attr( # pylint: disable=protected-access "_maximum_iterations", attr_value_pb2.AttrValue( i=tensor_util.constant_value(maximum_iterations)))
def sample(self, n, seed=None, name="sample"): """Sample `n` observations from the Uniform Distributions. Args: n: `Scalar`, type int32, the number of observations to sample. seed: Python integer, the random seed. name: The name to give this op. Returns: samples: a `Tensor` of shape `(n,) + self.batch_shape + self.event_shape` with values of type `self.dtype`. """ with ops.name_scope(self.name): with ops.op_scope([self.a, self.b, n], name): n = ops.convert_to_tensor(n, name="n") n_val = tensor_util.constant_value(n) shape = array_ops.concat(0, [array_ops.pack([n]), self.batch_shape()]) samples = random_ops.random_uniform(shape=shape, dtype=self.dtype, seed=seed) # Provide some hints to shape inference inferred_shape = tensor_shape.vector(n_val).concatenate( self.get_batch_shape()) samples.set_shape(inferred_shape) return (array_ops.expand_dims(self.a, 0) + array_ops.expand_dims( self.range(), 0) * samples)
def _shuffle_to_front(input_tensor, k): """Shuffles the last `k` indices of `input_tensor` to the front. Transposes `input_tensor` to have the last `k` indices at the front. The input may have arbitrary rank and unknown shape. Args: input_tensor: A `Tensor` of arbitrary rank and unknown shape. k: A scalar `Tensor` specifying how many indices to shuffle. Returns: A transposed version of `input_tensor` with `k` indices shuffled to the front. Raises: ValueError: If `input_tensor` is not at least rank `k` or `k` is not scalar. """ k = ops.convert_to_tensor(k, name="k") k.shape.with_rank(0) k_static = tensor_util.constant_value(k) if k_static is not None: input_tensor.shape.with_rank_at_least(k_static) rank = array_ops.rank(input_tensor) outer_indices, inner_indices = array_ops.split(math_ops.range(rank), [rank - k, k]) permutation = array_ops.concat([inner_indices, outer_indices], 0) return array_ops.transpose(input_tensor, perm=permutation)
def _apply_fn(dataset): """Function from `Dataset` to `Dataset` that applies the transformation.""" tensor_batch_size = ops.convert_to_tensor( batch_size, dtype=dtypes.int64, name="batch_size") flattened = _RestructuredDataset( dataset, tuple(nest.flatten(dataset.output_types)), output_classes=tuple(nest.flatten(dataset.output_classes))) def _predicate(*xs): """Return `True` if this element is a full batch.""" # Extract the dynamic batch size from the first component of the flattened # batched element. first_component = xs[0] first_component_batch_size = array_ops.shape( first_component, out_type=dtypes.int64)[0] return math_ops.equal(first_component_batch_size, tensor_batch_size) filtered = flattened.filter(_predicate) maybe_constant_batch_size = tensor_util.constant_value(tensor_batch_size) def _set_first_dimension(shape): return shape.merge_with( tensor_shape.vector(maybe_constant_batch_size).concatenate(shape[1:])) known_shapes = nest.map_structure(_set_first_dimension, dataset.output_shapes) return _RestructuredDataset( filtered, dataset.output_types, known_shapes, output_classes=dataset.output_classes)
def testPack_Partial_Axis1(self): input_ = np.random.rand(4, 7) tf_val = array_ops.stack( [input_, array_ops.placeholder(dtypes.float32)], axis=1) c_val = tensor_util.constant_value(tf_val, partial=True) self.assertIsNone(c_val)
def testUnpack_Axis0(self): inputs = np.random.rand(3, 4, 7) tf_vals = array_ops.unstack(inputs) c_vals = [tensor_util.constant_value(x) for x in tf_vals] self.assertAllClose(inputs, c_vals)
def _ConcatGradHelper(op, grad, start_value_index, end_value_index, dim_index): """Gradient for concat op. Args: op: An operation. grad: `Tensor` or `IndexedSlices` representing the gradients with respect to each output of the op. start_value_index: An integer index of the first value in the op.inputs. end_value_index: An integer index of the last value in the op.inputs. dim_index: An interger index of concat_dim or axis parameter in op.inputs. Returns: Tensors representing the partial gradients with respect to each input of the op. Raises: ValueError: if concat_dim/axis is not statically known. """ def _CreateDenseMaskAndBegin(sizes, concat_dim): """Create variables for iteratively slicing a dense gradients tensor.""" # Since shape is 1-D, shape_of_shape = [rank-of-inputs] shape_of_shape = array_ops.shape(sizes[0]) # Make a vector of length equal to the input's dimensions, # with 0's everywhere and 1 in the concat dim position. # Note: Can't use sparse_to_dense since it isn't GPU-capable (for now) mask = array_ops.concat([ array_ops.fill(array_ops.expand_dims(concat_dim, 0), 0), [1], array_ops.fill(shape_of_shape - concat_dim - 1, 0) ], 0) begin = array_ops.fill(shape_of_shape, 0) return mask, begin def _ExtractInputShapes(inputs): """Extract the shapes of a set of input tensors.""" if context.executing_eagerly(): return array_ops.shape_n(inputs) sizes = [] fully_known = True for x in inputs: input_shape = array_ops.shape(x) if not isinstance(input_shape, ops.Tensor) or input_shape.op.type != "Const": fully_known = False break sizes.append(input_shape) if fully_known: return sizes else: return array_ops.shape_n(inputs) # Degenerate concatenation, just return grad. if len(op.inputs) == 2: return grad + [None] if end_value_index <= dim_index else [None] + grad concat_dim = op.inputs[dim_index] input_values = op.inputs[start_value_index:end_value_index] out_grads = [] if isinstance(grad, ops.Tensor): if context.executing_eagerly() or isinstance(concat_dim, ops.EagerTensor): # Using mod here for convenience since concat_dim is already verified # in concat implementation to be within the allowed [-rank, rank) range. non_neg_concat_dim = ( concat_dim._numpy().item(0) % input_values[0]._rank()) # pylint: disable=protected-access # All inputs are guaranteed to be EagerTensors in eager mode sizes = pywrap_tensorflow.TFE_Py_TensorShapeSlice(input_values, non_neg_concat_dim) out_grads = array_ops.split(grad, sizes, non_neg_concat_dim) else: if constant_op.is_constant(concat_dim): # If concat_dim is a constant defined in a different context, # then we duplicate it in the current context to avoid passing it # through an Enter node. # This is a small optimization in general, but it is required when # compiling with XLA, as XLA needs the concat input to be folded into a # constant. grad_context = control_flow_util.GetOutputContext(grad.op) dim_context = control_flow_util.GetOutputContext(concat_dim.op) if dim_context != grad_context: value = tensor_util.constant_value(concat_dim) concat_dim = constant_op.constant(value=value, dtype=concat_dim.dtype) # Using mod here for convenience since concat_dim is already verified # in concat implementation to be within the allowed [-rank, rank) range. non_neg_concat_dim = concat_dim % array_ops.rank(input_values[0]) # Get the inputs' tensor shapes sizes = _ExtractInputShapes(input_values) # The magic number of 16 was found through benchmarking a range of sizes # on CPUs and a Maxwell TitanX. A speedup was seen in a large majority of # cases when switching implementations at N=16, but it is possible that # there will be a small number of performance regressions. if len(sizes) > 16: # extract the size of each input along the concat dimension sizes = array_ops.squeeze( array_ops.slice( array_ops.stack(sizes, axis=1), [non_neg_concat_dim, 0], [1, -1])) out_grads = array_ops.split(grad, sizes, non_neg_concat_dim) else: offset = gen_array_ops.concat_offset(non_neg_concat_dim, sizes) for (begin, size) in zip(offset, sizes): out_grads.append(array_ops.slice(grad, begin, size)) elif isinstance(grad, ops.IndexedSlices): # Using mod here for convenience since concat_dim is already verified # in concat implementation to be within the allowed [-rank, rank) range. non_neg_concat_dim = concat_dim % array_ops.rank(input_values[0]) concat_dim_static = tensor_util.constant_value(concat_dim) if concat_dim_static is None: raise ValueError("Can only compute IndexedSlices gradient with " "statically-known concat_dim") if concat_dim_static < 0: rank = tensor_util.constant_value(array_ops.rank(input_values[0])) if rank is None: raise ValueError("Can only compute IndexedSlices gradient with " "negative concat_dim when first value rank is " "statically-known.") concat_dim_static %= rank # Get the inputs' tensor shapes sizes = [array_ops.shape(x) for x in input_values] if concat_dim_static > 0: # IndexedSlices, non_neg_concat_dim > 0. Each input gets IndexedSlices # gradients with all the indices, but with grad.values sliced accordingly. # This is like the Tensor case, except shape(grad.values)[0] is not equal # to shape(sizes[i])[0], since only a subset of the dim-0 values are # stored. mask, begin = _CreateDenseMaskAndBegin(sizes, non_neg_concat_dim) for size in sizes: new_values = array_ops.slice( grad.values, begin, array_ops.concat([[-1], array_ops.slice(size, [1], [-1])], 0)) out_grads.append(ops.IndexedSlices(new_values, grad.indices, size)) # Lint complains begin = begin + ... begin = math_ops.add(begin, size * mask) else: # IndexedSlices, concat_dim == 0. Each input gets IndexedSlices gradients # only for the relevant indices. start = constant_op.constant(0, dtype=grad.indices.dtype) for size in sizes: size_concat_dim = array_ops.gather(size, non_neg_concat_dim) if size_concat_dim.dtype != grad.indices.dtype: size_concat_dim = math_ops.cast( size_concat_dim, dtype=grad.indices.dtype) end = start + size_concat_dim # Compute the 1-D Tensor of indices relevant for this input. indices_to_select = array_ops.squeeze( array_ops.where( math_ops.logical_and(grad.indices >= start, grad.indices < end)), axis=[1]) new_indices = array_ops.gather(grad.indices, indices_to_select) - start new_values = array_ops.gather(grad.values, indices_to_select) out_grads.append(ops.IndexedSlices(new_values, new_indices, size)) start = end else: raise TypeError("Expected Tensor or IndexedSlices, got %s" % type(grad)) return (out_grads + [None] if end_value_index <= dim_index else [None] + out_grads)
def map_resources(self): """Makes new resource handle ops corresponding to existing resource tensors. Creates resource handle ops in the current default graph, whereas `accessible_objects` will be from an eager context. Resource mapping adds resource handle ops to the main GraphDef of a SavedModel, which allows the C++ loader API to interact with variables. Returns: A tuple of (object_map, resource_map, asset_info): object_map: A dictionary mapping from object in `accessible_objects` to replacement objects created to hold the new resource tensors. resource_map: A dictionary mapping from resource tensors extracted from `accessible_objects` to newly created resource tensors. asset_info: An _AssetInfo tuple describing external assets referenced from accessible_objects. """ # Only makes sense when adding to the export Graph assert not context.executing_eagerly() # TODO(allenl): Handle MirroredVariables and other types of variables which # may need special casing. object_map = object_identity.ObjectIdentityDictionary() resource_map = {} asset_info = _AssetInfo( asset_defs=[], asset_initializers_by_resource={}, asset_filename_map={}, asset_index={}) for node_id, obj in enumerate(self.nodes): if isinstance(obj, tracking.CapturableResource): # pylint: disable=protected-access with ops.device(obj._resource_device): new_resource = obj._create_resource() # pylint: enable=protected-access resource_map[obj.resource_handle] = new_resource self.captured_tensor_node_ids[obj.resource_handle] = node_id elif ds_values.is_distributed_variable(obj): # Put both the distributed variable and component variable handles in # `captured_tensor_node_ids`. # Also create a new distributed variable for `object_map` with newly # created component variables. new_vars = [] for v in obj.values: new_variable = resource_variable_ops.copy_to_graph_uninitialized(v) object_map[v] = new_variable new_vars.append(new_variable) resource_map[v.handle] = new_variable.handle self.captured_tensor_node_ids[v.handle] = node_id object_map[obj] = obj._clone_with_new_values(new_vars) # pylint: disable=protected-access self.captured_tensor_node_ids[obj] = node_id elif resource_variable_ops.is_resource_variable(obj): new_variable = resource_variable_ops.copy_to_graph_uninitialized(obj) object_map[obj] = new_variable resource_map[obj.handle] = new_variable.handle self.captured_tensor_node_ids[obj.handle] = node_id elif isinstance(obj, tracking.Asset): _process_asset(obj, asset_info, resource_map) self.captured_tensor_node_ids[obj.asset_path] = node_id for concrete_function in self.concrete_functions: if not concrete_function.graph.saveable: raise ValueError( ("Unable to save function {name} for the following reason(s):\n" + "\n".join(concrete_function.graph.saving_errors)) .format(name=concrete_function.name)) for capture in concrete_function.captured_inputs: if (tensor_util.is_tensor(capture) and capture.dtype not in _UNCOPIABLE_DTYPES and capture not in self.captured_tensor_node_ids): capture_constant_value = tensor_util.constant_value(capture) if capture_constant_value is None: raise ValueError( ("Attempted to save a function {} which references a symbolic " "Tensor {} that is not a simple constant. This is not " "supported.").format(concrete_function.name, capture)) copied_tensor = constant_op.constant(capture_constant_value) node_id = len(self.nodes) node = _CapturedConstant( eager_tensor=capture, graph_tensor=copied_tensor) self.nodes.append(node) self.node_ids[capture] = node_id self.node_ids[node] = node_id self.captured_tensor_node_ids[capture] = node_id resource_map[capture] = copied_tensor return object_map, resource_map, asset_info
def shapes_from_loc_and_scale(loc, scale, name="shapes_from_loc_and_scale"): """Infer distribution batch and event shapes from a location and scale. Location and scale family distributions determine their batch/event shape by broadcasting the `loc` and `scale` args. This helper does that broadcast, statically if possible. Batch shape broadcasts as per the normal rules. We allow the `loc` event shape to broadcast up to that of `scale`. We do not allow `scale`'s event shape to change. Therefore, the last dimension of `loc` must either be size `1`, or the same as `scale.range_dimension`. See `MultivariateNormalLinearOperator` for a usage example. Args: loc: `N-D` `Tensor` with `N >= 1` (already converted to tensor) or `None`. If `None`, both batch and event shape are determined by `scale`. scale: A `LinearOperator` instance. name: A string name to prepend to created ops. Returns: batch_shape: `TensorShape` (if broadcast is done statically), or `Tensor`. event_shape: `TensorShape` (if broadcast is done statically), or `Tensor`. Raises: ValueError: If the last dimension of `loc` is determined statically to be different than the range of `scale`. """ with tf.name_scope(name, values=[loc] + scale.graph_parents): # Get event shape. event_size = scale.range_dimension_tensor() event_size_const = tensor_util.constant_value(event_size) if event_size_const is not None: event_shape = event_size_const.reshape([1]) else: event_shape = event_size[tf.newaxis] # Static check that event shapes match. if loc is not None: loc_event_size = loc.get_shape()[-1].value if loc_event_size is not None and event_size_const is not None: if loc_event_size != 1 and loc_event_size != event_size_const: raise ValueError( "Event size of 'scale' (%d) could not be broadcast up to that of " "'loc' (%d)." % (loc_event_size, event_size_const)) # Get batch shape. batch_shape = scale.batch_shape_tensor() if loc is None: batch_shape_const = tensor_util.constant_value(batch_shape) batch_shape = (batch_shape_const if batch_shape_const is not None else batch_shape) else: loc_batch_shape = loc.get_shape().with_rank_at_least(1)[:-1] if (loc.get_shape().ndims is None or not loc_batch_shape.is_fully_defined()): loc_batch_shape = tf.shape(loc)[:-1] else: loc_batch_shape = tf.convert_to_tensor(loc_batch_shape, name="loc_batch_shape") # This is defined in the core util module. # pylint: disable=undefined-variable batch_shape = prefer_static_broadcast_shape( batch_shape, loc_batch_shape) # pylint: enable=undefined-variable return batch_shape, event_shape
def __init__(self, cat, components, validate_args=False, allow_nan_stats=True, name="Mixture"): """Initialize a Mixture distribution. A `Mixture` is defined by a `Categorical` (`cat`, representing the mixture probabilities) and a list of `Distribution` objects all having matching dtype, batch shape, event shape, and continuity properties (the components). The `num_classes` of `cat` must be possible to infer at graph construction time and match `len(components)`. Args: cat: A `Categorical` distribution instance, representing the probabilities of `distributions`. components: A list or tuple of `Distribution` instances. Each instance must have the same type, be defined on the same domain, and have matching `event_shape` and `batch_shape`. validate_args: `Boolean`, default `False`. If `True`, raise a runtime error if batch or event ranks are inconsistent between cat and any of the distributions. This is only checked if the ranks cannot be determined statically at graph construction time. allow_nan_stats: Boolean, default `True`. If `False`, raise an exception if a statistic (e.g. mean/mode/etc...) is undefined for any batch member. If `True`, batch members with valid parameters leading to undefined statistics will return NaN for this statistic. name: A name for this distribution (optional). Raises: TypeError: If cat is not a `Categorical`, or `components` is not a list or tuple, or the elements of `components` are not instances of `Distribution`, or do not have matching `dtype`. ValueError: If `components` is an empty list or tuple, or its elements do not have a statically known event rank. If `cat.num_classes` cannot be inferred at graph creation time, or the constant value of `cat.num_classes` is not equal to `len(components)`, or all `components` and `cat` do not have matching static batch shapes, or all components do not have matching static event shapes. """ parameters = locals() parameters.pop("self") if not isinstance(cat, categorical.Categorical): raise TypeError( "cat must be a Categorical distribution, but saw: %s" % cat) if not components: raise ValueError("components must be a non-empty list or tuple") if not isinstance(components, (list, tuple)): raise TypeError("components must be a list or tuple, but saw: %s" % components) if not all( isinstance(c, distribution.Distribution) for c in components): raise TypeError( "all entries in components must be Distribution instances" " but saw: %s" % components) dtype = components[0].dtype if not all(d.dtype == dtype for d in components): raise TypeError("All components must have the same dtype, but saw " "dtypes: %s" % [(d.name, d.dtype) for d in components]) is_continuous = components[0].is_continuous if not all(d.is_continuous == is_continuous for d in components): raise TypeError( "All components must either be continuous or not, but continuity " "values are: %s" % [(d.name, d.is_continuous) for d in components]) static_event_shape = components[0].get_event_shape() static_batch_shape = cat.get_batch_shape() for d in components: static_event_shape = static_event_shape.merge_with( d.get_event_shape()) static_batch_shape = static_batch_shape.merge_with( d.get_batch_shape()) if static_event_shape.ndims is None: raise ValueError( "Expected to know rank(event_shape) from components, but " "none of the components provide a static number of ndims") # Ensure that all batch and event ndims are consistent. with ops.name_scope(name, values=[cat.logits]) as ns: num_components = cat.num_classes static_num_components = tensor_util.constant_value(num_components) if static_num_components is None: raise ValueError( "Could not infer number of classes from cat and unable " "to compare this value to the number of components passed in." ) # Possibly convert from numpy 0-D array. static_num_components = int(static_num_components) if static_num_components != len(components): raise ValueError( "cat.num_classes != len(components): %d vs. %d" % (static_num_components, len(components))) cat_batch_shape = cat.batch_shape() cat_batch_rank = array_ops.size(cat_batch_shape) if validate_args: batch_shapes = [d.batch_shape() for d in components] batch_ranks = [array_ops.size(bs) for bs in batch_shapes] check_message = ("components[%d] batch shape must match cat " "batch shape") self._assertions = [ check_ops.assert_equal(cat_batch_rank, batch_ranks[di], message=check_message % di) for di in range(len(components)) ] self._assertions += [ check_ops.assert_equal(cat_batch_shape, batch_shapes[di], message=check_message % di) for di in range(len(components)) ] else: self._assertions = [] self._cat = cat self._components = list(components) self._num_components = static_num_components self._static_event_shape = static_event_shape self._static_batch_shape = static_batch_shape # We let the Mixture distribution access _graph_parents since its arguably # more like a baseclass. graph_parents = self._cat._graph_parents # pylint: disable=protected-access for c in self._components: graph_parents += c._graph_parents # pylint: disable=protected-access super(Mixture, self).__init__(dtype=dtype, is_reparameterized=False, is_continuous=is_continuous, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=graph_parents, name=ns)
def testVariableV1(self): var = variables.VariableV1(1.0, name="variable_node") self.assertIsNone(tensor_util.constant_value(var))
def testShape(self): np_val = np.array([1, 2, 3], dtype=np.int32) tf_val = array_ops.shape(constant_op.constant(0.0, shape=[1, 2, 3])) c_val = tensor_util.constant_value(tf_val) self.assertAllEqual(np_val, c_val) self.assertEqual(np.int32, c_val.dtype)
def testFill(self): np_val = np.array([-1, -1, -1], dtype=np.float32) tf_val = array_ops.fill([3], constant_op.constant(-1.0)) c_val = tensor_util.constant_value(tf_val) self.assertAllEqual(np_val, c_val) self.assertEqual(np.float32, c_val.dtype)
def testSize(self): tf_val = array_ops.size(constant_op.constant(0.0, shape=[1, 2, 3])) c_val = tensor_util.constant_value(tf_val) self.assertEqual(6, c_val)
def testSizeOfScalar(self): tf_val = array_ops.size(constant_op.constant(0.0)) c_val = tensor_util.constant_value(tf_val) self.assertEqual(1, c_val) self.assertEqual(np.ndarray, type(c_val))
def _broadcast_to_ragged_shape(rt_input, dst_shape, broadcast_inner_dimensions): """Broadcasts rt_input to the ragged shape `dst_shape`.""" # dst_shape's rank and ragged_rank must be greater than or equal to rt_input's if rt_input.shape.ndims is None or dst_shape.rank is None: raise ValueError('Unable to broadcast: unknown rank') if rt_input.shape.ndims > dst_shape.rank: raise ValueError('Incompatible with shape: rank mismatch') if (isinstance(rt_input, ragged_tensor.RaggedTensor) and rt_input.ragged_rank >= dst_shape.num_partitioned_dimensions): raise ValueError('Incompatible with shape: ragged rank mismatch') src_shape = RaggedTensorDynamicShape.from_tensor(rt_input) src_shape = src_shape.broadcast_to_rank(dst_shape.rank) # Add dimensions to rt_input so its rank and ragged_rank matches dst_shape. if dst_shape.rank > rt_input.shape.ndims: if rt_input.shape.ndims < dst_shape.num_inner_dimensions + 1: rt_input = array_ops.reshape( rt_input, array_ops.concat([[-1], dst_shape.inner_dim_sizes], axis=0)) for _ in range(dst_shape.rank - rt_input.shape.ndims): rt_input = ragged_factory_ops.from_row_lengths( rt_input, [ragged_array_ops.nrows(rt_input)]) # Add ragged dimensions to match dst_shape. if ragged_tensor.is_ragged(rt_input): inner_rank_diff = (rt_input.inner_values.shape.ndims - 1 - dst_shape.num_inner_dimensions) if inner_rank_diff > 0: rt_input = rt_input.with_inner_values( ragged_conversion_ops.from_tensor(rt_input.inner_values, ragged_rank=inner_rank_diff)) else: rt_input = ragged_conversion_ops.from_tensor( rt_input, ragged_rank=dst_shape.num_partitioned_dimensions - 1) # Do broadcasting for any dimensions that will remain uniform. We can do # these all at once, since they're independent of one another. multiples = [1] * dst_shape.rank for axis in range(dst_shape.num_partitioned_dimensions): if not src_shape.is_ragged(axis) and not dst_shape.is_ragged(axis): src_size = src_shape.dimension_size(axis) dst_size = dst_shape.dimension_size(axis) if ((tensor_util.constant_value(src_size) in (1, None)) and (tensor_util.constant_value(dst_size) != 1)): multiples[axis] = array_ops.where(math_ops.equal(src_size, 1), dst_size, 1) if not all(isinstance(v, int) and v == 1 for v in multiples): multiples = array_ops.stack(multiples, axis=0) rt_input = ragged_array_ops.tile(rt_input, multiples) if broadcast_inner_dimensions: rt_input = rt_input.with_inner_values( array_ops.reshape( rt_input.inner_values, array_ops.concat([[-1], dst_shape.inner_dim_sizes], axis=0))) # Do broadcasting for dimensions that become ragged. We must do these from # outermost to innermost. for axis in range(dst_shape.num_partitioned_dimensions): if not src_shape.is_ragged(axis) and dst_shape.is_ragged(axis): dst_size = dst_shape.dimension_size(axis) rt_input = _ragged_tile_axis(rt_input, axis, dst_size) return rt_input
def evaluate(graph, output_dir, checkpoint_path, eval_dict, update_op=None, global_step_tensor=None, supervisor_master='', log_every_steps=10, feed_fn=None, max_steps=None): """Evaluate a model loaded from a checkpoint. Given `graph`, a directory to write summaries to (`output_dir`), a checkpoint to restore variables from, and a `dict` of `Tensor`s to evaluate, run an eval loop for `max_steps` steps. In each step of evaluation, all tensors in the `eval_dict` are evaluated, and every `log_every_steps` steps, they are logged. At the very end of evaluation, a summary is evaluated (finding the summary ops using `Supervisor`'s logic) and written to `output_dir`. Args: graph: A `Graph` to train. It is expected that this graph is not in use elsewhere. output_dir: A string containing the directory to write a summary to. checkpoint_path: A string containing the path to a checkpoint to restore. Can be `None` if the graph doesn't require loading any variables. eval_dict: A `dict` mapping string names to tensors to evaluate. It is evaluated in every logging step. The result of the final evaluation is returned. If update_op is None, then it's evaluated in every step. update_op: A `Tensor` which is run in every step. global_step_tensor: A `Variable` containing the global step. If `None`, one is extracted from the graph using the same logic as in `Supervisor`. Used to place eval summaries on training curves. supervisor_master: The master string to use when preparing the session. log_every_steps: Integer. Output logs every `log_every_steps` evaluation steps. The logs contain the `eval_dict` and timing information. feed_fn: A function that is called every iteration to produce a `feed_dict` passed to `session.run` calls. Optional. max_steps: Integer. Evaluate `eval_dict` this many times. Returns: A tuple `(eval_results, global_step)`: eval_results: A `dict` mapping `string` to numeric values (`int`, `float`) that are the result of running eval_dict in the last step. `None` if no eval steps were run. global_step: The global step this evaluation corresponds to. """ global_step_tensor = contrib_variables.assert_or_get_global_step( graph, global_step_tensor) # Add scalar summaries for every tensor in evaluation dict if there is not # one existing already or it's a string. existing_tags = [ tensor_util.constant_value(summary.op.inputs[0]) for summary in ops.get_collection(ops.GraphKeys.SUMMARIES) ] for key, value in eval_dict.items(): if key in existing_tags: continue if isinstance(value, ops.Tensor): summaries.summarize_tensor(value, tag=key) # Create or get summary op, global_step and saver. summary_op = logging_ops.get_summary_op() saver = _get_saver() local_init_op = _get_local_init_op() ready_op = _get_ready_op() session_manager = session_manager_lib.SessionManager( local_init_op=local_init_op, ready_op=ready_op) session, initialized = session_manager.recover_session( master=supervisor_master, saver=saver, checkpoint_dir=checkpoint_path) # Start queue runners. coord = coordinator.Coordinator() threads = _start_queue_runners(session, coord) with session: if not initialized: logging.warning('Failed to initialize from %s.', checkpoint_path) # TODO(ipolosukhin): This should be failing, but old code relies on that. session.run(variables.initialize_all_variables()) if checkpoint_path: _restore_from_checkpoint(session, graph, checkpoint_path, saver) current_global_step = session.run(global_step_tensor) eval_results = None # TODO(amodei): Fix this to run through the eval set exactly once. step = 0 logging.info('Eval steps [%d,%s) for training step %d.', step, 'inf' if max_steps is None else str(max_steps), current_global_step) try: try: while (max_steps is None) or (step < max_steps): start_time = time.time() feed_dict = feed_fn() if feed_fn is not None else None eval_results = None if update_op is not None: session.run(update_op, feed_dict=feed_dict) else: eval_results = _run_dict(session, eval_dict, feed_dict=feed_dict) # TODO(wicke): We should assert that the global step hasn't changed. step += 1 if step % log_every_steps == 0: if eval_results is None: eval_results = _run_dict(session, eval_dict, feed_dict=feed_dict) duration = time.time() - start_time logging.info( 'Results after %d steps (%.3f sec/batch): %s.', step, float(duration), ', '.join('%s = %s' % (k, v) for k, v in eval_results.items())) finally: if eval_results is None: eval_results = _run_dict(session, eval_dict, feed_dict=feed_dict) # Stop queue runners. coord.request_stop() coord.join(threads, stop_grace_period_secs=120) # Make our own summary writer and write a summary to the eval dir. # Only is feed_fn is not provided. # TODO(ipolosukhin): Convert evaluation to use streaming_metrics, # then we can save for non feed_fn as well. if summary_op is not None and feed_fn is None: summary_writer = None try: summary_writer = SummaryWriter( output_dir, graph_def=session.graph_def) summary_str = session.run(summary_op) if summary_str: summary_writer.add_summary(summary_str, current_global_step) finally: if summary_writer: summary_writer.close() # catch OutOfRangeError which is thrown when queue is out of data (and for # other reasons as well). except errors.OutOfRangeError as e: if max_steps is None: logging.info('Input queue is exhausted.') else: logging.warn('Input queue is exhausted: %s.', e) # catch StopIteration which is thrown is DataReader is out of data. except StopIteration as e: if max_steps is None: logging.info('Input iterator is exhausted.') else: logging.warn('Input iterator is exhausted: %s.', e) return eval_results, current_global_step
def resize_images(images, new_height, new_width, method=ResizeMethod.BILINEAR, align_corners=False): """Resize `images` to `new_width`, `new_height` using the specified `method`. Resized images will be distorted if their original aspect ratio is not the same as `new_width`, `new_height`. To avoid distortions see [`resize_image_with_crop_or_pad`](#resize_image_with_crop_or_pad). `method` can be one of: * <b>`ResizeMethod.BILINEAR`</b>: [Bilinear interpolation.] (https://en.wikipedia.org/wiki/Bilinear_interpolation) * <b>`ResizeMethod.NEAREST_NEIGHBOR`</b>: [Nearest neighbor interpolation.] (https://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) * <b>`ResizeMethod.BICUBIC`</b>: [Bicubic interpolation.] (https://en.wikipedia.org/wiki/Bicubic_interpolation) * <b>`ResizeMethod.AREA`</b>: Area interpolation. Args: images: 4-D Tensor of shape `[batch, height, width, channels]` or 3-D Tensor of shape `[height, width, channels]`. new_height: integer. new_width: integer. method: ResizeMethod. Defaults to `ResizeMethod.BILINEAR`. align_corners: bool. If true, exactly align all 4 cornets of the input and output. Defaults to `false`. Raises: ValueError: if the shape of `images` is incompatible with the shape arguments to this function ValueError: if an unsupported resize method is specified. Returns: If `images` was 4-D, a 4-D float Tensor of shape `[batch, new_height, new_width, channels]`. If `images` was 3-D, a 3-D float Tensor of shape `[new_height, new_width, channels]`. """ if images.get_shape().ndims is None: raise ValueError('\'images\' contains no shape.') # TODO(shlens): Migrate this functionality to the underlying Op's. is_batch = True if len(images.get_shape()) == 3: is_batch = False images = array_ops.expand_dims(images, 0) _, height, width, depth = _ImageDimensions(images) # Handle tensor-valued sizes as well as Python integers. try: new_width = ops.convert_to_tensor(new_width, dtypes.int32, name='new_width') new_width.get_shape().assert_has_rank(0) except (TypeError, ValueError): raise ValueError('new_width must be a scalar integer') try: new_height = ops.convert_to_tensor(new_height, dtypes.int32, name='new_height') new_height.get_shape().assert_has_rank(0) except (TypeError, ValueError): raise ValueError('new_height must be a scalar integer') new_width_const = tensor_util.constant_value(new_width) new_height_const = tensor_util.constant_value(new_height) if width == new_width_const and height == new_height_const: if not is_batch: images = array_ops.squeeze(images, squeeze_dims=[0]) return images new_size = array_ops.pack([new_height, new_width]) if method == ResizeMethod.BILINEAR: images = gen_image_ops.resize_bilinear(images, new_size, align_corners=align_corners) elif method == ResizeMethod.NEAREST_NEIGHBOR: images = gen_image_ops.resize_nearest_neighbor( images, new_size, align_corners=align_corners) elif method == ResizeMethod.BICUBIC: images = gen_image_ops.resize_bicubic(images, new_size, align_corners=align_corners) elif method == ResizeMethod.AREA: images = gen_image_ops.resize_area(images, new_size, align_corners=align_corners) else: raise ValueError('Resize method is not implemented.') # NOTE(mrry): The shape functions for the resize ops cannot unpack # the packed values in `new_size`, so set the shape here. images.set_shape([None, new_height_const, new_width_const, None]) if not is_batch: images = array_ops.squeeze(images, squeeze_dims=[0]) return images
def _introspect_ndims(self, ndims): """Helper to establish some properties of input ndims args.""" if self._is_all_constant_helper(ndims): return (tensor_util.constant_value(ndims), tensor_util.constant_value(ndims) == 0) return None, math_ops.equal(ndims, 0)
def testNumpyNdarray(self): np_val = np.random.rand(3, 4, 7).astype(np.float32) self.assertIs(np_val, tensor_util.constant_value(np_val))
def _is_all_constant_helper(self, *args): """Helper which returns True if all inputs are constant_value.""" return all(tensor_util.constant_value(x) is not None for x in args)
def testLiteral(self): x = "hi" self.assertIs(x, tensor_util.constant_value(x))
def _sample_n(self, n, seed=None): with ops.control_dependencies(self._assertions): n = ops.convert_to_tensor(n, name="n") static_n = tensor_util.constant_value(n) n = int(static_n) if static_n is not None else n cat_samples = self.cat.sample_n(n, seed=seed) static_samples_shape = cat_samples.get_shape() if static_samples_shape.is_fully_defined(): samples_shape = static_samples_shape.as_list() samples_size = static_samples_shape.num_elements() else: samples_shape = array_ops.shape(cat_samples) samples_size = array_ops.size(cat_samples) static_batch_shape = self.get_batch_shape() if static_batch_shape.is_fully_defined(): batch_shape = static_batch_shape.as_list() batch_size = static_batch_shape.num_elements() else: batch_shape = self.batch_shape() batch_size = array_ops.reduce_prod(batch_shape) static_event_shape = self.get_event_shape() if static_event_shape.is_fully_defined(): event_shape = np.array(static_event_shape.as_list(), dtype=np.int32) else: event_shape = self.event_shape() # Get indices into the raw cat sampling tensor. We will # need these to stitch sample values back out after sampling # within the component partitions. samples_raw_indices = array_ops.reshape( math_ops.range(0, samples_size), samples_shape) # Partition the raw indices so that we can use # dynamic_stitch later to reconstruct the samples from the # known partitions. partitioned_samples_indices = data_flow_ops.dynamic_partition( data=samples_raw_indices, partitions=cat_samples, num_partitions=self.num_components) # Copy the batch indices n times, as we will need to know # these to pull out the appropriate rows within the # component partitions. batch_raw_indices = array_ops.reshape( array_ops.tile(math_ops.range(0, batch_size), [n]), samples_shape) # Explanation of the dynamic partitioning below: # batch indices are i.e., [0, 1, 0, 1, 0, 1] # Suppose partitions are: # [1 1 0 0 1 1] # After partitioning, batch indices are cut as: # [batch_indices[x] for x in 2, 3] # [batch_indices[x] for x in 0, 1, 4, 5] # i.e. # [1 1] and [0 0 0 0] # Now we sample n=2 from part 0 and n=4 from part 1. # For part 0 we want samples from batch entries 1, 1 (samples 0, 1), # and for part 1 we want samples from batch entries 0, 0, 0, 0 # (samples 0, 1, 2, 3). partitioned_batch_indices = data_flow_ops.dynamic_partition( data=batch_raw_indices, partitions=cat_samples, num_partitions=self.num_components) samples_class = [None for _ in range(self.num_components)] for c in range(self.num_components): n_class = array_ops.size(partitioned_samples_indices[c]) seed = distribution_util.gen_new_seed(seed, "mixture") samples_class_c = self.components[c].sample_n(n_class, seed=seed) # Pull out the correct batch entries from each index. # To do this, we may have to flatten the batch shape. # For sample s, batch element b of component c, we get the # partitioned batch indices from # partitioned_batch_indices[c]; and shift each element by # the sample index. The final lookup can be thought of as # a matrix gather along locations (s, b) in # samples_class_c where the n_class rows correspond to # samples within this component and the batch_size columns # correspond to batch elements within the component. # # Thus the lookup index is # lookup[c, i] = batch_size * s[i] + b[c, i] # for i = 0 ... n_class[c] - 1. lookup_partitioned_batch_indices = ( batch_size * math_ops.range(n_class) + partitioned_batch_indices[c]) samples_class_c = array_ops.reshape( samples_class_c, array_ops.concat(0, ([n_class * batch_size], event_shape))) samples_class_c = array_ops.gather( samples_class_c, lookup_partitioned_batch_indices, name="samples_class_c_gather") samples_class[c] = samples_class_c # Stitch back together the samples across the components. lhs_flat_ret = data_flow_ops.dynamic_stitch( indices=partitioned_samples_indices, data=samples_class) # Reshape back to proper sample, batch, and event shape. ret = array_ops.reshape( lhs_flat_ret, array_ops.concat(0, (samples_shape, self.event_shape()))) ret.set_shape( tensor_shape.TensorShape(static_samples_shape).concatenate( self.get_event_shape())) return ret
def __init__(self, df, scale_operator_pd, cholesky_input_output_matrices=False, validate_args=False, allow_nan_stats=True, name=None): """Construct Wishart distributions. Args: df: `float` or `double` tensor, the degrees of freedom of the distribution(s). `df` must be greater than or equal to `k`. scale_operator_pd: `float` or `double` instance of `OperatorPDBase`. cholesky_input_output_matrices: Python `bool`. Any function which whose input or output is a matrix assumes the input is Cholesky and returns a Cholesky factored matrix. Example `log_prob` input takes a Cholesky and `sample_n` returns a Cholesky when `cholesky_input_output_matrices=True`. validate_args: Python `bool`, default `False`. When `True` distribution parameters are checked for validity despite possibly degrading runtime performance. When `False` invalid inputs may silently render incorrect outputs. allow_nan_stats: Python `bool`, default `True`. When `True`, statistics (e.g., mean, mode, variance) use the value "`NaN`" to indicate the result is undefined. When `False`, an exception is raised if one or more of the statistic's batch members are undefined. name: Python `str` name prefixed to Ops created by this class. Raises: TypeError: if scale is not floating-type TypeError: if scale.dtype != df.dtype ValueError: if df < k, where scale operator event shape is `(k, k)` """ parameters = locals() self._cholesky_input_output_matrices = cholesky_input_output_matrices with ops.name_scope(name): with ops.name_scope("init", values=[df, scale_operator_pd]): if not scale_operator_pd.dtype.is_floating: raise TypeError( "scale_operator_pd.dtype=%s is not a floating-point type" % scale_operator_pd.dtype) self._scale_operator_pd = scale_operator_pd self._df = ops.convert_to_tensor( df, dtype=scale_operator_pd.dtype, name="df") contrib_tensor_util.assert_same_float_dtype( (self._df, self._scale_operator_pd)) if (self._scale_operator_pd.get_shape().ndims is None or self._scale_operator_pd.get_shape()[-1].value is None): self._dimension = math_ops.cast( self._scale_operator_pd.vector_space_dimension(), dtype=self._scale_operator_pd.dtype, name="dimension") else: self._dimension = ops.convert_to_tensor( self._scale_operator_pd.get_shape()[-1].value, dtype=self._scale_operator_pd.dtype, name="dimension") df_val = tensor_util.constant_value(self._df) dim_val = tensor_util.constant_value(self._dimension) if df_val is not None and dim_val is not None: df_val = np.asarray(df_val) if not df_val.shape: df_val = [df_val] if any(df_val < dim_val): raise ValueError( "Degrees of freedom (df = %s) cannot be less than " "dimension of scale matrix (scale.dimension = %s)" % (df_val, dim_val)) elif validate_args: assertions = check_ops.assert_less_equal( self._dimension, self._df, message=("Degrees of freedom (df = %s) cannot be " "less than dimension of scale matrix " "(scale.dimension = %s)" % (self._dimension, self._df))) self._df = control_flow_ops.with_dependencies( [assertions], self._df) super(_WishartOperatorPD, self).__init__( dtype=self._scale_operator_pd.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=distribution.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=([self._df, self._dimension] + self._scale_operator_pd.inputs), name=name)
def assert_broadcastable(weights, values): """Asserts `weights` can be broadcast to `values`. In `tf.losses` and `tf.metrics`, we support limited weight broadcasting. We let weights be either scalar, or the same rank as the target values, with each dimension either 1, or the same as the corresponding values dimension. Args: weights: `Tensor` of weights. values: `Tensor` of values to which weights are applied. Returns: `Operation` raising `InvalidArgumentError` if `weights` has incorrect shape. `no_op` if static checks determine `weights` has correct shape. Raises: ValueError: If static checks determine `weights` has incorrect shape. """ with ops.name_scope(None, "assert_broadcastable", (weights, values)) as scope: with ops.name_scope(None, "weights", (weights, )) as weights_scope: weights = ops.convert_to_tensor(weights, name=weights_scope) weights_shape = array_ops.shape(weights, name="shape") weights_rank = array_ops.rank(weights, name="rank") weights_rank_static = tensor_util.constant_value(weights_rank) with ops.name_scope(None, "values", (values, )) as values_scope: values = ops.convert_to_tensor(values, name=values_scope) values_shape = array_ops.shape(values, name="shape") values_rank = array_ops.rank(values, name="rank") values_rank_static = tensor_util.constant_value(values_rank) # Try static checks. if weights_rank_static is not None and values_rank_static is not None: if weights_rank_static == 0: return control_flow_ops.no_op( name="static_scalar_check_success") if weights_rank_static != values_rank_static: raise ValueError( "%s values.rank=%s. weights.rank=%s." " values.shape=%s. weights.shape=%s." % (_ASSERT_BROADCASTABLE_ERROR_PREFIX, values_rank_static, weights_rank_static, values.shape, weights.shape)) weights_shape_static = tensor_util.constant_value(weights_shape) values_shape_static = tensor_util.constant_value(values_shape) if weights_shape_static is not None and values_shape_static is not None: # Sanity check, this should always be true since we checked rank above. ndims = len(values_shape_static) assert ndims == len(weights_shape_static) for i in range(ndims): if weights_shape_static[i] not in (1, values_shape_static[i]): raise ValueError( "%s Mismatch at dim %s. values.shape=%s weights.shape=%s." % (_ASSERT_BROADCASTABLE_ERROR_PREFIX, i, values_shape_static, weights_shape_static)) return control_flow_ops.no_op(name="static_dims_check_success") # Dynamic checks. is_scalar = math_ops.equal(0, weights_rank, name="is_scalar") data = ( _ASSERT_BROADCASTABLE_ERROR_PREFIX, "weights.shape=", weights.name, weights_shape, "values.shape=", values.name, values_shape, "is_scalar=", is_scalar, ) is_valid_shape = control_flow_ops.cond( is_scalar, lambda: is_scalar, lambda: _has_valid_nonscalar_shape( # pylint: disable=g-long-lambda weights_rank, weights_shape, values_rank, values_shape), name="is_valid_shape") return control_flow_ops.Assert(is_valid_shape, data, name=scope)
def static_value(x): """Returns the static value of a `Tensor` or `None`.""" return tensor_util.constant_value(ops.convert_to_tensor(x))
def assert_equal(x, y, data=None, summarize=None, message=None, name=None): """Assert the condition `x == y` holds element-wise. Example of adding a dependency to an operation: ```python with tf.control_dependencies([tf.assert_equal(x, y)]): output = tf.reduce_sum(x) ``` This condition holds if for every pair of (possibly broadcast) elements `x[i]`, `y[i]`, we have `x[i] == y[i]`. If both `x` and `y` are empty, this is trivially satisfied. Args: x: Numeric `Tensor`. y: Numeric `Tensor`, same dtype as and broadcastable to `x`. data: The tensors to print out if the condition is False. Defaults to error message and first few entries of `x`, `y`. summarize: Print this many entries of each tensor. message: A string to prefix to the default message. name: A name for this operation (optional). Defaults to "assert_equal". Returns: Op that raises `InvalidArgumentError` if `x == y` is False. @compatibility{eager} returns None Raises: InvalidArgumentError: if the check can be performed immediately and `x == y` is False. The check can be performed immediately during eager execution or if `x` and `y` are statically known. """ message = message or '' with ops.name_scope(name, 'assert_equal', [x, y, data]): x = ops.convert_to_tensor(x, name='x') y = ops.convert_to_tensor(y, name='y') if context.in_eager_mode(): eq = math_ops.equal(x, y) condition = math_ops.reduce_all(eq) if not condition: # Prepare a message with first elements of x and y. summary_msg = '' # Default to printing 3 elements like control_flow_ops.Assert (used # by graph mode) does. summarize = 3 if summarize is None else summarize if summarize: # reshape((-1,)) is the fastest way to get a flat array view. x_np = x.numpy().reshape((-1, )) y_np = y.numpy().reshape((-1, )) x_sum = min(x_np.size, summarize) y_sum = min(y_np.size, summarize) summary_msg = ('First %d elements of x:\n%s\n' 'First %d elements of y:\n%s\n' % (x_sum, x_np[:x_sum], y_sum, y_np[:y_sum])) # Get the values that actually differed and their indices. mask = math_ops.logical_not(eq) indices = array_ops.where(mask) indices_np = indices.numpy() x_vals = array_ops.boolean_mask(x, mask) y_vals = array_ops.boolean_mask(y, mask) summarize = min(summarize, indices_np.shape[0]) raise errors.InvalidArgumentError( node_def=None, op=None, message=('%s\nCondition x == y did not hold.\n' 'Indices of first %s different values:\n%s\n' 'Corresponding x values:\n%s\n' 'Corresponding y values:\n%s\n' '%s' % (message or '', summarize, indices_np[:summarize], x_vals.numpy().reshape( (-1, ))[:summarize], y_vals.numpy().reshape( (-1, ))[:summarize], summary_msg))) return if data is None: data = [ message, 'Condition x == y did not hold element-wise:', 'x (%s) = ' % x.name, x, 'y (%s) = ' % y.name, y ] condition = math_ops.reduce_all(math_ops.equal(x, y)) x_static = tensor_util.constant_value(x) y_static = tensor_util.constant_value(y) if x_static is not None and y_static is not None: condition_static = (x_static == y_static).all() _assert_static(condition_static, data) return control_flow_ops.Assert(condition, data, summarize=summarize)
def devices(self): distribute_lib.require_replica_context(self) replica_id = tensor_util.constant_value(self._replica_id_in_sync_group) return [ self._distribution_strategy.extended.worker_devices[replica_id] ]
def testIdentity(self): input_ = np.random.rand(4, 7) tf_val = array_ops.identity(input_) c_val = tensor_util.constant_value(tf_val) self.assertAllEqual(input_, c_val)
def _GatherV2Grad(op, grad): """Gradient for GatherV2 op.""" # params can be large, so colocate the shape calculation with it. # # params can be very large for sparse model, array_ops.shape raises # exception on the Windows platform when any dimension is larger than # int32. params_shape is not used in optimizer apply_sparse gradients, # so it's fine to convert it back to int32 regardless of truncation. params = op.inputs[0] with ops.colocate_with(params): params_shape = array_ops.shape(params, out_type=ops.dtypes.int64) params_shape = math_ops.cast(params_shape, dtypes.int32) indices = op.inputs[1] indices_size = array_ops.expand_dims(array_ops.size(indices), 0) axis = op.inputs[2] axis_static = tensor_util.constant_value(axis) batch_dims = int(op.get_attr("batch_dims")) if batch_dims < 0: batch_dims += indices.shape.ndims # For axis 0 gathers, build an appropriately shaped IndexedSlices. if axis_static == 0: if context.executing_eagerly(): params_tail_shape = params_shape.cpu()[1:] else: params_tail_shape = params_shape[1:] values_shape = array_ops.concat([indices_size, params_tail_shape], 0) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="Converting sparse IndexedSlices to a dense Tensor.*") values = array_ops.reshape(grad, values_shape) indices = array_ops.reshape(indices, indices_size) params_grad = ops.IndexedSlices(values, indices, params_shape) else: # Handle axis by transposing the axis dimension to be the first non-batch # dimension, compute the gradiend and transpose the result back. outer_shape = params_shape[:axis] inner_shape = params_shape[axis:][1:] values_shape = array_ops.concat([outer_shape, [-1], inner_shape], 0) values_dims = array_ops.size(values_shape) axis_dims = array_ops.size(outer_shape) outer_batches_indices = math_ops.range(batch_dims) batch_axis_indices = math_ops.range(batch_dims, axis_dims) inner_axes_indices = math_ops.range(axis_dims + 1, values_dims) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="Converting sparse IndexedSlices to a dense Tensor.*") values = array_ops.reshape(grad, values_shape) # Move values[axis] up to values[batch_dims] transpose_dims = array_ops.concat( [outer_batches_indices, [axis_dims], batch_axis_indices, inner_axes_indices], 0) values_transpose = array_ops.transpose(values, transpose_dims) params_grad = _BatchGatherGrad(params_shape, values_transpose, indices, batch_dims, params_shape[axis]) # Inverts the above transpose by moving dimension batch_dims back to its # original position. invert_transpose_dims = array_ops.concat( [outer_batches_indices, batch_axis_indices + 1, [batch_dims], inner_axes_indices], 0) params_grad = array_ops.transpose(params_grad, invert_transpose_dims) return [params_grad, None, None]
def testStopGradient(self): input_ = np.random.rand(4, 7) tf_val = array_ops.stop_gradient(input_) c_val = tensor_util.constant_value(tf_val) self.assertAllEqual(input_, c_val)
def testSplit_Axis0(self): inputs = np.random.rand(6, 5, 7) tf_vals = array_ops.split(inputs, 3) c_vals = [tensor_util.constant_value(x) for x in tf_vals] self.assertAllClose(np.split(inputs, 3), c_vals)
def test_loop(model, ins, batch_size=None, verbose=0, steps=None): """Abstract method to loop over some data in batches. Arguments: model: Model instance that is being evaluated in Eager mode. ins: list of tensors to be fed to `f`. batch_size: integer batch size or `None`. verbose: verbosity mode. steps: Total number of steps (batches of samples) before declaring predictions finished. Ignored with the default value of `None`. Returns: Scalar loss (if the model has a single output and no metrics) or list of scalars (if the model has multiple outputs and/or metrics). The attribute `model.metrics_names` will give you the display labels for the scalar outputs. """ K.set_learning_phase(False) num_samples = model._check_num_samples(ins, batch_size, steps, 'steps') outs = [] if verbose == 1: progbar = Progbar(target=num_samples) batches = make_batches(num_samples, batch_size) index_array = np.arange(num_samples) for batch_index, (batch_start, batch_end) in enumerate(batches): batch_ids = index_array[batch_start:batch_end] if isinstance(ins[-1], float): # Do not slice the training phase flag. ins_batch = slice_arrays(ins[:-1], batch_ids) + [ins[-1]] else: ins_batch = slice_arrays(ins, batch_ids) ins_batch_converted = [] for ib in ins_batch: ins_batch_converted.append( ops.convert_to_tensor(ib, dtype=K.floatx())) eager_model_inputs = [] eager_model_outputs = [] for i in range(len(model.inputs)): eager_model_inputs.append(ins_batch_converted[i]) for i in range(len(model.inputs), len(ins_batch_converted)): eager_model_outputs.append(ins_batch_converted[i]) loss_outs, loss, loss_metrics = _model_loss(model, eager_model_inputs, eager_model_outputs, training=False) _, metrics_results = _eager_metrics_fn(model, loss_outs, eager_model_outputs) batch_outs = [] for _, v in zip(model.metrics_names, [K.mean(loss)] + loss_metrics + metrics_results): batch_outs.append(tensor_util.constant_value(v)) if isinstance(batch_outs, list): if batch_index == 0: for batch_out in enumerate(batch_outs): outs.append(0.) for i, batch_out in enumerate(batch_outs): outs[i] += batch_out * len(batch_ids) else: if batch_index == 0: outs.append(0.) outs[0] += batch_outs * len(batch_ids) if verbose == 1: progbar.update(batch_end) for i in range(len(outs)): outs[i] /= num_samples if len(outs) == 1: return outs[0] return outs
def __init__(self, df, scale_operator_pd, cholesky_input_output_matrices=False, validate_args=False, allow_nan_stats=True, name=None): """Construct Wishart distributions. Args: df: `float` or `double` tensor, the degrees of freedom of the distribution(s). `df` must be greater than or equal to `k`. scale_operator_pd: `float` or `double` instance of `OperatorPDBase`. cholesky_input_output_matrices: `Boolean`. Any function which whose input or output is a matrix assumes the input is Cholesky and returns a Cholesky factored matrix. Example`log_pdf` input takes a Cholesky and `sample_n` returns a Cholesky when `cholesky_input_output_matrices=True`. validate_args: `Boolean`, default `False`. Whether to validate input with asserts. If `validate_args` is `False`, and the inputs are invalid, correct behavior is not guaranteed. allow_nan_stats: `Boolean`, default `True`. If `False`, raise an exception if a statistic (e.g., mean, mode) is undefined for any batch member. If True, batch members with valid parameters leading to undefined statistics will return `NaN` for this statistic. name: The name to give Ops created by the initializer. Raises: TypeError: if scale is not floating-type TypeError: if scale.dtype != df.dtype ValueError: if df < k, where scale operator event shape is `(k, k)` """ parameters = locals() parameters.pop("self") self._cholesky_input_output_matrices = cholesky_input_output_matrices with ops.name_scope(name) as ns: with ops.name_scope("init", values=[df, scale_operator_pd]): if not scale_operator_pd.dtype.is_floating: raise TypeError( "scale_operator_pd.dtype=%s is not a floating-point type" % scale_operator_pd.dtype) self._scale_operator_pd = scale_operator_pd self._df = ops.convert_to_tensor(df, dtype=scale_operator_pd.dtype, name="df") contrib_tensor_util.assert_same_float_dtype( (self._df, self._scale_operator_pd)) if (self._scale_operator_pd.get_shape().ndims is None or self._scale_operator_pd.get_shape()[-1].value is None): self._dimension = math_ops.cast( self._scale_operator_pd.vector_space_dimension(), dtype=self._scale_operator_pd.dtype, name="dimension") else: self._dimension = ops.convert_to_tensor( self._scale_operator_pd.get_shape()[-1].value, dtype=self._scale_operator_pd.dtype, name="dimension") df_val = tensor_util.constant_value(self._df) dim_val = tensor_util.constant_value(self._dimension) if df_val is not None and dim_val is not None: df_val = np.asarray(df_val) if not df_val.shape: df_val = (df_val, ) if any(df_val < dim_val): raise ValueError( "Degrees of freedom (df = %s) cannot be less than dimension of " "scale matrix (scale.dimension = %s)" % (df_val, dim_val)) elif validate_args: assertions = check_ops.assert_less_equal( self._dimension, self._df, message=( "Degrees of freedom (df = %s) cannot be less than " "dimension of scale matrix (scale.dimension = %s)" % (self._dimension, self._df))) self._df = control_flow_ops.with_dependencies([assertions], self._df) super(_WishartOperatorPD, self).__init__(dtype=self._scale_operator_pd.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, is_continuous=True, is_reparameterized=True, parameters=parameters, graph_parents=([self._df, self._dimension] + self._scale_operator_pd.inputs), name=ns)