# Difference between numpy dot() and Python 3.5+ matrix multiplication @

I recently moved to Python 3.5 and noticed the new matrix multiplication operator (@) sometimes behaves differently from the numpy dot operator. In example, for 3d arrays:

```    import numpy as np

a = np.random.rand(8,13,13)
b = np.random.rand(8,13,13)
c = a @ b  # Python 3.5+
d = np.dot(a, b)
```

The `@` operator returns an array of shape:

```    c.shape
(8, 13, 13)
```

while the `np.dot()` function returns:

```    d.shape
(8, 13, 8, 13)
```

How can I reproduce the same result with numpy dot? Are there any other significant differences?

The `@` operator calls the array's `__matmul__` method, not `dot`. This method is also present in the API as the function `np.matmul`.

```    >>> a = np.random.rand(8,13,13)
>>> b = np.random.rand(8,13,13)
>>> np.matmul(a, b).shape
(8, 13, 13)
```

From the documentation:

`matmul` differs from `dot` in two important ways.

• Multiplication by scalars is not allowed.
• Stacks of matrices are broadcast together as if the matrices were elements.

The last point makes it clear that `dot` and `matmul` methods behave differently when passed 3D (or higher dimensional) arrays. Quoting from the documentation some more:

For `matmul`:

If either argument is N-D, N > 2, it is treated as a stack of matrices residing in the last two indexes and broadcast accordingly.

For `np.dot`:

For 2-D arrays it is equivalent to matrix multiplication, and for 1-D arrays to inner product of vectors (without complex conjugation). For N dimensions it is a sum product over the last axis of a and the second-to-last of b

From: stackoverflow.com/q/34142485