Gradient for Min or Max. Amazingly it's precisely the same code.
(op, grad)
| 203 | |
| 204 | |
| 205 | def _MinOrMaxGrad(op, grad): |
| 206 | """Gradient for Min or Max. Amazingly it's precisely the same code.""" |
| 207 | input_shape = array_ops.shape(op.inputs[0]) |
| 208 | output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1]) |
| 209 | y = op.outputs[0] |
| 210 | y = array_ops.reshape(y, output_shape_kept_dims) |
| 211 | grad = array_ops.reshape(grad, output_shape_kept_dims) |
| 212 | |
| 213 | # Compute the number of selected (maximum or minimum) elements in each |
| 214 | # reduction dimension. If there are multiple minimum or maximum elements |
| 215 | # then the gradient will be divided between them. |
| 216 | indicators = math_ops.cast(math_ops.equal(y, op.inputs[0]), grad.dtype) |
| 217 | num_selected = array_ops.reshape( |
| 218 | math_ops.reduce_sum(indicators, op.inputs[1]), output_shape_kept_dims) |
| 219 | |
| 220 | return [math_ops.divide(indicators, num_selected) * grad, None] |
| 221 | |
| 222 | |
| 223 | @ops.RegisterGradient("Max") |