How to multiply matrices with NumPy

Matrix multiplication combines each row from one array with each column from another array. In NumPy, the @ operator keeps that linear algebra operation readable when code needs transforms, model features, or equation checks.

For two-dimensional arrays, a left shape (n, k) and a right shape (k, m) return a product shaped (n, m). The shared inner dimension must match, and np.matmul() follows the same matrix-product behavior as @ for regular arrays.

Element-wise multiplication is a different operation. Use * or np.multiply() when values at matching positions should be multiplied, and check shapes near data loading or transposes before a matrix product.

Steps to multiply matrices with NumPy:

  1. Create a script that multiplies a (2, 3) matrix by a (3, 2) matrix.
    matrix-multiply.py
    import numpy as np
     
    left = np.array(
        [
            [2, 1, 3],
            [0, 4, 5],
        ]
    )
    right = np.array(
        [
            [1, 2],
            [3, 0],
            [4, 1],
        ]
    )
    expected = np.array(
        [
            [17, 7],
            [32, 5],
        ]
    )
     
    product = left @ right
    column_scale = np.array([10, 100, 1000])
    elementwise = left * column_scale
     
    print("left shape:", left.shape)
    print("right shape:", right.shape)
    print("product:")
    print(product)
    print("product shape:", product.shape)
    print("matches expected:", np.array_equal(product, expected))
    print("matches np.matmul:", np.array_equal(product, np.matmul(left, right)))
    print("element-wise first row:", elementwise[0].tolist())

    The (2, 3) left matrix has three columns, and the (3, 2) right matrix has three rows, so the inner dimension is aligned.

  2. Run the script and verify the product shape and values.
    $ python matrix-multiply.py
    left shape: (2, 3)
    right shape: (3, 2)
    product:
    [[17  7]
     [32  5]]
    product shape: (2, 2)
    matches expected: True
    matches np.matmul: True
    element-wise first row: [20, 100, 3000]

    The product shape is (2, 2) because the outer dimensions remain after the shared inner dimension is summed. The element-wise row shows a separate column-scaling operation, not a matrix product.

  3. Confirm that incompatible inner dimensions fail before using arrays from external data.
    $ python - <<'PY'
    import numpy as np
    
    left = np.zeros((2, 3))
    right = np.zeros((2, 2))
    
    try:
        left @ right
    except ValueError as error:
        print(error)
    PY
    matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3)

    Transpose or reshape the source arrays only when the row and column meaning is still correct. A matching shape can still produce the wrong product if rows and columns were swapped earlier.
    Related: Transpose an array