Onnx: Using numpy arrays as input to network throws ValueError

I’m trying to convert my model from pytorch to caffe2 using onnx. I’m performing the conversion as shown below:

from torch.autograd import Variable
import torch.onnx
import _init_paths
from nets.resnet_v1 import resnetv1
import numpy as np

num_classes=30
model = resnetv1(batch_size=1, num_layers=101)
model.create_architecture(num_classes, tag='default',anchor_scales=[8,16,32],anchor_ratios=[0.5,1.0,2.0])
model.eval()
model.cuda()
model_path = "res101_faster_rcnn_iter_300000.pth"
model.load_state_dict(torch.load(model_path))

x = np.random.randn(1,224,224,3)
im_info = np.array([224.0,224.0,1.0], dtype=np.float32)
torch_out = torch.onnx.export(model,  # model being run
                               [x,im_info], # model input (or a tuple for multiple inputs)
                               "resnet101_fasterrcnn.onnx", # where to save the model (can be a file or file-like object)
                               export_params=True)      # store the trained parameter weights inside the model file

This throws the error: ValueError: NestedIOFunction doesn't know how to process an input object of type ndarray.

I know that I could easily convert the above numpy arrays to torch Variables, but my forward() method expects numpy arrays (and a string) as input (see below):

    def forward(self, image, im_info, gt_boxes=None, mode='TRAIN'):

        self._image = Variable(torch.from_numpy(image.transpose([0, 3, 1, 2])).cuda(), volatile=mode == 'TEST')
        self._im_info = im_info  # No need to change; actually it can be an list
        self._gt_boxes = Variable(torch.from_numpy(gt_boxes).cuda()) if gt_boxes is not None else None

        self._mode = mode

        rois, cls_prob, bbox_pred = self._predict(mode)

Is there a way to perform the conversion without modifying the original source code (for example, by allowing onnx.export() to take numpy arrays as input)?

1 Like

Hi @Feynman27,

The second parameter of torch.onnx.export is expected to be an object or tuple. You can try tuple (x, im_info) instead of a list.