Skip to content

DNN: load fp16 ONNX model as fp32#22337

Merged
asmorkalov merged 2 commits intoopencv:4.xfrom
zihaomu:load_ONNX_fp16_as_fp32
Aug 29, 2022
Merged

DNN: load fp16 ONNX model as fp32#22337
asmorkalov merged 2 commits intoopencv:4.xfrom
zihaomu:load_ONNX_fp16_as_fp32

Conversation

@zihaomu
Copy link
Copy Markdown
Member

@zihaomu zihaomu commented Aug 3, 2022

Related extra data
Download link

The FP16 model is half the size of the FP32 model, which will be edge device friendly.
Currently, OpenCV ONNX_importer cannot load FP16 models correctly and DNN also doesn't have full FP16 backend support.
So, my idea is that in the first step we make OpenCV DNN load FP16 ONNX model as FP32 model, and every layer will be computed as FP32.

Here is a FP16 text recognition model(CRNN) which was converted by my GSoC student Yiyao @Charles-258, and we found it even has better accuracy performance than the original FP32 model.
And I have tested these FP16 CRNN models in the existing High-Level API, testTextRecognitionModel, and it works well. Maybe we can use this to replace the original FP32 model.

How to convert ONNX fP32 model to FP16 model?

from onnx import load_model, save_model
from onnxmltools.utils import float16_converter

dir = "MODEL_DIR_PATH"
onnx_model = load_model(os.path.join(dir, "resnet50v1.onnx"))
trans_model = float16_converter.convert_float_to_float16(onnx_model, keep_io_types=False)
save_model(trans_model, os.path.join(dir, "resnet50v1_FP16.onnx"))

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@zihaomu zihaomu added category: dnn pr: needs test New functionality requires minimal tests set labels Aug 3, 2022
@vpisarev vpisarev self-requested a review August 3, 2022 06:09
@vpisarev
Copy link
Copy Markdown
Contributor

vpisarev commented Aug 3, 2022

the PR is important and is ready to be merged

@asmorkalov asmorkalov requested a review from rogday August 3, 2022 07:18
Copy link
Copy Markdown
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

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

I think we should log this behavior so that users are not surprised that OpenCV DNN takes twice as much RAM as other frameworks, otherwise looks good.

@zihaomu zihaomu requested review from rogday August 5, 2022 05:41
@fengyuentau fengyuentau self-requested a review August 5, 2022 08:59
@zihaomu zihaomu force-pushed the load_ONNX_fp16_as_fp32 branch from 838b4a4 to 3d0bea5 Compare August 5, 2022 09:30
Copy link
Copy Markdown
Member

@fengyuentau fengyuentau left a comment

Choose a reason for hiding this comment

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

👍

@zihaomu
Copy link
Copy Markdown
Member Author

zihaomu commented Aug 9, 2022

Hi @alalek and @asmorkalov, can you please check if the update can fix the data alignment issue?

@zihaomu zihaomu requested a review from alalek August 9, 2022 08:23
@asmorkalov
Copy link
Copy Markdown
Contributor

@zihaomu I checked other tickets and OpenCV patches that are alignment related and found general solution for it that is managed by macro CV_STRONG_ALIGNMENT. See

#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64))
.

I propose to use it and rework the patch in the same way as it's done for int64 tensors in the same function (Macro check + AutoBuffer).
Also related issue: #16373

@asmorkalov
Copy link
Copy Markdown
Contributor

Also it looks like fp64 branch suffers from the same problem, but it's not popular and the issue is invisible.

@zihaomu
Copy link
Copy Markdown
Member Author

zihaomu commented Aug 11, 2022

Great thanks! @asmorkalov I will follow your suggestion and re-implement it with CV_STRONG_ALIGNMENT .

@zihaomu zihaomu force-pushed the load_ONNX_fp16_as_fp32 branch from fc98f49 to 4901de2 Compare August 12, 2022 07:27
@zihaomu zihaomu added test and removed pr: needs test New functionality requires minimal tests set labels Aug 15, 2022
@asmorkalov
Copy link
Copy Markdown
Contributor

[  FAILED  ] Test_ONNX_nets.MobileNet_v2_FP16/0, where GetParam() = OCV/OCL
[  FAILED  ] Test_ONNX_nets.MobileNet_v2_FP16/1, where GetParam() = OCV/OCL_FP16
[  FAILED  ] Test_ONNX_nets.MobileNet_v2_FP16/2, where GetParam() = OCV/CPU

@zihaomu
Copy link
Copy Markdown
Member Author

zihaomu commented Aug 15, 2022

Thanks for the reminder, @asmorkalov. there seems to be a depth bug on float16 and I'm trying to fix it.

@zihaomu
Copy link
Copy Markdown
Member Author

zihaomu commented Aug 20, 2022

Hi @asenyaev, other CI works fine, only Win10 can not download the new added testing model from Github. Can you please check what's happening? Win10 CI error

@zihaomu zihaomu force-pushed the load_ONNX_fp16_as_fp32 branch from 52f5d5b to 0b155fa Compare August 20, 2022 23:56
@zihaomu zihaomu marked this pull request as draft August 21, 2022 04:27
@asenyaev
Copy link
Copy Markdown
Contributor

@zihaomu sure, I'll check it.

@asenyaev
Copy link
Copy Markdown
Contributor

@zihaomu, the model was downloaded manually on Windows machine and the pipeline for Windows passed.

@zihaomu zihaomu marked this pull request as ready for review August 22, 2022 11:23
@zihaomu zihaomu force-pushed the load_ONNX_fp16_as_fp32 branch 2 times, most recently from 8325b2b to 6204381 Compare August 22, 2022 11:26
@zihaomu
Copy link
Copy Markdown
Member Author

zihaomu commented Aug 22, 2022

Hi, ONNX_importer.cpp may encounter bugs when load float16 model.
When the format version of ONNX is lower than 7, dnn/misc/opencv_onnx.pb.cc will parse float 16 tensor into int32, which will cause the weight to be all 0.
Since the dnn/misc/opencv_onnx.pb.cc is generated by opencv-onnx.proto which was taken from https://github.com/onnx/onnx/blob/main/onnx/onnx.proto, I think this bug is not our responsibility.

In my test, this path works fine with model format version >= 6. So, I think we can merge this first, and then I will discuss the specific solution with the ONNX team.

Some example:
mobilenetv2 with ONNX format V3 (No)
mobilenetv2 with ONNX format V7 (Yes)

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Copy link
Copy Markdown
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

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

👍

{
const ::google::protobuf::RepeatedField<float> field = tensor_proto.float_data();
Mat(sizes, CV_32FC1, (void*)field.data()).copyTo(blob);
const int offset = isLittleEndianCPU() ? 0 : 1;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IIRC, we have this check in CMake scripts. Can we use a precomp macro here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please reuse WORDS_BIGENDIAN macro (from cvconfig.h)

{
return findDataFile(std::string("dnn/onnx/") + filename, required);
}
void printShape(InputArray blob_)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

unnecessary commit

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thx! Fixed, wrong commit.

@zihaomu zihaomu force-pushed the load_ONNX_fp16_as_fp32 branch from cb62e4f to a970e58 Compare August 24, 2022 03:31
@zihaomu
Copy link
Copy Markdown
Member Author

zihaomu commented Aug 24, 2022

Hi, with the help of ONNX teams, we can load all the ONNX float16 models now!
ONNX saves float 16 data to two different way: int32_t and raw_data.
ONNX convert float to float16

@zihaomu zihaomu force-pushed the load_ONNX_fp16_as_fp32 branch from a970e58 to 7eaec9d Compare August 26, 2022 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants