Numpy array dot product - python

We all know that dot product between vectors must return a scalar:
import numpy as np
a = np.array([1,2,3])
b = np.array([3,4,5])
print(a.shape) # (3,)
print(b.shape) # (3,)
a.dot(b) # 26
b.dot(a) # 26
perfect. BUT WHY if we use a "real" (take a look at Difference between numpy.array shape (R, 1) and (R,)) row vector or column vector the numpy dot product returns error on dimension ?
arow = np.array([[1,2,3]])
brow = np.array([[3,4,5]])
print(arow.shape) # (1,3)
print(brow.shape) # (1,3)
arow.dot(brow) # ERROR
brow.dot(arow) # ERROR
acol = np.array([[1,2,3]]).reshape(3,1)
bcol = np.array([[3,4,5]]).reshape(3,1)
print(acol.shape) # (3,1)
print(bcol.shape) # (3,1)
acol.dot(bcol) # ERROR
bcol.dot(acol) # ERROR

Because by explicitly adding a second dimension, you are no longer working with vectors but with two dimensional matrices. When taking the dot product of matrices, the inner dimensions of the product must match.
You therefore need to transpose one of your matrices. Which one you transpose will determine the meaning and shape of the result.
A 1x3 times a 3x1 matrix will result in a 1x1 matrix (i.e., a scalar). This is the inner product. A 3x1 times a 1x3 matrix will result in a 3x3 outer product.

You can also use the # operator, which is actually matrix multiplication.
In this case, as well as in dot product, you need to be aware to the matrices sizes (ndarray should always be dim compatible ), but it's more readable:
>>> a = np.array([1,2,3])
>>> a.shape
(3,)
>>> b= np.array([[1,2,3]])
>>> b.shape
(1, 3)
>>> a#b
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: shapes (3,) and (1,3) not aligned: 3 (dim 0) != 1 (dim 0)
>>> a#b.T
array([14])

You can also do like this
import numpy as npy
Vector1 = npy.array([0,2,3])
Vector2 = npy.array([3,5,1])
print("Dot Product of", Vector1, "and", Vector2,)
def DotProduct(a,b):
NetValue = 0
for i in range(len(a)):
NetValue += a[i]*b[i]
return NetValue
ans = DotProduct(Vector1,Vector2)
print("The answer is =",ans)

Related

"ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0 ... (size 2 is different from 1)"

I am just starting to learn Python/NumPy. I want to write a function which will apply an operation with 2 inputs and 1 output and a given weight matrix i.e two NumPy arrays of shape (2,1) and should return a NumPy array of shape (1,1) using tanh. Here is what I came up with:
import numpy as np
def test_neural(inputs,weights):
result=np.matmul(inputs,weights)
print(result)
z = np.tanh(result)
return (z)
x = np.array([[1],[1]])
y = np.array([[1],[1]])
z=test_neural(x,y)
print("final result:",z)
But I am getting the following matmul error:
ValueError: 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 1)
Can someone please tell me what I am missing?
The problem is the dimensions of the matrix multiplication.
You can multiply matrixes with shared dimensions like this (read more here):
(M , N) * (N , K) => Result dimensions is (M, K)
You try multiply:
(2 , 1) * (2, 1)
But the dimensions are illegal.
So you have to transpose inputs before multiply (just apply .T on the matrix), so you get valid dimensions for multiplication:
(1, 2) * (2, 1) => Result dimension is (1, 1)
Code:
import numpy as np
def test_neural(inputs,weights):
result=np.matmul(inputs.T, weights)
print(result)
z = np.tanh(result)
return (z)
x = np.array([[1],[1]])
y = np.array([[1],[1]])
z=test_neural(x,y)
# final result: [[0.96402758]]
print("final result:",z)

numpy.where with two-dimensional array

