|
50 | 50 | 'sequence_last_step', |
51 | 51 | 'dropout', |
52 | 52 | 'split', |
| 53 | + 'matmul', |
53 | 54 | ] |
54 | 55 |
|
55 | 56 |
|
@@ -1597,3 +1598,73 @@ def split(input, num_or_sections, dim=-1): |
1597 | 1598 | 'axis': dim |
1598 | 1599 | }) |
1599 | 1600 | return outs |
| 1601 | + |
| 1602 | + |
| 1603 | +def matmul(x, y, transpose_x=False, transpose_y=False, name=None): |
| 1604 | + """ |
| 1605 | + Applies matrix multipication to two tensors. Currently only rank 1 to rank |
| 1606 | + 3 input tensors are supported. |
| 1607 | +
|
| 1608 | + The actual behavior depends on the shapes of :math:`x`, :math:`y` and the |
| 1609 | + flag values of :attr:`transpose_x`, :attr:`transpose_y`. Specifically: |
| 1610 | +
|
| 1611 | + - If a transpose flag is specified, the last two dimensions of the tensor |
| 1612 | + are transposed. If the tensor is rank-1 of shape :math:`[D]`, then for |
| 1613 | + :math:`x` it is treated as :math:`[1, D]` in nontransposed form and as |
| 1614 | + :math:`[D, 1]` in transposed form, whereas for :math:`y` it is the |
| 1615 | + opposite: It is treated as :math:`[D, 1]` in nontransposed form and as |
| 1616 | + :math:`[1, D]` in transposed form. |
| 1617 | +
|
| 1618 | + - After transpose, the two tensors are 2-D or 3-D and matrix multipication |
| 1619 | + performs in the following way. |
| 1620 | +
|
| 1621 | + - If both are 2-D, they are multiplied like conventional matrices. |
| 1622 | + - If either is 3-D, it is treated as a stack of matrices residing in the |
| 1623 | + last two dimensions and a batched matrix multiply supporting broadcast |
| 1624 | + applies on the two tensors. |
| 1625 | +
|
| 1626 | + Also note that if the raw tensor :math:`x` or :math:`y` is rank-1 and |
| 1627 | + nontransposed, the prepended or appended dimension :math:`1` will be |
| 1628 | + removed after matrix multipication. |
| 1629 | +
|
| 1630 | + Args: |
| 1631 | + x (Variable): The input variable which is a Tensor or LoDTensor. |
| 1632 | + y (Variable): The input variable which is a Tensor or LoDTensor. |
| 1633 | + transpose_x (bool): Whether to transpose :math:`x` before multiplication. |
| 1634 | + transpose_y (bool): Whether to transpose :math:`y` before multiplication. |
| 1635 | + name(str|None): A name for this layer(optional). If set None, the layer |
| 1636 | + will be named automatically. |
| 1637 | +
|
| 1638 | + Returns: |
| 1639 | + Variable: The product Tensor variable. |
| 1640 | +
|
| 1641 | + Examples: |
| 1642 | + .. code-block:: python |
| 1643 | +
|
| 1644 | + # Examples to clarify shapes of the inputs and output |
| 1645 | + # x: [B, M, K], y: [B, K, N] |
| 1646 | + fluid.layers.matmul(x, y) # out: [B, M, N] |
| 1647 | + # x: [B, M, K], y: [K, N] |
| 1648 | + fluid.layers.matmul(x, y) # out: [B, M, N] |
| 1649 | + # x: [B, M, K], y: [K] |
| 1650 | + fluid.layers.matmul(x, y) # out: [B, M] |
| 1651 | + # x: [M, K], y: [K, N] |
| 1652 | + fluid.layers.matmul(x, y) # out: [M, N] |
| 1653 | + # x: [K], y: [K] |
| 1654 | + fluid.layers.matmul(x, y) # out: [1] |
| 1655 | + # x: [M], y: [N] |
| 1656 | + fluid.layers.matmul(x, y, True, True) # out: [M, N] |
| 1657 | + """ |
| 1658 | + helper = LayerHelper('matmul', **locals()) |
| 1659 | + assert max( |
| 1660 | + len(x.shape), len(y.shape) |
| 1661 | + ) <= 3, 'Currently only rank 1 to rank 3 input tensors are supported.' |
| 1662 | + out = helper.create_tmp_variable(dtype=helper.input_dtype()) |
| 1663 | + helper.append_op( |
| 1664 | + type='matmul', |
| 1665 | + inputs={'X': x, |
| 1666 | + 'Y': y}, |
| 1667 | + outputs={'Out': out}, |
| 1668 | + attrs={'transpose_X': transpose_x, |
| 1669 | + 'transpose_Y': transpose_y}) |
| 1670 | + return out |
0 commit comments