꾸준희
Enough is not enough
꾸준희

공지사항

  • 꾸준희 블로그
전체 방문자
2,416,075
오늘
2,018
어제
2,910
  • 분류 전체보기 (592)
    • Book Review (39)
    • Paper Review (23)
    • AI Research Topic (127)
      • Deep Learning (24)
      • Pose Estimation (29)
      • Object Detection (22)
      • Object Segmentation (3)
      • Object Tracking (11)
      • Video Surveillance (4)
      • Action Recognition (6)
      • Stereo Vision (6)
      • 3D Reconstruction (5)
      • Machine Vision (2)
      • Image Processing (11)
      • Dataset (4)
    • AI Development (77)
      • NVIDIA DeepStream (3)
      • NVIDIA TensorRT (30)
      • NVIDIA TAO Toolkit (2)
      • ONNX (9)
      • PyTorch (5)
      • TensorFlow (15)
      • TensorFlow Lite (1)
      • GPU | CUDA | PyCUDA (12)
    • Programming (147)
      • GStreamer | FFmpeg (6)
      • Python (27)
      • C | C++ (15)
      • OpenCV (34)
      • Linux (36)
      • Embedded linux (7)
      • Etc. (22)
    • Computer Science (64)
      • 학부 및 대학원 과목 (22)
      • 선형대수학 및 기타 수학 (9)
      • SQL-D (33)
    • 삽질 기록 (50)
    • 생각 (15)
    • 기타 (50)
      • 참고자료 (30)
      • 좋은 글 (5)
      • 티스토리 (2)
      • 논문 작성 관련 참고 (10)
      • 메모 (0)

블로그 메뉴

  • 👀 CV
  • 🌸 GitHub
  • 💌 LinkedIn
  • 📚 방명록

최근 댓글

  • 넵 저도 여기다 써놓고 두고두⋯
    꾸준희
  • 되게 헷갈리고 볼때마다 찾던⋯
    옐로우씨
  • 아뇨 ㅠ 저도 어디서 가져온거⋯
    꾸준희
  • 앗 감사합니다 🙇🏻‍♀️
    꾸준희
  • 항상 보면서 존경스럽습니다!⋯
    버터미소
08-18 17:12

티스토리

hELLO · Designed By 정상우.
꾸준희

[ONNX] ONNX Simplifier 사용하여 모델 간소화 하기
AI Development/ONNX

[ONNX] ONNX Simplifier 사용하여 모델 간소화 하기

2021. 7. 26. 18:13
728x90
반응형

 

 

ONNX Simplifier 는 복잡한 ONNX node 들 즉 ONNX 모델을 단순하게 만들어주는 툴이다. 

전체 계산 그래프(the whole computation graph)를 추론한 다음 중복 연산자(the redundant operators)를 상수 출력(their constant outputs)으로 대체한다. 

 

 

아래 그림의 왼쪽 그림은 어떤 모델의 ONNX 원본 모델이고, 오른쪽 그림은 onnx simplifier를 거친 ONNX 모델이다. 

(잘 보이진 않지만... 자세히 들여다보면 간소화 된 모습을 볼 수 있었다... 모델 크기도 줄어든다.)

 

 

 

 

 

아래 그림을 보면 더 명확히 와닿는다. 이런 느낌이다.

불필요한 Gather 및 Unsqueeze 연산자 등의 조합을 Reshape 으로 대체한다. 

원래 이런 툴이 나오기 전에는 일일히 노드들을 Reshape 으로 대체하곤 했다.. 

 

 

 

 

 

 

 

ONNX Simplifier 설치

$ pip3 install -U pip && pip3 install onnx-simplifier

 

ONNX Simplifier 사용

$ python3 -m onnxsim input_onnx_model output_onnx_model

 

ONNX Simplifier 옵션 보기

$ python3 -m onnxsim -h

 

 

 

API 는 아래와 같이 구성되어있다. 

import argparse
import sys

