| 506 | REGISTER_GRADIENT_OP("Slice", SliceGrad); |
| 507 | |
| 508 | Status ConcatGradHelper(const Scope& scope, const Operation& op, |
| 509 | const std::vector<Output>& grad_inputs, |
| 510 | std::vector<Output>* grad_outputs, |
| 511 | int start_value_index, int end_value_index, |
| 512 | int dim_index) { |
| 513 | if (end_value_index >= op.num_inputs()) { |
| 514 | return errors::Internal("Invalid input index"); |
| 515 | } |
| 516 | std::vector<Output> inputs; |
| 517 | for (int i = start_value_index; i < end_value_index; ++i) { |
| 518 | inputs.push_back(op.input(i)); |
| 519 | } |
| 520 | |
| 521 | auto shapes = ShapeN(scope, inputs); |
| 522 | const auto unique_name = scope.GetUniqueNameForOp("ConcatOffset"); |
| 523 | auto builder = |
| 524 | ::tensorflow::NodeBuilder(unique_name, "ConcatOffset") |
| 525 | .Input(::tensorflow::ops::AsNodeOut(scope, op.input(dim_index))) |
| 526 | .Input(::tensorflow::ops::AsNodeOutList(scope, shapes.output)); |
| 527 | scope.UpdateBuilder(&builder); |
| 528 | ::tensorflow::Node* concat_offset_node; |
| 529 | scope.UpdateStatus(builder.Finalize(scope.graph(), &concat_offset_node)); |
| 530 | scope.UpdateStatus(scope.DoShapeInference(concat_offset_node)); |
| 531 | if (concat_offset_node->num_outputs() != inputs.size()) { |
| 532 | return errors::Internal("ConcatOffset has invalid output count"); |
| 533 | } |
| 534 | if (grad_inputs.size() != 1) { |
| 535 | return errors::InvalidArgument("Concat grad should have 1 input"); |
| 536 | } |
| 537 | |
| 538 | // For each dx[i], we take a slice of dy. The offset and size of the |
| 539 | // slice is given by offset[i] and shape[i]. |
| 540 | const Output& dy = grad_inputs[0]; |
| 541 | for (int i = 0; i < inputs.size(); ++i) { |
| 542 | grad_outputs->push_back( |
| 543 | Slice(scope, dy, Output(concat_offset_node, i), shapes.output[i])); |
| 544 | } |
| 545 | |
| 546 | // Insert a NoGradient for the axis. |
| 547 | grad_outputs->insert(grad_outputs->begin() + dim_index, NoGradient()); |
| 548 | return scope.status(); |
| 549 | } |
| 550 | |
| 551 | Status ConcatV2Grad(const Scope& scope, const Operation& op, |
| 552 | const std::vector<Output>& grad_inputs, |
no test coverage detected