| 647 | } |
| 648 | |
| 649 | Output BatchGatherGrad(const Scope& scope, Output params_shape, Output values, |
| 650 | Output indices, int batch_dims, Output gather_dim_size) { |
| 651 | // Axis is the first non-batch dimension. |
| 652 | auto indices_size = ExpandDims(scope, Size(scope, indices), 0); |
| 653 | Output outer_shape, flat_values_shape; |
| 654 | if (batch_dims != 0) { |
| 655 | auto values_shape = Shape(scope, values); |
| 656 | // Add the batch offsets to indices and flatten the batch dimensions. |
| 657 | outer_shape = Slice(scope, values_shape, {0}, {batch_dims}); |
| 658 | auto inner_shape = |
| 659 | Slice(scope, Slice(scope, values_shape, {batch_dims}, {-1}), {1}, {-1}); |
| 660 | auto batch_size = Prod(scope, outer_shape, /*axis=*/0); |
| 661 | flat_values_shape = Concat(scope, {{-1}, inner_shape}, /*axis=*/0); |
| 662 | gather_dim_size = Multiply(scope, gather_dim_size, batch_size); |
| 663 | indices = GetBatchIndices(scope, params_shape, indices, batch_dims); |
| 664 | values = Reshape(scope, values, flat_values_shape); |
| 665 | } |
| 666 | |
| 667 | indices = Reshape(scope, indices, indices_size); |
| 668 | Output params_grad = |
| 669 | UnsortedSegmentSum(scope, values, indices, gather_dim_size); |
| 670 | |
| 671 | if (batch_dims != 0) { |
| 672 | // Put back the batch dimensions. |
| 673 | params_grad = Reshape(scope, params_grad, params_shape); |
| 674 | } |
| 675 | return params_grad; |
| 676 | } |
| 677 | |
| 678 | Status GatherV2Grad(const Scope& scope, const Operation& op, |
| 679 | const std::vector<Output>& grad_inputs, |
no test coverage detected