One can use numpy.where for selecting values from two arrays depending on a condition:
import numpy
a = numpy.random.rand(5)
b = numpy.random.rand(5)
c = numpy.where(a > 0.5, a, b) # okay
If the array has more dimensions, however, this does not work anymore:
import numpy
a = numpy.random.rand(5, 2)
b = numpy.random.rand(5, 2)
c = numpy.where(a[:, 0] > 0.5, a, b) # !
Traceback (most recent call last):
File "p.py", line 10, in <module>
c = numpy.where(a[:, 0] > 0.5, a, b) # okay
File "<__array_function__ internals>", line 6, in where
ValueError: operands could not be broadcast together with shapes (5,) (5,2) (5,2)
I would have expected a numpy array of shape (5,2).
What's the issue here? How to work around it?
Remember that broadcasting in numpy only works from the right, so while (5,) shaped arrays can broadcast with (2,5) shaped arrays they can't broadcast with (5,2) shaped arrays. to broadcast with a (5,2) shaped array you need to maintain the second dimension so that the shape is (5,1) (anything can broadcast with 1)
Thus, you need to maintain the second dimension when indexing it (otherwise it removes the indexed dimension when only one value exists). You can do this by putting the index in a one-element list:
a = numpy.random.rand(5, 2)
b = numpy.random.rand(5, 2)
c = numpy.where(a[:, [0]] > 0.5, a, b) # works
You can use c = numpy.where(a > 0.5, a, b)
however if you want to use only the first column of a then you need to consider the shape of the output.
let's first see what is the shape of this operation
(a[:, 0] > 0.5).shape # outputs (5,)
it's one dimensional
while the shape of a and b is (5, 2)
it's two dimensional and hence you can't broadcast this
the solution is to reshape the mask operation to be of shape (5, 1)
your code should look like this
a = numpy.random.rand(5, 2)
b = numpy.random.rand(5, 2)
c = numpy.where((a[:, 0] > 0.5).reshape(-1, 1), a, b) # !
You can try:
import numpy
a = numpy.random.rand(5, 2)
b = numpy.random.rand(5, 2)
c = numpy.where(a > 0.5, a, b)
instead of: c = np.where(a>0.5,a,b)
you can use: c = np.array([a,b])[a>0.5]
which works for multidimensional arrays if a and b have the same shape.

Numpy dotproduct weird behaviour

I am using python3.5 and i have question: Why np.dot() is behaving like this?
>> a = np.array([[1,2,3,4]])
>> b = np.array([123])
>> np.dot(a,b)
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: shapes (1,4) and (1,) not aligned: 4 (dim 1) != 1 (dim 0)
>>np.dot(b,a)
array([123, 246, 369, 492])
From help(np.dot), we learn that, np.dot(x,y) is a sum product over the last axis of x and the second-to-last of y
In the case of np.dot(a, b), the last axis of a is 4 and the length of the only axis of b is 1. They don't match: fail.
In the case of np.dot(b, a), the last axis of b is 1 and the 2nd to last of a is 1. They match: success.
Workarounds
Depending on what your intention is for np.dot(a,b), you may want:
>>> np.dot(a, np.resize(b,a.shape[-1]))
array([1230])
From the documentation for numpy.dot(x, y):
For 2-D arrays it is equivalent to matrix multiplication, and for 1-D arrays to inner product of vectors... For N dimensions it is a sum product over the last axis of x and the second-to-last of y:
So, where you have:
a = np.array([[1,2,3,4]]) # shape is (1, 4), 2-D array (matrix)
b = np.array([123]) # shape is (1,), 1-D array (vector)
np.dot(b, a) works ((1,) * (1, 4), the relevant dimensions agree)
np.dot(a, b) doesn't ((1, 4) * (1,), the relevant dimensions don't agree, the operation is undefined. Note that the 'second-to-last' axis of (1,) corresponds to its one and only axis)
This is the same behaviour as if you have two 2-D arrays, i.e. matrices:
a = np.array([[1,2,3,4]]) # shape is (1, 4)
b = np.array([[123]]) # shape is (1, 1)
np.dot(b, a) works ((1, 1) * (1, 4), inner matrix dimensions agree)
np.dot(a, b) doesn't ((1, 4) * (1, 1), inner matrix dimensions don't agree)
If however you have two 1-D arrays, i.e. vectors, neither operation works:
a = np.array([1,2,3,4]) # shape is (4,)
b = np.array([123]) # shape is (1,)
np.dot(b, a) doesn't work ((1,) * (4,), but can only define the inner product for vectors of the same length)
np.dot(a, b) doesn't work ((4,) * (1), same)

Broadcasting numpy matrices using arrays of indices

