CentAu
CentAu

Reputation: 11160

Tensorflow, how to multiply a 2D tensor (matrix) by corresponding elements in a 1D vector

I have a 2D matrix M of shape [batch x dim], I have a vector V of shape [batch]. How can I multiply each of the columns in the matrix by the corresponding element in the V? That is:

enter image description here

I know an inefficient numpy implementation would look like this:

import numpy as np
M = np.random.uniform(size=(4, 10))
V = np.random.randint(4)
def tst(M, V):
  rows = []
  for i in range(len(M)):
    col = []
    for j in range(len(M[i])):
      col.append(M[i][j] * V[i])
    rows.append(col)
  return np.array(rows)

In tensorflow, given two tensors, what is the most efficient way to achieve this?

import tensorflow as tf
sess = tf.InteractiveSession()
M = tf.constant(np.random.normal(size=(4,10)), dtype=tf.float32)
V = tf.constant([1,2,3,4], dtype=tf.float32)

Upvotes: 2

Views: 8181

Answers (2)

Divakar
Divakar

Reputation: 221554

In NumPy, we would need to make V 2D and then let broadcasting do the element-wise multiplication (i.e. Hadamard product). I am guessing, it should be the same on tensorflow. So, for expanding dims on tensorflow, we can use tf.newaxis (on newer versions) or tf.expand_dims or a reshape with tf.reshape -

tf.multiply(M, V[:,tf.newaxis])
tf.multiply(M, tf.expand_dims(V,1))
tf.multiply(M, tf.reshape(V, (-1, 1)))

Upvotes: 7

kmario23
kmario23

Reputation: 61345

In addition to @Divakar's answer, I would like to make a note that the order of M and V don't matter. It seems that tf.multiply also does broadcasting during multiplication.

Example:

In [55]: M.eval()
Out[55]: 
array([[1, 2, 3, 4],
       [2, 3, 4, 5],
       [3, 4, 5, 6]], dtype=int32)

In [56]: V.eval()
Out[56]: array([10, 20, 30], dtype=int32)

In [57]: tf.multiply(M, V[:,tf.newaxis]).eval()
Out[57]: 
array([[ 10,  20,  30,  40],
       [ 40,  60,  80, 100],
       [ 90, 120, 150, 180]], dtype=int32)

In [58]: tf.multiply(V[:, tf.newaxis], M).eval()
Out[58]: 
array([[ 10,  20,  30,  40],
       [ 40,  60,  80, 100],
       [ 90, 120, 150, 180]], dtype=int32)

Upvotes: 4

Related Questions