shape of the result matrix for multiplying 2 arrays in numpy - numpy

shape of result matrix
matrix A is 3X3
array B is 3X1
so the shape of AXB should be 3X1.
the numpy calculation shows it as 1X3
where am i wrong?
I was expecting the shape as 3X1

The documentation for matmul/# (and dot) is written with ndarray in mind:
With (3,3) and (3,):
In [99]: A= np.arange(9).reshape(3,3); b=np.arange(3)
matmul is (3,) (so would np.dot)):
In [100]: A#b
Out[100]: array([ 5, 14, 23])
But with np.matrix, it appears the result (3,) is "promoted" to matrix), which by default adds a leading dimension:
In [101]: np.matrix(A)#b
Out[101]: matrix([[ 5, 14, 23]])
Originally * was defined to be matrix multiplication for np.matrix (as it is in MATLAB):
In [102]: np.matrix(A)*b
ValueError: shapes (3,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
That tried to promote b to np.matrix, resulting in a (3,3) with (1,3) => error.
np.dot of the same behaves like #:
In [103]: np.dot(np.matrix(A),b)
Out[103]: matrix([[ 5, 14, 23]])
To use * we have to make the 2nd (3,1) shape:
In [104]: np.matrix(A)*np.matrix(b).T
Out[104]:
matrix([[ 5],
[14],
[23]])
In [105]: np.matrix(b).T
Out[105]:
matrix([[0],
[1],
[2]])
In short using np.matrix with matmul/# complicates things, producing a result that doesn't quite fit the documentation.

Related

Assign numpy matrix to pandas columns

I have dataframe with 48870 rows and calculated embeddings with shape (48870, 768)
I wanna assign this embeddings to padnas column
When i try
test['original_text_embeddings'] = embeddings
I have an error: Wrong number of items passed 768, placement implies 1
I know if a make something like df.loc['original_text_embeddings'] = embeddings[0] will work but i need to automate this process
A dataframe/column needs a 1d list/array:
In [84]: x = np.arange(12).reshape(3,4)
In [85]: pd.Series(x)
...
ValueError: Data must be 1-dimensional
Splitting the array into a list (of arrays):
In [86]: pd.Series(list(x))
Out[86]:
0 [0, 1, 2, 3]
1 [4, 5, 6, 7]
2 [8, 9, 10, 11]
dtype: object
In [87]: _.to_numpy()
Out[87]:
array([array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8, 9, 10, 11])],
dtype=object)
Your embeddings have 768 columns, which would translate to equally 768 columns in a data frame. You are trying to assign all columns from the embeddings to just one column in the data frame, which is not possible.
What you could do is generating a new data frame from the embeddings and concatenate the test df with the embedding df
embedding_df = pd.DataFrame(embeddings)
test = pd.concat([test, embedding_df], axis=1)
Have a look at the documentation for handling indexes and concatenating on different axis:
https://pandas.pydata.org/docs/reference/api/pandas.concat.html

Two 4D mat mul numpy and should expect output 5D

I want to apply attention weights (5 label) to my convolution with 3 filters, could any help me to do how to apply matmul. Appreciated if you give tensorflow version as well.
import numpy as np
conv = np.random.randint(10,size=[1,3,2,2], dtype=int) # [batches,filter,row,col]
attention = np.random.randint(5,size=[1,5,2,1], dtype=int) # [batches,label,row,col]
np.matmul(conv,attention).shape # expected output size [1,3,5,2,1] [batches,filter,label,row,col]
ValueError: operands could not be broadcast together with remapped shapes [original->remapped]: (1,3,2,2)->(1,3,2,newaxis,2) (1,5,2,1)->(1,5,newaxis,1,2)
According to the docs of 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.
and
Stacks of matrices are broadcast together as if the matrices were elements.
This means that in your case, all but the last two dimensions need to match up. If you want the output shape to be 1, 3, 5, 2, 1, you will need to explicitly insert an empty axis into each array. You can do that at creation time:
import numpy as np
conv = np.random.randint(10, size=[1, 3, 1, 2, 2], dtype=int)
attention = np.random.randint(5, size=[1, 1, 5,2,1], dtype=int)
np.matmul(conv,attention).shape
Alternatively, you can make the insertion explicit by multiplying views with the appropriate insertions:
np.matmul(conv[:, :, np.newaxis, ...], attention[:, np.newaxis, ...]).shape

