Raise Exception("MTCNN batch processing only compatible with equal-dimension images.")

Today I upgraded PyTorch and libtorch to the fresh 1.5 release .

mtcc.py :

import torch
import torchvision
from facenet_pytorch import MTCNN, InceptionResnetV1

device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

mtcnn_module = MTCNN(
            image_size=160, margin=0, min_face_size=160,
            thresholds=[0.6, 0.7, 0.7], factor=0.709, post_process=True,
            device=device
        )
sm_mtcc = torch.jit.script(mtcnn_module)

I’m still getting this error:

(base) marco@pc01:~/PyTorchMatters/facenet_pytorch/examples$ python3 ./mtcc.py
Traceback (most recent call last):
  File "./mtcc.py", line 15, in <module>
    sm_mtcc = torch.jit.script(mtcnn_module)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/__init__.py", line 1261, in 
script
    return torch.jit._recursive.create_script_module(obj, 
torch.jit._recursive.infer_methods_to_compile)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/_recursive.py", line 305, in 
create_script_module
    return create_script_module_impl(nn_module, concrete_type, stubs_fn)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/_recursive.py", line 361, in 
create_script_module_impl
    create_methods_from_stubs(concrete_type, stubs)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/_recursive.py", line 279, in 
create_methods_from_stubs
    concrete_type._create_methods(defs, rcbs, defaults)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/_recursive.py", line 587, in 
compile_unbound_method
    create_methods_from_stubs(concrete_type, (stub,))
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/_recursive.py", line 279, in 
create_methods_from_stubs
    concrete_type._create_methods(defs, rcbs, defaults)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/_recursive.py", line 568, in 
try_compile_fn
    return torch.jit.script(fn, _rcb=rcb)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/__init__.py", line 1287, in 
script
    ast = get_jit_def(obj)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 173, in 
get_jit_def
    return build_def(ctx, py_ast.body[0], type_line, self_name)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 206, in 
build_def
    build_stmts(ctx, body))
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 129, in 
build_stmts
    stmts = [build_stmt(ctx, s) for s in stmts]
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 129, in 
<listcomp>
    stmts = [build_stmt(ctx, s) for s in stmts]
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 181, in 
__call__
    return method(ctx, node)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 364, in 
build_If
    build_stmts(ctx, stmt.orelse))
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 129, in 
build_stmts
    stmts = [build_stmt(ctx, s) for s in stmts]
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 129, in 
<listcomp>
    stmts = [build_stmt(ctx, s) for s in stmts]
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 181, in 
__call__
    return method(ctx, node)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 362, in 
build_If
    return If(r, build_expr(ctx, stmt.test),
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 181, in 
__call__
    return method(ctx, node)
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 455, in 
build_Call
    args = [build_expr(ctx, py_arg) for py_arg in expr.args]
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 455, in 
<listcomp>
    args = [build_expr(ctx, py_arg) for py_arg in expr.args]
  File "/home/marco/anaconda3/lib/python3.7/site-packages/torch/jit/frontend.py", line 180, in 
__call__
    raise UnsupportedNodeError(ctx, node)
torch.jit.frontend.UnsupportedNodeError: GeneratorExp aren't supported:
  File "/home/marco/anaconda3/lib/python3.7/site-packages/facenet_pytorch/models/utils
/detect_face.py", line 19
        if not isinstance(imgs, (list, tuple)):
            imgs = [imgs]
        if any(img.size != imgs[0].size for img in imgs):
               ~ <--- HERE
            raise Exception("MTCNN batch processing only compatible with equal-dimension 
images.")
         imgs = np.stack([np.uint8(img) for img in imgs])
'MTCNN.detect' is being compiled since it was called from 'MTCNN.forward'
  File "/home/marco/anaconda3/lib/python3.7/site-packages/facenet_pytorch/models/mtcnn.py", 
line 247
        # Detect faces
        #with torch.no_grad():
        batch_boxes, batch_probs = self.detect(img)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <--- HERE
        #batch_boxes = batch_boxes.detach()
        #batch_probs = batch_probs.detach()

How to solve the problem?
Looking forward to your kind help.
Marco

The GeneratorExp is not supported in torch.jit:

if any(img.size != imgs[0].size for img in imgs)

To script the model you could wrap this code path with if not torch.jit.is_scripting() to ignore it.
Of course you would have to make sure to pass the right input before calling the model.

Hi @ptrblck, would you please give an example of how to use it and when we can and can’t use it please?

Are you running into the same issue regarding an unsupported GeneratorExp?
If so, then it’s still not supported in the scripting mode and you would have to guard this line of code with the mentioned if not torch.jit.is_scripting() code.

Let me know, which example you are looking for.

Hi @ptrblck thank you so much for your kind reply. I try to convert my model from detectron2 to jit. I am unfamiliar with jit and could not find any example of torch.jit.is_scripting in open resources. If possible, would you please share us a snippet of how to use it?

The master docs have a small example to show its usage.
You could use it as a standard condition to skip the code inside the block, if you are scripting the model.

This is useful, if you are using methods, which are unsupported in the current JIT and would have a valid workaround for them.

1 Like

Hi @ptrblck, thank you so much. My understanding of torch.jit.is_scripting is we need to provide a replacement if an operation is not supported. But in the first of your answer, you said we could ignore the GeneratorExp. I am confused.

I mentioned that this method should be ignored, but the actual check should be either moved outside of the model or somehow guaranteed (I’m not familiar with the complete code, so don’t know which would be easier or would make more sense):