Tensor.shape[0] is not supported in torchscript?

I got the following error while converting model to torchscript.

Traceback (most recent call last):
  File "ocr.py", line 206, in <module>
    ts = torch.jit.script(ocr)
  File "/home/dai/py36env/lib/python3.6/site-packages/torch/jit/__init__.py", line 1203, in script
    return torch.jit.torch.jit._recursive.recursive_script(obj)
  File "/home/dai/py36env/lib/python3.6/site-packages/torch/jit/_recursive.py", line 173, in recursive_script
    return copy_to_script_module(mod, overload_stubs + stubs)
  File "/home/dai/py36env/lib/python3.6/site-packages/torch/jit/_recursive.py", line 95, in copy_to_script_module
    torch.jit._create_methods_from_stubs(script_module, stubs)
  File "/home/dai/py36env/lib/python3.6/site-packages/torch/jit/__init__.py", line 1423, in _create_methods_from_stubs
    self._c._create_methods(self, defs, rcbs, defaults)
RuntimeError:
builtin cannot be used as a value:
at ocr.py:80:23
        img_tensor = resize_img(img_tensor)
        # self.show(img_tensor)

        img_tensor_ = (img_tensor - 0.5) / 0.5
        img_tensor_ = img_tensor_.permute(2,0,1).unsqueeze(0) # --> n x c x h x w
        boxes = self.east(img_tensor_)

        new_boxes = []
        pass_list:List[int] = []
        for i in range(boxes.shape[0]):
                       ~~~~~~~~~~~ <--- HERE
            for j in range(i+1,boxes.shape[0]):
                if i in pass_list or j in pass_list:
                    continue
                cx1,cy1,angle1 = box_analyse(boxes[i])
                cx2,cy2,angle2 = box_analyse(boxes[j])
                if torch.atan(torch.abs(torch.abs(cy2 - cy1) / torch.abs(cx2 - cx1))) - (90 - (angle1 + angle2) / 2) * 3.141592653 / 180 < 0.1:
                    b = torch.cat([boxes[i][:8].reshape(4, 2), boxes[j][:8].reshape(4, 2)], dim=0)
                    new_box = torch.ops.my_ops.min_rect(b)
                    new_boxes.append(new_box.reshape(-1))

The variable boxes is a tensor returned from model east, is tensor.shape a builtin function in torchscript?

By the way, how can I debug in torchscript?

I met many problems in torchscript, it will be great if there’s a way to debug torchscript.

Firstly, you should use boxes.size(). Secondly, https://pytorch.org/docs/stable/jit.html#disable-jit-for-debugging will give you some help and my tip is using @torch.jit.ignore to check the functionality.

Thank you, but boxes.size(0) and boxes.size()[0] doesn’t work.

I met the same error using boxes.size(0) and boxes.size()[0]:

Arguments for call are not valid.
The following operator variants are available:

  aten::size.int(Tensor self, int dim) -> (int):
  Expected a value of type 'Tensor' for argument 'self' but instead found type 'Optional[Tensor]'.

  aten::size(Tensor self) -> (int[]):
  Expected a value of type 'Tensor' for argument 'self' but instead found type 'Optional[Tensor]'.

The original call is:
at ocr.py:80:23
        img_tensor = resize_img(img_tensor)
        # self.show(img_tensor)

        img_tensor_ = (img_tensor - 0.5) / 0.5
        img_tensor_ = img_tensor_.permute(2,0,1).unsqueeze(0) # --> n x c x h x w
        boxes = self.east(img_tensor_)
        # self.show(img_tensor,boxes)
        new_boxes = []
        pass_list:List[int] = []
        for i in range(boxes.size(0)):
                       ~~~~~~~~~~ <--- HERE

And my code works well with environment variable PYTORCH_JIT=0.

What’s the difference between boxes.size()/boxes.shape in python and torchscript?

torch.Tensor has no attribute named shape while numpy has. I thought boxes is a tensor, so I suggest you to use size(). If it is a numpy array, torchscript doesn’t support it.

I’m sure boxes is a tensor, its value is as following:

tensor([[230.1149, 237.2053, 456.3304, 232.7983, 456.9069, 262.5309, 230.6913,
         266.9381, 202.8954],
        [331.7273, 324.1699, 679.4318, 317.2317, 680.0470, 348.1467, 332.3426,
         355.0850,  88.9529],
        [231.7705, 204.8157, 500.3940, 200.7935, 500.8643, 232.1562, 232.2409,
         236.1783,  60.0000],
        [231.7874, 157.3486, 441.9472, 153.3222, 442.4890, 181.6230, 232.3291,
         185.6494,  47.9981],
        [230.4137,  63.0557, 326.3553,  59.4965, 327.4994,  90.2845, 231.5578,
          93.8438,  40.9682],
        [152.8475, 326.7796, 311.2224, 324.2658, 311.6898, 353.6737, 153.3150,
         356.1875,  28.9999],
        [154.1073, 113.9810, 260.5620, 112.2871, 260.9745, 138.2966, 154.5198,
         139.9904,  27.9924],
        [293.3543, 111.8462, 390.4526, 108.3323, 391.4826, 136.8042, 294.3844,
         140.3180,  13.9621],
        [152.4046, 159.5459, 219.9668, 157.7393, 220.6146, 181.9012, 153.0524,
         183.7079,  12.9934],
        [153.1970, 206.8427, 218.1942, 205.0301, 218.8990, 230.2958, 153.9019,
         232.1084,   7.0000],
        [153.0565,  68.3798, 217.7016,  67.7295, 217.9489,  92.0420, 153.3038,
          92.6922,   6.9623]], grad_fn=<IndexBackward>)

Its type and shape is:

torch.FloatTensor torch.Size([11, 9])

I found boxes is not tensor, it’s Optional[Tensor]. It’s inferred as Optional[Tensor] because of the control flow in the east model. The forward method of model is like this:

def forward(self,x):
    if condition1:
        return None
    else:
        return boxes

It’s inferred as Optional[Tensor] because the return value of forward can be None or tensor.

And size() method if not supported by Optional[Tensor].