Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add res2net backbone #2237

Merged
merged 10 commits into from
May 21, 2020
Merged

add res2net backbone #2237

merged 10 commits into from
May 21, 2020

Conversation

gasvn
Copy link
Contributor

@gasvn gasvn commented Mar 11, 2020

No description provided.

@gasvn gasvn closed this Mar 11, 2020
@gasvn gasvn reopened this Mar 11, 2020
@hellock hellock requested a review from xvjiarui March 11, 2020 11:59
@xvjiarui
Copy link
Collaborator

Hi @gasvn
Thanks for the nice PR. LGTM.
We are benchmarking it and will get back to you very soon.

@greathope
Copy link

could you kindly provide coco-pretrained weights for these configs? Thanks

@gasvn
Copy link
Contributor Author

gasvn commented Mar 20, 2020

could you kindly provide coco-pretrained weights for these configs? Thanks

Once the mmdetection team finish the benchmarking, they will release the pretrained models.
For now, you can send me a email (shgao#live.com) to get the pretrained model you need.

@xvjiarui
Copy link
Collaborator

xvjiarui commented May 9, 2020

Hi @gasvn
I apologize for keeping you waiting. MMDetection v2.0 is released.
To integrate Res2Net with mmdetection, the following modifications are suggested.

  1. Use the new config system to rewrite all configs. You may inherit from any model and replace the backbone with Res2Net.
  2. Format the model zoo like other methods.
  3. For Res2Net, it may inherit from ResNet as ResNeXt did, which would make it simpler.

For other details, you may refer to this guide

@gasvn
Copy link
Contributor Author

gasvn commented May 11, 2020

Thanks, @xvjiarui I will follow your advice to integrate Res2Net into MMDetection v2.0 and reopen this pull request once I finish the code.

@gasvn gasvn reopened this May 11, 2020
@gasvn
Copy link
Contributor Author

gasvn commented May 12, 2020

@xvjiarui I have integrated Res2Net into the mmdetection v2. Please let me if there are any other requirements, thanks.

@gasvn
Copy link
Contributor Author

gasvn commented May 19, 2020

@xvjiarui Currently, the ImageNet pretrained model of res2net for mmdetv2 is hosted on my personal OSS, which may not stable.
https://shanghuagao.oss-cn-beijing.aliyuncs.com/res2net/res2net101_v1b_26w_4s_mmdetv2-f0a600f9.pth
Is it possible to upload this model to the mmdetection host server?

@xvjiarui
Copy link
Collaborator

@xvjiarui Currently, the ImageNet pretrained model of res2net for mmdetv2 is hosted on my personal OSS, which may not stable.
https://shanghuagao.oss-cn-beijing.aliyuncs.com/res2net/res2net101_v1b_26w_4s_mmdetv2-f0a600f9.pth
Is it possible to upload this model to the mmdetection host server?

I will upload it. Btw, the model is actually based on ResNetV1d, right? Since it uses deep_stem and avg_down.

@gasvn
Copy link
Contributor Author

gasvn commented May 19, 2020

Yes, it's based on the ResNetV1d, and we name it as Res2Net_v1b.

configs/res2net/README.md Outdated Show resolved Hide resolved
@xvjiarui xvjiarui requested a review from hellock May 19, 2020 12:10
def __init__(self,
inplanes,
planes,
scale=4,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to rename it to scales or num_scales

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed the term 'scale' to 'scales'.

if scale == 1:
self.nums = 1
else:
self.nums = scale - 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name nums is too ambiguous. Actually we can limit that scales > 1, otherwise it falls back to ResNet.
In this case we can just omit this variable and just use scales-1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nums are removed.


if self.scale != 1:
if self.stage_type == 'normal' \
or self.conv2_stride == 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid the backslash, we can write it as follows:
if (self.stage_type == 'normal' or self.conv2_stride == 1) and let yapf to format it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done as suggested.

return out


class ResLayer(nn.Sequential):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottleneck is named Bottle2neck. Maybe we can also name it Res2Layer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done as suggested.

@xvjiarui
Copy link
Collaborator

@gasvn
One more thing, unit test for Res2Net is missing.
You may add unit test for Res2Net in here

@gasvn
Copy link
Contributor Author

gasvn commented May 20, 2020

@gasvn
One more thing, unit test for Res2Net is missing.
You may add unit test for Res2Net in here

I have added the test unit for res2net.

@hellock hellock merged commit 6730084 into open-mmlab:master May 21, 2020
@gasvn
Copy link
Contributor Author

gasvn commented May 21, 2020

@hellock @xvjiarui Thanks for your help and advice.

@hellock
Copy link
Member

hellock commented May 21, 2020

@gasvn Thanks for your contribution to the community.

@zehuichen123
Copy link

zehuichen123 commented May 26, 2020

@gasvn Hi, I've tried res2net with DCN. However, I found there may be some conflicts with the original code when testing.
Res2net deleted conv2 attribute for Bottle2neck but mmdet will assert if conv_offset is in m.conv2, which will cause a No attribute Error. My solution is to remove this line(

delattr(self, 'conv2')
) directly and the result seems normal.
Since the author added this line explicitly, I wonder if I can simply remove this line.

@gasvn
Copy link
Contributor Author

gasvn commented May 26, 2020

@zehuichen123 The m.conv2 is not used in bottle2neck, so I removed this attribute. I think it's ok to keep this attribute. But if you are going to count parameters, it's possible that the conv2 parts are also included.

@xvjiarui
Copy link
Collaborator

xvjiarui commented May 26, 2020

Hi @zehuichen123
I think PyTorch will raise an error if some parameters are declared but not backpropagated during distributed training.

@zehuichen123
Copy link

zehuichen123 commented May 26, 2020

Thanks for your reply. So If we remove conv2 attribute since Bottle2neck doesn't use it, we need to modify this line to avoid NoAttributeError

if isinstance(m, Bottleneck) and hasattr(

or overwrite init_weights in res2net backbone.

Chrisfsj2051 added a commit to Chrisfsj2051/mmdetection that referenced this pull request May 28, 2020
mike112223 pushed a commit to mike112223/mmdetection that referenced this pull request Aug 25, 2020
* add res2net backbone

* add readme for res2net

* simplify res2net file

* remove some init in bottle2neck

* optimize forward code

* change init

* update results of res2net

* update config and readme

* add test and fix small issues
@sky-fly97
Copy link

sky-fly97 commented Sep 8, 2020

@gasvn Hi, I've tried res2net with DCN. However, I found there may be some conflicts with the original code when testing.
Res2net deleted conv2 attribute for Bottle2neck but mmdet will assert if conv_offset is in m.conv2, which will cause a No attribute Error. My solution is to remove this line(

delattr(self, 'conv2')

) directly and the result seems normal.
Since the author added this line explicitly, I wonder if I can simply remove this line.

Hello, after my training, I also encountered this problem during the test. I annotated this item according to your method. It can be tested, but this also appears. Is the final result correct?

`loading annotations into memory...
Done (t=0.02s)
creating index...
index created!
The model and loaded state dict do not match exactly

missing keys in source state_dict: backbone.layer1.0.conv2.weight, backbone.layer1.1.conv2.weight, backbone.layer1.2.conv2.weight, backbone.layer2.0.conv2.weight, backbone.layer2.0.conv2.conv_offset.weight, backbone.layer2.0.conv2.conv_offset.bias, backbone.layer2.1.conv2.weight, backbone.layer2.1.conv2.conv_offset.weight, backbone.layer2.1.conv2.conv_offset.bias, backbone.layer2.2.conv2.weight, backbone.layer2.2.conv2.conv_offset.weight, backbone.layer2.2.conv2.conv_offset.bias, backbone.layer2.3.conv2.weight, backbone.layer2.3.conv2.conv_offset.weight, backbone.layer2.3.conv2.conv_offset.bias, backbone.layer3.0.conv2.weight, backbone.layer3.0.conv2.conv_offset.weight, backbone.layer3.0.conv2.conv_offset.bias, backbone.layer3.1.conv2.weight, backbone.layer3.1.conv2.conv_offset.weight, backbone.layer3.1.conv2.conv_offset.bias, backbone.layer3.2.conv2.weight, backbone.layer3.2.conv2.conv_offset.weight, backbone.layer3.2.conv2.conv_offset.bias, backbone.layer3.3.conv2.weight, backbone.layer3.3.conv2.conv_offset.weight, backbone.layer3.3.conv2.conv_offset.bias, backbone.layer3.4.conv2.weight, backbone.layer3.4.conv2.conv_offset.weight, backbone.layer3.4.conv2.conv_offset.bias, backbone.layer3.5.conv2.weight, backbone.layer3.5.conv2.conv_offset.weight, backbone.layer3.5.conv2.conv_offset.bias, backbone.layer3.6.conv2.weight, backbone.layer3.6.conv2.conv_offset.weight, backbone.layer3.6.conv2.conv_offset.bias, backbone.layer3.7.conv2.weight, backbone.layer3.7.conv2.conv_offset.weight, backbone.layer3.7.conv2.conv_offset.bias, backbone.layer3.8.conv2.weight, backbone.layer3.8.conv2.conv_offset.weight, backbone.layer3.8.conv2.conv_offset.bias, backbone.layer3.9.conv2.weight, backbone.layer3.9.conv2.conv_offset.weight, backbone.layer3.9.conv2.conv_offset.bias, backbone.layer3.10.conv2.weight, backbone.layer3.10.conv2.conv_offset.weight, backbone.layer3.10.conv2.conv_offset.bias, backbone.layer3.11.conv2.weight, backbone.layer3.11.conv2.conv_offset.weight, backbone.layer3.11.conv2.conv_offset.bias, backbone.layer3.12.conv2.weight, backbone.layer3.12.conv2.conv_offset.weight, backbone.layer3.12.conv2.conv_offset.bias, backbone.layer3.13.conv2.weight, backbone.layer3.13.conv2.conv_offset.weight, backbone.layer3.13.conv2.conv_offset.bias, backbone.layer3.14.conv2.weight, backbone.layer3.14.conv2.conv_offset.weight, backbone.layer3.14.conv2.conv_offset.bias, backbone.layer3.15.conv2.weight, backbone.layer3.15.conv2.conv_offset.weight, backbone.layer3.15.conv2.conv_offset.bias, backbone.layer3.16.conv2.weight, backbone.layer3.16.conv2.conv_offset.weight, backbone.layer3.16.conv2.conv_offset.bias, backbone.layer3.17.conv2.weight, backbone.layer3.17.conv2.conv_offset.weight, backbone.layer3.17.conv2.conv_offset.bias, backbone.layer3.18.conv2.weight, backbone.layer3.18.conv2.conv_offset.weight, backbone.layer3.18.conv2.conv_offset.bias, backbone.layer3.19.conv2.weight, backbone.layer3.19.conv2.conv_offset.weight, backbone.layer3.19.conv2.conv_offset.bias, backbone.layer3.20.conv2.weight, backbone.layer3.20.conv2.conv_offset.weight, backbone.layer3.20.conv2.conv_offset.bias, backbone.layer3.21.conv2.weight, backbone.layer3.21.conv2.conv_offset.weight, backbone.layer3.21.conv2.conv_offset.bias, backbone.layer3.22.conv2.weight, backbone.layer3.22.conv2.conv_offset.weight, backbone.layer3.22.conv2.conv_offset.bias, backbone.layer4.0.conv2.weight, backbone.layer4.0.conv2.conv_offset.weight, backbone.layer4.0.conv2.conv_offset.bias, backbone.layer4.1.conv2.weight, backbone.layer4.1.conv2.conv_offset.weight, backbone.layer4.1.conv2.conv_offset.bias, backbone.layer4.2.conv2.weight, backbone.layer4.2.conv2.conv_offset.weight, backbone.layer4.2.conv2.conv_offset.bias`

@yuzhj
Copy link
Contributor

yuzhj commented Sep 8, 2020

@sky-fly97 you must retrain the network if you comment out this line (delattr(self, 'conv2')), because you change the architecture of the network

@sky-fly97
Copy link

@sky-fly97 you must retrain the network if you comment out this line (delattr(self, 'conv2')), because you change the architecture of the network

...The long time training is wasted... I‘m falling apart...

@yuzhj
Copy link
Contributor

yuzhj commented Sep 8, 2020

@sky-fly97 you must retrain the network if you comment out this line (delattr(self, 'conv2')), because you change the architecture of the network

...The long time training is wasted... I‘m falling apart...

@sky-fly97 you don't need to comment out delattr(self, 'conv2')
there is an easy way, you only need to comment out

if self.dcn is not None:
                for m in self.modules():
                    if isinstance(m, Bottleneck) and hasattr(
                            m.conv2, 'conv_offset'):
                        constant_init(m.conv2.conv_offset, 0)

in the resnet.py

@sky-fly97
Copy link

@sky-fly97 you must retrain the network if you comment out this line (delattr(self, 'conv2')), because you change the architecture of the network

...The long time training is wasted... I‘m falling apart...

@sky-fly97 you don't need to comment out delattr(self, 'conv2')
there is an easy way, you only need to comment out

if self.dcn is not None:
                for m in self.modules():
                    if isinstance(m, Bottleneck) and hasattr(
                            m.conv2, 'conv_offset'):
                        constant_init(m.conv2.conv_offset, 0)

in the resnet.py

Thanks, I'll try it now!

@sky-fly97
Copy link

@sky-fly97 you must retrain the network if you comment out this line (delattr(self, 'conv2')), because you change the architecture of the network

...The long time training is wasted... I‘m falling apart...

@sky-fly97 you don't need to comment out delattr(self, 'conv2')
there is an easy way, you only need to comment out

if self.dcn is not None:
                for m in self.modules():
                    if isinstance(m, Bottleneck) and hasattr(
                            m.conv2, 'conv_offset'):
                        constant_init(m.conv2.conv_offset, 0)

in the resnet.py

Thanks, I'll try it now!
Oh, it works! Thank you veryyyyyyyy much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants