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

jarvico: <p>Hi all,</p>
<p>I am having difficulties in one of my ongoing research task.</p>
<p>Somewhere in the task, I need to apply a method to a 2-D input tensor (MxN)</p>
<p>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.</p>
<p>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.</p>
<p>The output tensor will be the result of the outputs of different functions which will be decided on the label value.</p>
<p>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…</p>
<p>would you please guide me on how to implement this?</p>
<p>Best wishes…</p>

ParGG: <p>I have a few approaches, but here are two. Let’s start with the one I like the most:</p>
<ul>
<li>Loss contribution masking: apply all the functions to the incoming input, and get the resulting vector <code>[func1(input), func2(input), ..., func10(input)]</code> 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: <code>class = 2 -&gt; [0, 1, 0, ...]</code>, the loss will be <code>loss = 0 * func1(input) + 1 * func2(input) + 0 * func3(input) + ...</code>.</li>
<li>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.</li>
</ul>
<p>For both you might need to play a bit with concatenation and map.</p>
<p>The first approach wastes some compute but it’s much more flexile (for instance you can use soft labels).</p>
<p>I hope this will help you, let me know if you need any further clarification. <img src="https://discuss.pytorch.org/images/emoji/apple/slightly_smiling_face.png?v=12" title=":slightly_smiling_face:" class="emoji" alt=":slightly_smiling_face:" loading="lazy" width="20" height="20"></p>

jarvico: <p>Thank you Gian, I will try the first option. I really appreciate your help.</p>

ParGG: <p>You are welcome, let me know if you need any help. In case I can write some code for you.</p>

jarvico: <p>Hi Gian,</p>
<p>I am trying to implement your idea and I am stuck:(</p>
<pre><code class="lang-auto">    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 )
</code></pre>
<p>The output of above code piece is like this:</p>
<p>outputs shape  torch.Size([128, 10])<br>
outputs_0 shape  torch.Size([128, 10])<br>
all_outputs shape  torch.Size([10, 128, 10])<br>
one hot tensor([[1., 0., 0.,  …, 0., 0., 0.],<br>
[0., 0., 0.,  …, 0., 0., 0.],<br>
[0., 0., 0.,  …, 0., 0., 0.],<br>
…,<br>
[0., 0., 0.,  …, 0., 0., 1.],<br>
[0., 1., 0.,  …, 0., 0., 0.],<br>
[0., 0., 0.,  …, 0., 0., 0.]], device=‘cuda:0’)<br>
one hot shape torch.Size([128, 10])</p>
<p>But what I want is my final output is of shape 128x10</p>
<p>128 is my batch size.</p>
<p>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.</p>
<p>I couldn’t manage to implement this based on your suggestion. Would you please help on this?</p>