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 quantized Fully Convolutional Network model #877

Merged
merged 10 commits into from
Aug 5, 2019

Conversation

wuxun-zhang
Copy link
Collaborator

@xinyu-intel @pengzhao-intel

This PR is to add quantized FCN models into GluonCV model-zoo. With this PR, INT8 FCN model can get more than ~4x speedup on AWS C5.12xlarge.

@mli
Copy link
Member

mli commented Jul 22, 2019

Job PR-877-1 is done.
Docs are uploaded to http://gluon-vision-staging.s3-website-us-west-2.amazonaws.com/PR-877/1/index.html
Code coverage of this PR: pr.svg vs. Master: master.svg

@xinyu-intel xinyu-intel self-requested a review July 22, 2019 08:51
metric.update(targets, outputs)
pixAcc, mIoU = metric.get()
tbar.set_description( 'pixAcc: %.4f, mIoU: %.4f' % (pixAcc, mIoU))
else:
Copy link
Member

Choose a reason for hiding this comment

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

what will happen if not eval only

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In the current script, args.eval=False is only required for test mode, which will convert the input RGB images into segmented images as outputs. However, there are still incompatible issues for INT8 models and I'll try to fix them.

return args


def test(args, model):
Copy link
Member

Choose a reason for hiding this comment

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

also add a dummy benchmark like ssd.

Copy link
Member

@xinyu-intel xinyu-intel left a comment

Choose a reason for hiding this comment

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

Add test case in test_modelzoo.py. Once #863 fix mkldnn ci, quantized fcn will be test automatically.

@@ -0,0 +1,172 @@
import os
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you rename test.py to eval_segmentation.py?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add the quantization to the original test.py?
If it is not possible, please change keep the orginal test.py and create a seperate file. Do not deleate existing files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for your comments. Will keep original test.py and add support for quantized model in this script.

@wuxun-zhang wuxun-zhang force-pushed the int8-fcn branch 2 times, most recently from c39ea0c to e599ba0 Compare July 23, 2019 13:24
@wuxun-zhang
Copy link
Collaborator Author

@xinyu-intel @zhanghang1989 Updated. Please take a review again. Thanks.

@mli
Copy link
Member

mli commented Jul 23, 2019

Job PR-877-3 is done.
Docs are uploaded to http://gluon-vision-staging.s3-website-us-west-2.amazonaws.com/PR-877/3/index.html
Code coverage of this PR: pr.svg vs. Master: master.svg

@mli
Copy link
Member

mli commented Jul 23, 2019

Job PR-877-4 is done.
Docs are uploaded to http://gluon-vision-staging.s3-website-us-west-2.amazonaws.com/PR-877/4/index.html
Code coverage of this PR: pr.svg vs. Master: master.svg

data = mx.gluon.utils.split_and_load(batch, ctx_list=args.ctx, batch_axis=0, even_split=False)
outputs = None
for x in data:
output = model.forward(x)
Copy link
Contributor

Choose a reason for hiding this comment

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

why not using output=model(x)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

print(model)
evaluator = MultiEvalModel(model, testset.num_class, ctx_list=args.ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

This would break the exisiting multi-size evaluation code. Could you change this script to other filename instead of overwriting test.py?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since quantized models are generated based on fixed crop_size, so I cannot use MultiEvalModel class here. Can we add a new function or a new script for INT8 inference? @xinyu-intel

Copy link
Member

Choose a reason for hiding this comment

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

can use a separate function ‘def quantized_test’

@unittest.skip("temporarily disabled to fallback to non-mkl version")
@with_cpu(0)
def test_quantized_fcn_models():
model_list = ['fcn_resnet101_voc_int8', 'fcn_resnet101_coco_int8-symbol']
Copy link
Member

Choose a reason for hiding this comment

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

maybe model_list = ['fcn_resnet101_voc_int8', 'fcn_resnet101_coco_int8']

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

Copy link
Member

@xinyu-intel xinyu-intel left a comment

Choose a reason for hiding this comment

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

.

@wuxun-zhang
Copy link
Collaborator Author

@zhanghang1989 Already added a separated test function for quantized model in test.py. In eval mode, I can get the below error by using original script. So I did some changes for this.
Also, in test mode, I would expect the outputs are segemented images with different mask colors. I'm not sure if such changes meet your expectations. Thanks.

Traceback (most recent call last):
  File "/home/wuxunzha/anaconda3/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/home/wuxunzha/anaconda3/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/wuxunzha/github/gluon-cv/gluoncv/utils/metrics/segmentation.py", line 34, in evaluate_worker
    pred, label, self.nclass)
  File "/home/wuxunzha/github/gluon-cv/gluoncv/utils/metrics/segmentation.py", line 98, in batch_intersection_union
    predict = predict * (target > 0).astype(predict.dtype)
ValueError: operands could not be broadcast together with shapes (21,480) (480,480)

@wuxun-zhang
Copy link
Collaborator Author

@zhanghang1989 Could you please help take a review at this PR again? Thanks

@zhanghang1989
Copy link
Contributor

@zhanghang1989 Could you please help take a review at this PR again? Thanks

Could you keep the test function the same as the original to avoid introducing potential issues?

@wuxun-zhang
Copy link
Collaborator Author

@zhanghang1989 I will just put get_model() function outside test function, which can be reused for test_quantization function. Removed other changes done for test function.

@mli
Copy link
Member

