pytorch2keras icon indicating copy to clipboard operation
pytorch2keras copied to clipboard

Can't convert the official mobilenet model

Open Apollo-XI opened this issue 5 years ago • 6 comments

Describe the bug I can't convert mobilenet V2 pytorch official model.

To Reproduce

from mobilenet_helper import *
from torch.autograd import Variable
from pytorch2keras.converter import pytorch_to_keras
from torchvision.models import mobilenet_v2

model = mobilenet_v2(pretrained=True)

dummy_input = Variable(torch.randn(1, 3, 224, 224))
# we should specify shape of the input tensor
k_model = pytorch_to_keras(model, dummy_input, [(3, sz, sz,)], verbose=True)

Expected behavior Model converted without errors

Logs

....
____ 
graph node: Sequential/Sequential[0]/Sequential[0]/InvertedResidual[1]/Sequential[conv]/Conv2d[1]
node id: 363
type: onnx::Conv
inputs: ['352', '13']
outputs: ['Sequential/Sequential[0]/Sequential[0]/InvertedResidual[1]/Sequential[conv]/Conv2d[1]']
name in state_dict: 0.0.1.conv.0
attrs: {'dilations': [1, 1], 'group': 1, 'kernel_shape': [1, 1], 'pads': [0, 0, 0, 0], 'strides': [1, 1]}
is_terminal: False
Converting convolution ...
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
...

/opt/anaconda3/lib/python3.7/site-packages/pytorch2keras/convolution_layers.py in convert_conv(params, w_name, scope_name, inputs, layers, weights, names)
     33     input_name = inputs[0]
     34 
---> 35     if len(weights[weights_name].numpy().shape) == 5:  # 3D conv
     36         W = weights[weights_name].numpy().transpose(2, 3, 4, 1, 0)
     37         height, width, channels, n_layers, n_filters = W.shape

KeyError: '0.0.1.conv.0.weight'

Environment (please complete the following information):

  • OS: debian
  • Python: Python 3.7
  • Version pytorch 1.1.0, pytorch2keras 0.1.19

Additional context I think that the problem is in converter.py module, lines 279 - 294 (see me inline comment)

       try: 
            int(node_name_regex[-1])
            node_weigth_group_name = '.'.join(
                node_name_regex[:-1]
            )
          # My comment: state dict keys goes from '0.0.1.conv.0.1.num_batches_tracked' to 
         #'0.0.1.conv.1.weight' but here it's assume that will start at 0 ('0.0.1.conv.0.weight') and 
        # don't perform any validation. Doing: node_weights_name = '.'.join(node_name_regex)
        # would work. 

            node_weights_name = node_weigth_group_name + '.' + str(group_indices[node_weigth_group_name])
            group_indices[node_weigth_group_name] += 1

        except ValueError:
            node_weights_name = '.'.join(
                node_name_regex
            )
        except IndexError:

Pytorch State dict: ... '0.0.0.1.bias', '0.0.0.1.running_mean', '0.0.0.1.running_var', '0.0.0.1.num_batches_tracked', '0.0.1.conv.0.0.weight', '0.0.1.conv.0.1.weight', '0.0.1.conv.0.1.bias', '0.0.1.conv.0.1.running_mean', '0.0.1.conv.0.1.running_var', '0.0.1.conv.0.1.num_batches_tracked', '0.0.1.conv.1.weight', '0.0.1.conv.2.weight', '0.0.1.conv.2.bias', '0.0.1.conv.2.running_mean', '0.0.1.conv.2.running_var', '0.0.1.conv.2.num_batches_tracked', '0.0.2.conv.0.0.weight', ...

The model is defined in https://github.com/pytorch/vision/blob/master/torchvision/models/mobilenet.py and the problematic region is in the InvertedResidual block, the Conv2D just after ConvBNRelU block.

Apollo-XI avatar Jun 21 '19 11:06 Apollo-XI

Hello @Apollo-XI. I'm back with some updates:

  1. Yes, it's known problem with wrong weight names parsing
  2. You can watch updates on #84 issue. It will be a new module for onnx->keras conversion, I plan to done it this week and keep this repository as high-level wrapper. Probably I'll break some API, but it worth the updates.

gmalivenko avatar Jun 26 '19 08:06 gmalivenko

@Apollo-XI I successfully converted mobilenet from torchvision, with one modification. By default it uses:

x = x.mean([2, 3])

To calculate mean by 2 dimensions at once. Just replace it with:

x = x.mean(3).mean(2)

You can check it's equal:

a = torch.rand((1, 3, 224, 224))
a.mean(3).mean(2)

>> tensor([[0.4997, 0.5013, 0.4972]])

a.mean([2, 3])

>> tensor([[0.4997, 0.5013, 0.4972]])

gmalivenko avatar Jun 27 '19 08:06 gmalivenko

@Apollo-XI

You can update your version of pytorch2keras and try to convert the model.

gmalivenko avatar Jun 27 '19 09:06 gmalivenko

Hi @nerox8664

I updated to version 0.2.1 and I could convert the model successfully. However, I don't know if it's another bug but I'm using "channel_last" in keras config but I needed to specify input_shapes manually:

k_model = pytorch_to_keras(model, dummy_input, input_shapes=[(3, HEIGHT, WIDHT,)], change_ordering=True) 

# If I run this:
# k_model = pytorch_to_keras(model, dummy_input, change_ordering=True) 
# I get a Value error:
ValueError: An Input layer should be passed either a `batch_input_shape` or an `input_shape`.

Thanks for all!

Apollo-XI avatar Jun 27 '19 11:06 Apollo-XI

@Apollo-XI. I fixed the problem with input_shapes in the latest version. Yes, there are some problems with change_ordering, so, basically, it's not supported by now. I plan to fix it ASAP.

gmalivenko avatar Jun 27 '19 12:06 gmalivenko

If anyone wanna convert MobilenetV2 from PyTorch to Tensorflow. https://github.com/CR-Ko/Pytorch2TF This might help.

But it require to modify onnx-tf.

kkk324 avatar Aug 10 '20 07:08 kkk324