코드 한 줄 해석
torch.onnx.export(
wrapped_model,
# 변환할 주인공(모델 객체)입니다.
dummy_input,
# 이게 가장 중요합니다. "길잡이 데이터"입니다.
# 이유: 파이토치는 코드를 그냥 읽는 게 아니라,
# 이 데이터가 모델을 한 번 통과하는 길(Trace)을 따라가며 녹화합니다.
# 그래서 실제 데이터와 똑같은 모양(Shape)의 가짜 데이터가 반드시 필요합니다.
onnx_path_v14, # 파일 저장경로
# 예: "mission_16_vit_v14.onnx" 라는 이름으로 저장하라는 뜻입니다.
input_names=["pixel_values"],
# "나중에 찾기 위해서"입니다.
# 이 이름표를 안 붙이면 나중에 ONNX를 실행할 때
# "입력 구멍이 어딘지 몰라서" 데이터를 못 집어넣습니다. (기본값은 'input.1' 같이 어렵게 됨)
output_names=["logits"],
# 이것도 "출구 이름표"입니다.
# 모델이 계산한 결과값이 나오는 구멍에 'logits'라고 이름을 붙여놔야,
# 나중에 결과만 쏙 뽑아낼 수 있습니다.
opset_version=14,
# ONNX의 "문법 버전"입니다.
# 버전이 높을수록 더 복잡하고 최신 연산(Transformer 등)을 지원합니다.
do_constant_folding=True,
# "상수 접기"라는 최적화 기술입니다.
# 예: 모델 안에 '2 + 3'이라는 계산이 있으면,
# 저장할 때 미리 '5'로 계산해서 저장해버립니다. (실행 속도 빨라짐)
dynamic_axes={"pixel_values": {0: "batch_size"}, "logits": {0: "batch_size"}}
# [중요] "가변 차원" 설정입니다.
# 이걸 안 하면 무조건 dummy_input과 똑같이 "이미지 1장"만 처리할 수 있게 고정됩니다.
# {0: "batch_size"} -> "0번째 차원(개수)은 1개든 100개든 마음대로 들어와도 된다"고 허락해주는 겁니다.
)
쉬운 비유 (Analogy)
torch.onnx.export는 "요리 시연 영상 녹화"와 같습니다.
- wrapped_model (요리사): 요리를 할 줄 아는 전문가입니다.
- dummy_input (모형 음식 재료): 요리사가 칼질을 보여주려면 뭐라도 썰어야 하죠? 실제 먹을 건 아니지만 시연용 재료가 필요합니다. 이 재료가 지나가는 과정을 그대로 찍습니다.
- input_names / output_names (재료 투입구 / 완성품 배출구 라벨): 공장에 기계를 설치할 때 **"여기가 쌀 넣는 곳(pixel_values)", "저기가 밥 나오는 곳(logits)"**이라고 스티커를 붙여야 작업자가 헷갈리지 않는 것과 같습니다.
- opset_version (사용 언어): 레시피를 적는데 "옛날 말(v12)"로 적으면 신기술(ViT)을 설명 못 합니다. "최신 표준어(v14)"로 적어야 알아듣습니다.
그렇다면 파이토치 onnx양자화를 할때 왜? dummy_input에 dummy_data를 넣는걸까?
**"양자화(가중치 줄이기)"**와 **"ONNX 변환(설계도 그리기)"**은 서로 다른 작업인데, dummy_input은 설계도를 그리기 위해 반드시 필요합니다.
핵심 팩트부터 말씀드리면:
dummy_input은 양자화(숫자를 8비트로 줄이는 것)를 위해 넣는 게 아니라, 파이토치라는 '투명인간' 모델의 실체를 눈으로 확인하고 지도로 그리기 위해 넣는 것입니다.
이해하기 쉽게 두 가지 측면(비유와 기술적 이유)으로 설명해 드릴게요.
1. 비유: "발자국 추적하기"
파이토치(PyTorch)는 "그때그때 실행하는(Dynamic)" 녀석입니다. 코드가 실행되기 전까지는 모델의 구조가 고정되어 있지 않습니다. 마치 눈 덮인 들판과 같습니다.
- 파이토치: "나는 길이 어디 있는지 몰라. 그냥 네가 가라고 하면 갈게." (유연함)
- ONNX: "나는 정확한 **지도(Map)**가 필요해. 어디서 꺾어야 하고, 거리는 몇 미터인지 다 적어놔야 해." (고정됨)
여기서 dummy_input은 정찰병입니다.
- 눈 덮인 들판(파이토치 모델)에 **정찰병(dummy_input)**을 한 명 보냅니다.
- 정찰병이 모델 내부를 통과하면서 **발자국(Trace)**을 남깁니다. "아, 여기서 곱하기를 했고, 저기서 더하기를 했구나."
- ONNX는 그 **발자국을 그대로 본떠서 지도(Graph)**를 만듭니다.
만약 정찰병(dummy_input)을 안 보내면? 파이토치는 아무것도 실행하지 않은 상태라 발자국이 없고, ONNX는 지도를 그릴 수 없습니다. 그래서 값이 중요한 게 아니라, 지나가는 '형식'이 중요한 것입니다.
2. 기술적 팩트: "Graph Tracing (그래프 추적)"
파이토치 코드는 기본적으로 Python 코드입니다. 파이썬은 인터프리터 언어라 줄 단위로 실행되죠. 반면 ONNX는 **정적 그래프(Static Graph)**라는 고정된 구조체입니다.
dummy_input이 들어가야 하는 진짜 이유는 다음과 같습니다.
① 연결 순서 확정 (Connection)
모델 안에 Conv2d 레이어와 Linear 레이어가 있다고 칩시다. 코드를 그냥 눈으로 보면 알지만, 컴퓨터 입장에서는 데이터가 실제로 흘러봐야 "아! Conv2d에서 나온 결과물이 Linear의 입력으로 들어가는구나!"라고 연결 고리를 확정 지을 수 있습니다.
② 쉐이프(Shape) 확정
이게 가장 중요합니다.
- 파이토치 코드: x = x.view(x.size(0), -1) (그냥 변수로 적혀있음)
- ONNX 파일: Reshape to [1, 768] (정확한 숫자가 필요함)
dummy_input으로 (1, 3, 224, 224)를 넣어줘야, 모델 내부에서 연산이 일어날 때 "아, 이 단계에서는 데이터 크기가 (1, 197, 768)로 변하는구나"라는 것을 계산할 수 있습니다. 데이터가 안 들어가면 중간 단계의 행렬 크기를 알 방법이 없습니다.
3. 요약: 양자화랑은 무슨 상관?
질문하신 내용에 대한 정답입니다.
- dummy_input in torch.onnx.export:
- 목적: 양자화랑 상관없음. 오직 모델의 구조(설계도)를 파일로 만들기 위해 길을 트는 용도.
- 하는 일: 데이터가 흘러가는 파이프라인의 모양(Shape)을 확정 지음.
- 양자화 (Quantization):
- 이건 **설계도가 완성된 후(ONNX 파일이 만들어진 후)**에 일어나는 일입니다.
- 만들어진 지도(ONNX)를 보고 "어? 여기 도로(가중치)가 너무 넓네(32bit)? 좁게(8bit) 줄이자."라고 하는 작업입니다.
'AI 엔지니어준비' 카테고리의 다른 글
| ONNX(Open Neural Network Exchange)🌐 (0) | 2026.01.30 |
|---|---|
| float16(FP16) vs bfloat16(BF16)🥊 (1) | 2026.01.30 |
| BentoML 맛보기! (1) | 2026.01.27 |
| 🆚 지식 증류 & 가지치기 vs 양자화: 언제 누가 이길까? (0) | 2026.01.26 |
| 현업에서 많이 사용하는 양자화 기법에 대해 (0) | 2026.01.24 |