Returns the gradient of x and y given the gradient of x * y.
(op, grad)
| 1697 | |
| 1698 | @ops.RegisterGradient("BatchMatMulV2") |
| 1699 | def _BatchMatMulV2(op, grad): |
| 1700 | """Returns the gradient of x and y given the gradient of x * y.""" |
| 1701 | x = op.inputs[0] |
| 1702 | y = op.inputs[1] |
| 1703 | adj_x = op.get_attr("adj_x") |
| 1704 | adj_y = op.get_attr("adj_y") |
| 1705 | |
| 1706 | if not adj_x: |
| 1707 | if not adj_y: |
| 1708 | grad_x = math_ops.matmul(grad, y, adjoint_a=False, adjoint_b=True) |
| 1709 | grad_y = math_ops.matmul(x, grad, adjoint_a=True, adjoint_b=False) |
| 1710 | else: |
| 1711 | grad_x = math_ops.matmul(grad, y, adjoint_a=False, adjoint_b=False) |
| 1712 | grad_y = math_ops.matmul(grad, x, adjoint_a=True, adjoint_b=False) |
| 1713 | else: |
| 1714 | if not adj_y: |
| 1715 | grad_x = math_ops.matmul(y, grad, adjoint_a=False, adjoint_b=True) |
| 1716 | grad_y = math_ops.matmul(x, grad, adjoint_a=False, adjoint_b=False) |
| 1717 | else: |
| 1718 | grad_x = math_ops.matmul(y, grad, adjoint_a=True, adjoint_b=True) |
| 1719 | grad_y = math_ops.matmul(grad, x, adjoint_a=True, adjoint_b=True) |
| 1720 | |
| 1721 | # Reduce along the broadcasted batch dimensions, if broadcasting is required. |
| 1722 | shape_x_static = x.get_shape() |
| 1723 | shape_y_static = y.get_shape() |
| 1724 | if not (shape_x_static.is_fully_defined() and |
| 1725 | shape_y_static.is_fully_defined() and |
| 1726 | shape_x_static == shape_y_static): |
| 1727 | sx = array_ops.shape(x) |
| 1728 | sy = array_ops.shape(y) |
| 1729 | rx, ry = gen_array_ops.broadcast_gradient_args(sx[:-2], sy[:-2]) |
| 1730 | grad_x = array_ops.reshape(math_ops.reduce_sum(grad_x, rx), sx) |
| 1731 | grad_y = array_ops.reshape(math_ops.reduce_sum(grad_y, ry), sy) |
| 1732 | |
| 1733 | return grad_x, grad_y |
| 1734 | |
| 1735 | |
| 1736 | ops.NotDifferentiable("Range") |
nothing calls this directly
no test coverage detected