mli commented Jul 26, 2019

Job PR-877-7 is done.
Docs are uploaded to http://gluon-vision-staging.s3-website-us-west-2.amazonaws.com/PR-877/7/index.html
Code coverage of this PR: pr.svg vs. Master: master.svg

Copy link
Member

@xinyu-intel xinyu-intel left a comment

Choose a reason for hiding this comment

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

LGTM. @zhanghang1989 Can you help review again?

@zhanghang1989
Copy link
Contributor

zhanghang1989 commented Jul 29, 2019

@zhreshold @hetong007 @Jerryzcn Do we need to put json files into GluonCV? This PR has 37K lines of files.

@hetong007
Copy link
Member

My two cents on the json issue:

  • It won't be a scalable solution if the community plans to support all models in GluonCV. The size of this repository will largely increase and that is going to harm the user experience.
  • In terms of implementation and maintenance convenience, the descending order of places to host json is: this repo > public S3 > another repo (e.g. dmlc/web-data).
  • The issue of uploading to the public S3 is basically security consideration. @zhreshold may have more experience with it.
  • The issue of putting into another repo is the stability of github, and the risk of using absolute paths that are hard to maintain.

@zhreshold
Copy link
Member

there's indeed a controvercy between portability/availability against the maintainance difficulty.
As the latest json files are more than 500kb each, it will likely explode the loc in this repo quickly if we plan to add more.

However, I still prefer the model definition should remain in the gluon-cv repo, as this behavior is aligned with python definitions in model_zoo

My suggestion is to utilize inline python json.dumps and zlib.compress and as a general rule of thumb, the json files can be compressed to 20% the original sizes.

The workflow will be:

Encode: 
[original json] -> json.dumps() -> [\{\n"input":"data"\n}] -> zlib.compress() -> [b'x\x9c\xabVJT\xb2RPrT\xd2QPJ] -> b64encode() -> [b'eJyrVkpUslJQclTSUVBK] human readable string -> store in a python dict

Decode:
Lookup the model name in python dict -> b64decode() -> zlib.decompress -> json.loads

This way we will have compact int8 model definitions line by line and stored elegantly in code.
What do you guys think?

@hetong007
Copy link
Member

This proposal looks good to me at this stage.

@zhanghang1989
Copy link
Contributor

That sounds good.

@hetong007
Copy link
Member

My suggestion is to utilize inline python json.dumps and zlib.compress and as a general rule of thumb, the json files can be compressed to 20% the original sizes.

The workflow will be:

Encode: 
[original json] -> json.dumps() -> [\{\n"input":"data"\n}] -> zlib.compress() -> [b'x\x9c\xabVJT\xb2RPrT\xd2QPJ] -> b64encode() -> [b'eJyrVkpUslJQclTSUVBK] human readable string -> store in a python dict

Decode:
Lookup the model name in python dict -> b64decode() -> zlib.decompress -> json.loads

@wuxun-zhang @xinyu-intel Please refer to above discussion for our suggested modifications.
Basically we would like to have a compressed version for all json files in order to keep the repository size manageable.

This is the first PR that comes with a significantly large json file, so please implement the proposed internal compression and decompression apis into gluoncv.utils, and include the compressed json.

Once we have the APIs, please have the other existing json files compressed in another PR. Thanks!

@xinyu-intel
Copy link
Member

@hetong007 Okay

@wuxun-zhang
Copy link
Collaborator Author

Thanks @zhreshold for help. Now use compressed string instead of raw json file. @zhanghang1989 Please also help take a review. Thanks.

@mli
Copy link
Member

mli commented Aug 2, 2019

Job PR-877-10 is done.
Docs are uploaded to http://gluon-vision-staging.s3-website-us-west-2.amazonaws.com/PR-877/10/index.html
Code coverage of this PR: pr.svg vs. Master: master.svg

import zlib
import base64

_compressed_int8_json = {
Copy link
Member

Choose a reason for hiding this comment

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

I feel we should have the compressed string in another file or other files under model_zoo. Utils are utils, and different from specific model definitions.

@zhreshold what do you suggest?

Copy link
Member

Choose a reason for hiding this comment

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

agree, model_zoo is a better place for compressed strings

Copy link
Member

Choose a reason for hiding this comment

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

@wuxun-zhang Let's put the strings under gluoncv/model_zoo/quantized/. In the next PR we can replace all the current .json files with compressed strings.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fix.

@xinyu-intel
Copy link
Member

@wuxun-zhang Please rebase code and enable your skipped ut since #863 has been merged:)

@mli
Copy link
Member

mli commented Aug 5, 2019

Job PR-877-16 is done.
Docs are uploaded to http://gluon-vision-staging.s3-website-us-west-2.amazonaws.com/PR-877/16/index.html
Code coverage of this PR: pr.svg vs. Master: master.svg

@wuxun-zhang
Copy link
Collaborator Author

@hetong007 @zhreshold Now CI has passed. Please take a look again. Thanks.

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
import tempfile
if "fcn" in model_name:
Copy link
Member

Choose a reason for hiding this comment

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

Looking for elimination of json files completely!

@zhreshold
Copy link
Member

Looks good to me as a transition PR.

@hetong007 hetong007 merged commit baedaf8 into dmlc:master Aug 5, 2019
@wuxun-zhang wuxun-zhang deleted the int8-fcn branch August 6, 2019 09:12
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.

6 participants