| 340 | } |
| 341 | |
| 342 | Status SymbolicGradientBuilder::SumGradients(const Output& src, Output* grad) { |
| 343 | auto iter = backprops_.find(src); |
| 344 | if (iter == backprops_.end()) { |
| 345 | return errors::Internal( |
| 346 | "Unable to find backprop list for node.id ", src.node()->name()); |
| 347 | } |
| 348 | const auto& grads = iter->second; |
| 349 | // Filter any backproped 'NoGradient' Outputs from 'grads' (if needed). |
| 350 | // Return any valid backproped gradients that remain after filtering, |
| 351 | // or 'NoGradient' otherwise. |
| 352 | std::vector<Output> grads_to_keep; |
| 353 | for (const Output& o : grads) { |
| 354 | if (o == NoGradient()) continue; |
| 355 | grads_to_keep.push_back(o); |
| 356 | } |
| 357 | |
| 358 | if (grads_to_keep.empty()) { |
| 359 | // Nothing propagated back. Return 'NoGradient'. |
| 360 | *grad = NoGradient(); |
| 361 | } else if (grads_to_keep.size() == 1) { |
| 362 | // Just one backprop edge. |
| 363 | *grad = grads_to_keep[0]; |
| 364 | } else { |
| 365 | // Otherwise, adds backprop-ed gradients. |
| 366 | // TODO(andydavis) Use a better accumulator here. |
| 367 | *grad = ops::AddN(scope_, grads_to_keep); |
| 368 | } |
| 369 | |
| 370 | return Status::OK(); |
| 371 | } |
| 372 | |
| 373 | bool SymbolicGradientBuilder::IsPrimitiveOpWithNoGrad(const string& opname) { |
| 374 | ops::GradFunc grad_fn; |