Cannot manually assign new parameters via layer name - pytorch

I'm trying to manually assign new weights to my pytorch model. I can assign new weights like this:
import scipy.io as sio
import torch
caffe_params = sio.loadmat('export_conv1_1.mat')
net.conv1_1.weight = torch.nn.Parameter(torch.from_numpy(caffe_params['w']))
net.conv1_1.bias = torch.nn.Parameter(torch.from_numpy(caffe_params['b']))
caffe_params = sio.loadmat('export_conv2_1.mat')
net.conv2_1.weight = torch.nn.Parameter(torch.from_numpy(caffe_params['w']))
net.conv2_1.bias = torch.nn.Parameter(torch.from_numpy(caffe_params['b']))
Since I have a lot of layers I don't want to manually assign every layer via it's name. Instead I want rather to loop over a list of layer names and assign them automatically. Something like this:
varList = ['conv2_1','conv2_2']
for name in varList:
caffe_params = sio.loadmat(rootDir + 'export_' + name + '.mat')
setattr(net, name + '.weight' ,torch.nn.Parameter(torch.from_numpy(caffe_params['w'])))
setattr(net, name + '.bias' ,torch.nn.Parameter(torch.from_numpy(caffe_params['b'])))
Unfortunately this doesn't work. I guess setattr doesn't work with either pytorch weigths or with attributes of type layername.weight, which means the attribute to assign has depth 2 with respect to net.

Does the following work?
for name in varList:
caffe_params = sio.loadmat(rootDir + 'export_' + name + '.mat')
getattr(net, name).weight.data.copy_(torch.from_numpy(caffe_params['w']))
getattr(net, name).bias.data.copy_(torch.from_numpy(caffe_params['b']))

Related

How to set a default tensor as a Keras model input?

I have a Keras model with multiple images as inputs, but after trained, I'd like to set some images as default input and let just a single placeholder/input as the Query image.
I tried to use layers.Input(tensor=my_default_tensor) but it doesn't seems to be what I need, the model still seems to need this input to be given during inference time. I'd like it to be hidden from the user, so he just needs to pass the query image as input.
Have you tried tf.keras.layers.Input(tensor=tftensor, shape=())?
I discovered that it is so easy that's why I couldn't find an answer while googling hahaha
It just needed to wrap my "default input images" as a tf.constant(input_image), so I could now use them as normal Keras inputs, but without the need to pass it as a Model input.
Usage example:
from tensorflow.keras import layers
from tensorflow.keras import Model
image_1 = cv2.imread("image/path/1.jpg")
image_2 = cv2.imread("image/path/2.jpg")
normal_input = layers.Input((256, 256, 3))
default_input_1 = tf.constant(image_1)
default_input_2 = tf.constant(image_2)
x_1 = embeddingModule(default_input_1)
x_2 = embeddingModule(default_input_2)
x_3 = embeddingModule(normal_input)
concat_x1_x3 = layers.Concatenate()([x_1, x_3])
concat_x2_x3 = layers.Concatenate()([x_2, x_3])
relation_1 = relationModule(concat_x1_x3)
relation_2 = relationModule(concat_x2_x3)
model = Model(inputs=[normal_input], outputs=[relation_1, relation_2])
Here, embeddingModule and relationModule are two pre-trained Keras models.

custom loss function in Keras combining multiple outputs

I did a lot of searching and am still unable to figure out writing a custom loss function with multiple outputs where they interact.
I have a Neural Network defined as :
def NeuralNetwork():
inLayer = Input((2,));
layers = [Dense(numNeuronsPerLayer,activation = 'relu')(inLayer)];
for i in range(10):
hiddenLyr = Dense(5,activation = 'tanh',name = "layer"+ str(i+1))(layers[i]);
layers.append(hiddenLyr);
out_u = Dense(1,activation = 'linear',name = "out_u")(layers[i]);
out_k = Dense(1,activation = 'linear',name = "out_k")(layers[i]);
outLayer = Concatenate(axis=-1)([out_u,out_k]);
model = Model(inputs = [inLayer], outputs = outLayer);
return model
I am now trying to define a custom loss function as follows :
def computeLoss(true,prediction):
u_pred = prediction[:,0];
k_pred = prediction[:,1];
loss = f(u_pred)*k_pred;
return loss;
Where f(u_pred) is some manipulation of u_pred. The code seems to work correct and produce correct results when I use only u_pred (i.e., single output from the neural network only). However, the moment I try to include another output for k_pred and perform the slice of my prediction tensor in the loss function, I start getting wrong results. I feel I am doing something wrong in handling multiple outputs in Keras but am not sure where my mistake lies. Any help on how I may proceed is welcome.
I figured out that you can't just use indexing ( i.e., [:,0] or [:,1] ) to slice tensors in tf. The operation doesn't seem to work. Instead, use the built in function in tensorflow as
detailed in https://www.tensorflow.org/api_docs/python/tf/split?version=stable
So the code that worked was:
(u_pred, k_pred) = tf.split(prediction, num_or_size_splits=2, axis=1)

loop through a list with a function and store as variable