Elementwise multiplication of NumPy arrays of different shapes

When I use numpy.multiply(a,b) to multiply numpy arrays with shapes (2, 1),(2,) I get a 2 by 2 matrix. But what I want is element-wise multiplication.
I'm not familiar with numpy's rules. Can anyone explain what's happening here?
When doing an element-wise operation between two arrays, which are not of the same dimensionality, NumPy will perform broadcasting. In your case Numpy will broadcast b along the rows of a:
import numpy as np
a = np.array([[1],
[2]])
b = [3, 4]
print(a * b)
Gives:
[[3 4]
[6 8]]
To prevent this, you need to make a and b of the same dimensionality. You can add dimensions to an array by using np.newaxis or None in your indexing, like this:
print(a * b[:, np.newaxis])
Gives:
[[3]
[8]]
Let's say you have two arrays, a and b, with shape (2,3) and (2,) respectively:
a = np.random.randint(10, size=(2,3))
b = np.random.randint(10, size=(2,))
The two arrays, for example, contain:
a = np.array([[8, 0, 3],
[2, 6, 7]])
b = np.array([7, 5])
Now for handling a product element to element a*b you have to specify what numpy has to do when reaching for the absent axis=1 of array b. You can do so by adding None:
result = a*b[:,None]
With result being:
array([[56, 0, 21],
[10, 30, 35]])
Here are the input arrays a and b of the same shape as you mentioned:
In [136]: a
Out[136]:
array([[0],
[1]])
In [137]: b
Out[137]: array([0, 1])
Now, when we do multiplication using either * or numpy.multiply(a, b), we get:
In [138]: a * b
Out[138]:
array([[0, 0],
[0, 1]])
The result is a (2,2) array because numpy uses broadcasting.
# b
#a | 0 1
------------
0 | 0*0 0*1
1 | 1*0 1*1
I just explained the broadcasting rules in broadcasting arrays in numpy
In your case
(2,1) + (2,) => (2,1) + (1,2) => (2,2)
It has to add a dimension to the 2nd argument, and can only add it at the beginning (to avoid ambiguity).
So you want a (2,1) result, you have to expand the 2nd argument yourself, with reshape or [:, np.newaxis].

why the difference between numpy matrix and numpy array when selecting element

