Batched, Sequential, Multi-hot Vectors

mcognetta: <p>Hi all,</p>
<p>I am looking for an idiomatic way to make batched multi-hot vectors (multi-hot being like a one-hot but several can be hot). For example, we might have</p>
<pre><code class="lang-auto">[[1. 0. 1. 0. 0. 0.]
  [0. 1. 0. 0. 1. 0.]
  [0. 1. 0. 0. 0. 1.]]
</code></pre>
<p>as a sequence of three 2-hot vectors generated from the sequence [a b c] where a maps to classes 0 and 2, b maps to 2 and 4, etc.</p>
<p>Suppose I have function that maps elements in a sequence to a tuple of their class indices and I have a set of batched sequences of the same length. Is there an idiomatic way to transform the sequences to their batched, multi-hot representations? More specifically, I have a tensor of size <code>(Batch Size X Sequence Length)</code> and I want to build one that is <code>(Batch Size X Sequence Length X Classes)</code> where the feature dimension can be multi-hot based on a mapping from sequence elements to tuples of classes.</p>
<p>There is a one-hot version like:</p>
<pre><code class="lang-auto">def one_hot_encode(arr, n_labels):
    
    # Initialize the the encoded array
    one_hot = np.zeros((np.multiply(*arr.shape), n_labels), dtype=np.float32)
    
    # Fill the appropriate elements with ones
    one_hot[np.arange(one_hot.shape[0]), arr.flatten()] = 1.
    
    # Finally reshape it to get back to the original array
    one_hot = one_hot.reshape((*arr.shape, n_labels))
    
    return one_hot
</code></pre>
<p>and I have had luck summing two, batched, one-hot encoding arrays together, but this strikes me as inelegant.</p>
<p>Some notes:</p>
<ol>
<li>
<p>This is for input, not for a multi-label classification output.</p>
</li>
<li>
<p>I realize it would be possible to just do a one-hot encoding based on the Cartesian product of class pairs, but in my actual use case the number of classes and possible classes per element is such that combinatorial explosion makes one-hot encoding them infeasible.</p>
</li>
</ol>
<p>Thanks in advance.</p>

Caruso: <p>Maybe this post helps you! <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p><aside class="quote quote-modified" data-post="4" data-topic="32203">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ptrblck/48/1823_2.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/what-kind-of-loss-is-better-to-use-in-multilabel-classification/32203/4">What kind of loss is better to use in multilabel classification?</a> 
  </div>
  <blockquote>
    Sure! 
Given your example target, you could use scatter to create the multi-hot target: 
labels = torch.tensor([1, 4, 1, 0, 5, 2])
labels = labels.unsqueeze(0)
target = torch.zeros(labels.size(0), 15).scatter_(1, labels, 1.)
print(target)
&gt; tensor([[1., 1., 1., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

nn.BCEWithLogitsLoss takes the raw logits of your model (without any non-linearity) and applies the sigmoid internally. 
If you would like to add the sigmoid activation to your model, you…
  </blockquote>
</aside>


mcognetta: <p>Thanks, this was very useful. I have had to make some minor modifications, I will update this post later so that others may see.</p>