I have a list of variables I need to run though a function to produce a json table. I want to loop through this list (list_db) and create a new variable to look through them manually in spyder. I am having trouble creating those new variables from the for loop. I thought i could use the name of the items in list as the new variable name, but i cant get it to work. Here is what I have:
for i in list_db:
p = str(i)
p = getDF(i) #function to run
What am I missing? What is the more standard way of doing this i cant think of?
It seems variable names don't really act how you are expecting. When you do p = str(i), you are assigning to the variable p. And then your next line, p = getDF(i) overwrites the value of p. It does not write to a variable whose name is str(i) like you are expecting.
If you want to store values into named slots, you can use a dictionary:
p = {}
for i in list_db:
p[i] = getDF(i)

How to make the enabling of a given layer, in a keras model, trainable?

I have the following siamese model:
I would like to make the enabling/disabling of layers a-L1 and b-L1 trainable. ie: a-L1 and/or b-L1 should be transparent (not used or disabled) for the current input if necessary. So, the model after training, will learn when it should enable/disable one or both of the layers a-L1 and b-L1.
I managed to train this model with 4 cases, so I got 4 different models accordingly:
model-1: without a-L1 and b-L1
model-2: without a-L1
model-3: without b-L1
model-4: with both a-L1 and b-L1
the performances of these models complement each other and I would like to combine them. Do you have some suggestions, please?
Let's consider you have trained four models and them let's call them m1, m2, m3 and m4
first define the input layer which is common for all of them.
inputs = Input(shape=your_inputs_shape)
model_1_output = m1(inputs)
model_2_output = m2(inputs)
model_3_output = m3(inputs)
model_4_output = m4(inputs)
merged_layer = Concatenate(axis=your_concatanation_axis)([model_1_output, model_2_output, model_3_output,model_4_output)
new_model = Model(inputs=inputs, outputs=merged_layer)
I hope this will solve your problem.
EDIT:
To answer your question on comment, It is possible to combine only the layers before L2. But you have to decide which model's layers starting from L2, you are going to use(Since you are not combining layers starting from L2). Let's assume you want to use m1 model's layers after L2. In addition I want to add the weighting mechanism I've specified above in comments of the answer.
First let's define new models with common new inputs
new_inputs = Input(shape=(inputs_shape))
new_m1 = keras.models.Model(inputs = new_inputs, outputs = m1(new_inputs))
new_m2 = keras.models.Model(inputs = new_inputs, outputs = m2(new_inputs))
new_m3 = keras.models.Model(inputs = new_inputs, outputs = m3(new_inputs))
new_m4 = keras.models.Model(inputs = new_inputs, outputs = m4(new_inputs))
Now get the L2 layer for all models
model1_l2 = new_m1.layers[1].get_layer("L2").output
model2_l2 = new_m2.layers[1].get_layer("L2").output
model3_l2 = new_m3.layers[1].get_layer("L2").output
model4_l2 = new_m4.layers[1].get_layer("L2").output
weighted merge
merged = Concatenate(axis=your_concatanation_axis)([model1_l2, model2_l2, model3_l2,model4_l2])
merged_layer_shape = merged.get_shape().as_list()
# specify number of channels you want the output to have after merging
desired_output_channels = 32
new_trainable_weights = keras.backend.random_normal_variable(shape=(merged_layer_shape[-1], desired_output_channels),mean=0,scale=1)
weighted_output = keras.backend.dot(merged,new_trainable_weights)
now connect the layer of model1(m1) next to L2 with this new weighted_output
# I'm using some protected properties of layer. But it is not recommended way to do it.
# get the index of l2 layer in new_m1
for i in range(len(new_m1.layers[1].layers)):
if new_m1.layers[1].layers[i].name=="L2":
index = i
x = weighted_output
for i in range(index+1, len(new_m1.layers[1].layers)):
x = new_m1.layers[1].layers[i](x)
new_model = keras.models.Model(inputs=new_inputs, outputs=x)

Calling seperate theano functions with same inputs?

I have something like this:
x=T.matrix('x')
params = [self.W, self.b1, self.b2]
hidden = self.activation_function(T.dot(x, self.W)+self.b1)
output = T.dot(hidden,T.transpose(self.W))+self.b2
output = self.output_function(output)
L = -T.sum(x*T.log(output) + (1-x)*T.log(1-output), axis=1)
cost=L.mean()
th_train = th.function(inputs=[index], outputs=[cost], updates=updates,
givens={x:self.X[index:index+mini_batch_size,:]})
This is working fine. I would now like to see what the mean of the hidden units is. I tried adding this before the line where L = -T.sum... is declared:
hm = T.mean(hidden)
hidden_mean_func = th.function(inputs=[hm], outputs=[hm], name="hidden_mean_function_printer")
print hidden_mean_func(hm)
I get the following error:
TypeError: ('Bad input argument to theano function with name "hidden_mean_function_printer" at index 0(0-based)', 'Expected an array-like object, but found a Variable: maybe you are trying to call a function on a (possibly shared) variable instead of a numeric array?')
I really have two questions: 1) Why can't I do this? 2) What is the correct way to achieve what I want?
Thank you
As far as I can see, you are giving him the function as input. If you use your array/matrix of hidden units instead the code should work.
hidden_mean_func = th.function(inputs=[hidden], outputs=[hm], name="hidden_mean_function_printer")
print hidden_mean_func(hidden)

Resources