def forward_eval(self, batch):
        """for evaluation, batch only contain supervised data"""

        feature, label = batch['feature'], batch['label']
        supervised_txt, supervised_img = feature

        if torch.cuda.is_available():
            supervised_txt = supervised_txt.cuda()
            supervised_img = supervised_img.cuda()
            label = label.cuda()

        supervised_txt_hidden = self.txt_hidden(supervised_txt)
        supervised_img_hidden = self.resnet(supervised_img)
        supervised_img_hidden = torch.reshape(supervised_img_hidden, shape=[supervised_img_hidden.shape[0], 512])
        supervised_img_hidden = self.img_hidden(supervised_img_hidden)

        attn_txt = self.attn_mlp(supervised_txt_hidden)
        attn_img = self.attn_mlp(supervised_img_hidden)
        attn_modality = torch.cat([attn_txt, attn_img], dim=1)
        attn_modality = self.softmax(attn_modality)

        attn_img = torch.zeros([1, len(label)])
        attn_txt = torch.zeros([1, len(label)])

        if torch.cuda.is_available():
            attn_txt = attn_txt.cuda()
            attn_img = attn_img.cuda()

        attn_img[0] = attn_modality[:, 0]
        attn_img = torch.t(attn_img)
        attn_txt[0] = attn_modality[:, 1]
        attn_txt = torch.t(attn_txt)

        supervised_hidden = attn_txt * supervised_txt_hidden + attn_img * supervised_img_hidden
        supervised_predict = self.modality_predict(supervised_hidden)
        supervised_predict = self.sigmoid(supervised_predict)

        total_loss = self.criterion(supervised_predict, label)

        return {
            'loss': total_loss,
            'logit': supervised_predict,
            'fusion_feature': supervised_hidden,
            'img_feature': supervised_img_hidden,
            'txt_feature': supervised_txt_hidden
        }
for evaluation, batch only contain supervised data
torchmm/models/fusion/cmml.py