Selection and application of available methods based on information from other tensor

Hi all,

I am having difficulties in one of my ongoing research task.

Somewhere in the task, I need to apply a method to a 2-D input tensor (MxN)

Assume that there is another label tensor of size M corresponding to the input tensor. And there are 10 different label values for my dataset.

The method (lets say myfunc in general) that I need to apply on input tensor will behave differently based on the label information. There are actually 10 different methods like myfunc0, myfunc1, …, myfunc9.

The output tensor will be the result of the outputs of different functions which will be decided on the label value.

Assume that first entry of input tensor (input[0]) is from class 2, the first entry of the output tensor will be myfunc2(input[0]). If the second entry of input tensor (input[1]) is from class 7, the second entry of the output tensor will be myfunc7(input[1]). And so on…

would you please guide me on how to implement this?

Best wishes…

I have a few approaches, but here are two. Let’s start with the one I like the most:

  • Loss contribution masking: apply all the functions to the incoming input, and get the resulting vector [func1(input), func2(input), ..., func10(input)] and then perform the internal product (dot product) with the one hot encoded label vector. This will give you as loss just the value of the matching function. Example: class = 2 -> [0, 1, 0, ...], the loss will be loss = 0 * func1(input) + 1 * func2(input) + 0 * func3(input) + ....
  • Hash Label to select function: just compute the hash of the label tensor given its values; this will index a dictionary to get the function you want to compute.

For both you might need to play a bit with concatenation and map.

The first approach wastes some compute but it’s much more flexile (for instance you can use soft labels).

I hope this will help you, let me know if you need any further clarification. :slightly_smiling_face:

1 Like

Thank you Gian, I will try the first option. I really appreciate your help.

You are welcome, let me know if you need any help. In case I can write some code for you.

Hi Gian,

I am trying to implement your idea and I am stuck:(

    for X, y in loader:
        X, y = X.to(device), y.to(device)

        item_count = X.shape[0]

        outputs = model(X)

        print("outputs shape ", outputs.shape)

        outputs_0 = my_act_func0(outputs) 
        outputs_1 = my_act_func1(outputs) 
        outputs_2 = my_act_func2(outputs) 
        outputs_3 = my_act_func3(outputs) 
        outputs_4 = my_act_func4(outputs) 
        outputs_5 = my_act_func5(outputs) 
        outputs_6 = my_act_func6(outputs) 
        outputs_7 = my_act_func7(outputs) 
        outputs_8 = my_act_func8(outputs) 
        outputs_9 = my_act_func9(outputs) 

        print("outputs_0 shape ", outputs_0.shape)

        all_outputs = torch.zeros([10,item_count,10])

        all_outputs[0] = outputs_0
        all_outputs[1] = outputs_1
        all_outputs[2] = outputs_2
        all_outputs[3] = outputs_3
        all_outputs[4] = outputs_4
        all_outputs[5] = outputs_5
        all_outputs[6] = outputs_6
        all_outputs[7] = outputs_7
        all_outputs[8] = outputs_8
        all_outputs[9] = outputs_9

        print("all_outputs shape ", all_outputs.shape)

        #print("output shape ", outputs.shape)
        #print("y ", y.shape)

        one_hot = torch.nn.functional.one_hot(y,num_classes=10)
        one_hot = one_hot.to(torch.float32)
        print("one hot", one_hot )
        print("one hot shape", one_hot.shape )

The output of above code piece is like this:

outputs shape torch.Size([128, 10])
outputs_0 shape torch.Size([128, 10])
all_outputs shape torch.Size([10, 128, 10])
one hot tensor([[1., 0., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.],
…,
[0., 0., 0., …, 0., 0., 1.],
[0., 1., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.]], device=‘cuda:0’)
one hot shape torch.Size([128, 10])

But what I want is my final output is of shape 128x10

128 is my batch size.

If the label of first data point x_0 in my batch is of label 0 then the first row of the final output should be the output of my_func0(x_0) , if the label of second data point x_1 in my batch is of label 7 then the second row of the final output should be the output of my_func7(x_1), and so on.

I couldn’t manage to implement this based on your suggestion. Would you please help on this?