class_docstr: Multi-head classifier with separate heads for each task.
  
  Typically used in task-incremental benchmarks where task labels are
  available and provided to the model.
  
  .. note::
      Each output head may have a different shape, and the number of
      classes can be determined automatically.
  
      However, since pytorch doest not support jagged tensors, when you
      compute a minibatch's output you must ensure that each sample
      has the same output size, otherwise the model will fail to
      concatenate the samples together.
  
      These can be easily ensured in two possible ways:
  
      - each minibatch contains a single task, which is the case in most
          common benchmarks in Avalanche. Some exceptions to this setting
          are multi-task replay or cumulative strategies.
      - each head has the same size, which can be enforced by setting a
          large enough `initial_out_features`.
class_docstr_tok: ["Multi-head","classifier","with","separate","heads","for","each","task",".","Typically","used","in","task-incremental","benchmarks","where","task","labels","are","available","and","provided","to","the","model",".","..","note",":",":","Each","output","head","may","have","a","different","shape",",","and","the","number","of","classes","can","be","determined","automatically",".","However",",","since","pytorch","doest","not","support","jagged","tensors",",","when","you","compute","a","minibatch","'s","output","you","must","ensure","that","each","sample","has","the","same","output","size",",","otherwise","the","model","will","fail","to","concatenate","the","samples","together",".","These","can","be","easily","ensured","in","two","possible","ways",":","-","each","minibatch","contains","a","single","task",",","which","is","the","case","in","most","common","benchmarks","in","Avalanche",".","Some","exceptions","to","this","setting","are","multi-task","replay","or","cumulative","strategies",".","-","each","head","has","the","same","size",",","which","can","be","enforced","by","setting","a","large","enough","`","initial_out_features","`","."]
docstr: compute the output given the input `x`. This module uses the task
  label to activate the correct head.
  
  :param x:
  :param task_label:
  :return:
docstr_tok: ["compute","the","output","given","the","input","`","x","`",".","This","module","uses","the","task","label","to","activate","the","correct","head",".",":","param","x",":",":","param","task_label",":",":","return",":"]
code: def forward_single_task(self, x, task_label):
      """compute the output given the input `x`. This module uses the task
      label to activate the correct head.
  
      :param x:
      :param task_label:
      :return:
      """
      device = self._adaptation_device
      task_label = str(task_label)
      out = self.classifiers[task_label](x)
      if self.masking:
          au_name = f"active_units_T{task_label}"
          curr_au = self._buffers[au_name]
          nunits, oldsize = out.shape[-1], curr_au.shape[0]
          if oldsize < nunits:  # we have to update the mask
              old_mask = self._buffers[au_name]
              self._buffers[au_name] = torch.zeros(
                  nunits, dtype=torch.int8, device=device
              )
              self._buffers[au_name][:oldsize] = old_mask
              curr_au = self._buffers[au_name]
          out[..., torch.logical_not(curr_au)] = self.mask_value
      return out
  
imports: import torch
  from torch.nn import Module
  from typing import Optional
  from avalanche.benchmarks.utils.flat_data import ConstantSequence
  from avalanche.benchmarks.scenarios import CLExperience
label_desc: Use image node_id 5 for calling the MultiHeadClassifier obj's underlying member method code with example usage: obj.forward_single_task(x, task_label) and returns: out