This decorator allows fine grained control over the gradients of a sequence for operations. This may be useful for multiple reasons, including providing a more efficient or numerically stable gradient for a sequence of operations.
Arguments
- f
Function
f(...)that returns a tuple(output, grad_fn), where:...is a sequence of tensor inputs or nested structures of tensor inputs.outputis a (nested structure of) tensor outputs of applying the operations inf()to....grad_fnhas signaturegrad_fn(..., upstream)and returns a tuple of tensors the same size as flattened...: the derivatives of tensors inoutputwith respect to the tensors in....upstreamis a tensor or sequence of tensors holding the initial value gradients for each tensor inoutput.
Value
A function h(...) which returns the same value as f(...)[[1]] and whose
gradient is determined by f(...)[[2]].
Note
The gradient function's signature depends on the backend. With TensorFlow
and JAX, grad(upstream) is sufficient. With PyTorch, the gradient function
may also receive the original positional inputs, so define grad with ...
and upstream formals when they are required. The backend-agnostic example
above accepts both calling conventions.
Examples
This backend-agnostic implementation accepts the positional inputs used by PyTorch as well as the upstream gradient used by all backends.
log1pexp <- op_custom_gradient(function(x) {
e <- op_exp(x)
grad <- function(..., upstream = NULL) {
if (is.null(upstream))
upstream <- list(...)[[1]]
op_multiply(upstream, 1 - 1 / op_add(1, e))
}
tuple(op_log(1 + e), grad)
})
if (config_backend() == "tensorflow") {
tf <- tensorflow::tf
x <- op_convert_to_tensor(100)
with(tf$GradientTape() %as% tape, {
tape$watch(x)
y <- log1pexp(x)
})
dy_dx <- tape$gradient(y, x)
stopifnot(as.numeric(dy_dx) == 1)
}See also
Other core ops: op_associative_scan() op_cast() op_cond() op_convert_to_numpy() op_convert_to_tensor() op_dtype() op_fori_loop() op_is_tensor() op_jvp() op_map() op_rearrange() op_scan() op_scatter() op_scatter_update() op_searchsorted() op_shape() op_slice() op_slice_update() op_stop_gradient() op_subset() op_switch() op_unstack() op_vectorized_map() op_while_loop()
Other ops: op_abs() op_adaptive_average_pool() op_adaptive_max_pool() op_add() op_all() op_allclose() op_angle() op_any() op_append() op_arange() op_arccos() op_arccosh() op_arcsin() op_arcsinh() op_arctan() op_arctan2() op_arctanh() op_argmax() op_argmin() op_argpartition() op_argsort() op_array() op_array_split() op_associative_scan() op_average() op_average_pool() op_bartlett() op_batch_normalization() op_binary_crossentropy() op_bincount() op_bitwise_and() op_bitwise_invert() op_bitwise_left_shift() op_bitwise_not() op_bitwise_or() op_bitwise_right_shift() op_bitwise_xor() op_blackman() op_broadcast_to() op_cast() op_categorical_crossentropy() op_cbrt() op_cdist() op_ceil() op_celu() op_cholesky() op_cholesky_inverse() op_clip() op_concatenate() op_cond() op_conj() op_conv() op_conv_transpose() op_convert_to_numpy() op_convert_to_tensor() op_copy() op_corrcoef() op_correlate() op_cos() op_cosh() op_count_nonzero() op_cross() op_ctc_decode() op_ctc_loss() op_cumprod() op_cumsum() op_deg2rad() op_depth_to_space() op_depthwise_conv() op_det() op_diag() op_diagflat() op_diagonal() op_diff() op_digitize() op_divide() op_divide_no_nan() op_dot() op_dot_product_attention() op_dsplit() op_dstack() op_dtype() op_eig() op_eigh() op_einsum() op_elu() op_empty() op_empty_like() op_equal() op_erf() op_erfc() op_erfinv() op_exp() op_exp2() op_expand_dims() op_expm1() op_extract_sequences() op_eye() op_fabs() op_fft() op_fft2() op_flip() op_fliplr() op_flipud() op_floor() op_floor_divide() op_fmax() op_fmin() op_fmod() op_fold() op_fori_loop() op_full() op_full_like() op_gcd() op_gelu() op_geomspace() op_get_item() op_glu() op_greater() op_greater_equal() op_hamming() op_hanning() op_hard_shrink() op_hard_sigmoid() op_hard_silu() op_hard_tanh() op_heaviside() op_histogram() op_hsplit() op_hstack() op_hypot() op_i0() op_identity() op_ifft2() op_imag() op_image_affine_transform() op_image_crop() op_image_extract_patches() op_image_extract_patches_3d() op_image_gaussian_blur() op_image_hsv_to_rgb() op_image_map_coordinates() op_image_pad() op_image_perspective_transform() op_image_resize() op_image_rgb_to_grayscale() op_image_rgb_to_hsv() op_image_scale_and_translate() op_image_sobel_edges() op_image_ssim() op_in_top_k() op_inner() op_inv() op_irfft() op_is_tensor() op_isclose() op_isfinite() op_isin() op_isinf() op_isnan() op_isneginf() op_isposinf() op_isreal() op_istft() op_jvp() op_kaiser() op_kron() op_layer_normalization() op_lcm() op_ldexp() op_leaky_relu() op_left_shift() op_less() op_less_equal() op_linspace() op_log() op_log10() op_log1p() op_log2() op_log_sigmoid() op_log_softmax() op_logaddexp() op_logaddexp2() op_logdet() op_logical_and() op_logical_not() op_logical_or() op_logical_xor() op_logspace() op_logsumexp() op_lstsq() op_lu_factor() op_map() op_matmul() op_matrix_rank() op_max() op_max_pool() op_maximum() op_mean() op_median() op_meshgrid() op_min() op_minimum() op_mod() op_moments() op_moveaxis() op_multi_hot() op_multiply() op_nan_to_num() op_nanargmax() op_nanargmin() op_nancumprod() op_nancumsum() op_nanmax() op_nanmean() op_nanmedian() op_nanmin() op_nanpercentile() op_nanprod() op_nanquantile() op_nanstd() op_nansum() op_nanvar() op_ndim() op_negative() op_nextafter() op_nonzero() op_norm() op_normalize() op_not_equal() op_one_hot() op_ones() op_ones_like() op_outer() op_pad() op_percentile() op_pinv() op_polar() op_power() op_prod() op_psnr() op_ptp() op_qr() op_quantile() op_rad2deg() op_ravel() op_real() op_rearrange() op_reciprocal() op_relu() op_relu6() op_repeat() op_reshape() op_rfft() op_right_shift() op_rms_normalization() op_roll() op_rot90() op_round() op_rsqrt() op_saturate_cast() op_scan() op_scatter() op_scatter_update() op_searchsorted() op_segment_max() op_segment_min() op_segment_prod() op_segment_sum() op_select() op_selu() op_separable_conv() op_shape() op_sigmoid() op_sign() op_signbit() op_silu() op_sin() op_sinc() op_sinh() op_size() op_slice() op_slice_update() op_slogdet() op_soft_shrink() op_softmax() op_softplus() op_softsign() op_solve() op_solve_triangular() op_sort() op_space_to_depth() op_sparse_categorical_crossentropy() op_sparse_plus() op_sparse_sigmoid() op_sparsemax() op_split() op_sqrt() op_square() op_squareplus() op_squeeze() op_stack() op_std() op_stft() op_stop_gradient() op_subset() op_subtract() op_sum() op_svd() op_swapaxes() op_switch() op_take() op_take_along_axis() op_tan() op_tanh() op_tanh_shrink() op_tensordot() op_threshold() op_tile() op_top_k() op_trace() op_transpose() op_trapezoid() op_tri() op_tril() op_triu() op_trunc() op_unfold() op_unique() op_unravel_index() op_unstack() op_vander() op_var() op_vdot() op_vectorize() op_vectorized_map() op_view() op_view_as_complex() op_view_as_real() op_vsplit() op_vstack() op_where() op_while_loop() op_zeros() op_zeros_like()