I have these numpy objects:
>>> x = np.matrix([[1],[2],[3]])
>>> i = ([1,2],0)
>>> y = np.matrix([[4],[5]])
When I do x[i] I get as I expect:
>>> x[i]
matrix([[2],
[3]])
However, when I try to assign to x[i], I get funky behavior:
>>> x[i] = y
ValueError: array is not broadcastable to correct shape
>>> y.shape
(2, 1)
>>> x[i].shape
(2, 1)
I have figured out some workarounds, but they're workarounds and not what I want:
>>> x[1:,0] = y
>>> x
matrix([[1],
[4],
[5]])
>>> x = np.array([[1],[2],[3]]); y = np.array(y)
>>> x[i] = y[:,0]
>>> x
array([[1],
[4],
[5]])
The second workaround is not acceptable because y could have a more general shape than a column vector.
Don't use numpy.matrix. It's terrible. It causes so many weird incompatibilities and has so many inconsistencies, including this one.
Use numpy.array. With arrays, x[i] is one-dimensional, and assigning a one-dimensional y of equal shape to x[i] will work fine.
import numpy
x = numpy.array([[1], [2], [3]])
y = numpy.array([4, 5])
i = ([1, 2], 0)
print(x[i].shape)
print(y.shape)
x[i] = y
print(repr(x))
Output:
(2,)
(2,)
array([[1],
[4],
[5]])
If you want to do matrix multiplication, use the # operator, or the dot method if you're on too old a Python version or too old a NumPy version to have #.
Indexing with a simpe [1,2] works:
In [71]: x
Out[71]:
matrix([[1],
[2],
[3]])
In [72]: y
Out[72]:
matrix([[4],
[5]])
In [73]: x[[1,2],:]
Out[73]:
matrix([[2],
[3]])
In [74]: x[[1,2],:] = y
Trying to use a tuple has problems:
In [78]: i = ([1,2],0)
In [79]: x[i] = y
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-79-699d63749224> in <module>()
----> 1 x[i] = y
ValueError: shape mismatch: value array of shape (2,1) could not be broadcast to indexing result of shape (2,)
Changing i to i = ([1,2],slice(None)) matches my first case.
Using 0 instead of :' is also a problem:
In [82]: x[[1,2],0] = y
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-82-8b683eb93954> in <module>()
----> 1 x[[1,2],0] = y
ValueError: shape mismatch: value array of shape (2,1) could not be broadcast to indexing result of shape (2,)
I suspect it is trying to do the assgnment to a (2,) as a numpy array, before converting the results back to matrix.
It's trying to the equivalent of:
In [83]: x.A[[1,2],0] = y
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-83-b2ccc78af912> in <module>()
----> 1 x.A[[1,2],0] = y
ValueError: shape mismatch: value array of shape (2,1) could not be broadcast to indexing result of shape (2,)
where as it needs a flattened version of y:
In [84]: x.A[[1,2],0] = y.A1 # max `y` a 1d array
x[[1,2],0] = y.A1 # also works
Earlier today there was a similar problem: Copy NumPy matrix into NumPy array
The convenience of using * for matrix multiplication rarely outweighs the clumkiness of restricting dimensions to 2. np.dot works just as well. And arrays also provide tensordot, einsum and matmul (and the # operator).
np.matrix is a subclass of np.ndarray. It inherits methods. Often it performs the action with the ndarray method, and cleans up the dimesions, either forcing 1d results to 2d, or scalars.
Here's the code for the * matrix multiplication:
Signature: x.__mul__(other)
Source:
def __mul__(self, other):
if isinstance(other, (N.ndarray, list, tuple)) :
# This promotes 1-D vectors to row vectors
return N.dot(self, asmatrix(other))
if isscalar(other) or not hasattr(other, '__rmul__') :
return N.dot(self, other)
return NotImplemented

numpy array each element multiplication with matrix

I have a matrix
A = [[ 1. 1.]
[ 1. 1.]]
and two arrays (a and b), every array contains 20 float numbers How can I multiply the using formula:
( x' = A * ( x )
y' ) y
Is this correct? m = A * [a, b]
Matrix multiplication with NumPy arrays can be done with np.dot.
If X has shape (i,j) and Y has shape (j,k) then np.dot(X,Y) will be the matrix product and have shape (i,k). The last axis of X and the second-to-last axis of Y is multiplied and summed over.
Now, if a and b have shape (20,), then np.vstack([a,b]) has shape (2, 20):
In [66]: np.vstack([a,b]).shape
Out[66]: (2, 20)
You can think of np.vstack([a, b]) as a 2x20 matrix with the values of a on the first row, and the values of b on the second row.
Since A has shape (2,2), we can perform the matrix multiplication
m = np.dot(A, np.vstack([a,b]))
to arrive at an array of shape (2, 20).
The first row of m contains the x' values, the second row contains the y' values.
NumPy also has a matrix subclass of ndarray (a special kind of NumPy array) which has convenient syntax for doing matrix multiplication with 2D arrays. If we define A to be a matrix (rather than a plain ndarray which is what np.array(...) creates), then matrix multiplication can be done with the * operator.
I show both ways (with A being a plain ndarray and A2 being a matrix) below:
import numpy as np
A = np.array([[1.,1.],[1.,1.]])
A2 = np.matrix([[1.,1.],[1.,1.]])
a = np.random.random(20)
b = np.random.random(20)
c = np.vstack([a,b])
m = np.dot(A, c)
m2 = A2 * c
assert np.allclose(m, m2)

Categories

Resources