facebookresearch / ClassyVision

An end-to-end PyTorch framework for image and video classification
https://classyvision.ai
MIT License
1.59k stars 278 forks source link

Multi output and multi target not support? #719

Closed fangwudi closed 3 years ago

fangwudi commented 3 years ago

❓ Questions and Help

I wrote a model with multi output: self.model = ClassyModel.from_model(models.resnet50(pretrained=True)) head_1 = FullyConnectedHead(unique_id="1", num_classes=3, in_plane=2048) head_2 = FullyConnectedHead(unique_id="2", num_classes=4, in_plane=2048) head_3 = FullyConnectedHead(unique_id="3", num_classes=21, in_plane=2048) head_4 = FullyConnectedHead(unique_id="4", num_classes=21, in_plane=2048) self.model.set_heads({"layer4": [head_1, head_2, head_3, head_4]})

and a dataset with multi target: return image, (target1, target2, target3,target4)

but failed when training: Traceback (most recent call last): File "./classy_train.py", line 190, in main(args, config) File "./classy_train.py", line 112, in main trainer.train(task) File "/home/admin/.local/lib/python3.6/site-packages/classy_vision/trainer/local_trainer.py", line 26, in train super().train(task) File "/home/admin/.local/lib/python3.6/site-packages/classy_vision/trainer/classy_trainer.py", line 46, in train task.step() File "/home/admin/.local/lib/python3.6/site-packages/classy_vision/tasks/classy_task.py", line 163, in step self.train_step() File "/home/admin/.local/lib/python3.6/site-packages/classy_vision/tasks/classification_task.py", line 1119, in train_step self.losses.append(loss.data.cpu().item() * target.size(0)) AttributeError: 'list' object has no attribute 'size'

mannatsingh commented 3 years ago

Hi @fangwudi, it seems that we assume that the target is a tensor. So the error isn't because you're using multiple heads, but because your target isn't a tensor. We can get rid of this assumption, I will send a PR to change this. In the mean time, you can create a derived task which overrides the train_step and eval_step to unblock yourself.

I guess you already know this since your loss works, but for posterity, if you attach more than one heads, the output is returned as a dict in the following format -

{
    "1": head_1_output,
    "2": head_2_output,
    "3": head_3_output,
    "4": head_4_output,
}

The loss needs to be able to take this and the supplied target as input and return a scalar.

fangwudi commented 3 years ago

Hi @fangwudi, it seems that we assume that the target is a tensor. So the error isn't because you're using multiple heads, but because your target isn't a tensor. We can get rid of this assumption, I will send a PR to change this. In the mean time, you can create a derived task which overrides the train_step and eval_step to unblock yourself.

I guess you already know this since your loss works, but for posterity, if you attach more than one heads, the output is returned as a dict in the following format -

{
    "1": head_1_output,
    "2": head_2_output,
    "3": head_3_output,
    "4": head_4_output,
}

The loss needs to be able to take this and the supplied target as input and return a scalar.

thanks.

mannatsingh commented 3 years ago

Fixed in https://github.com/facebookresearch/ClassyVision/pull/722