Batchwise dot product. `batch_dot` is used to compute dot product of `x` and `y` when `x` and `y` are data in batch, i.e. in a shape of `(batch_size, :)`. `batch_dot` results in a tensor or variable with less dimensions than the input. If the number of dimensions is reduced to 1, we use
(x, y, axes=None)
| 1700 | |
| 1701 | @keras_export('keras.backend.batch_dot') |
| 1702 | def batch_dot(x, y, axes=None): |
| 1703 | """Batchwise dot product. |
| 1704 | |
| 1705 | `batch_dot` is used to compute dot product of `x` and `y` when |
| 1706 | `x` and `y` are data in batch, i.e. in a shape of |
| 1707 | `(batch_size, :)`. |
| 1708 | `batch_dot` results in a tensor or variable with less dimensions |
| 1709 | than the input. If the number of dimensions is reduced to 1, |
| 1710 | we use `expand_dims` to make sure that ndim is at least 2. |
| 1711 | |
| 1712 | Arguments: |
| 1713 | x: Keras tensor or variable with `ndim >= 2`. |
| 1714 | y: Keras tensor or variable with `ndim >= 2`. |
| 1715 | axes: list of (or single) int with target dimensions. |
| 1716 | The lengths of `axes[0]` and `axes[1]` should be the same. |
| 1717 | |
| 1718 | Returns: |
| 1719 | A tensor with shape equal to the concatenation of `x`'s shape |
| 1720 | (less the dimension that was summed over) and `y`'s shape |
| 1721 | (less the batch dimension and the dimension that was summed over). |
| 1722 | If the final rank is 1, we reshape it to `(batch_size, 1)`. |
| 1723 | |
| 1724 | Examples: |
| 1725 | Assume `x = [[1, 2], [3, 4]]` and `y = [[5, 6], [7, 8]]` |
| 1726 | `batch_dot(x, y, axes=1) = [[17, 53]]` which is the main diagonal |
| 1727 | of `x.dot(y.T)`, although we never have to calculate the off-diagonal |
| 1728 | elements. |
| 1729 | |
| 1730 | Shape inference: |
| 1731 | Let `x`'s shape be `(100, 20)` and `y`'s shape be `(100, 30, 20)`. |
| 1732 | If `axes` is (1, 2), to find the output shape of resultant tensor, |
| 1733 | loop through each dimension in `x`'s shape and `y`'s shape: |
| 1734 | |
| 1735 | * `x.shape[0]` : 100 : append to output shape |
| 1736 | * `x.shape[1]` : 20 : do not append to output shape, |
| 1737 | dimension 1 of `x` has been summed over. (`dot_axes[0]` = 1) |
| 1738 | * `y.shape[0]` : 100 : do not append to output shape, |
| 1739 | always ignore first dimension of `y` |
| 1740 | * `y.shape[1]` : 30 : append to output shape |
| 1741 | * `y.shape[2]` : 20 : do not append to output shape, |
| 1742 | dimension 2 of `y` has been summed over. (`dot_axes[1]` = 2) |
| 1743 | `output_shape` = `(100, 30)` |
| 1744 | |
| 1745 | ```python |
| 1746 | >>> x_batch = K.ones(shape=(32, 20, 1)) |
| 1747 | >>> y_batch = K.ones(shape=(32, 30, 20)) |
| 1748 | >>> xy_batch_dot = K.batch_dot(x_batch, y_batch, axes=[1, 2]) |
| 1749 | >>> K.int_shape(xy_batch_dot) |
| 1750 | (32, 1, 30) |
| 1751 | ``` |
| 1752 | """ |
| 1753 | if isinstance(axes, int): |
| 1754 | axes = (axes, axes) |
| 1755 | x_ndim = ndim(x) |
| 1756 | y_ndim = ndim(y) |
| 1757 | if axes is None: |
| 1758 | # behaves like tf.batch_matmul as default |
| 1759 | axes = [x_ndim - 1, y_ndim - 2] |
no test coverage detected