개요
ONNX는 추론(inference)에 중점을 둔 확장가능한 계산 그래프 모델임.
신경망을 사용한 딥러닝은 데이터 흐름 그래프(dataflow graph)에 대한 계산을 통해 수행됨. 일부 프레임워크(CNTK, Caffe2, Theano 및 TensorFlow)는 정적 그래프(static graph)를 사용하는 반면, 다른 프레임워크(Pytorch 및 Chainer)는 동적 그래프(dynamic graph)를 사용함.
- 정적 계산 그래프 : 계산 그래프를 정의한 뒤 데이터를 흘려보냄.
- 즉, 계산 그래프 정의는 사용자가 제공하고, 프레임워크는 주어진 그래프를 컴퓨터가 처리할 수 있는 형태로 변환하여 데이터를 흘려보냄.
- 계산 그래프 정의시, 실시간 계산이 이뤄지지 않음. 즉, ‘수치’가 아닌 ‘기호’를 대상으로 프로그래밍(심볼릭 프로그래밍)
장점 : 성능 - 계산 그래프를 최적화하면 성능도에 따라 최적화됨. 또한 데이터를 흘려보내기 전, 전체 계산 그래프가 파악되므로 전체를 고려하여 최적화할 수 있음. 분산학습시 유리.
- 동적 계산 그래프 : 데이터를 흘러보냄으로써 계산 그래프가 정의됨.
- 데이터 흘러보내기와 계산 글프 구축이 동시에 이뤄지는 것이 특징
장점 : 넘파이를 사용할 때와 같은 방식으로 수치 계산이 가능함. 계산 그래프를 컴파일하여 변화할 필요 없음. 파이썬 프로그램 형태로 실행되기 때문에 디버깅에 유리.
이처럼 오늘날 각 프레임워크는 모두 유사한 기능을 제공하지만, 고유한 그래프 표현을 가지고 있음. 또한 모든 프레임워크는 빠른 훈련(Training), 복잡한 네트워크 아키텍처 지원, 모바일 장치에서의 추론 등과 같은 일부 특성들에 각각 다르게 최적화 되어있음. 어떠한 프레임워크를 사용할지는 그 특성과 진행중인 프로젝트의 성질에 따라 달라지며, 종종 추가 개발을 통한 변환이 필요한 경우도 발생하고, 이로인해 지연현상이 발생함.
위에서 기재된 문제를 해결하기 위해, Common IR(Intermediate Representation)인 ONNX(개방형 신경망 교환)방식을 제안함.
ONNX Intermediate Representation (ONNX IR) Specification
ProtoBuf를 사용한 직렬화
- ONNX를 읽어드릴 때는 어떠한 기준으로 이를 저장해야된다. 이때 ONNX는 Protobuf라는 구조화된 데이터 직렬화 방식으로 인공신경망의 Weight 정보를 저장함.
.proto
또는.proto3
확장자로 정의됨
- Protobuf는 구조화된 직렬화에서 사용할 수 있는 가볍고 효율적인 구조적 데이터 스토리지 방식임.
- Protobuf는 데이터 저장 또는 데이터 교환 형식에 매우 적합함.
- 통신 프로토콜, 데이터 저장소 등 분야에서 사용할 수 있으며, 언어 독립적, 플랫폼 독립적 및 확장 가능한 직렬화 구조 데이터 형식임.
- 현재 API는 C++, Java, Python 3개 언어로 제공되고 있음.
- Protobuf는 *.proto 을 기본으로하며, 문서는 사용자 정의화된 데이터 구조로 되어있음.
ONNX 구성 요소
- 확장 가능한 계산 그래프 모델 정의
- 표준 데이터 타입의 정의
- 내장 연산자 정의
onnx.proto의 핵심 요소
- ModelProto
- GraphProto
- NodeProto
- AtrributeProto
- ValueInfoProto
- TensorProto
IR6
버전의 ONNX는 추론(inference)에만 사용가능했지만, IR7
부터는 훈련(training)도 지원함.ONNX의 구조를 보기 위해 ONNX 깃허브의 onnx.proto를 참고하면 되는데, 해당 문서는 ONNX 데이터 프로토콜 및 기타 정보가 들어있음.
ONNX를 로딩하면, ModelProto
를 얻을 수 있는데, 여기에는 버전관련 정보, 생성자 정보 및 GraphProto
이 들어있음.
GraphProto
에는 node(NodeProto
), input(ValueInfoProto
타입), output(ValueInfoProto
타입) 및 initializer(TensorProto
타입)등 4개의 repeated 수열(Array)이 들어있음.
Node
에는 모델의 모든 계산 노드가 포함됨.
input
에는 모델의 input 노드가 포함됨.
output
에는 모델의 output 노드가 포함됨.
initializer
에는 모델의 모든 weight param이 포함됨.
인공신경망의 완벽한 전달을 위해선 각 노드에 대한 정보 뿐만이 아닌, topology관계도 알아야됨.
ONNX에서의 topology관계 표현방법:
- ONNX의 매 계산 노드 별 input과 output 두 수열(Array)이 String타입으로 존재하며, input과 output의 포인팅 관계를 통해 인공신경망의 topology를 만들 수 있음.
- 각 계산 노드에는
AttributeProto
수열도 포함되어 있는데, 이는 각 노드의 속성을 나타냄.- 예를들어, Conv노드의 속성에는 Group, pad, Strides 가 포함되어있음.
- 여기서 주의할 점은,
GraphProto
에 있는 input 수열에는 모델의 모든 가중치(W)도 포함되어있음.- 예를들어, Conv Layer에서 가중치 W엔티티는
initializer
에 저장되며, input에 또한 동일한 이름으로 입력됨 .이는 가중치를 모델의 입력으로 보고, initializer의 가중치 엔티티를 통해 해당 입력에 대해 초기화, 즉 값을 할당하는 과정이라 볼 수 있음.
- 예를들어, Conv Layer에서 가중치 W엔티티는
IO관련된 자세한 설명은 https://github.com/onnx/onnx/blob/master/docs/Operators.md 에서 확인가능함.
Reference
https://onnx.ai/onnx/intro/concepts.html
https://github.com/onnx/onnx/blob/main/docs/Overview.md
https://zhuanlan.zhihu.com/p/346511883
https://zhuanlan.zhihu.com/p/456124635
https://zhuanlan.zhihu.com/p/371177698
https://xxxxxxxxxxxxxxxxx.tistory.com/entry/밑바닥부터-시작하는-딥러닝3-딥러닝-프레임워크의-동작-방식