import onnx     # type: ignore
import onnxsim
import numpy as np


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input_model', help='Input ONNX model')
    parser.add_argument('output_model', help='Output ONNX model')
    parser.add_argument('check_n', help='Check whether the output is correct with n random inputs',
                        nargs='?', type=int, default=3)
    parser.add_argument('--enable-fuse-bn', help='This option is deprecated. Fusing bn into conv is enabled by default.',
                        action='store_true')
    parser.add_argument('--skip-fuse-bn', help='Skip fusing batchnorm into conv.',
                        action='store_true')
    parser.add_argument('--skip-optimization', help='Skip optimization of ONNX optimizers.',
                        action='store_true')
    parser.add_argument(
        '--input-shape', help='The manually-set static input shape, useful when the input shape is dynamic. The value should be "input_name:dim0,dim1,...,dimN" or simply "dim0,dim1,...,dimN" when there is only one input, for example, "data:1,3,224,224" or "1,3,224,224". Note: you might want to use some visualization tools like netron to make sure what the input name and dimension ordering (NCHW or NHWC) is.', type=str, nargs='+')
    parser.add_argument(
        '--skip-optimizer', help='Skip a certain ONNX optimizer', type=str, nargs='+')
    parser.add_argument('--skip-shape-inference',
                        help='Skip shape inference. Shape inference causes segfault on some large models', action='store_true')
    parser.add_argument('--dynamic-input-shape', help='This option enables dynamic input shape support. "Shape" ops will not be eliminated in this case. Note that "--input-shape" is also needed for generating random inputs and checking equality. If "dynamic_input_shape" is False, the input shape in simplified model will be overwritten by the value of "input_shapes" param.', action='store_true')
    parser.add_argument(
        '--input-data-path', help='input data, The value should be "input_name1:xxx1.bin"  "input_name2:xxx2.bin ...", input data should be a binary data file.', type=str, nargs='+')
    parser.add_argument(
        '--custom-lib', help="custom lib path which should be absolute path, if you have custom onnxruntime backend you should use this to register you custom op", type=str)

    args = parser.parse_args()

    print("Simplifying...")

    if args.dynamic_input_shape and args.input_shape is None:
        raise RuntimeError(
            'Please pass "--input-shape" argument for generating random input and checking equality. Run "python3 -m onnxsim -h" for details.')
    if args.input_shape is not None and not args.dynamic_input_shape:
        print("Note: The input shape of the simplified model will be overwritten by the value of '--input-shape' argument. Pass '--dynamic-input-shape' if it is not what you want. Run 'python3 -m onnxsim -h' for details.")
    input_shapes = dict()
    if args.input_shape is not None:
        for x in args.input_shape:
            if ':' not in x:
                input_shapes[None] = list(map(int, x.split(',')))
            else:
                pieces = x.split(':')
                # for the input name like input:0
                name, shape = ':'.join(
                    pieces[:-1]), list(map(int, pieces[-1].split(',')))
                input_shapes.update({name: shape})

    input_data_paths = dict()
    if args.input_data_path is not None:
        for x in args.input_data_path:
            pieces = x.split(':')
            name, data = ':'.join(pieces[:-1]), pieces[-1]
            input_data_paths.update({name: data})

    input_tensors = dict()
    if len(input_data_paths) > 0 and args.input_shape is not None:
        for name in input_shapes.keys():
            input_data = np.fromfile(input_data_paths[name], dtype=np.float32)
            input_data = input_data.reshape(input_shapes[name])
            input_tensors.update({name: input_data})

    model_opt, check_ok = onnxsim.simplify(
        args.input_model,
        check_n=args.check_n,
        perform_optimization=not args.skip_optimization,
        skip_fuse_bn=args.skip_fuse_bn,
        input_shapes=input_shapes,
        skipped_optimizers=args.skip_optimizer,
        skip_shape_inference=args.skip_shape_inference,
        input_data=input_tensors,
        dynamic_input_shape=args.dynamic_input_shape,
        custom_lib=args.custom_lib)

    onnx.save(model_opt, args.output_model)

    if check_ok:
        print("Ok!")
    else:
        print("Check failed, please be careful to use the simplified model, or try specifying \"--skip-fuse-bn\" or \"--skip-optimization\" (run \"python3 -m onnxsim -h\" for details)")
        sys.exit(1)


