def kaiser_window(window_length, beta=12., dtype=dtypes.float32, name=None): """Generate a [Kaiser window][kaiser]. Args: window_length: A scalar `Tensor` indicating the window length to generate. beta: Beta parameter for Kaiser window, see reference below. dtype: The data type to produce. Must be a floating point type. name: An optional name for the operation. Returns: A `Tensor` of shape `[window_length]` of type `dtype`. [kaiser]: https://docs.scipy.org/doc/numpy/reference/generated/numpy.kaiser.html """ with ops.name_scope(name, 'kaiser_window'): window_length = _check_params(window_length, dtype) window_length_const = tensor_util.constant_value(window_length) if window_length_const == 1: return array_ops.ones([1], dtype=dtype) # tf.range does not support float16 so we work with float32 initially. halflen_float = (math_ops.cast(window_length, dtype=dtypes.float32) - 1.0) / 2.0 arg = math_ops.range(-halflen_float, halflen_float + 0.1, dtype=dtypes.float32) # Convert everything into given dtype which can be float16. arg = math_ops.cast(arg, dtype=dtype) beta = math_ops.cast(beta, dtype=dtype) one = math_ops.cast(1.0, dtype=dtype) two = math_ops.cast(2.0, dtype=dtype) halflen_float = math_ops.cast(halflen_float, dtype=dtype) num = beta * math_ops.sqrt(one - math_ops.pow(arg, two) / math_ops.pow(halflen_float, two)) window = math_ops.exp(num - beta) * (math_ops.bessel_i0e(num) / math_ops.bessel_i0e(beta)) return window
def _BesselI1eGrad(op, grad): """Compute gradient of bessel_i1e(x) with respect to its argument.""" x = op.inputs[0] y = op.outputs[0] with ops.control_dependencies([grad]): # For x = 0, the correct gradient is 0.5. # However, the main branch gives NaN because of the division by x, so # we impute the gradient manually. # An alternative solution is to express the gradient via bessel_i0e and # bessel_i2e, but the latter is not yet implemented in Eigen. eps = np.finfo(x.dtype.as_numpy_dtype).eps zeros = array_ops.zeros_like(x) x_is_not_tiny = math_ops.abs(x) > eps safe_x = array_ops.where(x_is_not_tiny, x, eps + zeros) dy_dx = math_ops.bessel_i0e(safe_x) - y * ( math_ops.sign(safe_x) + math_ops.reciprocal(safe_x)) return grad * array_ops.where(x_is_not_tiny, dy_dx, 0.5 + zeros)
def bessel_i0(x, name=None): """Computes the Bessel i0 function of `x` element-wise. Modified Bessel function of order 0. It is preferable to use the numerically stabler function `i0e(x)` instead. Args: x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, `float32`, `float64`. name: A name for the operation (optional). Returns: A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. @compatibility(scipy) Equivalent to scipy.special.i0 @end_compatibility """ with ops.name_scope(name, 'bessel_i0', [x]): return math_ops.exp(math_ops.abs(x)) * math_ops.bessel_i0e(x)