Simplest solution
Use numpy.dot or a.dot(b). See the documentation here.
>>> a = np.array([[ 5, 1 ,3], 
                  [ 1, 1 ,1], 
                  [ 1, 2 ,1]])
>>> b = np.array([1, 2, 3])
>>> print a.dot(b)
array([16, 6, 8])
This occurs because numpy arrays are not matrices, and the standard operations *, +, -, / work element-wise on arrays.
Note that while you can use numpy.matrix (as of early 2021) where * will be treated like standard matrix multiplication, numpy.matrix is deprecated and may be removed in future releases.. See the note in its documentation (reproduced below):
It is no longer recommended to use this class, even for linear algebra. Instead use regular arrays. The class may be removed in the future.
Thanks @HopeKing.
Other Solutions
Also know there are other options:
- As noted below, if using python3.5+ and numpy v1.10+, the - @operator works as you'd expect:
 - >>> print(a @ b)
array([16, 6, 8])
 
- If you want overkill, you can use - numpy.einsum.  The documentation will give you a flavor for how it works, but honestly, I didn't fully understand how to use it until reading this answer and just playing around with it on my own.
 - >>> np.einsum('ji,i->j', a, b)
array([16, 6, 8])
 
- As of mid 2016 (numpy 1.10.1), you can try the experimental - numpy.matmul, which works like- numpy.dotwith two major exceptions: no scalar multiplication but it works with stacks of matrices.
 - >>> np.matmul(a, b)
array([16, 6, 8])
 
- numpy.innerfunctions the same way as- numpy.dotfor matrix-vector multiplication but behaves differently for matrix-matrix and tensor multiplication (see Wikipedia regarding the differences between the inner product and dot product in general or see this SO answer regarding numpy's implementations).
 - >>> np.inner(a, b)
array([16, 6, 8])
# Beware using for matrix-matrix multiplication though!
>>> b = a.T
>>> np.dot(a, b)
array([[35,  9, 10],
       [ 9,  3,  4],
       [10,  4,  6]])
>>> np.inner(a, b) 
array([[29, 12, 19],
       [ 7,  4,  5],
       [ 8,  5,  6]])
 
- If you have multiple 2D arrays to - dottogether, you may consider the- np.linalg.multi_dotfunction, which simplifies the syntax of many nested- np.dots.  Note that this only works with 2D arrays (i.e. not for matrix-vector multiplication).
 -   >>> np.dot(np.dot(a, a.T), a).dot(a.T)
  array([[1406,  382,  446],
         [ 382,  106,  126],
         [ 446,  126,  152]])
  >>> np.linalg.multi_dot((a, a.T, a, a.T))
  array([[1406,  382,  446],
         [ 382,  106,  126],
         [ 446,  126,  152]])
 
Rarer options for edge cases
- If you have tensors (arrays of dimension greater than or equal to one), you can use - numpy.tensordotwith the optional argument- axes=1:
 - >>> np.tensordot(a, b, axes=1)
array([16,  6,  8])
 
- Don't use - numpy.vdotif you have a matrix of complex numbers, as the matrix will be flattened to a 1D array, then it will try to find the complex conjugate dot product between your flattened matrix and vector (which will fail due to a size mismatch- n*mvs- n).