MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / GatherV2Grad

Function GatherV2Grad

tensorflow/cc/gradients/array_grad.cc:678–760  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

676}
677
678Status GatherV2Grad(const Scope& scope, const Operation& op,
679 const std::vector<Output>& grad_inputs,
680 std::vector<Output>* grad_outputs) {
681 if (op.num_inputs() != 3) {
682 return errors::InvalidArgument("Gather requires 3 inputs");
683 }
684 if (grad_inputs.size() != 1) {
685 return errors::InvalidArgument("Gather grad requires 1 grad input");
686 }
687
688 // params can be large, so colocate the shape calculation with it.
689 // params can be very large for sparse model, array_ops.shape raises
690 // exception on the Windows platform when any dimension is larger than
691 // int32. params_shape is not used in optimizer apply_sparse gradients,
692 // so it's fine to convert it back to int32 regardless of truncation.
693 auto params = op.input(0);
694 auto colocate_scope = scope.ColocateWith(params);
695 Shape::Attrs shape_attrs;
696 shape_attrs.out_type_ = DT_INT64;
697 auto params_shape64 = Shape(colocate_scope, params, shape_attrs);
698 Output params_shape = Cast(colocate_scope, params_shape64, DT_INT32);
699
700 auto indices = op.input(1);
701 auto indices_size = ExpandDims(scope, Size(scope, indices), 0);
702 auto axis = op.input(2);
703 auto axis_expand = ExpandDims(scope, axis, 0);
704
705 int batch_dims;
706 TF_RETURN_IF_ERROR(
707 GetNodeAttr(op.node()->attrs(), "batch_dims", &batch_dims));
708 if (batch_dims < 0) {
709 // TODO(bdodson): Figure out if we can find the param rank here, like the
710 // python implementation does.
711 return errors::InvalidArgument(
712 "C++ GatherV2 gradient does not support negative batch_dims.");
713 }
714
715 // Handle axis by transposing the axis dimension to be the first non-batch
716 // dimension, compute the gradient and transpose the result back.
717 auto outer_shape = Slice(scope, params_shape, {0}, axis_expand);
718 auto inner_shape =
719 Slice(scope, Slice(scope, params_shape, axis_expand, {-1}), {1}, {-1});
720 auto values_shape = Concat(scope, {outer_shape, {-1}, inner_shape}, 0);
721 auto values_dims = Size(scope, values_shape);
722 auto axis_dims = Size(scope, outer_shape);
723
724 Output outer_batches_indices = Range(scope, 0, batch_dims, /*delta=*/1);
725 Output batch_axis_indices = Range(scope, batch_dims, axis_dims, /*delta=*/1);
726 Output inner_axes_indices =
727 Range(scope, Add(scope, axis_dims, 1), values_dims, /*delta=*/1);
728 Output axis_dims_expand = ExpandDims(scope, axis_dims, 0);
729
730 auto values = Reshape(scope, grad_inputs[0], values_shape);
731
732 // Move values[axis] up to values[batch_dims]
733 Output transpose_dims = Concat(scope,
734 {outer_batches_indices, axis_dims_expand,
735 batch_axis_indices, inner_axes_indices},

Callers

nothing calls this directly

Calls 15

InvalidArgumentFunction · 0.85
BatchGatherGradFunction · 0.85
NoGradientFunction · 0.85
ShapeClass · 0.50
CastFunction · 0.50
ExpandDimsFunction · 0.50
SizeFunction · 0.50
GetNodeAttrFunction · 0.50
SliceClass · 0.50
ConcatFunction · 0.50
RangeClass · 0.50
AddFunction · 0.50

Tested by

no test coverage detected