Alex Lenail
Alex Lenail

Reputation: 14440

Bilinear Tensor Product in TensorFlow

I'm working on re-implementing this paper and the key operation is a bilinear tensor product. I hardly know what that means, but the paper has a nice little graphic, which I understand.

enter image description here

The key operation is e_1 * W * e_2, and I want to know how to implement it in tensorflow, because the rest should be easy.

Basically, given 3D tensor W, slice it into matrices, and for the j'th slice (a matrix), multiply it on each side by e_1 and e_2, resulting in a scalar, which is the jth entry in the resulting vector (the output of this operation).

So I want to perform a product of e_1, a d-dimensional vector, W, the d x d x k tensor, and e_2, another d-dimensional vector. Could this product be expressed concisely in TensorFlow as it is now, or would I have to define my own op somehow?

EARLIER EDITS

Why doesn't multiplying these tensors work, and is there some way to define it more explicitly so that it works?

>>> import tensorflow as tf
>>> tf.InteractiveSession()
>>> a = tf.ones([3, 3, 3])
>>> a.eval()
array([[[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.]],

       [[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.]],

       [[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.]]], dtype=float32)
>>> b = tf.ones([3, 1, 1])
>>> b.eval()
array([[[ 1.]],

       [[ 1.]],

       [[ 1.]]], dtype=float32)
>>> 

The error message is

ValueError: Shapes TensorShape([Dimension(3), Dimension(3), Dimension(3)]) and TensorShape([Dimension(None), Dimension(None)]) must have the same rank

CURRENTLY

Turns out that multiplying two 3D tensors doesn't work either with tf.matmul, so but tf.batch_matmul does. tf.batch_matmul will also do 3D tensors and matrices. Then I tried 3D and a vector:

ValueError: Dimensions Dimension(3) and Dimension(1) are not compatible

Upvotes: 16

Views: 6378

Answers (2)

crow
crow

Reputation: 305

You can perform a rank 3 tensor and a vector multiplication between W and e2 which yields a 2D array and then multiply the result with e1. The following function makes use of tensor product and tensor contraction to define the this product (e.g. W * e3)

import sympy as sp

def tensor3_vector_product(T, v):
    """Implements a product of a rank 3 tensor (3D array) with a 
       vector using tensor product and tensor contraction.

    Parameters
    ----------
    T: sp.Array of dimensions n x m x k

    v: sp.Array of dimensions k x 1

    Returns
    -------
    A: sp.Array of dimensions n x m

    """
    assert(T.rank() == 3)
    # reshape v to ensure a 1D vector so that contraction do 
    # not contain x 1 dimension
    v.reshape(v.shape[0], )
    p = sp.tensorproduct(T, v)
    return sp.tensorcontraction(p, (2, 3))

You can verify this multiplication by using the examples provided in ref. The above function contracts the second and third axis, in your case I think you should contract (1, 2) because W is defined as d x d x k and not k x d x d as in my case.

Upvotes: 0

mdaoust
mdaoust

Reputation: 6367

You can do this with a simple reshape. For the first of the two matrix multiplies, you have k*d, length d vectors to dot product with.

This should be close:

temp = tf.matmul(E1,tf.reshape(Wddk,[d,d*k]))
result = tf.matmul(E2,tf.reshape(temp,[d,k]))

Upvotes: 12

Related Questions