facebookresearch / facebookresearch/detectron2
Unable to convert model to torchscript
- Dominant language
- Python
- Stars
- 34.7k
- Forks
- 7.9k
- PR merge metrics
- No merged PRs in 30d
Description
I am trying to export model with Faster R-CNN R 101 DC5 backbone into Torchscript. I utilised the R101 DC5.yaml file for configuration and built the model.
```
config_file = "COCO-Detection/faster_rcnn_R_101_DC5_3x.yaml"
cfg = get_cfg()
cfg.merge_from_file(model_zoo.get_config_file(config_file))
```
```
from detectron2.modeling import build_model
model = build_model(cfg).eval()
#model.eval()
checkpointer = DetectionCheckpointer(model)
checkpointer.load(cfg.MODEL.WEIGHTS)
import torch
model = torch.jit.script(model)
```
I get the following error :
```
---------------------------------------------------------------------------
NotSupportedError Traceback (most recent call last)
in
1 import torch
----> 2 model = torch.jit.script(model)
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_script.py in script(obj, optimize, _frames_up, _rcb, example_inputs)
1256 obj = call_prepare_scriptable_func(obj)
1257 return torch.jit._recursive.create_script_module(
-> 1258 obj, torch.jit._recursive.infer_methods_to_compile
1259 )
1260
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_recursive.py in create_script_module(nn_module, stubs_fn, share_types, is_tracing)
449 if not is_tracing:
450 AttributeTypeIsSupportedChecker().check(nn_module)
--> 451 return create_script_module_impl(nn_module, concrete_type, stubs_fn)
452
453 def create_script_module_impl(nn_module, concrete_type, stubs_fn):
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_recursive.py in create_script_module_impl(nn_module, concrete_type, stubs_fn)
511
512 # Actually create the ScriptModule, initializing it with the function we just defined
--> 513 script_module = torch.jit.RecursiveScriptModule._construct(cpp_module, init_fn)
514
515 # Compile methods if necessary
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_script.py in _construct(cpp_module, init_fn)
585 """
586 script_module = RecursiveScriptModule(cpp_module)
--> 587 init_fn(script_module)
588
589 # Finalize the ScriptModule: replace the nn.Module state with our
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_recursive.py in init_fn(script_module)
489 else:
490 # always reuse the provided stubs_fn to infer the methods to compile
--> 491 scripted = create_script_module_impl(orig_value, sub_concrete_type, stubs_fn)
492
493 cpp_module.setattr(name, scripted)
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_recursive.py in create_script_module_impl(nn_module, concrete_type, stubs_fn)
515 # Compile methods if necessary
516 if concrete_type not in concrete_type_store.methods_compiled:
--> 517 create_methods_and_properties_from_stubs(concrete_type, method_stubs, property_stubs)
518 # Create hooks after methods to ensure no name collisions between hooks and methods.
519 # If done before, hooks can overshadow methods that aren't exported.
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_recursive.py in create_methods_and_properties_from_stubs(concrete_type, method_stubs, property_stubs)
366 property_rcbs = [p.resolution_callback for p in property_stubs]
367
--> 368 concrete_type._create_methods_and_properties(property_defs, property_rcbs, method_defs, method_rcbs, method_defaults)
369
370 def create_hooks_from_stubs(concrete_type, hook_stubs, pre_hook_stubs):
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/annotations.py in try_ann_to_type(ann, loc)
338 if a is None:
339 inner.append(NoneType.get())
--> 340 maybe_type = try_ann_to_type(a, loc)
341 msg = "Unsupported annotation {} could not be resolved because {} could not be resolved."
342 assert maybe_type, msg.format(repr(ann), repr(maybe_type))
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/annotations.py in try_ann_to_type(ann, loc)
309 return TupleType([try_ann_to_type(a, loc) for a in ann.__args__])
310 if is_list(ann):
--> 311 elem_type = try_ann_to_type(ann.__args__[0], loc)
312 if elem_type:
313 return ListType(elem_type)
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/annotations.py in try_ann_to_type(ann, loc)
381 return maybe_script_class
382 if torch._jit_internal.can_compile_class(ann):
--> 383 return torch.jit._script._recursive_compile_class(ann, loc)
384
385 # Maybe resolve a NamedTuple to a Tuple Type
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_script.py in _recursive_compile_class(obj, loc)
1431 error_stack = torch._C.CallStack(_qual_name, loc)
1432 rcb = _jit_internal.createResolutionCallbackForClassMethods(obj)
-> 1433 return _compile_and_register_class(obj, rcb, _qual_name)
1434
1435 CompilationUnit = torch._C.CompilationUnit
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/_recursive.py in _compile_and_register_class(obj, rcb, qualified_name)
40
41 if not script_class:
---> 42 ast = get_jit_class_def(obj, obj.__name__)
43 defaults = torch.jit.frontend.get_default_args_for_class(obj)
44 script_class = torch._C._jit_script_class_compile(qualified_name, ast, defaults, rcb)
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/frontend.py in get_jit_class_def(cls, self_name)
199 name,
200 self_name=self_name,
--> 201 is_classmethod=is_classmethod(obj)) for (name, obj) in methods]
202
203 properties = get_class_properties(cls, self_name)
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/frontend.py in (.0)
199 name,
200 self_name=self_name,
--> 201 is_classmethod=is_classmethod(obj)) for (name, obj) in methods]
202
203 properties = get_class_properties(cls, self_name)
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/frontend.py in get_jit_def(fn, def_name, self_name, is_classmethod)
262 pdt_arg_types = type_trace_db.get_args_types(qualname)
263
--> 264 return build_def(parsed_def.ctx, fn_def, type_line, def_name, self_name=self_name, pdt_arg_types=pdt_arg_types)
265
266 # TODO: more robust handling of recognizing ignore context manager
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/frontend.py in build_def(ctx, py_def, type_line, def_name, self_name, pdt_arg_types)
300 py_def.col_offset + len("def"))
301
--> 302 param_list = build_param_list(ctx, py_def.args, self_name, pdt_arg_types)
303 return_type = None
304 if getattr(py_def, 'returns', None) is not None:
~/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/torch/jit/frontend.py in build_param_list(ctx, py_args, self_name, pdt_arg_types)
324 expr = py_args.kwarg
325 ctx_range = ctx.make_range(expr.lineno, expr.col_offset - 1, expr.col_offset + len(expr.arg))
--> 326 raise NotSupportedError(ctx_range, _vararg_kwarg_err)
327 if py_args.vararg is not None:
328 expr = py_args.vararg
NotSupportedError: Compiled functions can't take variable number of arguments or use keyword-only arguments with defaults:
File "/home/ec2-user/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/detectron2/structures/instances.py", line 38
def __init__(self, image_size: Tuple[int, int], **kwargs: Any):
~~~~~~~ <--- HERE
"""
Args:
'__torch__.detectron2.structures.instances.Instances' is being compiled since it was called from 'RPN.forward'
File "/home/ec2-user/anaconda3/envs/pytorch_latest_p36/lib/python3.6/site-packages/detectron2/modeling/proposal_generator/rpn.py", line 431
def forward(
~~~~~~~~~~~~
self,
~~~~~
images: ImageList,
~~~~~~~~~~~~~~~~~~
features: Dict[str, torch.Tensor],
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gt_instances: Optional[List[Instances]] = None,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
):
~~
"""
~~~
Args:
~~~~~
images (ImageList): input images of length `N`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
features (dict[str, Tensor]): input data as a mapping from feature
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
map name to tensor. Axis 0 represents the number of images `N` in
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
the input data; axes 1-3 are channels, height, and width, which may
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vary between feature maps (e.g., if a feature pyramid is used).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gt_instances (list[Instances], optional): a length `N` list of `Instances`s.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each `Instances` stores ground-truth instances for the corresponding image.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Returns:
~~~~~~~~
proposals: list[Instances]: contains fields "proposal_boxes", "objectness_logits"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
loss: dict[Tensor] or None
~~~~~~~~~~~~~~~~~~~~~~~~~~
"""
~~~
features = [features[f] for f in self.in_features]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anchors = self.anchor_generator(features)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pred_objectness_logits, pred_anchor_deltas = self.rpn_head(features)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Transpose the Hi*Wi*A dimension to the middle:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pred_objectness_logits = [
~~~~~~~~~~~~~~~~~~~~~~~~~~
# (N, A, Hi, Wi) -> (N, Hi, Wi, A) -> (N, Hi*Wi*A)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
score.permute(0, 2, 3, 1).flatten(1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for score in pred_objectness_logits
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]
~
pred_anchor_deltas = [
~~~~~~~~~~~~~~~~~~~~~~
# (N, A*B, Hi, Wi) -> (N, A, B, Hi, Wi) -> (N, Hi, Wi, A, B) -> (N, Hi*Wi*A, B)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x.view(x.shape[0], -1, self.anchor_generator.box_dim, x.shape[-2], x.shape[-1])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.permute(0, 3, 4, 1, 2)
~~~~~~~~~~~~~~~~~~~~~~~
.flatten(1, -2)
~~~~~~~~~~~~~~~
for x in pred_anchor_deltas
~~~~~~~~~~~~~~~~~~~~~~~~~~~
]
~
if self.training:
~~~~~~~~~~~~~~~~~
assert gt_instances is not None, "RPN requires gt_instances in training!"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gt_labels, gt_boxes = self.label_and_sample_anchors(anchors, gt_instances)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
losses = self.losses(
~~~~~~~~~~~~~~~~~~~~~
anchors, pred_objectness_logits, gt_labels, pred_anchor_deltas, gt_boxes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
)
~
else:
~~~~~
losses = {}
~~~~~~~~~~~
proposals = self.predict_proposals(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anchors, pred_objectness_logits, pred_anchor_deltas, images.image_sizes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
)
~
return proposals, losses
~~~~~~~~~~~~~~~~~~~~~~~~ <--- HERE
```
Kindly guide.
Contributor guide
Research direction
Reproduce the failure with torch.jit.script(model) using the Faster R-CNN R101 DC5 configuration, then inspect detectron2/structures/instances.py and detectron2/modeling/proposal_generator/rpn.py, especially Instances.__init__ and RPN.forward. Done means the model exports to TorchScript without the reported NotSupportedError and its scripted inference remains usable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- computer-vision, machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100