def log_combinations(n, counts, name="log_combinations"): """Multinomial coefficient. Given `n` and `counts`, where `counts` has last dimension `k`, we compute the multinomial coefficient as: ```n! / sum_i n_i!``` where `i` runs over all `k` classes. Args: n: Numeric `Tensor` broadcastable with `counts`. This represents `n` outcomes. counts: Numeric `Tensor` broadcastable with `n`. This represents counts in `k` classes, where `k` is the last dimension of the tensor. name: A name for this operation (optional). Returns: `Tensor` representing the multinomial coefficient between `n` and `counts`. """ # First a bit about the number of ways counts could have come in: # E.g. if counts = [1, 2], then this is 3 choose 2. # In general, this is (sum counts)! / sum(counts!) # The sum should be along the last dimension of counts. This is the # "distribution" dimension. Here n a priori represents the sum of counts. with ops.name_scope(name, values=[n, counts]): n = ops.convert_to_tensor(n, name="n") counts = ops.convert_to_tensor(counts, name="counts") total_permutations = math_ops.lgamma(n + 1) counts_factorial = math_ops.lgamma(counts + 1) redundant_permutations = math_ops.reduce_sum(counts_factorial, reduction_indices=[-1]) return total_permutations - redundant_permutations
def __init__(self, embedding, start_tokens, end_token): """Initializer. Args: embedding: A callable that takes a vector tensor of `ids` (argmax ids), or the `params` argument for `embedding_lookup`. The returned tensor will be passed to the decoder input. start_tokens: `int32` vector shaped `[batch_size]`, the start tokens. end_token: `int32` scalar, the token that marks end of decoding. Raises: ValueError: if `start_tokens` is not a 1D tensor or `end_token` is not a scalar. """ if callable(embedding): self._embedding_fn = embedding else: self._embedding_fn = ( lambda ids: embedding_ops.embedding_lookup(embedding, ids)) self._start_tokens = ops.convert_to_tensor( start_tokens, dtype=dtypes.int32, name="start_tokens") self._end_token = ops.convert_to_tensor( end_token, dtype=dtypes.int32, name="end_token") if self._start_tokens.get_shape().ndims != 1: raise ValueError("start_tokens must be a vector") self._batch_size = array_ops.size(start_tokens) if self._end_token.get_shape().ndims != 0: raise ValueError("end_token must be a scalar") self._start_inputs = self._embedding_fn(self._start_tokens)
def broadcast_weights(weights, values): """Broadcast `weights` to the same shape as `values`. This returns a version of `weights` following the same broadcast rules as `mul(weights, values)`, but limited to the weights shapes allowed by `assert_broadcastable`. When computing a weighted average, use this function to broadcast `weights` before summing them; e.g., `reduce_sum(w * v) / reduce_sum(_broadcast_weights(w, v))`. Args: weights: `Tensor` whose shape is broadcastable to `values` according to the rules of `assert_broadcastable`. values: `Tensor` of any shape. Returns: `weights` broadcast to `values` shape according to the rules of `assert_broadcastable`. """ with ops.name_scope(None, "broadcast_weights", (weights, values)) as scope: values = ops.convert_to_tensor(values, name="values") weights = ops.convert_to_tensor( weights, dtype=values.dtype.base_dtype, name="weights") # Try static check for exact match. weights_shape = weights.get_shape() values_shape = values.get_shape() if (weights_shape.is_fully_defined() and values_shape.is_fully_defined() and weights_shape.is_compatible_with(values_shape)): return weights with ops.control_dependencies((assert_broadcastable(weights, values),)): return math_ops.multiply( weights, array_ops.ones_like(values), name=scope)
def test_complex_tensor_with_imag_zero_doesnt_raise(self): x = ops.convert_to_tensor([1., 0, 3]) y = ops.convert_to_tensor([0., 0, 0]) z = math_ops.complex(x, y) with self.cached_session(): # Should not raise. linear_operator_util.assert_zero_imag_part(z, message="ABC123").run()
def __init__(self, inputs, sequence_length, time_major=False, name=None): """Initializer. Args: inputs: A (structure of) input tensors. sequence_length: An int32 vector tensor. time_major: Python bool. Whether the tensors in `inputs` are time major. If `False` (default), they are assumed to be batch major. name: Name scope for any created operations. Raises: ValueError: if `sequence_length` is not a 1D tensor. """ with ops.name_scope(name, "TrainingHelper", [inputs, sequence_length]): inputs = ops.convert_to_tensor(inputs, name="inputs") if not time_major: inputs = nest.map_structure(_transpose_batch_time, inputs) self._input_tas = nest.map_structure(_unstack_ta, inputs) self._sequence_length = ops.convert_to_tensor( sequence_length, name="sequence_length") if self._sequence_length.get_shape().ndims != 1: raise ValueError( "Expected sequence_length to be a vector, but received shape: %s" % self._sequence_length.get_shape()) self._zero_inputs = nest.map_structure( lambda inp: array_ops.zeros_like(inp[0, :]), inputs) self._batch_size = array_ops.size(sequence_length)
def init_variable(v, init, name="init"): """Initializes variable with "init". This op does the following: if init is a Tensor, v = init if callable(init): v = init(VariableShape(v), v.dtype) Args: v: Variable to initialize init: Tensor to assign to v, Or an object convertible to Tensor e.g. nparray, Or an Initializer that generates a tensor given the shape and type of v. An "Initializer" is a callable that returns a tensor that "v" should be set to. It will be called as init(shape, dtype). name: Optional name for the op. Returns: The operation that initializes v. """ with ops.name_scope(None, v.op.name + "/", [v, init]): with ops.name_scope(name) as scope: with ops.colocate_with(v): if callable(init): assert v.get_shape().is_fully_defined(), "Variable shape unknown." # TODO(mrry): Convert to v.shape when the property and # accessor are reconciled (and all initializers support # tf.TensorShape objects). value = init(v.get_shape().as_list(), v.dtype.base_dtype) value = ops.convert_to_tensor(value, name="value") return gen_state_ops.assign(v, value, name=scope) else: init = ops.convert_to_tensor(init, name="init") return gen_state_ops.assign(v, init, name=scope)
def read_and_augment_data(image_list, label_list, image_size, batch_size, max_nrof_epochs, random_crop, random_flip, random_rotate, nrof_preprocess_threads, shuffle=True): images = ops.convert_to_tensor(image_list, dtype=tf.string) labels = ops.convert_to_tensor(label_list, dtype=tf.int32) # Makes an input queue input_queue = tf.train.slice_input_producer([images, labels], num_epochs=max_nrof_epochs, shuffle=shuffle) images_and_labels = [] for _ in range(nrof_preprocess_threads): image, label = read_images_from_disk(input_queue) if random_rotate: image = tf.py_func(random_rotate_image, [image], tf.uint8) if random_crop: image = tf.random_crop(image, [image_size, image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, image_size, image_size) if random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((image_size, image_size, 3)) image = tf.image.per_image_standardization(image) images_and_labels.append([image, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size, capacity=4 * nrof_preprocess_threads * batch_size, allow_smaller_final_batch=True) return image_batch, label_batch
def test_add_weight_in_model(self): class MyModel(keras.Model): def __init__(self): super(MyModel, self).__init__() self.b = self.add_weight('bias', (10,)) self.c = self.add_weight('bias2', (10,), trainable=False) def call(self, inputs): return inputs + self.b + self.c x = ops.convert_to_tensor(np.ones((10, 10), 'float32')) model = MyModel() model(x) self.assertEqual(1, len(model.trainable_weights)) self.assertEqual(1, len(model.non_trainable_weights)) self.assertEqual(2, len(model.weights)) class MyModelCustomBuild(keras.Model): def build(self, input_shape): self.b = self.add_weight('bias', (10,)) self.c = self.add_weight('bias2', (10,), trainable=False) def call(self, inputs): return inputs + self.b + self.c x = ops.convert_to_tensor(np.ones((10, 10), 'float32')) model = MyModelCustomBuild() model(x) self.assertEqual(1, len(model.trainable_weights)) self.assertEqual(1, len(model.non_trainable_weights)) self.assertEqual(2, len(model.weights))
def __init__(self, example_indices, feature_indices, feature_values): """Creates a `SparseFeatureColumn` representation. Args: example_indices: A 1-D int64 tensor of shape `[N]`. Also, accepts python lists, or numpy arrays. feature_indices: A 1-D int64 tensor of shape `[N]`. Also, accepts python lists, or numpy arrays. feature_values: An optional 1-D tensor float tensor of shape `[N]`. Also, accepts python lists, or numpy arrays. Returns: A `SparseFeatureColumn` """ with name_scope(None, 'SparseFeatureColumn', [example_indices, feature_indices]): self._example_indices = convert_to_tensor(example_indices, name='example_indices', dtype=dtypes.int64) self._feature_indices = convert_to_tensor(feature_indices, name='feature_indices', dtype=dtypes.int64) self._feature_values = None if feature_values is not None: with name_scope(None, 'SparseFeatureColumn', [feature_values]): self._feature_values = convert_to_tensor(feature_values, name='feature_values', dtype=dtypes.float32)
def _check_labels_and_scores(boolean_labels, scores, check_shape): """Check the rank of labels/scores, return tensor versions.""" with ops.op_scope([boolean_labels, scores], '_check_labels_and_scores'): boolean_labels = ops.convert_to_tensor(boolean_labels, name='boolean_labels') scores = ops.convert_to_tensor(scores, name='scores') if boolean_labels.dtype != dtypes.bool: raise ValueError( 'Argument boolean_labels should have dtype bool. Found: %s', boolean_labels.dtype) if check_shape: labels_rank_1 = logging_ops.Assert( math_ops.equal(1, array_ops.rank(boolean_labels)), ['Argument boolean_labels should have rank 1. Found: ', boolean_labels.name, array_ops.shape(boolean_labels)]) scores_rank_1 = logging_ops.Assert( math_ops.equal(1, array_ops.rank(scores)), ['Argument scores should have rank 1. Found: ', scores.name, array_ops.shape(scores)]) with ops.control_dependencies([labels_rank_1, scores_rank_1]): return boolean_labels, scores else: return boolean_labels, scores
def __init__(self, indices, values, shape): """Creates a `SparseTensor`. Args: indices: A 2-D int64 tensor of shape `[N, ndims]`. values: A 1-D tensor of any type and shape `[N]`. shape: A 1-D int64 tensor of shape `[ndims]`. Returns: A `SparseTensor` """ with ops.name_scope(None, "SparseTensor", [indices, values, shape]): indices = ops.convert_to_tensor( indices, name="indices", dtype=dtypes.int64) # Always pass as_ref=True because we want to be able to update # values later if it is a VariableOp. # TODO(touts): Consider adding mutable_values() when 'values' # is a VariableOp and updating users of SparseTensor. values = ops.convert_to_tensor(values, name="values", as_ref=True) shape = ops.convert_to_tensor(shape, name="shape", dtype=dtypes.int64) self._indices = indices self._values = values self._shape = shape indices_shape = indices.get_shape().with_rank(2) values_shape = values.get_shape().with_rank(1) shape_shape = shape.get_shape().with_rank(1) # Assert number of rows in indices match the number of elements in values. indices_shape[0].merge_with(values_shape[0]) # Assert number of columns in indices matches the number of elements in # shape. indices_shape[1].merge_with(shape_shape[0])
def matmul(a, b, transpose_a=False, transpose_b=False, a_is_sparse=False, b_is_sparse=False, name=None): """Multiplies matrix `a` by matrix `b`, producing `a` * `b`. The inputs must be two-dimensional matrices, with matching inner dimensions, possibly after transposition. Both matrices must be of the same type. The supported types are: `float`, `double`, `int32`, `complex64`. Either matrix can be transposed on the fly by setting the corresponding flag to `True`. This is `False` by default. If one or both of the matrices contain a lot of zeros, a more efficient multiplication algorithm can be used by setting the corresponding `a_is_sparse` or `b_is_sparse` flag to `True`. These are `False` by default. For example: ```python # 2-D tensor `a` a = tf.constant([1, 2, 3, 4, 5, 6], shape=[2, 3]) => [[1. 2. 3.] [4. 5. 6.]] # 2-D tensor `b` b = tf.constant([7, 8, 9, 10, 11, 12], shape=[3, 2]) => [[7. 8.] [9. 10.] [11. 12.]] c = tf.matmul(a, b) => [[58 64] [139 154]] ``` Args: a: `Tensor` of type `float`, `double`, `int32` or `complex64`. b: `Tensor` with same type as `a`. transpose_a: If `True`, `a` is transposed before multiplication. transpose_b: If `True`, `b` is transposed before multiplication. a_is_sparse: If `True`, `a` is treated as a sparse matrix. b_is_sparse: If `True`, `b` is treated as a sparse matrix. name: Name for the operation (optional). Returns: A `Tensor` of the same type as `a`. """ with ops.op_scope([a, b], name, "MatMul") as name: a = ops.convert_to_tensor(a, name="a") b = ops.convert_to_tensor(b, name="b") if a.dtype == dtypes.float32 and (a_is_sparse or b_is_sparse): return sparse_matmul(a, b, transpose_a=transpose_a, transpose_b=transpose_b, a_is_sparse=a_is_sparse, b_is_sparse=b_is_sparse, name=name) else: return gen_math_ops._mat_mul(a, b, transpose_a=transpose_a, transpose_b=transpose_b, name=name)
def __init__(self, partitioned_dim_sizes, inner_dim_sizes, dim_size_dtype=None): """Creates a RaggedTensorDynamicShape. Args: partitioned_dim_sizes: A `list` of 0-D or 1-D integer `Tensor`, one for each partitioned dimension. If dimension `d` is uniform, then `partitioned_dim_sizes[d]` must be an integer scalar, specifying the size of all slices across dimension `d`. If dimension `d` is ragged, then `partitioned_dim_sizes[d]` must be an integer vector, specifying the size of each slice across dimension `d`. inner_dim_sizes: A 1-D integer `Tensor`, whose length is equal to the number of inner dimensions. `inner_dim_sizes[n]` is the size of all slices across the `n`th inner dimension (which is the `(len(partitioned_dim_sizes)+n)`th dimension in the overall tensor. dim_size_dtype: dtype for dimension sizes. If not specified, then it is chosen based on the dtypes of `partitioned_dim_sizes` and `inner_dim_sizes`. """ assert isinstance(partitioned_dim_sizes, (list, tuple)) with ops.name_scope(None, 'RaggedTensorDynamicShape', (partitioned_dim_sizes, inner_dim_sizes)): partitioned_dim_sizes = tuple( ops.convert_to_tensor(size, name='partitioned_dimension_size_%d' % i) for (i, size) in enumerate(partitioned_dim_sizes)) inner_dim_sizes = ops.convert_to_tensor( inner_dim_sizes, name='inner_dim_sizes') # Validate shapes. if partitioned_dim_sizes: for axis, dimension_size in enumerate(partitioned_dim_sizes): if dimension_size.shape.ndims is None: raise ValueError( 'rank of partitioned_dim_sizes[%d] is unknown' % axis) dimension_size.shape.with_rank_at_most(1) if partitioned_dim_sizes[0].shape.ndims == 1: raise ValueError('outermost partitioned dimension must be uniform') if partitioned_dim_sizes[-1].shape.ndims == 0: raise ValueError('innermost partitioned dimension must be ragged') inner_dim_sizes.shape.assert_has_rank(1) # Convert dimension size tensors to a single dtype. if dim_size_dtype is None: dim_size_dtypes = set([p.dtype for p in partitioned_dim_sizes if p.shape.ndims == 1]) if not dim_size_dtypes: dim_size_dtype = dtypes.int64 elif len(dim_size_dtypes) == 1: dim_size_dtype = dim_size_dtypes.pop() else: if not ragged_config.auto_cast_partition_dtype(): raise ValueError('partitioned_dim_sizes must have matching dtypes') dim_size_dtype = dtypes.int64 partitioned_dim_sizes = tuple(math_ops.cast(p, dim_size_dtype) for p in partitioned_dim_sizes) inner_dim_sizes = math_ops.cast(inner_dim_sizes, dim_size_dtype) self._partitioned_dim_sizes = partitioned_dim_sizes self._inner_dim_sizes = inner_dim_sizes
def _interp_evaluate(coefficients, t0, t1, t): """Evaluate polynomial interpolation at the given time point. Args: coefficients: list of Tensor coefficients as created by `interp_fit`. t0: scalar float64 Tensor giving the start of the interval. t1: scalar float64 Tensor giving the end of the interval. t: scalar float64 Tensor giving the desired interpolation point. Returns: Polynomial interpolation of the coefficients at time `t`. """ with ops.name_scope('interp_evaluate'): t0 = ops.convert_to_tensor(t0) t1 = ops.convert_to_tensor(t1) t = ops.convert_to_tensor(t) dtype = coefficients[0].dtype assert_op = control_flow_ops.Assert( (t0 <= t) & (t <= t1), ['invalid interpolation, fails `t0 <= t <= t1`:', t0, t, t1]) with ops.control_dependencies([assert_op]): x = math_ops.cast((t - t0) / (t1 - t0), dtype) xs = [constant_op.constant(1, dtype), x] for _ in range(2, len(coefficients)): xs.append(xs[-1] * x) return _dot_product(coefficients, reversed(xs))
def saturate_cast(value, dtype, name=None): """Performs a safe saturating cast of `value` to `dtype`. This function casts the input to `dtype` without applying any scaling. If there is a danger that values would over or underflow in the cast, this op applies the appropriate clamping before the cast. Args: value: A `Tensor`. dtype: The desired output `DType`. name: A name for the operation (optional). Returns: `value` safely cast to `dtype`. """ # When casting to a type with smaller representable range, clamp. # Note that this covers casting to unsigned types as well. with ops.op_scope([value], name, "saturate_cast") as name: value = ops.convert_to_tensor(value, name="value") dtype = dtypes.as_dtype(dtype).base_dtype if value.dtype.min < dtype.min: value = maximum(value, ops.convert_to_tensor( dtype.min, dtype=value.dtype, name="min")) if value.dtype.max > dtype.max: value = minimum(value, ops.convert_to_tensor( dtype.max, dtype=value.dtype, name="max")) return cast(value, dtype, name=name)
def __init__(self, df, mu, sigma, name="StudentT"): """Construct Student's t distributions. The distributions have degree of freedom `df`, mean `mu`, and scale `sigma`. The parameters `df`, `mu`, and `sigma` must be shaped in a way that supports broadcasting (e.g. `df + mu + sigma` is a valid operation). Args: df: `float` or `double` tensor, the degrees of freedom of the distribution(s). `df` must contain only positive values. mu: `float` or `double` tensor, the means of the distribution(s). sigma: `float` or `double` tensor, the scaling factor for the distribution(s). `sigma` must contain only positive values. Note that `sigma` is not the standard deviation of this distribution. name: The name to give Ops created by the initializer. Raises: TypeError: if mu and sigma are different dtypes. """ super(StudentT, self).__init__() with ops.op_scope([df, mu, sigma], name) as scope: with ops.control_dependencies([check_ops.assert_positive(df), check_ops.assert_positive(sigma)]): self._df = ops.convert_to_tensor(df, name="df") self._mu = ops.convert_to_tensor(mu, name="mu") self._sigma = ops.convert_to_tensor(sigma, name="sigma") contrib_tensor_util.assert_same_float_dtype( (self._df, self._mu, self._sigma)) self._name = scope self._get_batch_shape = self._ones().get_shape() self._get_event_shape = tensor_shape.TensorShape([])
def __init__(self, input_dataset, map_func, batch_size, num_parallel_batches): """See `Dataset.map()` for details.""" super(_MapAndBatchDataset, self).__init__(input_dataset, map_func) self._batch_size = ops.convert_to_tensor( batch_size, dtype=dtypes.int64, name="batch_size") self._num_parallel_batches = ops.convert_to_tensor( num_parallel_batches, dtype=dtypes.int64, name="num_parallel_batches")
def testConvertToTensorPreferredDtypeIsRespected(self): self.assertEqual( ops.convert_to_tensor(0.5, preferred_dtype=dtypes.int32).dtype, dtypes.float32) self.assertEqual( ops.convert_to_tensor(0.5, preferred_dtype=dtypes.float64).dtype, dtypes.float64)
def _inplace_helper(x, i, v, op): """Applies an inplace op on (x, i, v). op is one of gen_array_ops.alias_inplace_update, gen_array_ops.alias_inplace_add, or gen_array_ops.alias_inplace_sub. If i is None, x and v must be the same shape. Computes x op v; If i is a scalar, x has a rank 1 higher than v's. Computes x[i, :] op v; Otherwise, x and v must have the same rank. Computes x[i, :] op v; Args: x: A Tensor. i: None, a scalar or a vector. v: A Tensor. op: alias_inplace_update, alias_inplace_add, or alias_inplace_sub. Returns: Returns x. """ x = ops.convert_to_tensor(x) v = ops.convert_to_tensor(v, x.dtype) if i is None: # Full tensor. return array_ops.reshape( op(array_ops.reshape(x, [1, -1]), [0], array_ops.reshape(v, [1, -1])), array_ops.shape(x)) i = math_ops.cast(i, dtypes.int32) if i.get_shape().ndims == 0: # Single 0-dim update. return op(x, array_ops.reshape(i, [1]), array_ops.expand_dims(v, 0)) return op(x, i, v)
def power_sums_tensor(array_size, power_matrix, multiplier): r"""Computes \sum_{i=0}^{N-1} A^i B (A^i)^T for N=0..(array_size + 1). Args: array_size: The number of non-trivial sums to pre-compute. power_matrix: The "A" matrix above. multiplier: The "B" matrix above Returns: A Tensor with S[N] = \sum_{i=0}^{N-1} A^i B (A^i)^T S[0] is the zero matrix S[1] is B S[2] is A B A^T + B ...and so on """ array_size = math_ops.cast(array_size, dtypes.int32) power_matrix = ops.convert_to_tensor(power_matrix) identity_like_power_matrix = linalg_ops.eye( array_ops.shape(power_matrix)[0], dtype=power_matrix.dtype) identity_like_power_matrix.set_shape( ops.convert_to_tensor(power_matrix).get_shape()) transition_powers = functional_ops.scan( lambda previous_power, _: math_ops.matmul(previous_power, power_matrix), math_ops.range(array_size - 1), initializer=identity_like_power_matrix) summed = math_ops.cumsum( array_ops.concat([ array_ops.expand_dims(multiplier, 0), math_ops.matmul( batch_times_matrix(transition_powers, multiplier), transition_powers, adjoint_b=True) ], 0)) return array_ops.concat( [array_ops.expand_dims(array_ops.zeros_like(multiplier), 0), summed], 0)
def quadrature_scheme_softmaxnormal_gauss_hermite( normal_loc, normal_scale, quadrature_size, validate_args=False, name=None): """Use Gauss-Hermite quadrature to form quadrature on `K - 1` simplex. A `SoftmaxNormal` random variable `Y` may be generated via ``` Y = SoftmaxCentered(X), X = Normal(normal_loc, normal_scale) ``` Note: for a given `quadrature_size`, this method is generally less accurate than `quadrature_scheme_softmaxnormal_quantiles`. Args: normal_loc: `float`-like `Tensor` with shape `[b1, ..., bB, K-1]`, B>=0. The location parameter of the Normal used to construct the SoftmaxNormal. normal_scale: `float`-like `Tensor`. Broadcastable with `normal_loc`. The scale parameter of the Normal used to construct the SoftmaxNormal. quadrature_size: Python `int` scalar representing the number of quadrature points. 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. name: Python `str` name prefixed to Ops created by this class. Returns: grid: Shape `[b1, ..., bB, K, quadrature_size]` `Tensor` representing the convex combination of affine parameters for `K` components. `grid[..., :, n]` is the `n`-th grid point, living in the `K - 1` simplex. probs: Shape `[b1, ..., bB, K, quadrature_size]` `Tensor` representing the associated with each grid point. """ with ops.name_scope(name, "quadrature_scheme_softmaxnormal_gauss_hermite", [normal_loc, normal_scale]): normal_loc = ops.convert_to_tensor(normal_loc, name="normal_loc") dt = normal_loc.dtype.base_dtype normal_scale = ops.convert_to_tensor( normal_scale, dtype=dt, name="normal_scale") normal_scale = maybe_check_quadrature_param( normal_scale, "normal_scale", validate_args) grid, probs = np.polynomial.hermite.hermgauss(deg=quadrature_size) grid = grid.astype(dt.dtype.as_numpy_dtype) probs = probs.astype(dt.dtype.as_numpy_dtype) probs /= np.linalg.norm(probs, ord=1, keepdims=True) probs = ops.convert_to_tensor(probs, name="probs", dtype=dt) grid = softmax( -distribution_util.pad( (normal_loc[..., array_ops.newaxis] + np.sqrt(2.) * normal_scale[..., array_ops.newaxis] * grid), axis=-2, front=True), axis=-2) # shape: [B, components, deg] return grid, probs
def stateless_random_normal(shape, seed, mean=0.0, stddev=1.0, dtype=dtypes.float32, name=None): """Outputs deterministic pseudorandom values from a normal distribution. This is a stateless version of `tf.random.normal`: if run twice with the same seeds, it will produce the same pseudorandom numbers. The output is consistent across multiple runs on the same hardware (and between CPU and GPU), but may change between versions of TensorFlow or on non-CPU/GPU hardware. Args: shape: A 1-D integer Tensor or Python array. The shape of the output tensor. seed: A shape [2] integer Tensor of seeds to the random number generator. mean: A 0-D Tensor or Python value of type `dtype`. The mean of the normal distribution. stddev: A 0-D Tensor or Python value of type `dtype`. The standard deviation of the normal distribution. dtype: The type of the output. name: A name for the operation (optional). Returns: A tensor of the specified shape filled with random normal values. """ with ops.name_scope(name, "stateless_random_normal", [shape, seed, mean, stddev]) as name: shape = random_ops._ShapeTensor(shape) # pylint: disable=protected-access mean = ops.convert_to_tensor(mean, dtype=dtype, name="mean") stddev = ops.convert_to_tensor(stddev, dtype=dtype, name="stddev") rnd = gen_stateless_random_ops.stateless_random_normal(shape, seed, dtype) return math_ops.add(rnd * stddev, mean, name=name)
def gcd(a, b, name=None): """Returns the greatest common divisor via Euclid's algorithm. Args: a: The dividend. A scalar integer `Tensor`. b: The divisor. A scalar integer `Tensor`. name: An optional name for the operation. Returns: A scalar `Tensor` representing the greatest common divisor between `a` and `b`. Raises: ValueError: If `a` or `b` are not scalar integers. """ with ops.name_scope(name, 'gcd', [a, b]): a = ops.convert_to_tensor(a) b = ops.convert_to_tensor(b) a.shape.assert_has_rank(0) b.shape.assert_has_rank(0) if not a.dtype.is_integer: raise ValueError('a must be an integer type. Got: %s' % a.dtype) if not b.dtype.is_integer: raise ValueError('b must be an integer type. Got: %s' % b.dtype) cond = lambda _, b: math_ops.greater(b, array_ops.zeros_like(b)) body = lambda a, b: [b, math_ops.mod(a, b)] a, b = control_flow_ops.while_loop(cond, body, [a, b], back_prop=False) return a
def Counter(start=0, step=1, dtype=dtypes.int64): """Creates a `Dataset` that counts from `start` in steps of size `step`. For example: ```python Dataset.count() == [0, 1, 2, ...) Dataset.count(2) == [2, 3, ...) Dataset.count(2, 5) == [2, 7, 12, ...) Dataset.count(0, -1) == [0, -1, -2, ...) Dataset.count(10, -1) == [10, 9, ...) ``` Args: start: (Optional.) The starting value for the counter. Defaults to 0. step: (Optional.) The step size for the counter. Defaults to 1. dtype: (Optional.) The data type for counter elements. Defaults to `tf.int64`. Returns: A `Dataset` of scalar `dtype` elements. """ with ops.name_scope("counter"): start = ops.convert_to_tensor(start, dtype=dtype, name="start") step = ops.convert_to_tensor(step, dtype=dtype, name="step") return dataset_ops.Dataset.from_tensors(0).repeat(None).apply( scan_ops.scan(start, lambda state, _: (state + step, state)))
def rot90(image, k=1, name=None): """Rotate an image counter-clockwise by 90 degrees. Args: image: A 3-D tensor of shape `[height, width, channels]`. k: A scalar integer. The number of times the image is rotated by 90 degrees. name: A name for this operation (optional). Returns: A rotated 3-D tensor of the same type and shape as `image`. """ with ops.name_scope(name, 'rot90', [image, k]) as scope: image = ops.convert_to_tensor(image, name='image') _Check3DImage(image, require_static=False) k = ops.convert_to_tensor(k, dtype=dtypes.int32, name='k') k.get_shape().assert_has_rank(0) k = math_ops.mod(k, 4) def _rot90(): return array_ops.transpose(array_ops.reverse_v2(image, [1]), [1, 0, 2]) def _rot180(): return array_ops.reverse_v2(image, [0, 1]) def _rot270(): return array_ops.reverse_v2(array_ops.transpose(image, [1, 0, 2]), [1]) cases = [(math_ops.equal(k, 1), _rot90), (math_ops.equal(k, 2), _rot180), (math_ops.equal(k, 3), _rot270)] ret = control_flow_ops.case(cases, default=lambda: image, exclusive=True, name=scope) ret.set_shape([None, None, image.get_shape()[2]]) return ret
def embedding_lookup(params, ids, name='embedding_lookup'): """Provides a N dimensional version of tf.embedding_lookup. Ids are flattened to a 1d tensor before being passed to embedding_lookup then, they are unflattend to match the original ids shape plus an extra leading dimension of the size of the embeddings. Args: params: List of tensors of size D0 x D1 x ... x Dn-2 x Dn-1. ids: N-dimensional tensor of B0 x B1 x .. x Bn-2 x Bn-1. Must contain indexes into params. name: Optional name for the op. Returns: A tensor of size B0 x B1 x .. x Bn-2 x Bn-1 x D1 x ... x Dn-2 x Dn-1 containing the values from the params tensor(s) for indecies in ids. Raises: ValueError: if some parameters are invalid. """ with ops.name_scope(name, 'embedding_lookup', [params, ids]): params = ops.convert_to_tensor(params) ids = ops.convert_to_tensor(ids) shape = array_ops_.shape(ids) ids_flat = array_ops_.reshape( ids, math_ops.reduce_prod(shape, keep_dims=True)) embeds_flat = nn.embedding_lookup(params, ids_flat, name) embed_shape = array_ops_.concat_v2([shape, [-1]], 0) embeds = array_ops_.reshape(embeds_flat, embed_shape) embeds.set_shape(ids.get_shape().concatenate(params.get_shape()[1:])) return embeds
def __init__(self, filenames, record_bytes, header_bytes=None, footer_bytes=None, buffer_size=None): """Creates a `FixedLengthRecordDataset`. Args: filenames: A `tf.string` tensor containing one or more filenames. record_bytes: A `tf.int64` scalar representing the number of bytes in each record. header_bytes: (Optional.) A `tf.int64` scalar representing the number of bytes to skip at the start of a file. footer_bytes: (Optional.) A `tf.int64` scalar representing the number of bytes to ignore at the end of a file. buffer_size: (Optional.) A `tf.int64` scalar representing the number of bytes to buffer when reading. """ super(FixedLengthRecordDataset, self).__init__() self._filenames = ops.convert_to_tensor( filenames, dtype=dtypes.string, name="filenames") self._record_bytes = ops.convert_to_tensor( record_bytes, dtype=dtypes.int64, name="record_bytes") self._header_bytes = _convert_optional_param_to_tensor( "header_bytes", header_bytes) self._footer_bytes = _convert_optional_param_to_tensor( "footer_bytes", footer_bytes) self._buffer_size = _convert_optional_param_to_tensor( "buffer_size", buffer_size, _DEFAULT_READER_BUFFER_SIZE_BYTES)
def fused_batch_norm( x, scale, offset, # pylint: disable=invalid-name mean=None, variance=None, epsilon=0.001, data_format="NHWC", is_training=True, name=None): r"""Batch normalization. As described in http://arxiv.org/abs/1502.03167. Args: x: Input `Tensor` of 4 dimensions. scale: A `Tensor` of 1 dimension for scaling. offset: A `Tensor` of 1 dimension for bias. mean: A `Tensor` of 1 dimension for population mean used for inference. variance: A `Tensor` of 1 dimension for population variance used for inference. epsilon: A small float number added to the variance of x. data_format: The data format for x. Either "NHWC" (default) or "NCHW". is_training: A bool value to specify if the operation is used for training or inference. name: A name for this operation (optional). Returns: y: A 4D Tensor for the normalized, scaled, offsetted x. batch_mean: A 1D Tensor for the mean of x. batch_var: A 1D Tensor for the variance of x. Raises: ValueError: If mean or variance is not None when is_training is True. """ x = ops.convert_to_tensor(x, name="input") scale = ops.convert_to_tensor(scale, name="scale") offset = ops.convert_to_tensor(offset, name="offset") if is_training: if (mean is not None) or (variance is not None): raise ValueError("Both 'mean' and 'variance' must be None " "if is_training is True.") if mean is None: mean = constant_op.constant([]) if variance is None: variance = constant_op.constant([]) # Add 1e-12 to epsilon when epsilon <= 1e-5 to prevent CUDNN exception. epsilon = epsilon if epsilon > 1e-5 else epsilon + 1e-12 # pylint: disable=protected-access y, batch_mean, batch_var, _, _ = gen_nn_ops._fused_batch_norm( x, scale, offset, mean, variance, epsilon=epsilon, data_format=data_format, is_training=is_training, name=name) return y, batch_mean, batch_var
def test_complex_tensor_with_nonzero_imag_raises(self): x = ops.convert_to_tensor([1., 2, 0]) y = ops.convert_to_tensor([1., 2, 0]) z = math_ops.complex(x, y) with self.cached_session(): with self.assertRaisesOpError("ABC123"): linear_operator_util.assert_zero_imag_part(z, message="ABC123").run()
def _generateData(self, matrix_size, batch_size, num_rhs, seed=42): np.random.seed(seed) data = np.random.normal(size=(batch_size, matrix_size, 3 + num_rhs)) diags = np.stack([data[:, :, 0], data[:, :, 1], data[:, :, 2]], axis=-2) rhs = data[:, :, 3:] return (ops.convert_to_tensor(diags, dtype=dtypes.float64), ops.convert_to_tensor(rhs, dtype=dtypes.float64))
def __init__(self, input_dataset, initial_state, scan_func): """See `scan()` for details.""" super(_ScanDataset, self).__init__() self._input_dataset = input_dataset with ops.name_scope("initial_state"): self._initial_state = nest.pack_sequence_as(initial_state, [ ops.convert_to_tensor(t, name="component_%d" % i) for i, t in enumerate(nest.flatten(initial_state)) ]) # Compute initial values for the state shapes and types based on # the initial state. These will be refined by running # `tf_scan_func` one or more times below. # TODO(b/68937811): Allow the initial state to be a tf.SparseTensor. self._state_shapes = nest.pack_sequence_as( self._initial_state, [t.shape for t in nest.flatten(self._initial_state)]) self._state_types = nest.pack_sequence_as( self._initial_state, [t.dtype for t in nest.flatten(self._initial_state)]) # Will be populated by calling `tf_scan_func`. self._output_classes = None self._output_shapes = None self._output_types = None # Iteratively rerun the scan function until reaching a fixed pont on # `self._state_shapes`. need_to_rerun = True while need_to_rerun: flat_state_shapes = nest.flatten(self._state_shapes) flat_state_types = nest.flatten(self._state_types) # Create a list in which `tf_scan_func` will store the s flat_new_state_shapes = [] @function.Defun(*(flat_state_types + nest.flatten( sparse.as_dense_types(input_dataset.output_types, input_dataset.output_classes)))) def tf_scan_func(*args): """A wrapper for Defun that facilitates shape inference.""" # Pass in shape information from the state and input_dataset. # TODO(b/69424092): Check that neither inputs nor outputs are sparse. dense_shapes = sparse.as_dense_shapes(input_dataset.output_shapes, input_dataset.output_classes) for arg, shape in zip(args, flat_state_shapes + nest.flatten(dense_shapes)): arg.set_shape(shape) pivot = len(flat_state_shapes) old_state = nest.pack_sequence_as(self._initial_state, args[:pivot]) input_value = nest.pack_sequence_as(input_dataset.output_types, args[pivot:]) ret = scan_func(old_state, input_value) if not isinstance(ret, collections.Sequence) or len(ret) != 2: raise TypeError("The scan function must return a pair comprising the " "new state and the output value.") new_state, output_value = ret flat_new_state = [ ops.convert_to_tensor(t) for t in nest.flatten(new_state) ] flat_output_value = [ ops.convert_to_tensor(t) for t in nest.flatten(output_value) ] # Extract shape information from the returned values. flat_new_state_shapes.extend([t.shape for t in flat_new_state]) self._output_shapes = nest.pack_sequence_as( output_value, [t.shape for t in flat_output_value]) # Extract and validate type information from the returned values. for t, dtype in zip(flat_new_state, flat_state_types): if t.dtype != dtype: raise TypeError( "The element types for the new state must match the initial " "state. Expected %s; got %s." % (self._state_types, nest.pack_sequence_as( self._state_types, [t.dtype for t in flat_new_state]))) self._output_classes = nest.pack_sequence_as( output_value, [ops.Tensor for _ in flat_output_value]) self._output_types = nest.pack_sequence_as( output_value, [t.dtype for t in flat_output_value]) return flat_new_state + flat_output_value # Use the private method that will execute `tf_scan_func` but delay # adding it to the graph in case we need to rerun the function. tf_scan_func._create_definition_if_needed() # pylint: disable=protected-access weakened_state_shapes = [ original.most_specific_compatible_shape(new) for original, new in zip(flat_state_shapes, flat_new_state_shapes) ] need_to_rerun = False for original_shape, weakened_shape in zip(flat_state_shapes, weakened_state_shapes): if original_shape.ndims is not None and ( weakened_shape.ndims is None or original_shape.as_list() != weakened_shape.as_list()): need_to_rerun = True break if need_to_rerun: # NOTE(mrry): `self._output_shapes` will be overwritten when we rerun # `tf_scan_func`. self._state_shapes = nest.pack_sequence_as(self._state_shapes, weakened_state_shapes) self._scan_func = tf_scan_func
def main(): # 导入模型 network = importlib.import_module(Config.model_def) # 相当于导入 .py 文件 # 用时间命名 subdir = datetime.strftime(datetime.now(),'%Y%m%d-%H%M%S') model_dir = os.path.join(os.path.expanduser(Config.models_base_dir),subdir) if not os.path.isdir(model_dir): os.makedirs(model_dir) # 读取数据 train_set = data_process.get_data_set(Config.data_dir) # 类别总数 nrof_classes = len(train_set) pretrained_model = None if Config.pretrained_model: pretrained_model = os.path.expanduser(Config.pretrained_model) print('Pre-trained model: %s'%pretrained_model) with tf.Graph().as_default(): global_step = tf.Variable(0,trainable=False) image_list, label_list = data_process.get_image_paths_and_labels(train_set) assert len(image_list)>0,'The dataset should not empty' labels = ops.convert_to_tensor(label_list,dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size,num_epochs=None,shuffle=True,seed = None,capacity=32) index_dequeue_op = index_queue.dequeue_many(Config.batch_size*Config.epoch_size,'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32,name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32,name='batch_size') train_flag = tf.placeholder(tf.bool,name='phase_train') image_paths_placeholder = tf.placeholder(tf.string,shape=(None,1),name='image_paths') labels_placeholder = tf.placeholder(tf.int64,shape=(None,1),name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=500000, dtypes=[tf.string,tf.int64], shapes=[(1,),(1,)], shared_name=None,name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder,labels_placeholder],name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if Config.random_rotate: image = tf.py_func(data_process.random_rotate_image, [image], tf.uint8) if Config.random_crop: image = tf.random_crop(image, [Config.image_size, Config.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, Config.image_size, Config.image_size) if Config.random_flip: image = tf.image.random_flip_left_right(image) # pylint: disable=no-member image.set_shape((Config.image_size, Config.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch,label_batch = tf.train.batch_join( images_and_labels,batch_size=batch_size_placeholder, shapes=[(Config.image_size,Config.image_size,3),()],enqueue_many=True, capacity=4*nrof_preprocess_threads*Config.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch,'image_batch') image_batch = tf.identity(image_batch,'input') label_batch = tf.identity(label_batch,'label_batch') print('Total number of classes: %d'%nrof_classes) print('Total number of examples: %d'%len(image_list)) print('Building training graph') prelogits = network.inference(image_batch,Config.keep_prob, phase_train = train_flag,bottleneck_layer_size = Config.embedding_size, weight_decay = Config.weight_decay) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(Config.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # 添加中心损失 if Config.center_loss_weight >0.0: prelogits_center_loss,_ = utils.center_loss(prelogits,label_batch,Config.center_loss_alfa,nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,prelogits_center_loss*Config.center_loss_weight) learning_rate = tf.train.exponential_decay(learning_rate_placeholder,global_step, Config.learning_rate_decay_epochs*Config.epoch_size, Config.learning_rate_decay_factor,staircase=True) cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=label_batch,logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy,name='cross_entropy') tf.add_to_collection('losses',cross_entropy_mean) # 把中心损失加到交叉softmax损失上 regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean]+regularization_losses,name='total_loss') # 一个batch 训练操作并更新模型参数 train_op = train_batch(total_loss,global_step,Config.optimizer,learning_rate, Config.moving_average_decay,tf.global_variables()) # 创建一个保存器 saver = tf.train.Saver(tf.trainable_variables(),max_to_keep=3) gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction = Config.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,log_device_placement=False)) sess.run(tf.global_variables_initializer()) # 获得线程坐标,启动填充队列的线程 coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord,sess=sess) with sess.as_default(): sess.run(tf.local_variables_initializer()) if pretrained_model: print('Restoring pretrained model: %s'%pretrained_model) meta_file, ckpt_file = utils.get_model_filenames(Config.pretrained_model) saver = tf.train.import_meta_graph(os.path.join(Config.pretrained_model, meta_file)) saver.restore(sess, os.path.join(Config.pretrained_model, ckpt_file)) print('Running training') epoch = 0 while epoch < Config.max_nrof_epochs: step = sess.run(global_step,feed_dict=None) utils.save_variables_and_metagraph(sess, saver, model_dir, subdir, step) print('++++++++++save done++++++++++') epoch = step // Config.epoch_size # 训练一个epoch train(sess,epoch,image_list,label_list,index_dequeue_op,enqueue_op,image_paths_placeholder,labels_placeholder, learning_rate_placeholder,train_flag,batch_size_placeholder,global_step, total_loss,train_op,regularization_losses) utils.save_variables_and_metagraph(sess,saver,model_dir,subdir,step) return model_dir
def main(args): # 模型,定义在inception_resnet_v1 V2里(), --model_def models.inception_resnet_v1 network = importlib.import_module(args.model_def) image_size = (args.image_size, args.image_size) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) stat_file_name = os.path.join(log_dir, 'stat.h5') # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) dataset = facenet.get_dataset(args.data_dir) if args.filter_filename: dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) if args.validation_set_split_ratio>0.0: train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels # 训练数据 image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The training set should not be empty' # 测试数据 val_image_list, val_label_list = facenet.get_image_paths_and_labels(val_set) # Create a queue that produces indices into the image_list and label_list # tf.convert_to_tensor用于将不同数据变成张量:比如可以让数组变成张量、也可以让列表变成张量。 labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] # 多线程读取数据,shuffle=True表示不是按顺序存储,可以随机获取,并一直循环。 # https://blog.csdn.net/lyg5623/article/details/69387917 index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # epoch 大数据时迭代完一轮时次数,少量数据应该epoch = 全部数据个数/batch index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue(capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1,), (1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline(input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # 因为模型输出的(bottleneck_layer_size)没有计算最后一层(映射到图片类型),这里计算最后一层 logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # 按行进行泛化,行的平方求和再求平方根,得到的值按行除每个行的元素,对深度层面泛化? interface里最后一层输出为128个节点,slim.fully_connected(net, bottleneck_layer_size, activation_fn=None, #https://blog.csdn.net/abiggg/article/details/79368982 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # 计算loss函数,当然还有其它训练参数也会加到这里来,通过比训练过程中一个weight加到正则化参数里来tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weight) # 模型中最后会把这个加到优化的loss中来。 #L= L_softmax + λL_cneter = Softmax(W_i + b_yj) + λ1/2||f(x_i) - c_yj ||_2^2 # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits)+eps, ord=args.prelogits_norm_p, axis=1)) # 模型中最后输出(bottleneck_layer_size每个类型的输出值的个数)的平均值加到正则化loss中,但prelogits_norm_loss_factor貌似为0 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # 计算中心损失及增加的正则化loss中 # Add center loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 计算预测损失,和上面框架的Softmax(W_i + b_yj) cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') # 预测损失平均值加到losses变量中 tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) #计算总损失,cross_entropy_mean + 前面增加的一些正则化损失(包括模型中增加的),通过tf.GraphKeys.REGULARIZATION_LOSSES获取出来 # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') nrof_steps = args.max_nrof_epochs*args.epoch_size nrof_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs)) # Validate every validate_every_n_epochs as well as in the last epoch stat = { 'loss': np.zeros((nrof_steps,), np.float32), 'center_loss': np.zeros((nrof_steps,), np.float32), 'reg_loss': np.zeros((nrof_steps,), np.float32), 'xent_loss': np.zeros((nrof_steps,), np.float32), 'prelogits_norm': np.zeros((nrof_steps,), np.float32), 'accuracy': np.zeros((nrof_steps,), np.float32), 'val_loss': np.zeros((nrof_val_samples,), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples,), np.float32), 'val_accuracy': np.zeros((nrof_val_samples,), np.float32), 'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_train': np.zeros((args.max_nrof_epochs,), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1,args.max_nrof_epochs+1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() # 训练模型 cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch-1] = time.time() - t if not cont: break # 在测试数据上计算正确率 t = time.time() if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or epoch==args.max_nrof_epochs): validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization) stat['time_validate'][epoch-1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch-1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.items(): f.create_dataset(key, data=value) return model_dir
def convert_nonref_to_tensor(value, dtype=None, dtype_hint=None, name=None): """Converts the given `value` to a `Tensor` if input is nonreference type. This function converts Python objects of various types to `Tensor` objects except if the input has nonreference semantics. Reference semantics are characterized by `is_ref` and is any object which is a `tf.Variable` or instance of `tf.Module`. This function accepts any input which `tf.convert_to_tensor` would also. Note: This function diverges from default Numpy behavior for `float` and `string` types when `None` is present in a Python list or scalar. Rather than silently converting `None` values, an error will be thrown. Args: value: An object whose type has a registered `Tensor` conversion function. dtype: Optional element type for the returned tensor. If missing, the type is inferred from the type of `value`. dtype_hint: Optional element type for the returned tensor, used when dtype is None. In some cases, a caller may not have a dtype in mind when converting to a tensor, so dtype_hint can be used as a soft preference. If the conversion to `dtype_hint` is not possible, this argument has no effect. name: Optional name to use if a new `Tensor` is created. Returns: tensor: A `Tensor` based on `value`. Raises: TypeError: If no conversion function is registered for `value` to `dtype`. RuntimeError: If a registered conversion function returns an invalid value. ValueError: If the `value` is a tensor not of given `dtype` in graph mode. #### Examples: ```python x = tf.Variable(0.) y = convert_nonref_to_tensor(x) x is y # ==> True x = tf.constant(0.) y = convert_nonref_to_tensor(x) x is y # ==> True x = np.array(0.) y = convert_nonref_to_tensor(x) x is y # ==> False tf.is_tensor(y) # ==> True x = tfp.util.DeferredTensor(13.37, lambda x: x) y = convert_nonref_to_tensor(x) x is y # ==> True tf.is_tensor(y) # ==> False tf.equal(y, 13.37) # ==> True ``` """ # We explicitly do not use a tf.name_scope to avoid graph clutter. if value is None: return None if is_ref(value): if dtype is None: return value dtype_base = base_dtype(dtype) value_dtype_base = base_dtype(value.dtype) if dtype_base != value_dtype_base: raise TypeError( 'Mutable type must be of dtype "{}" but is "{}".'.format( dtype_name(dtype_base), dtype_name(value_dtype_base))) return value return ops.convert_to_tensor(value, dtype=dtype, dtype_hint=dtype_hint, name=name)
def broadcast_matrix_batch_dims(batch_matrices, name=None): """Broadcast leading dimensions of zero or more [batch] matrices. Example broadcasting one batch dim of two simple matrices. ```python x = [[1, 2], [3, 4]] # Shape [2, 2], no batch dims y = [[[1]]] # Shape [1, 1, 1], 1 batch dim of shape [1] x_bc, y_bc = broadcast_matrix_batch_dims([x, y]) x_bc ==> [[[1, 2], [3, 4]]] # Shape [1, 2, 2], 1 batch dim of shape [1]. y_bc ==> same as y ``` Example broadcasting many batch dims ```python x = tf.random.normal(shape=(2, 3, 1, 4, 4)) y = tf.random.normal(shape=(1, 3, 2, 5, 5)) x_bc, y_bc = broadcast_matrix_batch_dims([x, y]) x_bc.shape ==> (2, 3, 2, 4, 4) y_bc.shape ==> (2, 3, 2, 5, 5) ``` Args: batch_matrices: Iterable of `Tensor`s, each having two or more dimensions. name: A string name to prepend to created ops. Returns: bcast_matrices: List of `Tensor`s, with `bcast_matricies[i]` containing the values from `batch_matrices[i]`, with possibly broadcast batch dims. Raises: ValueError: If any input `Tensor` is statically determined to have less than two dimensions. """ with ops.name_scope(name or "broadcast_matrix_batch_dims", values=batch_matrices): check_ops.assert_proper_iterable(batch_matrices) batch_matrices = list(batch_matrices) for i, mat in enumerate(batch_matrices): batch_matrices[i] = ops.convert_to_tensor(mat) assert_is_batch_matrix(batch_matrices[i]) if len(batch_matrices) < 2: return batch_matrices # Try static broadcasting. # bcast_batch_shape is the broadcast batch shape of ALL matrices. # E.g. if batch_matrices = [x, y], with # x.shape = [2, j, k] (batch shape = [2]) # y.shape = [3, 1, l, m] (batch shape = [3, 1]) # ==> bcast_batch_shape = [3, 2] bcast_batch_shape = batch_matrices[0].shape[:-2] for mat in batch_matrices[1:]: bcast_batch_shape = array_ops.broadcast_static_shape( bcast_batch_shape, mat.shape[:-2]) if bcast_batch_shape.is_fully_defined(): for i, mat in enumerate(batch_matrices): if mat.shape[:-2] != bcast_batch_shape: bcast_shape = array_ops.concat([ bcast_batch_shape.as_list(), array_ops.shape(mat)[-2:] ], axis=0) batch_matrices[i] = array_ops.broadcast_to( mat, bcast_shape) return batch_matrices # Since static didn't work, do dynamic, which always copies data. bcast_batch_shape = array_ops.shape(batch_matrices[0])[:-2] for mat in batch_matrices[1:]: bcast_batch_shape = array_ops.broadcast_dynamic_shape( bcast_batch_shape, array_ops.shape(mat)[:-2]) for i, mat in enumerate(batch_matrices): batch_matrices[i] = array_ops.broadcast_to( mat, array_ops.concat( [bcast_batch_shape, array_ops.shape(mat)[-2:]], axis=0)) return batch_matrices
def test_slicing(self): v = [ variables_lib.Variable([[1, 2], [3, 4], [5, 6]]), variables_lib.Variable([[7, 8], [9, 10], [11, 12]]), variables_lib.Variable([[13, 14], [15, 16]]) ] sv = sharded_variable.ShardedVariable(v) empty = v[0][0:0] # Test cases: positive step self.assertAllEqual(sv[:], array_ops.concat(v, axis=0)) self.assertAllEqual(sv[:2], [[1, 2], [3, 4]]) self.assertAllEqual(sv[-8:2], [[1, 2], [3, 4]]) self.assertAllEqual(sv[-10:2], [[1, 2], [3, 4]]) self.assertAllEqual(sv[5:], [[11, 12], [13, 14], [15, 16]]) self.assertAllEqual(sv[5:-1], [[11, 12], [13, 14]]) self.assertAllEqual(sv[::3], [[1, 2], [7, 8], [13, 14]]) self.assertAllEqual(sv[::5], [[1, 2], [11, 12]]) self.assertAllEqual(sv[1::6], [[3, 4], [15, 16]]) self.assertAllEqual(sv[1:5:6], [[3, 4]]) self.assertAllEqual(sv[1::7], [[3, 4]]) self.assertAllEqual(sv[2:7], [[5, 6], [7, 8], [9, 10], [11, 12], [13, 14]]) self.assertAllEqual(sv[2:7:2], [[5, 6], [9, 10], [13, 14]]) self.assertAllEqual(sv[2:7:3], [[5, 6], [11, 12]]) # Test cases: negative step self.assertAllEqual( sv[::-1], array_ops.reverse(array_ops.concat(v, axis=0), axis=[0])) self.assertAllEqual(sv[2::-1], [[5, 6], [3, 4], [1, 2]]) self.assertAllEqual(sv[2:-8:-1], [[5, 6], [3, 4]]) self.assertAllEqual(sv[2:-10:-1], [[5, 6], [3, 4], [1, 2]]) self.assertAllEqual(sv[4::-1], [[9, 10], [7, 8], [5, 6], [3, 4], [1, 2]]) self.assertAllEqual(sv[-1:-3:-1], [[15, 16], [13, 14]]) self.assertAllEqual(sv[::-5], [[15, 16], [5, 6]]) self.assertAllEqual(sv[6::-6], [[13, 14], [1, 2]]) self.assertAllEqual(sv[6:5:-6], [[13, 14]]) self.assertAllEqual(sv[6::-7], [[13, 14]]) self.assertAllEqual( sv[7:1:-1], [[15, 16], [13, 14], [11, 12], [9, 10], [7, 8], [5, 6]]) self.assertAllEqual(sv[7:1:-2], [[15, 16], [11, 12], [7, 8]]) self.assertAllEqual(sv[7:1:-4], [[15, 16], [7, 8]]) # Test cases: empty slice self.assertAllEqual(sv[0:0], empty) self.assertAllEqual(sv[5:3], empty) self.assertAllEqual(sv[3:5:-1], empty) self.assertAllEqual(sv[-1:0], empty) self.assertAllEqual(sv[2:-1:-1], empty) # Test cases: slicing other dimensions self.assertAllEqual(sv[:, 0], [1, 3, 5, 7, 9, 11, 13, 15]) self.assertAllEqual(sv[:, 0:1], [[1], [3], [5], [7], [9], [11], [13], [15]]) # Test cases: normal indexing self.assertAllEqual(sv[2], [5, 6]) self.assertAllEqual(sv[6], [13, 14]) self.assertAllEqual(sv[2, 1], 6) self.assertAllEqual(sv[-2], [13, 14]) with self.assertRaisesRegex(IndexError, 'out of bounds'): _ = sv[100] with self.assertRaisesRegex(IndexError, 'out of bounds'): _ = sv[-100] # Test cases: Ellipsis self.assertAllEqual(sv[...], array_ops.concat(v, axis=0)) self.assertAllEqual(sv[..., 0], [1, 3, 5, 7, 9, 11, 13, 15]) self.assertAllEqual(sv[0:1, ...], [[1, 2]]) # Test cases: newaxis self.assertAllEqual( sv[array_ops.newaxis, ...], array_ops.expand_dims_v2(array_ops.concat(v, axis=0), axis=0)) # Test cases: boolean masks self.assertAllEqual(sv[ops.convert_to_tensor(sv) > 10], [11, 12, 13, 14, 15, 16]) # Test cases: tensor input with self.assertRaisesRegex(TypeError, 'not allowed'): _ = sv[constant_op.constant(1)::] with self.assertRaisesRegex(TypeError, 'not allowed'): _ = sv[:constant_op.constant(1):] with self.assertRaisesRegex(TypeError, 'not allowed'): _ = sv[constant_op.constant(1)] # Test cases: inside tf.function @def_function.function def func(): a = sv[:, 0] return a self.assertAllEqual(func(), [1, 3, 5, 7, 9, 11, 13, 15])
def __init__(self, logits=None, probs=None, dtype=dtypes.int32, validate_args=False, allow_nan_stats=True, name="Categorical"): """Initialize Categorical distributions using class log-probabilities. Args: logits: An N-D `Tensor`, `N >= 1`, representing the log probabilities of a set of Categorical distributions. The first `N - 1` dimensions index into a batch of independent distributions and the last dimension represents a vector of logits for each class. Only one of `logits` or `probs` should be passed in. probs: An N-D `Tensor`, `N >= 1`, representing the probabilities of a set of Categorical distributions. The first `N - 1` dimensions index into a batch of independent distributions and the last dimension represents a vector of probabilities for each class. Only one of `logits` or `probs` should be passed in. dtype: The type of the event samples (default: int32). 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. """ parameters = locals() with ops.name_scope(name, values=[logits, probs]): self._logits, self._probs = distribution_util.get_logits_and_probs( logits=logits, probs=probs, validate_args=validate_args, multidimensional=True, name=name) if validate_args: self._logits = distribution_util.embed_check_categorical_event_shape( self._logits) logits_shape_static = self._logits.get_shape().with_rank_at_least( 1) if logits_shape_static.ndims is not None: self._batch_rank = ops.convert_to_tensor( logits_shape_static.ndims - 1, dtype=dtypes.int32, name="batch_rank") else: with ops.name_scope(name="batch_rank"): self._batch_rank = array_ops.rank(self._logits) - 1 logits_shape = array_ops.shape(self._logits, name="logits_shape") if logits_shape_static[-1].value is not None: self._event_size = ops.convert_to_tensor( logits_shape_static[-1].value, dtype=dtypes.int32, name="event_size") else: with ops.name_scope(name="event_size"): self._event_size = logits_shape[self._batch_rank] if logits_shape_static[:-1].is_fully_defined(): self._batch_shape_val = constant_op.constant( logits_shape_static[:-1].as_list(), dtype=dtypes.int32, name="batch_shape") else: with ops.name_scope(name="batch_shape"): self._batch_shape_val = logits_shape[:-1] super(Categorical, self).__init__( dtype=dtype, reparameterization_type=distribution.NOT_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._logits, self._probs], name=name)
def fully_connected(inputs, num_outputs, activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_normalizer_fn=None, weights_normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer(), biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None): # Be copied and modified from tensorflow-0.12.0.contrib.layer.fully_connected, # add weights_nomalizer_* options. """Adds a fully connected layer. `fully_connected` creates a variable called `weights`, representing a fully connected weight matrix, which is multiplied by the `inputs` to produce a `Tensor` of hidden units. If a `normalizer_fn` is provided (such as `batch_norm`), it is then applied. Otherwise, if `normalizer_fn` is None and a `biases_initializer` is provided then a `biases` variable would be created and added the hidden units. Finally, if `activation_fn` is not `None`, it is applied to the hidden units as well. Note: that if `inputs` have a rank greater than 2, then `inputs` is flattened prior to the initial matrix multiply by `weights`. Args: inputs: A tensor of with at least rank 2 and value for the last dimension, i.e. `[batch_size, depth]`, `[None, None, None, channels]`. num_outputs: Integer or long, the number of output units in the layer. activation_fn: activation function, set to None to skip it and maintain a linear activation. normalizer_fn: normalization function to use instead of `biases`. If `normalizer_fn` is provided then `biases_initializer` and `biases_regularizer` are ignored and `biases` are not created nor added. default set to None for no normalizer function normalizer_params: normalization function parameters. weights_normalizer_fn: weights normalization function. weights_normalizer_params: weights normalization function parameters. weights_initializer: An initializer for the weights. weights_regularizer: Optional regularizer for the weights. biases_initializer: An initializer for the biases. If None skip biases. biases_regularizer: Optional regularizer for the biases. reuse: whether or not the layer and its variables should be reused. To be able to reuse the layer scope must be given. variables_collections: Optional list of collections for all the variables or a dictionary containing a different list of collections per variable. outputs_collections: collection to add the outputs. trainable: If `True` also add variables to the graph collection `GraphKeys.TRAINABLE_VARIABLES` (see tf.Variable). scope: Optional scope for variable_scope. Returns: the tensor variable representing the result of the series of operations. Raises: ValueError: if x has rank less than 2 or if its last dimension is not set. """ if not (isinstance(num_outputs, six.integer_types)): raise ValueError('num_outputs should be int or long, got %s.', num_outputs) with variable_scope.variable_scope(scope, 'fully_connected', [inputs], reuse=reuse) as sc: inputs = ops.convert_to_tensor(inputs) dtype = inputs.dtype.base_dtype inputs_shape = inputs.get_shape() num_input_units = utils.last_dimension(inputs_shape, min_rank=2) static_shape = inputs_shape.as_list() static_shape[-1] = num_outputs out_shape = array_ops.unpack(array_ops.shape(inputs), len(static_shape)) out_shape[-1] = num_outputs weights_shape = [num_input_units, num_outputs] weights_collections = utils.get_variable_collections( variables_collections, 'weights') weights = variables.model_variable('weights', shape=weights_shape, dtype=dtype, initializer=weights_initializer, regularizer=weights_regularizer, collections=weights_collections, trainable=trainable) if weights_normalizer_fn is not None: weights_normalizer_params = weights_normalizer_params or {} weights = weights_normalizer_fn(weights, **weights_normalizer_params) if len(static_shape) > 2: # Reshape inputs inputs = array_ops.reshape(inputs, [-1, num_input_units]) outputs = standard_ops.matmul(inputs, weights) if normalizer_fn is not None: normalizer_params = normalizer_params or {} outputs = normalizer_fn(outputs, **normalizer_params) else: if biases_initializer is not None: biases_collections = utils.get_variable_collections( variables_collections, 'biases') biases = variables.model_variable( 'biases', shape=[ num_outputs, ], dtype=dtype, initializer=biases_initializer, regularizer=biases_regularizer, collections=biases_collections, trainable=trainable) outputs = nn.bias_add(outputs, biases) if activation_fn is not None: outputs = activation_fn(outputs) if len(static_shape) > 2: # Reshape back outputs outputs = array_ops.reshape(outputs, array_ops.pack(out_shape)) outputs.set_shape(static_shape) return utils.collect_named_outputs(outputs_collections, sc.original_name_scope, outputs)
def __init__(self, cache_name, host="localhost", port=10800, schema_host=None, schema_port=None, local=False, part=-1, page_size=100, username=None, password=None, certfile=None, keyfile=None, cert_password=None): """Create a IgniteDataset. Args: cache_name: Cache name to be used as datasource. host: Apache Ignite Thin Client host to be connected. port: Apache Ignite Thin Client port to be connected. schema_host: Host to be connected to retrieve cache schema. schema_port: Port to be connected to retrieve cache schema. local: Local flag that defines to query only local data. part: Number of partitions to be queried. page_size: Apache Ignite Thin Client page size. username: Apache Ignite Thin Client authentication username. password: Apache Ignite Thin Client authentication password. certfile: File in PEM format containing the certificate as well as any number of CA certificates needed to establish the certificate's authenticity. keyfile: File containing the private key (otherwise the private key will be taken from certfile as well). cert_password: Password to be used if the private key is encrypted and a password is necessary. """ super(IgniteDataset, self).__init__() if not schema_host: schema_host = host if not schema_port: schema_port = port with IgniteClient(schema_host, schema_port, username, password, certfile, keyfile, cert_password) as client: client.handshake() self.cache_type = client.get_cache_type(cache_name) self.cache_name = ops.convert_to_tensor(cache_name, dtype=dtypes.string, name="cache_name") self.host = ops.convert_to_tensor(host, dtype=dtypes.string, name="host") self.port = ops.convert_to_tensor(port, dtype=dtypes.int32, name="port") self.local = ops.convert_to_tensor(local, dtype=dtypes.bool, name="local") self.part = ops.convert_to_tensor(part, dtype=dtypes.int32, name="part") self.page_size = ops.convert_to_tensor(page_size, dtype=dtypes.int32, name="page_size") self.schema = ops.convert_to_tensor(self.cache_type.to_flat(), dtype=dtypes.int32, name="schema") self.permutation = ops.convert_to_tensor( self.cache_type.to_permutation(), dtype=dtypes.int32, name="permutation")
def select(labeled_tensor, selection, name=None): """Slice out a subset of the tensor. Args: labeled_tensor: The input tensor. selection: A dictionary mapping an axis name to a scalar, slice or list of values to select. Currently supports two types of selections: (a) Any number of scalar and/or slice selections. (b) Exactly one list selection, without any scalars or slices. name: Optional op name. Returns: The selection as a `LabeledTensor`. Raises: ValueError: If the tensor doesn't have an axis in the selection or if that axis lacks labels. KeyError: If any labels in a selection are not found in the original axis. NotImplementedError: If you attempt to combine a list selection with scalar selection or another list selection. """ with ops.name_scope(name, 'lt_select', [labeled_tensor]) as scope: labeled_tensor = core.convert_to_labeled_tensor(labeled_tensor) slices = {} indexers = {} for axis_name, value in selection.items(): if axis_name not in labeled_tensor.axes: raise ValueError( 'The tensor does not have an axis named %s. Its axes are: %r' % (axis_name, labeled_tensor.axes.keys())) axis = labeled_tensor.axes[axis_name] if axis.labels is None: raise ValueError( 'The axis named %s does not have labels. The axis is: %r' % (axis_name, axis)) if isinstance(value, slice): # TODO(shoyer): consider deprecating using slices in favor of lists if value.start is None: start = None else: start = axis.index(value.start) if value.stop is None: stop = None else: # For now, follow the pandas convention of making labeled slices # inclusive of both bounds. stop = axis.index(value.stop) + 1 if value.step is not None: raise NotImplementedError( 'slicing with a step is not yet supported') slices[axis_name] = slice(start, stop) else: # We're allowing anything NumPy treats as a scalar or 1D array. value = np.asarray(value) if value.ndim == 0: slices[axis_name] = axis.index(value.item()) elif value.ndim == 1: if indexers: raise NotImplementedError( 'select does not yet support more than one list selection at ' 'the same time') indexer = [axis.index(v) for v in value.tolist()] indexers[axis_name] = ops.convert_to_tensor( indexer, dtype=dtypes.int64) else: raise NotImplementedError( 'select does not yet support selections with more than one ' 'dimension: %s on axis %r' % (value, axis_name)) if indexers and slices: raise NotImplementedError( 'select does not yet support combined scalar and list selection' ) # For now, handle array selection separately, because tf.gather_nd does # not support gradients yet. Later, using gather_nd will let us combine # these paths. if indexers: (axis_name, indexer), = indexers.items() axis = core.Axis(axis_name, selection[axis_name]) return _gather_1d_on_axis(labeled_tensor, indexer, axis, name=scope) else: return core.slice_function(labeled_tensor, slices, name=scope)
def scan(fn, elems, initializer=None, parallel_iterations=10, back_prop=True, swap_memory=False, infer_shape=True, name=None): """scan on the list of tensors unpacked from `elems` on dimension 0. The simplest version of `scan` repeatedly applies the callable `fn` to a sequence of elements from first to last. The elements are made of the tensors unpacked from `elems` on dimension 0. The callable fn takes two tensors as arguments. The first argument is the accumulated value computed from the preceding invocation of fn. If `initializer` is None, `elems` must contain at least one element, and its first element is used as the initializer. Suppose that `elems` is unpacked into `values`, a list of tensors. The shape of the result tensor is `[len(values)] + fn(initializer, values[0]).shape`. This method also allows multi-arity `elems` and accumulator. If `elems` is a (possibly nested) list or tuple of tensors, then each of these tensors must have a matching first (unpack) dimension. The second argument of `fn` must match the structure of `elems`. If no `initializer` is provided, the output structure and dtypes of `fn` are assumed to be the same as its input; and in this case, the first argument of `fn` must match the structure of `elems`. If an `initializer` is provided, then the output of `fn` must have the same structure as `initializer`; and the first argument of `fn` must match this structure. For example, if `elems` is `(t1, [t2, t3])` and `initializer` is `[i1, i2]` then an appropriate signature for `fn` in `python2` is: `fn = lambda (acc_p1, acc_p2), (t1, [t2, t3]):` and `fn` must return a list, `[acc_n1, acc_n2]`. An alternative correct signature for `fn`, and the one that works in `python3`, is: `fn = lambda a, t:`, where `a` and `t` correspond to the input tuples. Args: fn: The callable to be performed. It accepts two arguments. The first will have the same structure as `initializer` if one is provided, otherwise it will have the same structure as `elems`. The second will have the same (possibly nested) structure as `elems`. Its output must have the same structure as `initializer` if one is provided, otherwise it must have the same structure as `elems`. elems: A tensor or (possibly nested) sequence of tensors, each of which will be unpacked along their first dimension. The nested sequence of the resulting slices will be the first argument to `fn`. initializer: (optional) A tensor or (possibly nested) sequence of tensors, initial value for the accumulator, and the expected output type of `fn`. parallel_iterations: (optional) The number of iterations allowed to run in parallel. back_prop: (optional) True enables support for back propagation. swap_memory: (optional) True enables GPU-CPU memory swapping. infer_shape: (optional) False disables tests for consistent output shapes. name: (optional) Name prefix for the returned tensors. Returns: A tensor or (possibly nested) sequence of tensors. Each tensor packs the results of applying `fn` to tensors unpacked from `elems` along the first dimension, and the previous accumulator value(s), from first to last. Raises: TypeError: if `fn` is not callable or the structure of the output of `fn` and `initializer` do not match. ValueError: if the lengths of the output of `fn` and `initializer` do not match. Examples: ```python elems = np.array([1, 2, 3, 4, 5, 6]) sum = scan(lambda a, x: a + x, elems) # sum == [1, 3, 6, 10, 15, 21] ``` ```python elems = np.array([1, 2, 3, 4, 5, 6]) initializer = np.array(0) sum_one = scan( lambda a, x: x[0] - x[1] + a, (elems + 1, elems), initializer) # sum_one == [1, 2, 3, 4, 5, 6] ``` ```python elems = np.array([1, 0, 0, 0, 0, 0]) initializer = (np.array(0), np.array(1)) fibonaccis = scan(lambda a, _: (a[1], a[0] + a[1]), elems, initializer) # fibonaccis == ([1, 1, 2, 3, 5, 8], [1, 2, 3, 5, 8, 13]) ``` """ if not callable(fn): raise TypeError("fn must be callable.") input_is_sequence = nest.is_sequence(elems) input_flatten = lambda x: nest.flatten(x) if input_is_sequence else [x] def input_pack(x): return nest.pack_sequence_as(elems, x) if input_is_sequence else x[0] if initializer is None: output_is_sequence = input_is_sequence output_flatten = input_flatten output_pack = input_pack else: output_is_sequence = nest.is_sequence(initializer) output_flatten = lambda x: nest.flatten( x) if output_is_sequence else [x] def output_pack(x): return (nest.pack_sequence_as(initializer, x) if output_is_sequence else x[0]) elems_flat = input_flatten(elems) in_graph_mode = context.in_graph_mode() with ops.name_scope(name, "scan", elems_flat): # TODO(akshayka): Remove the in_graph_mode check once caching devices are # supported in Eager if in_graph_mode: # Any get_variable calls in fn will cache the first call locally # and not issue repeated network I/O requests for each iteration. varscope = vs.get_variable_scope() varscope_caching_device_was_none = False if varscope.caching_device is None: # TODO(ebrevdo): Change to using colocate_with here and in other # methods. varscope.set_caching_device(lambda op: op.device) varscope_caching_device_was_none = True # Convert elems to tensor array. elems_flat = [ ops.convert_to_tensor(elem, name="elem") for elem in elems_flat ] n = array_ops.shape(elems_flat[0])[0] # TensorArrays are always flat elems_ta = [ tensor_array_ops.TensorArray(dtype=elem.dtype, size=n, dynamic_size=False, infer_shape=True) for elem in elems_flat ] # Unpack elements elems_ta = [ elem_ta.unstack(elem) for elem_ta, elem in zip(elems_ta, elems_flat) ] if initializer is None: a_flat = [elem.read(0) for elem in elems_ta] i = constant_op.constant(1) else: initializer_flat = output_flatten(initializer) a_flat = [ops.convert_to_tensor(init) for init in initializer_flat] i = constant_op.constant(0) # Create a tensor array to store the intermediate values. accs_ta = [ tensor_array_ops.TensorArray( dtype=init.dtype, size=n, element_shape=init.shape if infer_shape else None, dynamic_size=False, infer_shape=infer_shape) for init in a_flat ] if initializer is None: accs_ta = [ acc_ta.write(0, a) for (acc_ta, a) in zip(accs_ta, a_flat) ] def compute(i, a_flat, tas): """The loop body of scan. Args: i: the loop counter. a_flat: the accumulator value(s), flattened. tas: the output accumulator TensorArray(s), flattened. Returns: [i + 1, a_flat, tas]: the updated counter + new accumulator values + updated TensorArrays Raises: TypeError: if initializer and fn() output structure do not match ValueType: if initializer and fn() output lengths do not match """ packed_elems = input_pack( [elem_ta.read(i) for elem_ta in elems_ta]) packed_a = output_pack(a_flat) a_out = fn(packed_a, packed_elems) nest.assert_same_structure( elems if initializer is None else initializer, a_out) flat_a_out = output_flatten(a_out) tas = [ta.write(i, value) for (ta, value) in zip(tas, flat_a_out)] return (i + 1, flat_a_out, tas) _, _, r_a = control_flow_ops.while_loop( lambda i, _1, _2: i < n, compute, (i, a_flat, accs_ta), parallel_iterations=parallel_iterations, back_prop=back_prop, swap_memory=swap_memory) results_flat = [r.stack() for r in r_a] n_static = elems_flat[0].get_shape().with_rank_at_least(1)[0] for elem in elems_flat[1:]: n_static.merge_with(elem.get_shape().with_rank_at_least(1)[0]) for r in results_flat: r.set_shape( tensor_shape.TensorShape(n_static).concatenate( r.get_shape()[1:])) # TODO(akshayka): Remove the in_graph_mode check once caching devices are # supported in Eager if in_graph_mode and varscope_caching_device_was_none: varscope.set_caching_device(None) return output_pack(results_flat)
def convolution(inputs, num_outputs, kernel_size, stride=1, padding='SAME', data_format=None, rate=1, activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_normalizer_fn=None, weights_normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer(), biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None): # Be copied and modified from tensorflow-0.12.0.contrib.layer.convolution, # add weights_nomalizer_* options. """Adds an N-D convolution followed by an optional batch_norm layer. It is required that 1 <= N <= 3. `convolution` creates a variable called `weights`, representing the convolutional kernel, that is convolved (actually cross-correlated) with the `inputs` to produce a `Tensor` of activations. If a `normalizer_fn` is provided (such as `batch_norm`), it is then applied. Otherwise, if `normalizer_fn` is None and a `biases_initializer` is provided then a `biases` variable would be created and added the activations. Finally, if `activation_fn` is not `None`, it is applied to the activations as well. Performs a'trous convolution with input stride/dilation rate equal to `rate` if a value > 1 for any dimension of `rate` is specified. In this case `stride` values != 1 are not supported. Args: inputs: a Tensor of rank N+2 of shape `[batch_size] + input_spatial_shape + [in_channels]` if data_format does not start with "NC" (default), or `[batch_size, in_channels] + input_spatial_shape` if data_format starts with "NC". num_outputs: integer, the number of output filters. kernel_size: a sequence of N positive integers specifying the spatial dimensions of of the filters. Can be a single integer to specify the same value for all spatial dimensions. stride: a sequence of N positive integers specifying the stride at which to compute output. Can be a single integer to specify the same value for all spatial dimensions. Specifying any `stride` value != 1 is incompatible with specifying any `rate` value != 1. padding: one of `"VALID"` or `"SAME"`. data_format: A string or None. Specifies whether the channel dimension of the `input` and output is the last dimension (default, or if `data_format` does not start with "NC"), or the second dimension (if `data_format` starts with "NC"). For N=1, the valid values are "NWC" (default) and "NCW". For N=2, the valid values are "NHWC" (default) and "NCHW". For N=3, currently the only valid value is "NDHWC". rate: a sequence of N positive integers specifying the dilation rate to use for a'trous convolution. Can be a single integer to specify the same value for all spatial dimensions. Specifying any `rate` value != 1 is incompatible with specifying any `stride` value != 1. activation_fn: activation function, set to None to skip it and maintain a linear activation. normalizer_fn: normalization function to use instead of `biases`. If `normalizer_fn` is provided then `biases_initializer` and `biases_regularizer` are ignored and `biases` are not created nor added. default set to None for no normalizer function normalizer_params: normalization function parameters. weights_normalizer_fn: weights normalization function. weights_normalizer_params: weights normalization function parameters. weights_initializer: An initializer for the weights. weights_regularizer: Optional regularizer for the weights. biases_initializer: An initializer for the biases. If None skip biases. biases_regularizer: Optional regularizer for the biases. reuse: whether or not the layer and its variables should be reused. To be able to reuse the layer scope must be given. variables_collections: optional list of collections for all the variables or a dictionary containing a different list of collection per variable. outputs_collections: collection to add the outputs. trainable: If `True` also add variables to the graph collection `GraphKeys.TRAINABLE_VARIABLES` (see tf.Variable). scope: Optional scope for `variable_scope`. Returns: a tensor representing the output of the operation. Raises: ValueError: if `data_format` is invalid. ValueError: both 'rate' and `stride` are not uniformly 1. """ if data_format not in [None, 'NWC', 'NCW', 'NHWC', 'NCHW', 'NDHWC']: raise ValueError('Invalid data_format: %r' % (data_format, )) with variable_scope.variable_scope(scope, 'Conv', [inputs], reuse=reuse) as sc: inputs = ops.convert_to_tensor(inputs) dtype = inputs.dtype.base_dtype input_rank = inputs.get_shape().ndims if input_rank is None: raise ValueError('Rank of inputs must be known') if input_rank < 3 or input_rank > 5: raise ValueError( 'Rank of inputs is %d, which is not >= 3 and <= 5' % input_rank) conv_dims = input_rank - 2 kernel_size = utils.n_positive_integers(conv_dims, kernel_size) stride = utils.n_positive_integers(conv_dims, stride) rate = utils.n_positive_integers(conv_dims, rate) if data_format is None or data_format.endswith('C'): num_input_channels = inputs.get_shape()[input_rank - 1].value elif data_format.startswith('NC'): num_input_channels = inputs.get_shape()[1].value else: raise ValueError('Invalid data_format') if num_input_channels is None: raise ValueError('Number of in_channels must be known.') weights_shape = (list(kernel_size) + [num_input_channels, num_outputs]) weights_collections = utils.get_variable_collections( variables_collections, 'weights') weights = variables.model_variable('weights', shape=weights_shape, dtype=dtype, initializer=weights_initializer, regularizer=weights_regularizer, collections=weights_collections, trainable=trainable) if weights_normalizer_fn is not None: weights_normalizer_params = weights_normalizer_params or {} weights = weights_normalizer_fn(weights, **weights_normalizer_params) outputs = nn.convolution(input=inputs, filter=weights, dilation_rate=rate, strides=stride, padding=padding, data_format=data_format) if normalizer_fn is not None: normalizer_params = normalizer_params or {} outputs = normalizer_fn(outputs, **normalizer_params) else: if biases_initializer is not None: biases_collections = utils.get_variable_collections( variables_collections, 'biases') biases = variables.model_variable( 'biases', shape=[num_outputs], dtype=dtype, initializer=biases_initializer, regularizer=biases_regularizer, collections=biases_collections, trainable=trainable) outputs = nn.bias_add(outputs, biases, data_format=data_format) if activation_fn is not None: outputs = activation_fn(outputs) return utils.collect_named_outputs(outputs_collections, sc.original_name_scope, outputs)
def stack_dynamic_partitions(data, partitions, num_partitions, name=None): """Stacks dynamic partitions of a Tensor or RaggedTensor. Returns a RaggedTensor `output` with `num_partitions` rows, where the row `output[i]` is formed by stacking all slices `data[j1...jN]` such that `partitions[j1...jN] = i`. Slices of `data` are stacked in row-major order. If `num_partitions` is an `int` (not a `Tensor`), then this is equivalent to `tf.ragged.stack(tf.dynamic_partition(data, partitions, num_partitions))`. #### Example: >>> data = ['a', 'b', 'c', 'd', 'e'] >>> partitions = [ 3, 0, 2, 2, 3] >>> num_partitions = 5 >>> tf.ragged.stack_dynamic_partitions(data, partitions, num_partitions) <tf.RaggedTensor [[b'b'], [], [b'c', b'd'], [b'a', b'e'], []]> Args: data: A `Tensor` or `RaggedTensor` containing the values to stack. partitions: An `int32` or `int64` `Tensor` or `RaggedTensor` specifying the partition that each slice of `data` should be added to. `partitions.shape` must be a prefix of `data.shape`. Values must be greater than or equal to zero, and less than `num_partitions`. `partitions` is not required to be sorted. num_partitions: An `int32` or `int64` scalar specifying the number of partitions to output. This determines the number of rows in `output`. name: A name prefix for the returned tensor (optional). Returns: A `RaggedTensor` containing the stacked partitions. The returned tensor has the same dtype as `data`, and its shape is `[num_partitions, (D)] + data.shape[partitions.rank:]`, where `(D)` is a ragged dimension whose length is the number of data slices stacked for each `partition`. """ with ops.name_scope(name, 'SegmentStack', [data, partitions, num_partitions]): # Convert inputs to tensors. data = ragged_tensor.convert_to_tensor_or_ragged_tensor(data, name='data') row_splits_dtype = (data.row_splits.dtype if isinstance( data, ragged_tensor.RaggedTensor) else None) partitions = ragged_tensor.convert_to_tensor_or_ragged_tensor( partitions, name='partitions', preferred_dtype=row_splits_dtype) num_partitions = ops.convert_to_tensor( num_partitions, name='num_partitions', preferred_dtype=partitions.dtype) if row_splits_dtype is not None: partitions = math_ops.cast(partitions, row_splits_dtype) num_partitions = math_ops.cast(num_partitions, partitions.dtype) # Sanity-checks for shapes. partitions_rank = partitions.shape.ndims if partitions_rank is None: raise ValueError('partitions must have known rank.') num_partitions.shape.assert_has_rank(0) partitions.shape.assert_is_compatible_with( data.shape[:partitions_rank]) if partitions_rank == 0: # If partitions is a scalar, then just create a RaggedTensor containing # that single the complete `data` value in the specified row. return ragged_tensor.RaggedTensor.from_value_rowids( values=array_ops.stack([data]), value_rowids=array_ops.stack([partitions]), nrows=num_partitions, validate=False) elif partitions_rank == 1: # If partitions is a vector (the typical case): we can just use data and # partitions as the `values` and `value_rowids` for `from_value_rowids`, # as long as we sort them first. permutation = sort_ops.argsort(partitions, stable=True) value_rowids = array_ops.gather(partitions, permutation) values = array_ops.gather(data, permutation) check = check_ops.assert_less( value_rowids[-1:], num_partitions, message='partitions must be less than num_partitions') with ops.control_dependencies([check]): return ragged_tensor.RaggedTensor.from_value_rowids( values, value_rowids, nrows=num_partitions, validate=False) else: # Handle higher-dimensional partitions via recursion. if not isinstance(data, ragged_tensor.RaggedTensor): data = ragged_tensor.RaggedTensor.from_tensor( data, row_splits_dtype=partitions.dtype, ragged_rank=1) if not isinstance(partitions, ragged_tensor.RaggedTensor): partitions = ragged_tensor.RaggedTensor.from_tensor( partitions, row_splits_dtype=partitions.dtype, ragged_rank=max(data.ragged_rank, partitions_rank - 1)) check = check_ops.assert_equal( data.row_splits, partitions.row_splits, message='data and partitions have incompatible ragged shapes') with ops.control_dependencies([check]): return stack_dynamic_partitions(data.values, partitions.values, num_partitions)
def foldl(fn, elems, initializer=None, parallel_iterations=10, back_prop=True, swap_memory=False, name=None): """foldl on the list of tensors unpacked from `elems` on dimension 0. This foldl operator repeatedly applies the callable `fn` to a sequence of elements from first to last. The elements are made of the tensors unpacked from `elems` on dimension 0. The callable fn takes two tensors as arguments. The first argument is the accumulated value computed from the preceding invocation of fn. If `initializer` is None, `elems` must contain at least one element, and its first element is used as the initializer. Suppose that `elems` is unpacked into `values`, a list of tensors. The shape of the result tensor is fn(initializer, values[0]).shape`. Args: fn: The callable to be performed. elems: A tensor to be unpacked on dimension 0. initializer: (optional) The initial value for the accumulator. parallel_iterations: (optional) The number of iterations allowed to run in parallel. back_prop: (optional) True enables support for back propagation. swap_memory: (optional) True enables GPU-CPU memory swapping. name: (optional) Name prefix for the returned tensors. Returns: A tensor resulting from applying `fn` consecutively to the list of tensors unpacked from `elems`, from first to last. Raises: TypeError: if `fn` is not callable. Example: ```python elems = [1, 2, 3, 4, 5, 6] sum = foldl(lambda a, x: a + x, elems) # sum == 21 ``` """ if not callable(fn): raise TypeError("fn must be callable.") in_graph_mode = context.in_graph_mode() with ops.name_scope(name, "foldl", [elems]): # TODO(akshayka): Remove the in_graph_mode check once caching devices are # supported in Eager if in_graph_mode: # Any get_variable calls in fn will cache the first call locally # and not issue repeated network I/O requests for each iteration. varscope = vs.get_variable_scope() varscope_caching_device_was_none = False if varscope.caching_device is None: # TODO(ebrevdo): Change to using colocate_with here and in other # methods. varscope.set_caching_device(lambda op: op.device) varscope_caching_device_was_none = True # Convert elems to tensor array. elems = ops.convert_to_tensor(elems, name="elems") n = array_ops.shape(elems)[0] elems_ta = tensor_array_ops.TensorArray(dtype=elems.dtype, size=n, dynamic_size=False, infer_shape=True) elems_ta = elems_ta.unstack(elems) if initializer is None: a = elems_ta.read(0) i = constant_op.constant(1) else: a = ops.convert_to_tensor(initializer) i = constant_op.constant(0) def compute(i, a): a = fn(a, elems_ta.read(i)) return [i + 1, a] _, r_a = control_flow_ops.while_loop( lambda i, a: i < n, compute, [i, a], parallel_iterations=parallel_iterations, back_prop=back_prop, swap_memory=swap_memory) # TODO(akshayka): Remove the in_graph_mode check once caching devices are # supported in Eager if in_graph_mode and varscope_caching_device_was_none: varscope.set_caching_device(None) return r_a
def _param_shapes(sample_shape): return {"df": ops.convert_to_tensor(sample_shape, dtype=dtypes.int32)}
def map_fn(fn, elems, dtype=None, parallel_iterations=10, back_prop=True, swap_memory=False, infer_shape=True, name=None): """map on the list of tensors unpacked from `elems` on dimension 0. The simplest version of `map_fn` repeatedly applies the callable `fn` to a sequence of elements from first to last. The elements are made of the tensors unpacked from `elems`. `dtype` is the data type of the return value of `fn`. Users must provide `dtype` if it is different from the data type of `elems`. Suppose that `elems` is unpacked into `values`, a list of tensors. The shape of the result tensor is `[values.shape[0]] + fn(values[0]).shape`. This method also allows multi-arity `elems` and output of `fn`. If `elems` is a (possibly nested) list or tuple of tensors, then each of these tensors must have a matching first (unpack) dimension. The signature of `fn` may match the structure of `elems`. That is, if `elems` is `(t1, [t2, t3, [t4, t5]])`, then an appropriate signature for `fn` is: `fn = lambda (t1, [t2, t3, [t4, t5]]):`. Furthermore, `fn` may emit a different structure than its input. For example, `fn` may look like: `fn = lambda t1: return (t1 + 1, t1 - 1)`. In this case, the `dtype` parameter is not optional: `dtype` must be a type or (possibly nested) tuple of types matching the output of `fn`. To apply a functional operation to the nonzero elements of a SparseTensor one of the following methods is recommended. First, if the function is expressible as TensorFlow ops, use ```python result = SparseTensor(input.indices, fn(input.values), input.dense_shape) ``` If, however, the function is not expressible as a TensorFlow op, then use ```python result = SparseTensor( input.indices, map_fn(fn, input.values), input.dense_shape) ``` instead. Args: fn: The callable to be performed. It accepts one argument, which will have the same (possibly nested) structure as `elems`. Its output must have the same structure as `dtype` if one is provided, otherwise it must have the same structure as `elems`. elems: A tensor or (possibly nested) sequence of tensors, each of which will be unpacked along their first dimension. The nested sequence of the resulting slices will be applied to `fn`. dtype: (optional) The output type(s) of `fn`. If `fn` returns a structure of Tensors differing from the structure of `elems`, then `dtype` is not optional and must have the same structure as the output of `fn`. parallel_iterations: (optional) The number of iterations allowed to run in parallel. back_prop: (optional) True enables support for back propagation. swap_memory: (optional) True enables GPU-CPU memory swapping. infer_shape: (optional) False disables tests for consistent output shapes. name: (optional) Name prefix for the returned tensors. Returns: A tensor or (possibly nested) sequence of tensors. Each tensor packs the results of applying `fn` to tensors unpacked from `elems` along the first dimension, from first to last. Raises: TypeError: if `fn` is not callable or the structure of the output of `fn` and `dtype` do not match, or if elems is a SparseTensor. ValueError: if the lengths of the output of `fn` and `dtype` do not match. Examples: ```python elems = np.array([1, 2, 3, 4, 5, 6]) squares = map_fn(lambda x: x * x, elems) # squares == [1, 4, 9, 16, 25, 36] ``` ```python elems = (np.array([1, 2, 3]), np.array([-1, 1, -1])) alternate = map_fn(lambda x: x[0] * x[1], elems, dtype=tf.int64) # alternate == [-1, 2, -3] ``` ```python elems = np.array([1, 2, 3]) alternates = map_fn(lambda x: (x, -x), elems, dtype=(tf.int64, tf.int64)) # alternates[0] == [1, 2, 3] # alternates[1] == [-1, -2, -3] ``` """ if not callable(fn): raise TypeError("fn must be callable.") if isinstance(elems, sparse_tensor.SparseTensor): raise TypeError( "To perform a map on the values of a sparse tensor use either " " SparseTensor(input.indices, fn(input.values), input.dense_shape) or " " SparseTensor(input.indices, map_fn(fn, input.values), " "input.dense_shape)") input_is_sequence = nest.is_sequence(elems) input_flatten = lambda x: nest.flatten(x) if input_is_sequence else [x] def input_pack(x): return nest.pack_sequence_as(elems, x) if input_is_sequence else x[0] if dtype is None: output_is_sequence = input_is_sequence output_flatten = input_flatten output_pack = input_pack else: output_is_sequence = nest.is_sequence(dtype) output_flatten = lambda x: nest.flatten( x) if output_is_sequence else [x] def output_pack(x): return (nest.pack_sequence_as(dtype, x) if output_is_sequence else x[0]) elems_flat = input_flatten(elems) in_graph_mode = context.in_graph_mode() with ops.name_scope(name, "map", elems_flat): # TODO(akshayka): Remove the in_graph_mode check once caching devices are # supported in Eager if in_graph_mode: # Any get_variable calls in fn will cache the first call locally # and not issue repeated network I/O requests for each iteration. varscope = vs.get_variable_scope() varscope_caching_device_was_none = False if varscope.caching_device is None: # TODO(ebrevdo): Change to using colocate_with here and in other # methods. varscope.set_caching_device(lambda op: op.device) varscope_caching_device_was_none = True elems_flat = [ ops.convert_to_tensor(elem, name="elem") for elem in elems_flat ] dtype = dtype or input_pack([elem.dtype for elem in elems_flat]) dtype_flat = output_flatten(dtype) # Convert elems to tensor array. n = array_ops.shape(elems_flat[0])[0] # TensorArrays are always flat elems_ta = [ tensor_array_ops.TensorArray(dtype=elem.dtype, size=n, dynamic_size=False, infer_shape=True) for elem in elems_flat ] # Unpack elements elems_ta = [ elem_ta.unstack(elem) for elem_ta, elem in zip(elems_ta, elems_flat) ] i = constant_op.constant(0) accs_ta = [ tensor_array_ops.TensorArray(dtype=dt, size=n, dynamic_size=False, infer_shape=infer_shape) for dt in dtype_flat ] def compute(i, tas): """The loop body of map_fn. Args: i: the loop counter tas: the flat TensorArray accumulator list Returns: (i + 1, tas): the updated counter + updated TensorArrays Raises: TypeError: if dtype and packed_fn_values structure do not match ValueType: if dtype and packed_fn_values lengths do not match """ packed_values = input_pack( [elem_ta.read(i) for elem_ta in elems_ta]) packed_fn_values = fn(packed_values) nest.assert_same_structure(dtype or elems, packed_fn_values) flat_fn_values = output_flatten(packed_fn_values) tas = [ ta.write(i, value) for (ta, value) in zip(tas, flat_fn_values) ] return (i + 1, tas) _, r_a = control_flow_ops.while_loop( lambda i, _: i < n, compute, (i, accs_ta), parallel_iterations=parallel_iterations, back_prop=back_prop, swap_memory=swap_memory) results_flat = [r.stack() for r in r_a] n_static = elems_flat[0].get_shape().with_rank_at_least(1)[0] for elem in elems_flat[1:]: n_static.merge_with(elem.get_shape().with_rank_at_least(1)[0]) for r in results_flat: r.set_shape( tensor_shape.TensorShape(n_static).concatenate( r.get_shape()[1:])) # TODO(akshayka): Remove the in_graph_mode check once caching devices are # supported in Eager if in_graph_mode and varscope_caching_device_was_none: varscope.set_caching_device(None) return output_pack(results_flat)
def _resource_apply_dense(self, grad, var): var_dtype = var.dtype.base_dtype lr_t = array_ops.identity(self._get_hyper('learning_rate', var_dtype)) beta_1_t = array_ops.identity(self._get_hyper('beta_1', var_dtype)) beta_2_t = array_ops.identity(self._get_hyper('beta_2', var_dtype)) epsilon_t = ops.convert_to_tensor(self.epsilon, var_dtype) m = self.get_slot(var, 'm') v = self.get_slot(var, 'v') local_step = math_ops.cast(self.iterations + 1, var_dtype) next_step = math_ops.cast(self.iterations + 2, var_dtype) decay_base = math_ops.cast(0.96, var_dtype) # Learning rate multipliers if self.lr_multipliers is not None: lr_t = _apply_lr_multiplier(self, lr_t, var) # Due to the recommendations in [2], i.e. warming momentum schedule momentum_cache_t = beta_1_t * ( 1. - 0.5 * (math_ops.pow(decay_base, self._initial_decay * local_step))) momentum_cache_t_1 = beta_1_t * ( 1. - 0.5 * (math_ops.pow(decay_base, self._initial_decay * next_step))) m_schedule_new = math_ops.cast(self._m_cache_read, var_dtype) * momentum_cache_t if var_dtype is self._m_cache.dtype: m_schedule_new = array_ops.identity( state_ops.assign(self._m_cache, m_schedule_new, use_locking=self._use_locking)) m_schedule_next = m_schedule_new * momentum_cache_t_1 # the following equations given in [1] g_prime = grad / (1. - m_schedule_new) m_t = beta_1_t * m + (1. - beta_1_t) * grad m_t_prime = m_t / (1. - m_schedule_next) v_t = beta_2_t * v + (1. - beta_2_t) * math_ops.square(grad) v_t_prime = v_t / (1. - math_ops.pow(beta_2_t, local_step)) m_t_bar = (1. - momentum_cache_t) * g_prime + (momentum_cache_t * m_t_prime) m_t = state_ops.assign(m, m_t, use_locking=self._use_locking) v_t = state_ops.assign(v, v_t, use_locking=self._use_locking) var_t = math_ops.sub( var, self.eta_t * lr_t * m_t_bar / (math_ops.sqrt(v_t_prime + epsilon_t))) # Weight decays if var.name in self.weight_decays.keys(): var_t = _apply_weight_decays(self, var, var_t) var_update = state_ops.assign(var, var_t, use_locking=self._use_locking) # Cosine annealing (iteration_done, t_cur_update, eta_t_update) = _update_t_cur_eta_t_v2(self, lr_t, var) if iteration_done and not self._init_notified: self._init_notified = True updates = [var_update, m_t, v_t] if iteration_done: updates += [t_cur_update] if self.use_cosine_annealing and iteration_done: updates += [eta_t_update] return control_flow_ops.group(*updates)
def dynamic_distraction_decoder_wrapper(decoder_inputs, initial_state, distract_initial_state, attention_states, attention_states_query, cell_encoder, distraction_cell, num_symbols, embedding_size, num_heads=1, output_size=None, output_projection=None, feed_previous=False, update_embedding_for_previous=True, embedding_scope=None, dtype=None, scope=None, initial_state_attention=False): """RNN decoder with embedding and attention and a pure-decoding option. Args: decoder_inputs: A list of 1D batch-sized int32 Tensors (decoder inputs). initial_state: 2D Tensor [batch_size x cell.state_size]. attention_states: 3D Tensor [batch_size x attn_length x attn_size]. cell: rnn_cell.RNNCell defining the cell function. num_symbols: Integer, how many symbols come into the embedding. embedding_size: Integer, the length of the embedding vector for each symbol. num_heads: Number of attention heads that read from attention_states. output_size: Size of the output vectors; if None, use output_size. output_projection: None or a pair (W, B) of output projection weights and biases; W has shape [output_size x num_symbols] and B has shape [num_symbols]; if provided and feed_previous=True, each fed previous output will first be multiplied by W and added B. feed_previous: Boolean; if True, only the first of decoder_inputs will be used (the "GO" symbol), and all other decoder inputs will be generated by: next = embedding_lookup(embedding, argmax(previous_output)), In effect, this implements a greedy decoder. It can also be used during training to emulate http://arxiv.org/abs/1506.03099. If False, decoder_inputs are used as given (the standard decoder case). update_embedding_for_previous: Boolean; if False and feed_previous=True, only the embedding for the first symbol of decoder_inputs (the "GO" symbol) will be updated by back propagation. Embeddings for the symbols generated from the decoder itself remain unchanged. This parameter has no effect if feed_previous=False. dtype: The dtype to use for the RNN initial states (default: tf.float32). scope: VariableScope for the created subgraph; defaults to "embedding_attention_decoder". initial_state_attention: If False (default), initial attentions are zero. If True, initialize the attentions from the initial state and attention states -- useful when we wish to resume decoding from a previously stored decoder state and attention states. Returns: A tuple of the form (outputs, state), where: outputs: A list of the same length as decoder_inputs of 2D Tensors with shape [batch_size x output_size] containing the generated outputs. state: The state of each decoder cell at the final time-step. It is a 2D Tensor of shape [batch_size x cell.state_size]. Raises: ValueError: When output_projection has the wrong shape. """ if output_size is None: output_size = cell_encoder.output_size if output_projection is not None: proj_biases = ops.convert_to_tensor(output_projection[1], dtype=dtype) proj_biases.get_shape().assert_is_compatible_with([num_symbols]) with variable_scope.variable_scope( embedding_scope or "dynamic_distraction_decoder_wrapper", dtype=dtype, reuse=True) as s1: print("Preksha", s1.name) embedding = variable_scope.get_variable("embedding", [num_symbols, embedding_size]) loop_function = _extract_argmax_and_embed( embedding, output_projection, update_embedding_for_previous) if feed_previous else None emb_inp = [ embedding_ops.embedding_lookup(embedding, i) for i in decoder_inputs ] with variable_scope.variable_scope( scope or "dynamic_distraction_decoder_wrapper", dtype=dtype) as scope: return dynamic_distraction_decoder( emb_inp, initial_state=initial_state, attention_states_query=attention_states_query, attention_states=attention_states, cell=cell_encoder, distract_initial_state=distract_initial_state, distraction_cell=distraction_cell, output_size=output_size, num_heads=num_heads, loop_function=loop_function, initial_state_attention=initial_state_attention)
train_labels_file) test_filepaths, test_labels = read_label_file(dataset_path + test_labels_file) # transform relative path into full path train_filepaths = [dataset_path + fp for fp in train_filepaths] test_filepaths = [dataset_path + fp for fp in test_filepaths] # for this example we will create or own test partition all_filepaths = train_filepaths + test_filepaths all_labels = train_labels + test_labels all_filepaths = all_filepaths[:20] all_labels = all_labels[:20] # convert string into tensors all_images = ops.convert_to_tensor(all_filepaths, dtype=dtypes.string) all_labels = ops.convert_to_tensor(all_labels, dtype=dtypes.int32) # create a partition vector partitions = [0] * len(all_filepaths) partitions[:test_set_size] = [1] * test_set_size random.shuffle(partitions) # partition our data into a test and train set according to our partition vector train_images, test_images = tf.dynamic_partition(all_images, partitions, 2) train_labels, test_labels = tf.dynamic_partition(all_labels, partitions, 2) # create input queues train_input_queue = tf.train.slice_input_producer([train_images, train_labels], shuffle=False) test_input_queue = tf.train.slice_input_producer([test_images, test_labels],
def _resource_apply_sparse(self, grad, var, indices, apply_state=None): var_dtype = var.dtype.base_dtype lr_t = array_ops.identity(self._get_hyper('learning_rate', var_dtype)) beta_1_t = array_ops.identity(self._get_hyper('beta_1', var_dtype)) beta_2_t = array_ops.identity(self._get_hyper('beta_2', var_dtype)) epsilon_t = ops.convert_to_tensor(self.epsilon, var_dtype) m = self.get_slot(var, 'm') v = self.get_slot(var, 'v') local_step = math_ops.cast(self.iterations + 1, var_dtype) next_step = math_ops.cast(self.iterations + 2, var_dtype) decay_base = math_ops.cast(0.96, var_dtype) # Learning rate multipliers if self.lr_multipliers is not None: lr_t = _apply_lr_multiplier(self, lr_t, var) momentum_cache_t = beta_1_t * ( 1. - 0.5 * (math_ops.pow(decay_base, self._initial_decay * local_step))) momentum_cache_t_1 = beta_1_t * ( 1. - 0.5 * (math_ops.pow(decay_base, self._initial_decay * next_step))) m_schedule_new = math_ops.cast(self._m_cache_read, var_dtype) * momentum_cache_t if var_dtype is self._m_cache.dtype: m_schedule_new = array_ops.identity( state_ops.assign(self._m_cache, m_schedule_new, use_locking=self._use_locking)) m_schedule_next = m_schedule_new * momentum_cache_t_1 m_scaled_g_values = grad * (1. - beta_1_t) m_t = state_ops.assign(m, m * beta_1_t, use_locking=self._use_locking) with ops.control_dependencies([m_t]): m_t = self._resource_scatter_add(m, indices, m_scaled_g_values) m_t_slice = array_ops.gather(m_t, indices) m_t_prime = m_t_slice / (1. - m_schedule_next) g_prime = grad / (1. - m_schedule_new) m_t_bar = (1. - momentum_cache_t) * g_prime + (momentum_cache_t_1 * m_t_prime) v_scaled_g_values = (grad * grad) * (1. - beta_2_t) v_t = state_ops.assign(v, v * beta_2_t, use_locking=self._use_locking) with ops.control_dependencies([v_t]): v_t = self._resource_scatter_add(v, indices, v_scaled_g_values) v_t_slice = array_ops.gather(v_t, indices) v_t_prime_denominator = 1. - math_ops.pow(beta_2_t, local_step) v_t_prime = v_t_slice / v_t_prime_denominator v_prime_sqrt_plus_eps = math_ops.sqrt(v_t_prime) + epsilon_t var_t = self._resource_scatter_add( var, indices, -self.eta_t * lr_t * m_t_bar / v_prime_sqrt_plus_eps) # Weight decays if var.name in self.weight_decays.keys(): var_t = _apply_weight_decays(self, var, var_t) var_update = state_ops.assign(var, var_t, use_locking=self._use_locking) # Cosine annealing (iteration_done, t_cur_update, eta_t_update) = _update_t_cur_eta_t_v2(self, lr_t, var) if iteration_done and not self._init_notified: self._init_notified = True updates = [var_update, m_t_bar, v_t] if iteration_done: updates += [t_cur_update] if self.use_cosine_annealing and iteration_done: updates += [eta_t_update] return control_flow_ops.group(*updates)
def __call__(self, *inputs, **kwargs): inputs = [ops.convert_to_tensor(_) for _ in inputs] return _call(self._sig, *inputs, **kwargs)[0]
def __init__(self, size): super(IdentityIndexedDataset, self).__init__() # TODO(saeta): Verify _size is a scalar! self._size = ops.convert_to_tensor(size, dtype=dtypes.uint64, name="size")
def __init__( self, # pylint: disable=super-init-not-called initial_value=None, trainable=None, caching_device=None, name=None, dtype=None, constraint=None, **unused_kwargs): """Creates a variable. Args: initial_value: A `Tensor`, or Python object convertible to a `Tensor`, which is the initial value for the Variable. The initial value must have a shape specified unless `validate_shape` is set to False. Can also be a callable with no argument that returns the initial value when called. (Note that initializer functions from init_ops.py must first be bound to a shape before being used here.) trainable: If `True`, GradientTapes automatically watch uses of this Variable. caching_device: Optional device string or function describing where the Variable should be cached for reading. Defaults to the Variable's device. If not `None`, caches on another device. Typical use is to cache on the device where the Ops using the Variable reside, to deduplicate copying through `Switch` and other conditional statements. name: Optional name for the variable. Defaults to `'Variable'` and gets uniquified automatically. dtype: If set, initial_value will be converted to the given type. If None, either the datatype will be kept (if initial_value is a Tensor) or float32 will be used (if it is a Python object convertible to a Tensor). constraint: An optional projection function to be applied to the variable after being updated by an `Optimizer` (e.g. used to implement norm constraints or value constraints for layer weights). The function must take as input the unprojected Tensor representing the value of the variable and return the Tensor for the projected value (which must have the same shape). Constraints are not safe to use when doing asynchronous distributed training. Raises: ValueError: If the initial value is not specified, or does not have a shape and `validate_shape` is `True`. RuntimeError: If called outside of a function definition. """ if context.executing_eagerly(): # If we've been init_scope()d out of the function definition nothing to do # here; we can't really do the capturing or conditional logic. resource_variable_ops.ResourceVariable.__init__( self, initial_value=initial_value, trainable=trainable, caching_device=caching_device, name=name, dtype=dtype, constraint=constraint) return with ops.init_scope(): if not context.executing_eagerly(): raise RuntimeError( "UnliftedInitializerVariable does not support legacy graph mode." ) self._in_graph_mode = False if initial_value is None: raise ValueError("initial_value must be specified.") init_from_fn = callable(initial_value) if constraint is not None and not callable(constraint): raise ValueError("The `constraint` argument must be a callable.") if isinstance(initial_value, checkpointable.CheckpointInitialValue): self._maybe_initialize_checkpointable() self._update_uid = initial_value.checkpoint_position.restore_uid initial_value = initial_value.wrapped_value if trainable is None: trainable = True self._trainable = trainable self._save_slice_info = None self._initial_value = None self._initializer_op = None self._is_initialized_op = None self._graph_element = None self._cached_value = None # Store the graph key so optimizers know how to only retrieve variables from # this graph. Guaranteed to be the same as the eager graph_key. self._graph_key = ops.get_default_graph()._graph_key # pylint: disable=protected-access with ops.name_scope(name, "Variable", [] if init_from_fn else [initial_value]) as name: # pylint: disable=protected-access with ops.init_scope(): assert context.executing_eagerly() shared_name = ops._name_from_scope_name(name) shared_name = "%s_%d" % (shared_name, ops.uid()) # Use attr_scope and device(None) to simulate the behavior of # colocate_with when the variable we want to colocate with doesn't # yet exist. with ops.name_scope("Initializer"), ops.device(None): initial_value = ops.convert_to_tensor( initial_value() if init_from_fn else initial_value, name="initial_value", dtype=dtype) with ops.init_scope(): self._handle = resource_variable_ops.eager_safe_variable_handle( shape=initial_value.get_shape(), dtype=initial_value.dtype.base_dtype, shared_name=shared_name, name=name, graph_mode=False) self._shape = initial_value.shape self._unique_id = shared_name self._handle_name = shared_name + ":0" self._dtype = initial_value.dtype.base_dtype self._constraint = constraint assert initial_value is not None def assign_fn(): with ops.name_scope("Assign") as n, ops.colocate_with( self._handle): resource_variable_ops.assign_variable_op(self._handle, initial_value, name=n) # Returning values to keep tf.cond happy. return ops.convert_to_tensor(1) def not_assign_fn(): return ops.convert_to_tensor(0) # Note: this cond is always guaranteed to run because we're inside a defun # which will insert automatic control dependencies. control_flow_ops.cond( resource_variable_ops.var_is_initialized_op(self._handle), not_assign_fn, assign_fn) # After the handle has been created, set up a way to clean it up when # executing eagerly. We'll hold the only reference to the deleter, so that # when this object is garbage collected the deleter will be too. This # means ResourceVariables can be part of reference cycles without those # cycles being uncollectable. self._handle_deleter = resource_variable_ops.EagerResourceDeleter( handle=self._handle, handle_device=self._handle.device) self._cached_shape_as_list = None
def _param_shapes(sample_shape): return dict( zip(("mu", "sigma"), ([ops.convert_to_tensor(sample_shape, dtype=dtypes.int32)] * 2)))
def _log_prob(self, x): with ops.control_dependencies(self._assertions): x = ops.convert_to_tensor(x, name="x") cat_log_prob = self._cat.log_prob(math_ops.cast(clip_ops.clip_by_value(x, 0, self.K), dtypes.int32)) return where(x < self.K, cat_log_prob, cat_log_prob + self._dist.log_prob(x - self.K))
def _TensorListGatherGrad(op, dtensor): _, indices = op.inputs return gen_list_ops.tensor_list_scatter( tensor=dtensor, indices=indices, element_shape=ops.convert_to_tensor(-1, dtype=dtypes.int32)), None
def __init__(self, cell, embedding, start_tokens, end_token, initial_state, beam_width, output_layer=None, length_penalty_weight=0.0, coverage_penalty_weight=0.0, reorder_tensor_arrays=True): """Initialize the BeamSearchDecoder. Args: cell: An `RNNCell` instance. embedding: A callable that takes a vector tensor of `ids` (argmax ids), or the `params` argument for `embedding_lookup`. start_tokens: `int32` vector shaped `[batch_size]`, the start tokens. end_token: `int32` scalar, the token that marks end of decoding. initial_state: A (possibly nested tuple of...) tensors and TensorArrays. beam_width: Python integer, the number of beams. output_layer: (Optional) An instance of `tf.layers.Layer`, i.e., `tf.layers.Dense`. Optional layer to apply to the RNN output prior to storing the result or sampling. length_penalty_weight: Float weight to penalize length. Disabled with 0.0. coverage_penalty_weight: Float weight to penalize the coverage of source sentence. Disabled with 0.0. reorder_tensor_arrays: If `True`, `TensorArray`s' elements within the cell state will be reordered according to the beam search path. If the `TensorArray` can be reordered, the stacked form will be returned. Otherwise, the `TensorArray` will be returned as is. Set this flag to `False` if the cell state contains `TensorArray`s that are not amenable to reordering. Raises: TypeError: if `cell` is not an instance of `RNNCell`, or `output_layer` is not an instance of `tf.layers.Layer`. ValueError: If `start_tokens` is not a vector or `end_token` is not a scalar. """ rnn_cell_impl.assert_like_rnncell("cell", cell) # pylint: disable=protected-access if (output_layer is not None and not isinstance(output_layer, layers_base.Layer)): raise TypeError("output_layer must be a Layer, received: %s" % type(output_layer)) self._cell = cell self._output_layer = output_layer self._reorder_tensor_arrays = reorder_tensor_arrays if callable(embedding): self._embedding_fn = embedding else: self._embedding_fn = ( lambda ids: embedding_ops.embedding_lookup(embedding, ids)) self._start_tokens = ops.convert_to_tensor(start_tokens, dtype=dtypes.int32, name="start_tokens") if self._start_tokens.get_shape().ndims != 1: raise ValueError("start_tokens must be a vector") self._end_token = ops.convert_to_tensor(end_token, dtype=dtypes.int32, name="end_token") if self._end_token.get_shape().ndims != 0: raise ValueError("end_token must be a scalar") self._batch_size = array_ops.size(start_tokens) self._beam_width = beam_width self._length_penalty_weight = length_penalty_weight self._coverage_penalty_weight = coverage_penalty_weight self._initial_cell_state = nest.map_structure( self._maybe_split_batch_beams, initial_state, self._cell.state_size) self._start_tokens = array_ops.tile( array_ops.expand_dims(self._start_tokens, 1), [1, self._beam_width]) self._start_inputs = self._embedding_fn(self._start_tokens) self._finished = array_ops.one_hot(array_ops.zeros([self._batch_size], dtype=dtypes.int32), depth=self._beam_width, on_value=False, off_value=True, dtype=dtypes.bool)
def not_assign_fn(): return ops.convert_to_tensor(0)
def ScalarShape(): return ops.convert_to_tensor([], dtype=dtypes.int32)
def _beam_search_step(time, logits, next_cell_state, beam_state, batch_size, beam_width, end_token, length_penalty_weight, coverage_penalty_weight): """Performs a single step of Beam Search Decoding. Args: time: Beam search time step, should start at 0. At time 0 we assume that all beams are equal and consider only the first beam for continuations. logits: Logits at the current time step. A tensor of shape `[batch_size, beam_width, vocab_size]` next_cell_state: The next state from the cell, e.g. an instance of AttentionWrapperState if the cell is attentional. beam_state: Current state of the beam search. An instance of `BeamSearchDecoderState`. batch_size: The batch size for this input. beam_width: Python int. The size of the beams. end_token: The int32 end token. length_penalty_weight: Float weight to penalize length. Disabled with 0.0. coverage_penalty_weight: Float weight to penalize the coverage of source sentence. Disabled with 0.0. Returns: A new beam state. """ static_batch_size = tensor_util.constant_value(batch_size) # Calculate the current lengths of the predictions prediction_lengths = beam_state.lengths previously_finished = beam_state.finished not_finished = math_ops.logical_not(previously_finished) # Calculate the total log probs for the new hypotheses # Final Shape: [batch_size, beam_width, vocab_size] step_log_probs = nn_ops.log_softmax(logits) step_log_probs = _mask_probs(step_log_probs, end_token, previously_finished) total_probs = array_ops.expand_dims(beam_state.log_probs, 2) + step_log_probs # Calculate the continuation lengths by adding to all continuing beams. vocab_size = logits.shape[-1].value or array_ops.shape(logits)[-1] lengths_to_add = array_ops.one_hot(indices=array_ops.fill( [batch_size, beam_width], end_token), depth=vocab_size, on_value=np.int64(0), off_value=np.int64(1), dtype=dtypes.int64) add_mask = math_ops.to_int64(not_finished) lengths_to_add *= array_ops.expand_dims(add_mask, 2) new_prediction_lengths = (lengths_to_add + array_ops.expand_dims(prediction_lengths, 2)) # Calculate the accumulated attention probabilities if coverage penalty is # enabled. accumulated_attention_probs = None attention_probs = get_attention_probs(next_cell_state, coverage_penalty_weight) if attention_probs is not None: attention_probs *= array_ops.expand_dims( math_ops.to_float(not_finished), 2) accumulated_attention_probs = (beam_state.accumulated_attention_probs + attention_probs) # Calculate the scores for each beam scores = _get_scores( log_probs=total_probs, sequence_lengths=new_prediction_lengths, length_penalty_weight=length_penalty_weight, coverage_penalty_weight=coverage_penalty_weight, finished=previously_finished, accumulated_attention_probs=accumulated_attention_probs) time = ops.convert_to_tensor(time, name="time") # During the first time step we only consider the initial beam scores_flat = array_ops.reshape(scores, [batch_size, -1]) # Pick the next beams according to the specified successors function next_beam_size = ops.convert_to_tensor(beam_width, dtype=dtypes.int32, name="beam_width") next_beam_scores, word_indices = nn_ops.top_k(scores_flat, k=next_beam_size) next_beam_scores.set_shape([static_batch_size, beam_width]) word_indices.set_shape([static_batch_size, beam_width]) # Pick out the probs, beam_ids, and states according to the chosen predictions next_beam_probs = _tensor_gather_helper(gather_indices=word_indices, gather_from=total_probs, batch_size=batch_size, range_size=beam_width * vocab_size, gather_shape=[-1], name="next_beam_probs") # Note: just doing the following # math_ops.to_int32(word_indices % vocab_size, # name="next_beam_word_ids") # would be a lot cleaner but for reasons unclear, that hides the results of # the op which prevents capturing it with tfdbg debug ops. raw_next_word_ids = math_ops.mod(word_indices, vocab_size, name="next_beam_word_ids") next_word_ids = math_ops.to_int32(raw_next_word_ids) next_beam_ids = math_ops.to_int32(word_indices / vocab_size, name="next_beam_parent_ids") # Append new ids to current predictions previously_finished = _tensor_gather_helper( gather_indices=next_beam_ids, gather_from=previously_finished, batch_size=batch_size, range_size=beam_width, gather_shape=[-1]) next_finished = math_ops.logical_or(previously_finished, math_ops.equal(next_word_ids, end_token), name="next_beam_finished") # Calculate the length of the next predictions. # 1. Finished beams remain unchanged. # 2. Beams that are now finished (EOS predicted) have their length # increased by 1. # 3. Beams that are not yet finished have their length increased by 1. lengths_to_add = math_ops.to_int64( math_ops.logical_not(previously_finished)) next_prediction_len = _tensor_gather_helper(gather_indices=next_beam_ids, gather_from=beam_state.lengths, batch_size=batch_size, range_size=beam_width, gather_shape=[-1]) next_prediction_len += lengths_to_add next_accumulated_attention_probs = () if accumulated_attention_probs is not None: next_accumulated_attention_probs = _tensor_gather_helper( gather_indices=next_beam_ids, gather_from=accumulated_attention_probs, batch_size=batch_size, range_size=beam_width, gather_shape=[batch_size * beam_width, -1], name="next_accumulated_attention_probs") # Pick out the cell_states according to the next_beam_ids. We use a # different gather_shape here because the cell_state tensors, i.e. # the tensors that would be gathered from, all have dimension # greater than two and we need to preserve those dimensions. # pylint: disable=g-long-lambda next_cell_state = nest.map_structure( lambda gather_from: _maybe_tensor_gather_helper( gather_indices=next_beam_ids, gather_from=gather_from, batch_size=batch_size, range_size=beam_width, gather_shape=[batch_size * beam_width, -1]), next_cell_state) # pylint: enable=g-long-lambda next_state = BeamSearchDecoderState( cell_state=next_cell_state, log_probs=next_beam_probs, lengths=next_prediction_len, finished=next_finished, accumulated_attention_probs=next_accumulated_attention_probs) output = BeamSearchDecoderOutput(scores=next_beam_scores, predicted_ids=next_word_ids, parent_ids=next_beam_ids) return output, next_state