Search code examples
machine-learningdeep-learningkeraskeras-layerkeras-2

Weighing a Tensor in Keras


I have a really simple issue that seems to have no built-in solution in Keras.

Here' my problem:

I have a (50,) dimensional tensor (layer 1's output) which is supposed to be multiplied to a (50, 49) dimensional tensor.

These tensors are the output of some layers.

I thought simple multiply([layer1, layer2]) would work, but it turns out they need the tensors to be of the same shape.

I am trying to get this: each element of the (50,) layer should be multiplied to each 49 dimensional vector in the (50, 49) layer giving the output as a (50, 49) tensor.

Any ways this could be done in Keras?


Solution

  • New answer, considering layer2 as (50,49)

    Here, you want a scalar multiplication for each line in layer2. Then we're going to consider the "50" as part of the batch, and actually make multiplications of shapes (1,1) with shapes (49,1). And to keep the 50 separate in the batch_dot, we will reshape things inside the lambda function using -1 as a wildcard:

    out = Lambda(myMultiplication, output_shape=(50,49))([layer1,layer2])
    

    Where

    import keras.backend as K
    
    def myMultiplication(x):
        
        #inside lambda functions, there is an aditional axis, the batch axis. Normally, we use -1 for this dimension. We can take advantage of it and simply hide the unwanted 50 inside this -1. 
    
        L1 = K.reshape(x[0], (-1,1,1))
        L2 = K.reshape(x[1], (-1,49,1))
    
        result = K.batch_dot(L1,L2, axes=[1,2])
    
        #here, we bring the 50 out again, keeping the batch dimension as it was originally   
        return K.reshape(result,(-1,50,49))
    

    Old answer, when I supposed layer2 was (49,) instead of (50,49)

    You need a lambda layer (for custom functions) with a batch_dot.

    Batch dot is an actual matrix multiplication, while multiply is elementwise multiplication. For that, you should reshape your vectors to matrices, being one of them transposed in order to achieve the multiplication you want.

    So:

    layer1 = Reshape((1,50))(layer1)
    layer2 = Reshape((49,1))(layer2)
    out = Lambda(myMultiplication, output_shape=(50,49))([layer1,layer2])
    

    Where

    import keras.backend as K
    
    def myMultiplication(x):
        return K.batch_dot(x[0],x[1],axes=[1,2])