I know in numpy if you have a matrix A and I subtract a vector v by performing A - v, v will be broadcasted so that v becomes the same dimension as A and an elementwise subtraction will be performed.
I was wondering if I had to perform the above operation many times with the same A but with different v, would I be able to do it using vectorization.
A naive implementation would be as follow
def foo(A, V):
"""
@params: A, V
A - an n by m matrix
V - a list of n by 1 column vectors
@returns: result
"""
result = []
for v in V:
result.append(A-v)
return result
I know that I could pass in V as a n by p matrix where each column represents a v. However, I couldn't think of any way of describing the above operation in terms of linear algebra
For example if
A = [[1 2 3],
[1 2 3]]
V = [[1 4],
[1 4]]
the output should be two matrices
[
[[0 1 2],
[0,1,2]],
[[-3 -2 -1],
[-3 -2, -1]]
]
a = np.zeros((4,3)) + [1,2,3]
V = [np.ones(3),np.ones(3)*2,np.ones(3)*3]
Your desired is
>>> a-V[0]
array([[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.]])
>>> a-V[1]
array([[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.]])
>>> a-V[2]
array([[-2., -1., 0.],
[-2., -1., 0.],
[-2., -1., 0.],
[-2., -1., 0.]])
Stack the vectors in V then add a dimension to subtract.
>>> W = np.vstack(V)
>>> a - W[:,None,:]
array([[[ 0., 1., 2.],
[ 0., 1., 2.],
[ 0., 1., 2.],
[ 0., 1., 2.]],
[[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.]],
[[-2., -1., 0.],
[-2., -1., 0.],
[-2., -1., 0.],
[-2., -1., 0.]]])
Try it again adjusting for (n,m) is (4,3)
a = np.zeros((4,3)) + [1,2,3] # (n.m) = (4,3)
V = [np.ones(4),np.ones(4)*2,np.ones(4)*3] # three (nx1) vectors
W = np.vstack(V)
>>> a.shape
(4, 3)
>>> W.shape
(3, 4)
>>> Z = a - W[...,None]
>>> Z[0]
array([[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.]])
>>> Z[1]
array([[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.]])
>>> Z[2]
array([[-2., -1., 0.],
[-2., -1., 0.],
[-2., -1., 0.],
[-2., -1., 0.]])
>>> Z.shape
(3, 4, 3)
In [104]: A = [[1, 2, 3],
...: [1, 2, 3]]
...:
...: V = [[1, 4],
...: [1, 4]]
In [105]: A=np.array(A);V=np.array(V)
In [106]: A # (n,m)
Out[106]:
array([[1, 2, 3],
[1, 2, 3]])
In [107]: V # (n,p)
Out[107]:
array([[1, 4],
[1, 4]])
The iterative subtraction; [0] used to make the array (2,1) (which broadcasts with (2,3) A:
In [108]: [A-V[:,[0]], A-V[:,[1]]]
Out[108]:
[array([[0, 1, 2],
[0, 1, 2]]),
array([[-3, -2, -1],
[-3, -2, -1]])]
Lets try whole array broadcasting:
In [109]: A[None,:,:]-V[:,:,None]
Out[109]:
array([[[ 0, 1, 2],
[-3, -2, -1]],
[[ 0, 1, 2],
[-3, -2, -1]]])
Oops, wrong mix; try again, changing V to (p,n). That would have been clearer is V wasn't (2,2):
In [110]: A[None,:,:]-V.T[:,:,None]
Out[110]:
array([[[ 0, 1, 2],
[ 0, 1, 2]],
[[-3, -2, -1],
[-3, -2, -1]]])
With (2,4) V:
In [112]: V1=np.hstack((V,V))
In [113]: V1.shape
Out[113]: (2, 4)
In [114]: (A[None,:,:]-V1.T[:,:,None]).shape
Out[114]: (4, 2, 3)
In [115]: (A-V1.T[:,:,None]).shape
Out[115]: (4, 2, 3)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With