    def forward(self, samples, targets=None, inference=False):
        """
        Args:
            samples (`torch.Tensor`):
                The forward expects a NestedTensor, which consists of:
                samples.tensor: batched images, of shape [batch_size x 3 x H x W].
            targets (`torch.Tensor`):
                This has verbs, roles and labels information.
            inference (`bool`):
                Used in inference.
        Returns:
            (`dict`):
                Dict of tensors. 'pred_verb', 'pred_noun', 'pred_bbox' and 'pred_bbox_conf' are keys.
        """
        max_num_roles = 6
        if isinstance(samples, (list, torch.Tensor)):
            samples = nested_tensor_from_tensor_list(samples)
        features, pos = self.backbone(samples)
        src, mask = features[-1].decompose()
        assert mask is not None

        batch_size = src.shape[0]
        batch_verb, batch_noun_1, batch_noun_2, batch_noun_3, batch_bbox, batch_bbox_conf = [], [], [], [], [], []
        # model prediction
        for i in range(batch_size):
            if not inference:
                outs = self.transformer(self.input_proj(src[i:i + 1]),
                                        mask[i:i + 1], self.il_token_embed.weight, self.rl_token_embed.weight,
                                        self.verb_token_embed.weight, self.role_token_embed.weight,
                                        pos[-1][i:i + 1], self.vidx_ridx, targets=targets[i], inference=inference)
            else:
                outs = self.transformer(self.input_proj(src[i:i + 1]),
                                        mask[i:i + 1], self.il_token_embed.weight, self.rl_token_embed.weight,
                                        self.verb_token_embed.weight, self.role_token_embed.weight,
                                        pos[-1][i:i + 1], self.vidx_ridx, inference=inference)

            # output features & predictions
            verb_pred, extracted_rhs, aggregated_rhs, final_rhs, selected_roles = outs[0], outs[1], outs[2], outs[3], \
                                                                                  outs[4]
            num_selected_roles = len(selected_roles)
            # auxiliary classifiers
            if not inference:
                extracted_rhs = self.ln1(extracted_rhs[:, :, selected_roles, :])
                noun_1_pred = self.noun_1_classifier(extracted_rhs)
                noun_1_pred = F.pad(noun_1_pred,
                                    (0, 0, 0, max_num_roles - num_selected_roles),
                                    mode='constant',
                                    value=0,
                                    )[-1].view(1, max_num_roles, self.num_noun_classes)
                aggregated_rhs = self.ln2(
                    aggregated_rhs[selected_roles].permute(1, 0, 2).view(1, 1, num_selected_roles, -1))
                noun_2_pred = self.noun_2_classifier(aggregated_rhs)
                noun_2_pred = F.pad(noun_2_pred,
                                    (0, 0, 0, max_num_roles - num_selected_roles),
                                    mode='constant',
                                    value=0,
                                    )[-1].view(1, max_num_roles, self.num_noun_classes)
            else:
                noun_1_pred = None
                noun_2_pred = None
            noun_3_pred = self.noun_3_classifier(final_rhs)
            noun_3_pred = F.pad(noun_3_pred,
                                (0, 0, 0, max_num_roles - num_selected_roles),
                                mode='constant',
                                value=0,
                                )[-1].view(1, max_num_roles, self.num_noun_classes)
            bbox_pred = self.bbox_predictor(final_rhs).sigmoid()
            bbox_pred = F.pad(bbox_pred, (0, 0, 0, max_num_roles - num_selected_roles), mode='constant', value=0)[
                -1].view(1, max_num_roles, 4)
            bbox_conf_pred = self.bbox_conf_predictor(final_rhs)
            bbox_conf_pred = \
                F.pad(bbox_conf_pred, (0, 0, 0, max_num_roles - num_selected_roles), mode='constant', value=0)[-1].view(
                    1,
                    max_num_roles,
                    1)

            batch_verb.append(verb_pred)
            batch_noun_1.append(noun_1_pred)
            batch_noun_2.append(noun_2_pred)
            batch_noun_3.append(noun_3_pred)
            batch_bbox.append(bbox_pred)
            batch_bbox_conf.append(bbox_conf_pred)

        # outputs
        out = {}
        out['pred_verb'] = torch.cat(batch_verb, dim=0)
        if not inference:
            out['pred_noun_1'] = torch.cat(batch_noun_1, dim=0)
            out['pred_noun_2'] = torch.cat(batch_noun_2, dim=0)
        out['pred_noun_3'] = torch.cat(batch_noun_3, dim=0)
        out['pred_bbox'] = torch.cat(batch_bbox, dim=0)
        out['pred_bbox_conf'] = torch.cat(batch_bbox_conf, dim=0)

        return out
Args:
samples (`torch.Tensor`):
The forward expects a NestedTensor, which consists of:
samples.tensor: batched images, of shape [batch_size x 3 x H x W].
targets (`torch.Tensor`):
This has verbs, roles and labels information.
inference (`bool`):
Used in inference.
Returns:
(`dict`):
Dict of tensors. 'pred_verb', 'pred_noun', 'pred_bbox' and 'pred_bbox_conf' are keys.
towhee/models/coformer/coformer.py