| 74 | } |
| 75 | |
| 76 | Status SoftmaxCrossEntropyWithLogitsGrad(const Scope& scope, |
| 77 | const Operation& op, |
| 78 | const std::vector<Output>& grad_inputs, |
| 79 | std::vector<Output>* grad_outputs) { |
| 80 | // Softmax gradient with cross entropy logits function. |
| 81 | // We multiply the backprop for cost with the gradients - op.output[1]. |
| 82 | // There is no gradient for labels. |
| 83 | |
| 84 | // The outputs of the network are at input index 0. |
| 85 | auto logits = op.input(0); |
| 86 | // The "truth" labels are at index 1. |
| 87 | auto softmax_grad = op.output(1); |
| 88 | |
| 89 | // The loss is the output at index 0, and backprop is the output at index 1. |
| 90 | auto grad_loss = grad_inputs[0]; |
| 91 | auto grad_grad = grad_inputs[1]; |
| 92 | |
| 93 | auto grad = BroadcastMul(scope, grad_loss, softmax_grad); |
| 94 | if (!IsZero(scope, grad_grad)) { |
| 95 | std::vector<int> axis; |
| 96 | auto logits_softmax = Softmax(scope, logits); |
| 97 | |
| 98 | auto grad_grad_expand = ExpandDims(scope, grad_grad, 1); |
| 99 | auto logits_softmax_expand = ExpandDims(scope, logits_softmax, 2); |
| 100 | auto matmul_result = |
| 101 | BatchMatMul(scope, grad_grad_expand, logits_softmax_expand); |
| 102 | axis.push_back(1); |
| 103 | auto squeeze_result = Squeeze(scope, matmul_result, Squeeze::Axis(axis)); |
| 104 | auto subtraction_result = Subtract(scope, grad_grad, squeeze_result); |
| 105 | auto multiply_result = Multiply(scope, subtraction_result, logits_softmax); |
| 106 | grad = Add(scope, grad, multiply_result); |
| 107 | } |
| 108 | auto minus_log_softmax = Multiply(scope, LogSoftmax(scope, logits), -1.0f); |
| 109 | grad_outputs->push_back(grad); |
| 110 | grad_outputs->push_back(BroadcastMul(scope, grad_loss, minus_log_softmax)); |
| 111 | return scope.status(); |
| 112 | } |
| 113 | REGISTER_GRADIENT_OP("SoftmaxCrossEntropyWithLogits", |
| 114 | SoftmaxCrossEntropyWithLogitsGrad); |
| 115 |
nothing calls this directly
no test coverage detected