if __name__ == '__main__':
    main()

 

 

 

 

 

참고자료 : https://github.com/daquexian/onnx-simplifier

 

GitHub - daquexian/onnx-simplifier: Simplify your onnx model

Simplify your onnx model. Contribute to daquexian/onnx-simplifier development by creating an account on GitHub.

github.com

 

728x90
반응형
저작자표시비영리
  • 카카오스토리
  • 트위터
  • 페이스북

'AI Development > ONNX' 카테고리의 다른 글

[ONNX] Brevitas, QAT 모델을 Standard ONNX 모델로 생성하는 라이브러리  (0) 2022.07.04
[ONNX] ONNX Simplifier 사용하여 모델 간소화 하기  (8) 2021.07.26
[ONNX] Pytorch 모델을 ONNX 모델로 변환 할 때 dynamic_axes 지정하는 방법  (0) 2021.06.29
[ONNX] ONNX 배치 사이즈 변경하는 방법 + 삽질  (3) 2021.02.02
[ONNX] Pytorch 모델을 ONNX 모델로 변환하기  (4) 2020.08.23
[ONNX] onnx-graphsurgeon 이용하여 plugin 사용하기 - Group Normalization  (3) 2020.07.21
    'AI Development/ONNX' 카테고리의 다른 글
    • [ONNX] Brevitas, QAT 모델을 Standard ONNX 모델로 생성하는 라이브러리
    • [ONNX] Pytorch 모델을 ONNX 모델로 변환 할 때 dynamic_axes 지정하는 방법
    • [ONNX] ONNX 배치 사이즈 변경하는 방법 + 삽질
    • [ONNX] Pytorch 모델을 ONNX 모델로 변환하기
    꾸준희
    꾸준희
    생각과 기록 그리고 발전
    댓글쓰기
    1. seob2
      2021.07.28 22:50 신고
      혹시 이거하구 나서 tensorrt로 변환 해보셨나요?
      수정/삭제댓글쓰기댓글보기
      1. 꾸준희
        2021.07.29 00:08 신고
        네네 해봤는데 변환되는지 여부만 확인해봤어요~
        수정/삭제
    2. seob2
      2021.07.29 00:10 신고
      오.. 답변감사합니다 한번 속도비교도 해봐야겠네요
      수정/삭제댓글쓰기댓글보기
      1. 꾸준희
        2021.07.29 08:40 신고
        넵넵 저도 해볼게요~~
        수정/삭제
    3. seob2
      2021.07.29 15:58 신고
      모델에따라 굉장히 편차가 크겠지만 제가 쓰는모델은 속도 향상이있네요 좋은정보 공유 감사합니다
      수정/삭제댓글쓰기댓글보기
      1. 꾸준희
        2021.07.29 21:06 신고
        아하 그렇군요~~ 참고하겠습니다~~ 감사합니다 ^^
        수정/삭제
    4. RS
      2022.06.21 16:46
      onnx 간소화한 모델과 안한 모델의 성능 차이가 있을까요?
      수정/삭제댓글쓰기댓글보기
      1. 꾸준희
        2022.06.27 00:00 신고
        안녕하세요 제가 바빠서 답변을 늦게 드렸네요! onnx simplifier의 방식이 전체 그래프를 살핀 뒤에 중복된 연산자들(operator)을 constant 로 대체하는 것이기 때문에 정확도에 영향은 없을 것 같고(제 의견입니다) 속도 측면에서는 조금 더 빨라집니다. (깃헙 이슈 참고했어요)

        https://github.com/daquexian/onnx-simplifier/issues/51
        수정/삭제
    다음 글
    [ONNX] Brevitas, QAT 모델을 Standard ONNX 모델로 생성하는 라이브러리
    이전 글
    [ONNX] Pytorch 모델을 ONNX 모델로 변환 할 때 dynamic_axes 지정하는 방법
    • 이전
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • ···
    • 9
    • 다음

    티스토리툴바