Keras: how to reshape last channel into squares - python

I have an input layer of size 32x32. Then I apply a 2d convolution with stride (4,4) and with 16 filters each having kernel size 4x4. Hence, the resulting shape will be 8 x 8 x 16. Now I want to reshape the result back to the input shape so that the channel dimension will turn back into 4x4 squares in the corresponding places, i.e. if we define the result of the convolution as T and the desired result as D, then I want D[i * 4 + k, j * 4 + l] = T [i , j , k * 8 + l], with i,j = 0,..,7 and k,l = 0,..,3. Is there a way to do this?
import numpy as np
from keras.layers import Input, Conv2D
from keras.initializers import Constant
input = Input(( 32, 32), dtype = 'float32')
filters = np.ndarray((4, 4, 16), dtype=np.float32)
# Initialization of the filter
filter_layer = Conv2D(16, 4, strides =(4,4), kernel_initialzer=Constant(filters), trainable = False)(input)
# no idea how to reshape the filter back

Related

Initializing Keras Convolution Kernel as a numpy array

I would like to initialize the weights for a (5,5) convolutional layer with four channels to be a numpy array. The input to this layer is of shape (128,128,1). In particular, I would like the following:
def custom_weights(shape, dtype=None):
matrix = np.zeros((1,5,5,4))
matrix[0,2,2,0,0] = 1
matrix[0,2,1,0,0] = -1
matrix[0,2,2,0,1] = 1
matrix[0,3,2,0,1] = -1
matrix[0,2,2,0,2] = 2
matrix[0,2,1,0,2] = -1
matrix[0,2,3,0,2] = -1
matrix[0,2,2,0,3] = 2
matrix[0,1,2,0,3] = -1
matrix[0,3,2,0,3] = -1
weights = K.variable(matrix)
return weights
input_shape = (128, 128, 1)
images = Input(input_shape, name='phi_input')
conv1 = Conv2D(4,[5, 5], use_bias = False, kernel_initializer=custom_weights, padding='valid', name='Conv2D_1', strides=1)(images)
However, when I try to do this, I get an error of
Depth of input (1) is not a multiple of input depth of filter (5) for 'Conv2D_1_19/convolution' (op: 'Conv2D') with input shapes: [?,128,128,1], [1,5,5,4].
Is my error in the shape of the weight matrix?
There are many inconsistencies (which led to errors) in your code, the error you're getting is not from the given code as it doesn't even index the matrix properly.
matrix = np.zeros((1,5,5,4))
matrix[0,2,2,0,0] = 1
You are initializing a numpy array with 4 dimensions but using 5 indices to change value.
Your dimensions for kernel weights are wrong. Here's the fixed code.
from tensorflow.keras.layers import *
from tensorflow.keras import backend as K
import numpy as np
def custom_weights(shape, dtype=None):
kernel = np.zeros((5,5,1,4))
# change value here
kernel = K.variable(kernel)
return kernel
input_shape = (128, 128, 1)
images = Input(input_shape, name='phi_input')
conv1 = Conv2D(4,[5, 5], use_bias = False, kernel_initializer=custom_weights, padding='valid', name='Conv2D_1', strides=1)(images)

Embedding lookup from a specific axis

I have two tensors.
v, shape=(50, 64, 128), dtype=float32
m, shape=(64, 50, 1), dtype=int32
Values in m are integers between 0 and 50 (<=49)
I want to use values of m, to get a specific tensor of v for the same index out of 64.
Resulting tensor is r: shape=(64, 50, 128), dtype=float32
For example values for r(i, j, 0-128) = v(m(i, j), i, 0-128)
The closest thing I see is tf.nn.embedding_lookup but I'm not sure how to use it for this use case
You can use the following tf.nn.embedding_lookup or tf.gather_nd methods to achieve your goals.
import tensorflow as tf
import numpy as np
m_np = np.random.randint(0,50,(64, 50, 1))
m = tf.constant(m_np)
n = tf.random.normal((50, 64, 128))
# Method 1
tmp = tf.nn.embedding_lookup(n,m[:,:,0]) # shape=(64,50,64,128)
tmp = tf.transpose(tmp,[1,3,0,2]) # shape=(50,128,64,64)
result1 = tf.transpose(tf.matrix_diag_part(tmp),[2,0,1]) # shape=(64,50,128)
# Method 2
indices = tf.tile(tf.reshape(tf.range(64),(-1,1,1)),(1,50,1)) # shape=(64,50,1)
indices = tf.concat([m,indices],axis=-1) # shape=(64,50,2)
result2 = tf.gather_nd(n,indices) # shape=(64,50,128)
with tf.Session() as sess:
# Randomly select a location for test
n_value,result_value = sess.run([n,result1])
print((n_value[m_np[5,4],5,:]==result_value[5,4]).all())
# True