I have a calculated matrix
from numpy import matrix
vec=matrix([[ 4.79263398e-01+0.j , -2.94883960e-14+0.34362808j,
5.91036823e-01+0.j , -2.06730654e-14+0.41959935j,
-3.20298698e-01+0.08635809j, -5.97136351e-02+0.22325523j],
[ 9.45394208e-14+0.34385164j, 4.78941900e-01+0.j ,
1.07732017e-13+0.41891016j, 5.91969770e-01+0.j ,
-6.06877417e-02-0.2250884j , 3.17803028e-01+0.08500215j],
[ 4.63795513e-01-0.00827114j, -1.15263719e-02+0.33287485j,
-2.78282097e-01-0.20137267j, -2.81970922e-01-0.1980647j ,
9.26109539e-02-0.38428445j, 5.12483437e-01+0.j ],
[ -1.15282610e-02+0.33275927j, 4.63961516e-01-0.00826978j,
-2.84077490e-01-0.19723838j, -2.79429184e-01-0.19984041j,
-4.42104809e-01+0.25708681j, -2.71973825e-01+0.28735795j],
[ 4.63795513e-01+0.00827114j, 1.15263719e-02+0.33287485j,
-2.78282097e-01+0.20137267j, 2.81970922e-01-0.1980647j ,
2.73235786e-01+0.28564581j, -4.44053596e-01-0.25584307j],
[ 1.15282610e-02+0.33275927j, 4.63961516e-01+0.00826978j,
2.84077490e-01-0.19723838j, -2.79429184e-01+0.19984041j,
5.11419878e-01+0.j , -9.22028113e-02-0.38476356j]])
I want to get 2nd row, 3rd column element
vec[1][2]
IndexError: index 1 is out of bounds for axis 0 with size 1
and slicing works well
vec[1,2]
(1.07732017e-13+0.41891015999999998j)
My first question why first way does not work in this case? it worked before when I used it.
Second question is: the result of slicing is an array, how to make it an complex value without bracket? My experience was using
vec[1,2][0]
but again it is not working here.
I tried to do everything on numpy array at begining, those methods that do not work on numpy matrix work on numpy array. Why there are such differences?
The key difference is that a matrix is always 2d, always. (This is supposed to be familiar to MATLAB users.)
In [85]: mat = np.matrix('1,2;3,4')
In [86]: mat
Out[86]:
matrix([[1, 2],
[3, 4]])
In [87]: mat.shape
Out[87]: (2, 2)
In [88]: mat[1]
Out[88]: matrix([[3, 4]])
In [89]: _.shape
Out[89]: (1, 2)
Selecting a row of mat returns a matrix - a 1 row one. It should be clear that it cannot be indexed again with [1].
Indexing with the tuple returns a scalar:
In [90]: mat[1,1]
Out[90]: 4
In [91]: type(_)
Out[91]: numpy.int32
As a general rule operations on a np.matrix returns a matrix or a scalar, not a np.ndarray.
The other key point is that mat[1][1] is not one numpy operation. It is two, a mat[1] followed by another [1]. Imagine yourself to be a Python interpreter without any special knowledge of numpy. How would you evaluate that expression?
Now for the complex question:
In [92]: mat = np.matrix('1+3j, 2;-2, 2+1j')
In [93]: mat
Out[93]:
matrix([[ 1.+3.j, 2.+0.j],
[-2.+0.j, 2.+1.j]])
In [94]: mat[1,1]
Out[94]: (2+1j)
In [95]: type(_)
Out[95]: numpy.complex128
As expected the tuple index has returned a scalar numpy element. () is just part of numpys way of displaying a complex number.
We can use item to extra python equivalent, but the display still uses ()
In [96]: __.item()
Out[96]: (2+1j)
In [97]: type(_)
Out[97]: complex
In [98]: 1+3j
Out[98]: (1+3j)
mat has A property that gives the array equivalent. But notice the shapes.
In [99]: mat.A # a 2d array
Out[99]:
array([[ 1.+3.j, 2.+0.j],
[-2.+0.j, 2.+1.j]])
In [100]: mat.A1 # a 1d array
Out[100]: array([ 1.+3.j, 2.+0.j, -2.+0.j, 2.+1.j])
In [101]: mat[1].A
Out[101]: array([[-2.+0.j, 2.+1.j]])
In [102]: mat[1].A1
Out[102]: array([-2.+0.j, 2.+1.j])
Sometimes this behavior of matrix is handy. For example np.sum acts like the array keepdims=True:
In [108]: np.sum(mat,1)
Out[108]:
matrix([[ 3.+3.j],
[ 0.+1.j]])
In [110]: np.sum(mat.A,1, keepdims=True)
Out[110]:
array([[ 3.+3.j],
[ 0.+1.j]])

The represetaion of vector in numpy: is the return of np.array() a row vector?

I am new to numpy, I guess the return of np.array() is a row vector, Because the dot product between two vectors is commutative, is my guess right? Any respone is grateful.
vx = np.array([1, 2])
vw = np.array([3, 5])
np.dot(vx, vw)
np.dot(vw, vx)
The arrays are 1d ('vectors', not row/column vectors).
First paragraph from dot docuentation:
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
So you are getting the inner product, which is commutative.
In [118]: vx = np.array([1, 2])
In [119]: vx.shape
Out[119]: (2,)
dot returns a scalar:
In [120]: np.dot(vx,vx)
Out[120]: 5
For a 2d 'row vector', shape matters. dot is matrix multiplication, and last dim as to match 2nd to the last, e.g. 2 matches with 2.
In [121]: vx2 = np.array([[1,2]])
In [122]: vx2.shape
Out[122]: (1, 2)
In [123]: np.dot(vx2, vx2)
...
ValueError: shapes (1,2) and (1,2) not aligned: 2 (dim 1) != 1 (dim 0)
In [124]: np.dot(vx2, vx2.T)
Out[124]: array([[5]])
In this case the result is 2d (1,1).