| 862 | REGISTER_GRADIENT_OP("Max", MinOrMaxGrad); |
| 863 | |
| 864 | Status ProdGrad(const Scope& scope, const Operation& op, |
| 865 | const std::vector<Output>& grad_inputs, |
| 866 | std::vector<Output>* grad_outputs) { |
| 867 | auto zero = Const(scope, 0); |
| 868 | auto one = Const(scope, 1); |
| 869 | |
| 870 | // The gradient can be expressed by dividing the product by each entry of |
| 871 | // the input tensor. If our input is |
| 872 | // [ |
| 873 | // [3, 4], |
| 874 | // [5, 6], |
| 875 | // [7, 8] |
| 876 | // ] |
| 877 | // and we do a Prod operation on the axis 1, we will obtain [[105, 192]]. |
| 878 | // The gradient will have the same shape as the input |
| 879 | // [ |
| 880 | // [105/3, 192/4], |
| 881 | // dz * [105/5, 192/6], |
| 882 | // [105/7, 192/6] |
| 883 | // ] |
| 884 | // If the input contains a zero, the division is impossible but |
| 885 | // if we take the calculation that gave the first gradient |
| 886 | // (3 * 5 * 6)/3 is equal to 5 * 6 |
| 887 | // the trick will be to cumprod the elements on the axis without |
| 888 | // the element at the current position (3 in the example above). |
| 889 | // We will take as example: |
| 890 | // [ |
| 891 | // [ |
| 892 | // [3.0, 4.0], |
| 893 | // [5.0, 6.0], |
| 894 | // [7.0, 8.0] |
| 895 | // ], |
| 896 | // [ |
| 897 | // [3.0, 5.0], |
| 898 | // [0.0, 6.0], |
| 899 | // [5.0, 6.0] |
| 900 | // ] |
| 901 | // ] |
| 902 | |
| 903 | // [2, 3, 2] |
| 904 | auto input_shape = Shape(scope, op.input(0)); |
| 905 | |
| 906 | // The Reshape with -1 flattens the reduction indices. |
| 907 | // [1] |
| 908 | auto reduction_indices = Reshape(scope, op.input(1), {-1}); |
| 909 | |
| 910 | // [2, 1, 2] |
| 911 | auto output_shape_kept_dims = |
| 912 | ReducedShapeHelper(scope, input_shape, reduction_indices); |
| 913 | |
| 914 | // [1, 3, 1] |
| 915 | auto tile_scaling = SafeDivHelper(scope, input_shape, output_shape_kept_dims); |
| 916 | |
| 917 | // [[[105, 192]], [[0, 180]]] |
| 918 | auto grad = Reshape(scope, grad_inputs[0], output_shape_kept_dims); |
| 919 | |
| 920 | // [[[105, 192], [105, 192], [105, 192]], [[0, 180], [0, 180], [0, 180]]] |
| 921 | auto grad_tiled = Tile(scope, grad, tile_scaling); |
nothing calls this directly
no test coverage detected