TensorFlow: weighted sum of high dimension tensors?

Suppose I got a 3 dimension tensor input with shape(batch_size, dim_a, dim_b).
If I have a weight vector with shape (batch_size, dim_a), and want to get weighted sum of input, weighted_sum of shape (batch_size, dim_b). What should I do?
You could reshape your weight vector and make use of tf.reduce_sum:
import numpy as np
import tensorflow as tf
a = np.random.rand(5, 3, 2)
b = np.random.rand(5, 3)
input = tf.constant(a)
weight = tf.constant(b)
C = input * weight.reshape((5, 3, 1)) # Reshape and multiply weights and input
weighted_sum = tf.reduce_sum(C, axis=1) # Sum along dim_a
weighted_sum.shape
Out[9]: TensorShape([Dimension(5), Dimension(2)])

merge multiple keras max pooling layers

I am new to keras.
My goal is to have total of 4 max pooling layers. All of them take same input with shape (N, 256). The first layer does global max pooling and give 1 output. The second layer with N / 2 pooling size and N / 2 stride, gives 2 outputs. The third gives 4 outputs and the fourth gives 8 outputs. Here is my code.
test_x = np.random.rand(N, 256, 1)
model = Sequential()
input1 = Input(shape=test_x.shape, name='input1')
input2 = Input(shape=test_x.shape, name='input2')
input3 = Input(shape=test_x.shape, name='input3')
input4 = Input(shape=test_x.shape, name='input4')
max1 = MaxPooling2D(pool_size=(N, 256), strides=N)(input1)
max2 = MaxPooling2D(pool_size=(N / 2, 256), strides=N / 2)(input2)
max3 = MaxPooling2D(pool_size=(N / 4, 256), strides=N / 4)(input3)
max4 = MaxPooling2D(pool_size=(N / 8, 256), strides=N / 8)(input4)
mrg = Merge(mode='concat')([max1, max2, max3, max4])
After creating 4 max pooling layers, I try to merge them together, but keras gives this error.
ValueError: Dimension 1 in both shapes must be equal, but are 4 and 8 for 'merge_1/concat' (op: 'ConcatV2') with input shapes: [?,1,1,1], [?,2,1,1], [?,4,1,1], [?,8,1,1], [] and with computed input tensors: input[4] = <3>.
How can I solve this issue? Is merging the correct way to achieve my goal in keras?
For concatenation, all dimensions must have the same number of elements, except for the concat dimension itself.
As you can see, your results have shape:
(?, 1, 1, 1)
(?, 2, 1, 1)
(?, 4, 1, 1)
(?, 8, 1, 1)
Naturally, the only possible way to concatenate them is in the second axis (axis=1)
mrg = Concatenate(axis=1)([max1,max2,max3,max4])
But notice that (unless you have specific reasons for that and know exaclty what you're doing) this will result in a very weird image, since you're concatenating in a spatial dimension, not in a channel dimension.

How to multiply weighted value to matrix in keras?

I have two vectors, weighted: shape (None, 3) and D: shape (None, 3, 5). Then I want to multiply weighted to D like weighted * D: shape(None, 3, 5).
I attached my image below. So each scalar value is multiplied to each row element.
So I tried multiply([weighted, D]), but I got an error ValueError: Operands could not be broadcast together with shapes (3, 5) (3,). I assume this is caused of different shape of inputs. Then, how do I fix this?
Update
multiply([weighted, Permute((2, 1))(D)]) worked. I am not sure but last element of shape must be same..
You can reshape weighted and use broadcasting to accomplish that. Like this:
weighted = weighted.reshape(-1, 3, 1)
result = weighted * D
Update 1: The same concept (broadcasting) can be used for instance in tensorflow with tf.expand_dims(weights, dim=2). My POC:
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
anp = np.array([[1, 2, 10], [2, 1, 10]])
bnp = np.random.random((2, 3, 5))
with tf.Session() as sess:
weighted = tf.placeholder(tf.float32, shape=(None, 3))
D = tf.placeholder(tf.float32, shape=(None, 3, 5))
rweighted = tf.expand_dims(weighted, dim=2)
result = rweighted * D
r = sess.run(result, feed_dict={weighted: anp, D: bnp})
print(bnp)
print("--")
print(r)
For keras use the backend API:
from keras import backend as K
...
K.expand_dims(weighted, 2)

Categories