def _decode_and_random_crop(image_bytes): """Make a random crop of 224.""" img_size = tf.image.extract_jpeg_shape(image_bytes) area = tf.cast(img_size[1] * img_size[0], tf.float32) target_area = tf.random.uniform([], 0.08, 1.0, dtype=tf.float32) * area log_ratio = (tf.math.log(3 / 4), tf.math.log(4 / 3)) aspect_ratio = tf.math.exp( tf.random.uniform([], *log_ratio, dtype=tf.float32)) w = tf.cast(tf.round(tf.sqrt(target_area * aspect_ratio)), tf.int32) h = tf.cast(tf.round(tf.sqrt(target_area / aspect_ratio)), tf.int32) w = tf.minimum(w, img_size[1]) h = tf.minimum(h, img_size[0]) offset_w = tf.random.uniform((), minval=0, maxval=img_size[1] - w + 1, dtype=tf.int32) offset_h = tf.random.uniform((), minval=0, maxval=img_size[0] - h + 1, dtype=tf.int32) crop_window = tf.stack([offset_h, offset_w, h, w]) image = tf.io.decode_and_crop_jpeg(image_bytes, crop_window, channels=3) return image
def test_quantile(self): d = tfd.BatchBroadcast(tfd.Normal(loc=[0., 1, 2], scale=.5), [2, 1]) expected = tf.broadcast_to(tf.constant([0., 1, 2]), [2, 3]) self.assertAllEqual(expected, d.quantile(.5)) x = d.quantile([[.45], [.55]]) self.assertAllEqual(expected, tf.round(x)) self.assertAllTrue(x[0] < x[1])
def compress(self, bottleneck): """Compresses a floating-point tensor. Compresses the tensor to bit strings. `bottleneck` is first quantized as in `quantize()`, and then compressed using the probability tables derived from `self.prior`. The quantized tensor can later be recovered by calling `decompress()`. The innermost `self.coding_rank` dimensions are treated as one coding unit, i.e. are compressed into one string each. Any additional dimensions to the left are treated as batch dimensions. Arguments: bottleneck: `tf.Tensor` containing the data to be compressed. Must have at least `self.coding_rank` dimensions, and the innermost dimensions must be broadcastable to `self.prior_shape`. Returns: A `tf.Tensor` having the same shape as `bottleneck` without the `self.coding_rank` innermost dimensions, containing a string for each coding unit. """ input_shape = tf.shape(bottleneck) input_rank = tf.shape(input_shape)[0] batch_shape, coding_shape = tf.split( input_shape, [input_rank - self.coding_rank, self.coding_rank]) broadcast_shape = coding_shape[:self.coding_rank - len(self.prior_shape)] indexes, offset = self._compute_indexes_and_offset(broadcast_shape) if offset is not None: bottleneck -= offset symbols = tf.cast(tf.round(bottleneck), tf.int32) symbols = tf.reshape(symbols, tf.concat([[-1], coding_shape], 0)) # Prevent tensors from bouncing back and forth between host and GPU. with tf.device("/cpu:0"): cdf = self.cdf cdf_length = self.cdf_length cdf_offset = self.cdf_offset def loop_body(symbols): return range_coding_ops.unbounded_index_range_encode( symbols, indexes, cdf, cdf_length, cdf_offset, precision=self.range_coder_precision, overflow_width=4, debug_level=1) # TODO(jonycgn,ssjhv): Consider switching to Python control flow. strings = tf.map_fn(loop_body, symbols, dtype=tf.string, name="compress") strings = tf.reshape(strings, batch_shape) return strings
def _round_through(x, use_stochastic_rounding=False): """Rounds x but using straight through estimator. We use the trick from [Sergey Ioffe](http://stackoverflow.com/a/36480182). Straight through estimator is a biased estimator for the rounding operation defined by Hinton"s Coursera Lecture 9c where dL/dx is made equal to dL/dy for y = f(x) during gradient computation, where f(x) is a non-derivable function. In that case, we assume df/dx = 1 in: dL dL df dL -- = -- -- = -- dx df dx dy (https://www.youtube.com/watch?v=LN0xtUuJsEI&list=PLoRl3Ht4JOcdU872GhiYWf6jwrk_SNhz9&index=41) Arguments: x: tensor to perform round operation with straight through gradient. use_stochastic_rounding: if true, we perform stochastic rounding. Returns: Rounded tensor. """ if use_stochastic_rounding: return x + tf.stop_gradient(-x + stochastic_round(x)) else: return x + tf.stop_gradient(-x + tf.round(x))
def proposal(seed): """Proposal for log-concave rejection sampler.""" (top_lobe_fractions_seed, exponential_samples_seed, top_selector_seed, rademacher_seed) = samplers.split_seed( seed, n=4, salt='log_concave_rejection_sampler_proposal') top_lobe_fractions = samplers.uniform( mode_shape, seed=top_lobe_fractions_seed, dtype=dtype) # V in ref [1]. top_offsets = top_lobe_fractions * top_width / mode_height exponential_samples = exponential_distribution.sample( mode_shape, seed=exponential_samples_seed) # E in ref [1]. exponential_height = (exponential_distribution.prob(exponential_samples) * mode_height) exponential_offsets = (top_width + exponential_samples) / mode_height top_selector = samplers.uniform( mode_shape, seed=top_selector_seed, dtype=dtype) # U in ref [1]. on_top_mask = tf.less_equal(top_selector, top_fraction) unsigned_offsets = tf.where(on_top_mask, top_offsets, exponential_offsets) offsets = tf.round( tfp_random.rademacher( mode_shape, seed=rademacher_seed, dtype=dtype) * unsigned_offsets) potential_samples = mode + offsets envelope_height = tf.where(on_top_mask, mode_height, exponential_height) return potential_samples, envelope_height
def compress(self, bottleneck, indexes): """Compresses a floating-point tensor. Compresses the tensor to bit strings. `bottleneck` is first quantized as in `quantize()`, and then compressed using the probability tables derived from `indexes`. The quantized tensor can later be recovered by calling `decompress()`. The innermost `self.coding_rank` dimensions are treated as one coding unit, i.e. are compressed into one string each. Any additional dimensions to the left are treated as batch dimensions. Arguments: bottleneck: `tf.Tensor` containing the data to be compressed. indexes: `tf.Tensor` specifying the scalar distribution for each element in `bottleneck`. See class docstring for examples. Returns: A `tf.Tensor` having the same shape as `bottleneck` without the `self.coding_rank` innermost dimensions, containing a string for each coding unit. """ indexes = self._normalize_indexes(indexes) flat_indexes = self._flatten_indexes(indexes) symbols_shape = tf.shape(flat_indexes) batch_shape = symbols_shape[:-self.coding_rank] flat_shape = tf.concat([[-1], symbols_shape[-self.coding_rank:]], 0) flat_indexes = tf.reshape(flat_indexes, flat_shape) offset = helpers.quantization_offset(self._make_prior(indexes)) symbols = tf.cast(tf.round(bottleneck - offset), tf.int32) symbols = tf.reshape(symbols, flat_shape) # Prevent tensors from bouncing back and forth between host and GPU. with tf.device("/cpu:0"): cdf = self.cdf cdf_length = self.cdf_length cdf_offset = self.cdf_offset def loop_body(args): return range_coding_ops.unbounded_index_range_encode( args[0], args[1], cdf, cdf_length, cdf_offset, precision=self.range_coder_precision, overflow_width=4, debug_level=1) # TODO(jonycgn,ssjhv): Consider switching to Python control flow. strings = tf.map_fn(loop_body, (symbols, flat_indexes), dtype=tf.string, name="compress") strings = tf.reshape(strings, batch_shape) return strings
def around(a, decimals=0): a = asarray(a) factor = math.pow(10, decimals) factor = tf.cast(factor, a.dtype) a_t = tf.multiply(a.data, factor) a_t = tf.round(a_t) a_t = tf.math.divide(a_t, factor) return utils.tensor_to_ndarray(a_t)
def _refercence_rate_fn(t): # The input `t` is a real `Tensor` specifying the time from valuation. # We convert it into a `DateTensor` by first conversting it into the # corresponding ordinal (assuming ACT_365 convention). interpolation_ordinals = tf.cast( tf.round(t * 365.0 + valuation_date_ordinal), dtype=tf.int32) interpolation_dates = dateslib.convert_to_date_tensor( interpolation_ordinals) return reference_curve.discount_rate(interpolation_dates)
def stochastic_round(x): """Performs stochastic rounding to the first decimal point.""" s = tf.sign(x) s += (1.0 - tf.abs(s)) * (2.0 * tf.round(tf.random.uniform(tf.shape(x))) - 1.0) t = tf.floor(x) - (s - 1.0) / 2.0 p = tf.abs(x - t) f = s * (tf.sign(p - tf.random.uniform(tf.shape(p))) + 1.0) / 2.0 return t + f
def _compute_new_dynamic_size(image, min_dimension, max_dimension): """Compute new dynamic shape for resize_to_range method.""" image_shape = tf.shape(input=image) orig_height = tf.cast(image_shape[0], dtype=tf.float32) orig_width = tf.cast(image_shape[1], dtype=tf.float32) num_channels = image_shape[2] orig_min_dim = tf.minimum(orig_height, orig_width) # Calculates the larger of the possible sizes min_dimension = tf.constant(min_dimension, dtype=tf.float32) large_scale_factor = min_dimension / orig_min_dim # Scaling orig_(height|width) by large_scale_factor will make the smaller # dimension equal to min_dimension, save for floating point rounding errors. # For reasonably-sized images, taking the nearest integer will reliably # eliminate this error. large_height = tf.cast(tf.round(orig_height * large_scale_factor), dtype=tf.int32) large_width = tf.cast(tf.round(orig_width * large_scale_factor), dtype=tf.int32) large_size = tf.stack([large_height, large_width]) if max_dimension: # Calculates the smaller of the possible sizes, use that if the larger # is too big. orig_max_dim = tf.maximum(orig_height, orig_width) max_dimension = tf.constant(max_dimension, dtype=tf.float32) small_scale_factor = max_dimension / orig_max_dim # Scaling orig_(height|width) by small_scale_factor will make the larger # dimension equal to max_dimension, save for floating point rounding # errors. For reasonably-sized images, taking the nearest integer will # reliably eliminate this error. small_height = tf.cast(tf.round(orig_height * small_scale_factor), dtype=tf.int32) small_width = tf.cast(tf.round(orig_width * small_scale_factor), dtype=tf.int32) small_size = tf.stack([small_height, small_width]) new_size = tf.cond(pred=tf.cast(tf.reduce_max(input_tensor=large_size), dtype=tf.float32) > max_dimension, true_fn=lambda: small_size, false_fn=lambda: large_size) else: new_size = large_size return tf.stack(tf.unstack(new_size) + [num_channels])
def _get_indices(interp_type): """Get values of y at the indices implied by interp_type.""" if interp_type == 'lower': indices = tf.math.floor((d - 1) * frac_at_q_or_below) elif interp_type == 'higher': indices = tf.math.ceil((d - 1) * frac_at_q_or_below) elif interp_type == 'nearest': indices = tf.round((d - 1) * frac_at_q_or_below) # d - 1 will be distinct from d in int32, but not necessarily double. # So clip to avoid out of bounds errors. return tf.clip_by_value(tf.cast(indices, tf.int32), 0, ps.shape(y)[-1] - 1)
def around(a, decimals=0): # pylint: disable=missing-docstring a = asarray(a) dtype = a.dtype factor = math.pow(10, decimals) # Use float as the working dtype instead of a.dtype, because a.dtype can be # integer and `decimals` can be negative. float_dtype = dtypes.default_float_type() a = a.astype(float_dtype).data factor = tf.cast(factor, float_dtype) a = tf.multiply(a, factor) a = tf.round(a) a = tf.math.divide(a, factor) return utils.tensor_to_ndarray(a).astype(dtype)
def _get_indices(interp_type): """Get values of y at the indices implied by interp_type.""" # Note `lower` <--> ceiling. Confusing, huh? Due to the fact that # _sort_tensor sorts highest to lowest, tf.ceil corresponds to the higher # index, but the lower value of y! if interp_type == 'lower': indices = tf.math.ceil((d - 1) * frac_at_q_or_above) elif interp_type == 'higher': indices = tf.floor((d - 1) * frac_at_q_or_above) elif interp_type == 'nearest': indices = tf.round((d - 1) * frac_at_q_or_above) # d - 1 will be distinct from d in int32, but not necessarily double. # So clip to avoid out of bounds errors. return tf.clip_by_value(tf.cast(indices, tf.int32), 0, tf.shape(input=y)[-1] - 1)
def _sample_n(self, n, seed=None): # random_von_mises does not work for zero concentration, so round it up to # something very small. tiny = np.finfo(dtype_util.as_numpy_dtype(self.dtype)).tiny concentration = tf.maximum(self.concentration, tiny) sample_batch_shape = tf.concat([[n], self._batch_shape_tensor()], axis=0) samples = random_von_mises( sample_batch_shape, concentration, dtype=self.dtype, seed=seed) # vonMises(0, concentration) -> vonMises(loc, concentration) samples += self.loc # Map the samples to [-pi, pi]. samples -= 2. * np.pi * tf.round(samples / (2. * np.pi)) return samples
def __call__(self, x): assert self.alpha != 0 if self.use_stochastic_rounding: x = self.alpha * _round_through( x / self.alpha, use_stochastic_rounding=self.use_stochastic_rounding) k_sign = tf.sign(x) if self.use_stochastic_rounding: k_sign += (1.0 - tf.abs(k_sign)) * ( 2.0 * tf.round(tf.random.uniform(tf.shape(x))) - 1.0) else: k_sign += (1.0 - tf.abs(k_sign)) if self.use_01: k_sign = (k_sign + 1.0) / 2.0 return x + tf.stop_gradient(-x + self.alpha * k_sign)
def around(a, decimals=0): # pylint: disable=missing-docstring a = asarray(a) dtype = a.dtype factor = math.pow(10, decimals) if np.issubdtype(dtype, np.inexact): factor = tf.cast(factor, dtype) else: # Use float as the working dtype when a.dtype is exact (e.g. integer), # because `decimals` can be negative. float_dtype = dtypes.default_float_type() a = a.astype(float_dtype).data factor = tf.cast(factor, float_dtype) a = tf.multiply(a, factor) a = tf.round(a) a = tf.math.divide(a, factor) return utils.tensor_to_ndarray(a).astype(dtype)
def around(a, decimals=0): """Rounds each array element to the specified number of decimals. Args: a: array_like. Could be an ndarray, a Tensor or any object that can be converted to a Tensor using `tf.convert_to_tensor`. decimals: Optional, defaults to 0. The number of decimal places to round to. Could be negative. Returns: An ndarray. """ a = array_creation.asarray(a) factor = math.pow(10, decimals) a_t = tf.multiply(a.data, factor) a_t = tf.round(a_t) a_t = tf.math.divide(a_t, factor) return utils.tensor_to_ndarray(a_t)
def quantization_offset(distribution): """Computes distribution-dependent quantization offset. For range coding of continuous random variables, the values need to be quantized first. Typically, it is beneficial for compression performance to align the centers of the quantization bins such that one of them coincides with the mode of the distribution. With `offset` being the mode of the distribution, for instance, this can be achieved simply by computing: ``` x_hat = tf.round(x - offset) + offset ``` This method tries to determine the offset in a best-effort fashion, based on which statistics the `Distribution` implements. First, a method `self._quantization_offset()` is tried. If that isn't defined, it tries in turn: `self.mode()`, `self.quantile(.5)`, then `self.mean()`. If none of these are implemented, it falls back on quantizing to integer values (i.e., an offset of zero). Note the offset is always in the range [-.5, .5] as it is assumed to be combined with a round quantizer. Arguments: distribution: A `tfp.distributions.Distribution` object. Returns: A `tf.Tensor` broadcastable to shape `self.batch_shape`, containing the determined quantization offsets. No gradients are allowed to flow through the return value. """ try: offset = distribution._quantization_offset() # pylint:disable=protected-access except (AttributeError, NotImplementedError): try: offset = distribution.mode() except NotImplementedError: try: offset = distribution.quantile(.5) except NotImplementedError: try: offset = distribution.mean() except NotImplementedError: offset = tf.constant(0, dtype=distribution.dtype) return tf.stop_gradient(offset - tf.round(offset))
def cal_longest_subsequence(softmaxed_logits): int_logits = tf.dtypes.cast(tf.round(softmaxed_logits), dtype=tf.int32) index_tensor = tf.range(softmaxed_logits.shape[1], dtype=tf.int32) t_index = tf.reshape(index_tensor, [softmaxed_logits.shape[1], 1]) new_seq = tf.transpose(tf.matmul(int_logits, t_index))[0].numpy().tolist() # new_seq = [3,2,4,5,6,5,5,6,7] # print(new_seq) subseq = [] indexseq = [] for i in range(len(new_seq)): if i == 0: subseq.append(new_seq[i]) indexseq.append(i) else: if new_seq[i] > subseq[-1]: subseq.append(new_seq[i]) indexseq.append(i) elif new_seq[i] < subseq[0]: subseq[0] = new_seq[i] indexseq[0] = i else: index = binarySearch(subseq, 0, len(subseq) - 1, new_seq[i]) if index != -1: subseq[index] = new_seq[i] indexseq[index] = i # print(subseq) # print(indexseq) subseq_tensor = tf.reshape(subseq, [1, -1]) index_tensor = tf.reshape(indexseq, [1, -1]) # print(subseq_tensor,index_tensor) te = tf.subtract(subseq_tensor, index_tensor) # print(te) minus_result = tf.square(tf.subtract(subseq_tensor, index_tensor)) one_tensor = tf.ones([1, len(subseq)], tf.int32) result = tf.divide(one_tensor, tf.add(one_tensor, minus_result)) # return tf.reduce_sum(result) return subseq
def stochastic_round_po2(x): """Performs stochastic rounding for the power of two.""" # TODO(hzhuang): test stochastic_round_po2 and constraint. # because quantizer is applied after constraint. y = tf.abs(x) eps = tf.keras.backend.epsilon() log2 = tf.keras.backend.log(2.0) x_log2 = tf.round(tf.keras.backend.log(y + eps) / log2) sign = tf.sign(x) po2 = tf.cast(pow(2.0, tf.cast(x_log2, dtype="float32")), dtype="float32") left_val = tf.where(po2 > y, x_log2 - 1, x_log2) right_val = tf.where(po2 > y, x_log2, x_log2 + 1) # sampling in [2**left_val, 2**right_val]. minval = 2**left_val maxval = 2**right_val val = tf.random.uniform(tf.shape(y), minval=minval, maxval=maxval) # use y as a threshold to keep the probabliy [2**left_val, y, 2**right_val] # so that the mean value of the sample should be y x_po2 = tf.where(y < val, left_val, right_val) return x_po2
output_layer=decoderNetwork.dense_layer) decoderNetwork.attention_mechanism.setup_memory(a) #pass [ last step activations , encoder memory_state ] as input to decoder for LSTM print("decoder_initial_state = [a_tx, c_tx] :", np.array([a_tx, c_tx]).shape) decoder_initial_state = decoderNetwork.build_decoder_initial_state( inference_batch_size, encoder_state=[a_tx, c_tx], Dtype=tf.float32) print( "\nCompared to simple encoder-decoder without attention, the decoder_initial_state \ is an AttentionWrapperState object containing s_prev tensors and context and alignment vector \n " ) print("decoder initial state shape :", np.array(decoder_initial_state).shape) print("decoder_initial_state tensor \n", decoder_initial_state) # Since we do not know the target sequence lengths in advance, we use maximum_iterations to limit the translation lengths. # One heuristic is to decode up to two times the source sentence lengths. maximum_iterations = tf.round(tf.reduce_max(Tx) * 2) #initialize inference decoder decoder_embedding_matrix = decoderNetwork.decoder_embedding.variables[0] (first_finished, first_inputs, first_state) = decoder_instance.initialize( decoder_embedding_matrix, start_tokens=start_tokens, end_token=end_token, initial_state=decoder_initial_state) #print( first_finished.shape) print( "\nfirst_inputs returns the same decoder_input i.e. embedding of <start> :", first_inputs.shape) print("start_index_emb_avg ", tf.reduce_sum(tf.reduce_mean(first_inputs, axis=0))) # mean along the batch
def _sample_n(self, n, seed=None, conditional_input=None, training=False): """Samples from the distribution, with optional conditional input. Args: n: `int`, number of samples desired. seed: `int`, seed for RNG. Setting a random seed enforces reproducability of the samples between sessions (not within a single session). conditional_input: `Tensor` on which to condition the distribution (e.g. class labels), or `None`. training: `bool` or `None`. If `bool`, it controls the dropout layer, where `True` implies dropout is active. If `None`, it defers to Keras' handling of train/eval status. Returns: samples: a `Tensor` of shape `[n, height, width, num_channels]`. """ if conditional_input is not None: conditional_input = tf.convert_to_tensor(conditional_input, dtype=self.dtype) conditional_event_rank = tensorshape_util.rank( self.conditional_shape) conditional_input_shape = prefer_static.shape(conditional_input) conditional_sample_rank = prefer_static.rank( conditional_input) - conditional_event_rank # If `conditional_input` has no sample dimensions, prepend a sample # dimension if conditional_sample_rank == 0: conditional_input = conditional_input[tf.newaxis, ...] conditional_sample_rank = 1 # Assert that the conditional event shape in the `PixelCnnNetwork` is the # same as that implied by `conditional_input`. conditional_event_shape = conditional_input_shape[ conditional_sample_rank:] with tf.control_dependencies([ tf.assert_equal(self.conditional_shape, conditional_event_shape) ]): conditional_sample_shape = conditional_input_shape[: conditional_sample_rank] repeat = n // prefer_static.reduce_prod( conditional_sample_shape) h = tf.reshape( conditional_input, prefer_static.concat([(-1, ), self.conditional_shape], axis=0)) h = tf.tile( h, prefer_static.pad([repeat], paddings=[[0, conditional_event_rank]], constant_values=1)) samples_0 = tf.random.uniform(prefer_static.concat( [(n, ), self.event_shape], axis=0), minval=-1., maxval=1., dtype=self.dtype, seed=seed) inputs = samples_0 if conditional_input is None else [samples_0, h] params_0 = self.network(inputs, training=training) samples_0 = self._sample_channels(*params_0, seed=seed) image_height, image_width, _ = tensorshape_util.as_list( self.event_shape) def loop_body(index, samples): """Loop for iterative pixel sampling. Args: index: 0D `Tensor` of type `int32`. Index of the current pixel. samples: 4D `Tensor`. Images with pixels sampled in raster order, up to pixel `[index]`, with dimensions `[batch_size, height, width, num_channels]`. Returns: samples: 4D `Tensor`. Images with pixels sampled in raster order, up to and including pixel `[index]`, with dimensions `[batch_size, height, width, num_channels]`. """ inputs = samples if conditional_input is None else [samples, h] params = self.network(inputs, training=training) samples_new = self._sample_channels(*params, seed=seed) # Update the current pixel samples = tf.transpose(samples, [1, 2, 3, 0]) samples_new = tf.transpose(samples_new, [1, 2, 3, 0]) row, col = index // image_width, index % image_width updates = samples_new[row, col, ...][tf.newaxis, ...] samples = tf.tensor_scatter_nd_update(samples, [[row, col]], updates) samples = tf.transpose(samples, [3, 0, 1, 2]) return index + 1, samples index0 = tf.zeros([], dtype=tf.int32) # Construct the while loop for sampling total_pixels = image_height * image_width loop_cond = lambda ind, _: tf.less(ind, total_pixels) # noqa: E731 init_vars = (index0, samples_0) _, samples = tf.while_loop(loop_cond, loop_body, init_vars, parallel_iterations=1) transformed_samples = (self._low + 0.5 * (self._high - self._low) * (samples + 1.)) return tf.round(transformed_samples)
def von_mises_cdf(x, concentration): """Computes the cumulative density function (CDF) of von Mises distribution. Denote the density of vonMises(loc=0, concentration=concentration) by p(t). Note that p(t) is periodic, p(t) = p(t + 2 pi). The CDF at the point x is defined as int_{-pi}^x p(t) dt. Thus, when x in [-pi, pi], the CDF is in [0, 1]; when x is in [pi, 3pi], the CDF is in [1, 2], etc. The CDF is not available in closed form. Instead, we use the method [1] which uses either a series expansion or a Normal approximation, depending on the value of concentration. We also compute the derivative of the CDF w.r.t. both x and concentration. The derivative w.r.t. x is p(x), while the derivative w.r.t. concentration is computed using automatic differentiation. We use forward mode for the series case (which allows to save memory) and backward mode for the Normal approximation. Args: x: The point at which to evaluate the CDF. concentration: The concentration parameter of the von Mises distribution. Returns: The value of the CDF computed elementwise. References: [1] G. Hill "Algorithm 518: Incomplete Bessel Function I_0. The Von Mises Distribution." ACM Transactions on Mathematical Software, 1977 """ x = tf.convert_to_tensor(x) concentration = tf.convert_to_tensor(concentration) dtype = x.dtype # Map x to [-pi, pi]. num_periods = tf.round(x / (2. * np.pi)) x = x - (2. * np.pi) * num_periods # We take the hyperparameters from Table I of [1], the row for D=8 # decimal digits of accuracy. ck is the cut-off for concentration: # if concentration < ck, the series expansion is used; # otherwise, the Normal approximation is used. ck = 10.5 # The number of terms in the series expansion. [1] chooses it as a function # of concentration, n(concentration). This is hard to implement in TF. # Instead, we upper bound it over concentrations: # num_terms = ceil ( max_{concentration <= ck} n(concentration) ). # The maximum is achieved for concentration = ck. num_terms = 20 cdf_series, dcdf_dconcentration_series = _von_mises_cdf_series( x, concentration, num_terms, dtype) cdf_normal, dcdf_dconcentration_normal = _von_mises_cdf_normal( x, concentration, dtype) use_series = concentration < ck cdf = tf.where(use_series, cdf_series, cdf_normal) cdf = cdf + num_periods dcdf_dconcentration = tf.where(use_series, dcdf_dconcentration_series, dcdf_dconcentration_normal) def grad(dy): prob = tf.exp(concentration * (tf.cos(x) - 1.)) / ( (2. * np.pi) * tf.math.bessel_i0e(concentration)) return dy * prob, dy * dcdf_dconcentration return cdf, grad
def _quantize_offset(self, inputs, offset): return tf.round(inputs - offset) + offset, lambda x: (x, None)
def _quantize_no_offset(self, inputs): return tf.round(inputs), lambda x: x
def st_round(inputs): return tf.round(inputs), lambda dy: dy
def resize_and_crop_image(image, desired_size, padded_size, aug_scale_min=1.0, aug_scale_max=1.0, seed=1, method=tf.image.ResizeMethod.BILINEAR): """Resizes the input image to output size. Resize and pad images given the desired output size of the image and stride size. Here are the preprocessing steps. 1. For a given image, keep its aspect ratio and rescale the image to make it the largest rectangle to be bounded by the rectangle specified by the `desired_size`. 2. Pad the rescaled image to the padded_size. Args: image: a `Tensor` of shape [height, width, 3] representing an image. desired_size: a `Tensor` or `int` list/tuple of two elements representing [height, width] of the desired actual output image size. padded_size: a `Tensor` or `int` list/tuple of two elements representing [height, width] of the padded output image size. Padding will be applied after scaling the image to the desired_size. aug_scale_min: a `float` with range between [0, 1.0] representing minimum random scale applied to desired_size for training scale jittering. aug_scale_max: a `float` with range between [1.0, inf] representing maximum random scale applied to desired_size for training scale jittering. seed: seed for random scale jittering. method: function to resize input image to scaled image. Returns: output_image: `Tensor` of shape [height, width, 3] where [height, width] equals to `output_size`. image_info: a 2D `Tensor` that encodes the information of the image and the applied preprocessing. It is in the format of [[original_height, original_width], [scaled_height, scaled_width], [y_scale, x_scale], [y_offset, x_offset]], where [scaled_height, scaled_width] is the actual scaled image size, and [y_scale, x_scale] is the scaling factory, which is the ratio of scaled dimension / original dimension. """ with tf.name_scope('resize_and_crop_image'): image_size = tf.cast(tf.shape(input=image)[0:2], tf.float32) random_jittering = (aug_scale_min != 1.0 or aug_scale_max != 1.0) if random_jittering: random_scale = tf.random.uniform([], aug_scale_min, aug_scale_max, seed=seed) scaled_size = tf.round(random_scale * desired_size) else: scaled_size = desired_size scale = tf.minimum(scaled_size[0] / image_size[0], scaled_size[1] / image_size[1]) scaled_size = tf.round(image_size * scale) # Computes 2D image_scale. image_scale = scaled_size / image_size # Selects non-zero random offset (x, y) if scaled image is larger than # desired_size. if random_jittering: max_offset = scaled_size - desired_size max_offset = tf.where(tf.less(max_offset, 0), tf.zeros_like(max_offset), max_offset) offset = max_offset * tf.random.uniform([ 2, ], 0, 1, seed=seed) offset = tf.cast(offset, tf.int32) else: offset = tf.zeros((2, ), tf.int32) scaled_image = tf.image.resize(image, tf.cast(scaled_size, tf.int32), method=method) if random_jittering: scaled_image = scaled_image[offset[0]:offset[0] + desired_size[0], offset[1]:offset[1] + desired_size[1], :] output_image = tf.image.pad_to_bounding_box(scaled_image, 0, 0, padded_size[0], padded_size[1]) image_info = tf.stack([ image_size, scaled_size, image_scale, tf.cast(offset, tf.float32) ]) return output_image, image_info