Python - matrix multiplication - python

i have an array y with shape (n,), I want to compute the inner product matrix, which is a n * n matrix
However, when I tried to do it in Python
np.dot(y , y)
I got the answer n, this is not what I am looking for
I have also tried:
np.dot(np.transpose(y),y)
np.dot(y, np.transpose(y))
I always get the same answer n

I think you are looking for:
np.multiply.outer(y,y)
or equally:
y = y[None,:]
y.T#y
example:
y = np.array([1,2,3])[None,:]
output:
#[[1 2 3]
# [2 4 6]
# [3 6 9]]

You can try to reshape y from shape (70,) to (70,1) before multiplying the 2 matrices.
# Reshape
y = y.reshape(70,1)
# Either below code would work
y*y.T
np.matmul(y,y.T)

One-liner?
np.dot(a[:, None], a[None, :])
transpose doesn't work on 1-D arrays, because you need atleast two axes to 'swap' them. This solution adds a new axis to the array; in the first argument, it looks like a column vector and has two axes; in the second argument it still looks like a row vector but has two axes.

Looks like what you need is the # matrix multiplication operator. dot method is only to compute dot product between vectors, what you want is matrix multiplication.
>>> a = np.random.rand(70, 1)
>>> (a # a.T).shape
(70, 70)
UPDATE:
Above answer is incorrect. dot does the same things if the array is 2D. See the docs here.
np.dot computes the dot product of two arrays. Specifically,
If both a and b are 1-D arrays, it is inner product of vectors (without complex conjugation).
If both a and b are 2-D arrays, it is matrix multiplication, but using matmul or a # b is preferred.
Simplest way to do what you want is to convert the vector to a matrix first using np.matrix and then using the #. Although, dot can also be used # is better because conventionally dot is used for vectors and # for matrices.
>>> a = np.random.rand(70)
(70,)
>>> a.shape
>>> a = np.matrix(a).T
>>> a.shape
(70, 1)
>>> (a # a.T).shape
(70, 70)

Related

Dimensions when subtracting numpy.ndarray() that are column vector (dimension [m,1])

I am subtracting 2 numpy.ndarrays h and y with shape of (47,1) and (47,) respectively. When I use python to subtract both of the next functions return an array of shape (47,47). I know that mathematically this operation should keep the dimensions of the input arrays, but its not working that way.
The operations I used are:
e = h - y
e = np.subtract(h,y)
Is that something about how numpy does the operations, or should I be using other types of operations for this? How do I fix it so that the dimensions of the resulting array match with the correct ones mathematically?
The shape of h and y should be identical for elementwise subtraction as you mentioned.
The both methods you describe are identical.
The following code works
import numpy as np
a = np.array([1,2,3,4,5,6,7])
b = np.array([[1,2,3,4,5,6,7]])
print(a.shape) # (7,)
print(b.shape) # (1,7)
c = a-b # or np.subtract(a,b)
print(c.shape) # (1,7)
print(c) # [[0,0,0,0,0,0,0]]
Maybe one of ndarrays is transposed. The shape of a-b.T is (7,7) as you described.
Edit
I forgot the fact that you described a column vector.
In this case the following would do the trick for elementwise subtraction:
h.T-y

np.transpose doesn't return transpose of matrix

When I write my code in the following manner :
from numpy import *
H = array([1,1])
Ht = transpose(H)
Ht
I get the same matrix as H instead of the transpose of H.
But when I change the matrix H in the following way :
from numpy import *
H = array(([1,1],[2,3]))
Ht = transpose(H)
Ht
I get the transpose of H.
I fail to understand what is happening here. Is it the way transpose function is used or is it the way a matrix is defined?
From the documentation:
numpy.matrix.transpose. Returns a view of the array with axes transposed. For a 1-D array, this has no effect. (To change between column and row vectors, first cast the 1-D array into a matrix object.)
I think this is the behavior you're looking for:
>>> H = np.array([[1,1]])
>>> H.T
array([[1],
[1]])
Equivalently you can write np.transpose(H). Notice this array has shape (1,2), so it has two dimensions. The array H = np.array([1,2]) has shape (2,). It only has one dimension. To swap the dimensions (transpose), you need at least two of them.

Calculating dot product of two numpy row arrays (vectors) in Python gives a shape vector

I'm trying to understand how numpy works when you try to call the dot product of two row vectors.
I have this code:
X = np.array([[1,2,3]])
THETA = np.array([[1,2,3]])
print X.dot(THETA)
This gives me the error:
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
I thought that you could take the dot product of two row vectors however to get:
x1*theta1 + x2*theta2 + x3*theta3
And this would also transfer to the dot product of two column vectors.
The weird part is, I have to take the transpose of the second matrix in order to actually use the dot product:
print X.dot(THETA.T)
array([[14]])
However, I didn't think this would actually work, and why it would work instead of just doing a row dot row operation. Can anyone help me understand what's going on? Is it some rule in linear algebra that I forgot from long ago?
dot for 2D input is matrix multiplication, not a dot product. What you're seeing is just the result of the normal rules of matrix multiplication. If you want a vector dot product, the easiest way is to use 1D vectors, with no superfluous second dimension:
X = np.array([1, 2, 3])
THETA = np.array([1, 2, 3])
print X.dot(THETA)
dot-ting two 1D arrays takes a dot product and produces a scalar result.
If you want to use row and column vectors, then by the standard rules of matrix multiplication, you need to multiply a 1-by-N array (a row vector) by an N-by-1 array (a column vector) to get a 1-by-1 result, and NumPy will give you a 1-by-1 array rather than a scalar.
The alignment error you're seeing is because you're trying to represent a 1D vector as a 2D array.
In [1]: import numpy as np
In [2]: X = np.array([1,2,3])
In [3]: THETA = np.array([1,2,3])
In [4]: print X.dot(THETA)
14
In [5]: print X.dot(THETA.T)
14
And:
x1*theta1 + x2*theta2 + x3*theta3 =
1*1 + 2*2 + 3*3 =
14

Pairwise product between array of vectors and array of matrices

I have a 2D array A which I am representing here as [v_1, v_2, v_3, ..., v_n].
I have a 3-d tensor B which I am representing here as [m_1, m_2, m_3, ...n m_n].
A.type = numpy.ndarray
A.shape = (300, 4)
B.type = numpy.ndarray
B.shape = (300, 4, 2)
I want to get the 1D array C = A*B such that C = [u_1, u_2, u_3, ..., u_n] where u_i = np.dot(v_i, m_i)
How can I do this without iterating over 1 to n and using numpy.tensordot() over A and B?
You can use the np.einsum function to do that. that will let you give a letter (index) to each dimension of the arrays you supply as a string and use the einstein sum notation to process. so in you case I'd say something like:
np.einsum( "ik,ikl->il", A,B )
so in this case i'd name the dimensions of A i,k --> 300,4 and the dimensions of B have to be i,k and something else e.g. l --> 300,4,2 an then with the arrow you specify which dimensions you want to get out. If you don't supply a letter (index) in the notation after the arrow this dimension will be summed over. so had you done "ik,ikl->l" it would have summed over the 300 dimension.

numpy broadcast from first dimension

In NumPy, is there an easy way to broadcast two arrays of dimensions e.g. (x,y) and (x,y,z)? NumPy broadcasting typically matches dimensions from the last dimension, so usual broadcasting will not work (it would require the first array to have dimension (y,z)).
Background: I'm working with images, some of which are RGB (shape (h,w,3)) and some of which are grayscale (shape (h,w)). I generate alpha masks of shape (h,w), and I want to apply the mask to the image via mask * im. This doesn't work because of the above-mentioned problem, so I end up having to do e.g.
mask = mask.reshape(mask.shape + (1,) * (len(im.shape) - len(mask.shape)))
which is ugly. Other parts of the code do operations with vectors and matrices, which also run into the same issue: it fails trying to execute m + v where m has shape (x,y) and v has shape (x,). It's possible to use e.g. atleast_3d, but then I have to remember how many dimensions I actually wanted.
how about use transpose:
(a.T + c.T).T
numpy functions often have blocks of code that check dimensions, reshape arrays into compatible shapes, all before getting down to the core business of adding or multiplying. They may reshape the output to match the inputs. So there is nothing wrong with rolling your own that do similar manipulations.
Don't offhand dismiss the idea of rotating the variable 3 dimension to the start of the dimensions. Doing so takes advantage of the fact that numpy automatically adds dimensions at the start.
For element by element multiplication, einsum is quite powerful.
np.einsum('ij...,ij...->ij...',im,mask)
will handle cases where im and mask are any mix of 2 or 3 dimensions (assuming the 1st 2 are always compatible. Unfortunately this does not generalize to addition or other operations.
A while back I simulated einsum with a pure Python version. For that I used np.lib.stride_tricks.as_strided and np.nditer. Look into those functions if you want more power in mixing and matching dimensions.
as another angle: if you encounter this pattern frequently, it may be useful to create a utility function to enforce right-broadcasting:
def right_broadcasting(arr, target):
return arr.reshape(arr.shape + (1,) * (target.ndim - arr.ndim))
Although if there are only two types of input (already having 3 dims or having only 2), id say the single if statement is preferable.
Indexing with np.newaxis creates a new axis in that place. Ie
xyz = #some 3d array
xy = #some 2d array
xyz_sum = xyz + xy[:,:,np.newaxis]
or
xyz_sum = xyz + xy[:,:,None]
Indexing in this way creates an axis with shape 1 and stride 0 in this location.
Why not just decorate-process-undecorate:
def flipflop(func):
def wrapper(a, mask):
if len(a.shape) == 3:
mask = mask[..., None]
b = func(a, mask)
return np.squeeze(b)
return wrapper
#flipflop
def f(x, mask):
return x * mask
Then
>>> N = 12
>>> gs = np.random.random((N, N))
>>> rgb = np.random.random((N, N, 3))
>>>
>>> mask = np.ones((N, N))
>>>
>>> f(gs, mask).shape
(12, 12)
>>> f(rgb, mask).shape
(12, 12, 3)
Easy, you just add a singleton dimension at the end of the smaller array. For example, if xyz_array has shape (x,y,z) and xy_array has shape (x,y), you can do
xyz_array + np.expand_dims(xy_array, xy_array.ndim)

Categories

Resources