ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ONNX 변환은 성공했는데 입력 크기를 바꾸면 실패하는 이유
    AI Agent 2026. 9. 28. 21:25
    728x90
    반응형

    배치 하나와 네 개의 입력 행이 같은 Linear(16,4) 모델로 들어가는 도식
    배치 축을 바꾸어도 표본당 특징 16개는 유지하는 입력 계약입니다. 직접 작성한 설명도이며 실행 결과가 아닙니다.

    배치 1로 변환한 모델에 배치 4를 넣었더니 입력 크기가 맞지 않는다는 오류가 납니다. ONNX 파일은 만들어졌지만, 그 파일에 적힌 입력 조건은 아직 배치 1일 수 있습니다. 예시 입력의 shape와 허용할 동적 차원을 분리해 선언하고, 대상 런타임에서 경계 입력까지 비교하세요.

    먼저 오류에 나온 축 번호를 보세요. [4, 16]에서 0번 축은 표본 수, 1번 축은 표본당 특징 수라고 가정하면, 배치를 늘리는 일과 특징을 늘리는 일은 모델에 전혀 다른 요구입니다. 아래에서는 특징 16개로 출력 4개를 계산하는 작은 모델을 예로 듭니다. PyTorch 2.14 공식 문서를 기준으로 작성했으며 실제 ONNX 변환이나 추론 결과는 아닙니다.

    늘릴 축을 하나만 정합니다

    Linear(16, 4)에는 입력 특징 16개에 대응하는 학습 파라미터가 있습니다. 표본을 네 개 쌓아 [4, 16]으로 넣으면 같은 계산을 네 표본에 적용할 수 있습니다. 그러나 [4, 20]은 특징 수부터 달라집니다. 동적 차원 옵션이 선형층의 파라미터까지 새로 만들어 주지는 않습니다.

    이 모델의 입력 약속을 문장으로 먼저 적으면 “float32, 2차원, 특징 16개, 배치만 변경”입니다. 이미지 모델의 높이·너비나 언어 모델의 토큰 길이를 바꾸려면 별도의 약속이 필요합니다. 가령 토큰 길이를 바꾸면서 attention mask 길이는 그대로 두면 입력들 사이의 관계가 깨집니다.

    PyTorch의 내보내기는 예시 입력에서 shape 정보를 얻습니다. 가변 입력이 필요하면 dynamic_shapes로 해당 차원을 지정하라는 것이 공식 ONNX FAQ의 안내입니다. 모든 축을 한꺼번에 가변으로 열기보다 실제 서비스가 바꿔 넣을 축부터 좁히는 편이 오류를 읽기 쉽습니다.

    dynamo 경로에 맞게 선언합니다

    다음은 배치를 1~8로 사용할 계획인 예제입니다. 내보내기 시 사용할 표본은 배치 2로 준비합니다. x는 forward의 인자 이름이며, {0: batch}는 0번 축만 가변으로 선언한다는 뜻입니다.

    import torch
    
    class Projector(torch.nn.Module):
        def __init__(self):
            super().__init__()
            self.projection = (
                torch.nn.Linear(16, 4)
            )
    
        def forward(self, x):
            return self.projection(x)
    
    model = Projector().eval()
    example = torch.randn(2, 16)
    batch = torch.export.Dim(
        "batch", min=1, max=8
    )
    
    program = torch.onnx.export(
        model,
        (example,),
        dynamo=True,
        input_names=["x"],
        output_names=["scores"],
        dynamic_shapes={
            "x": {0: batch}
        },
    )
    program.save("projector.onnx")
    

    이 코드는 ONNX 관련 의존성이 설치된 환경에서 실행할 구성 예시입니다. 파일이 이미 있다면 새 이름이나 빈 작업 폴더를 사용하세요. 배포할 학습 모델의 가중치를 불러오는 코드도 따로 필요합니다. 여기서 만든 선형층은 구조 설명용 초기값을 가집니다.

    PyTorch 2.14에서 dynamo=True는 권장 내보내기 경로이고 dynamic_shapes가 여기에 대응합니다. 예전 예제의 dynamic_axes는 dynamo=False 경로와 구분해서 읽어야 합니다. input_names에 이름을 붙이는 것만으로 가변 차원이 되지도 않습니다. torch.onnx.export 매개변수

    또 Dim의 범위를 서비스 요청 검증기로 대신 쓰면 안 됩니다. 내보내기 중 필요한 shape 제약과 배포 런타임이 실제로 거부하는 입력 범위는 따로 확인해야 합니다. 서비스가 배치 8까지만 받기로 했다면 요청 처리에서도 그 조건을 검사하세요. 동적 차원과 제약

    파일을 만든 다음에는 입력을 바꿔 비교합니다

    검증용 입력은 세 부류로 나눌 수 있습니다. 먼저 예시와 같은 [2, 16]으로 변환 전후가 맞는지 확인합니다. 이어 [1, 16], [4, 16], [8, 16]으로 배치만 바꿉니다. 마지막으로 [4, 20]과 배치 9처럼 서비스 약속을 벗어난 입력이 적절한 단계에서 거부되는지 확인합니다.

    정상 입력에서는 오류 없이 실행되는지만 보지 말고 출력 shape와 값도 비교하세요. 위 모델이라면 배치 N에서 출력 shape는 [N, 4]여야 합니다. 같은 입력과 같은 가중치로 얻은 PyTorch 결과와 런타임 결과를 정한 허용 오차 안에서 대조합니다. 작은 모델의 오차 기준을 다른 정밀도나 큰 모델에 그대로 옮기지는 않습니다.

    오류가 생긴 위치도 남겨 두면 다음 수정이 달라집니다. 내보내기 중 제약 오류가 났다면 모델 연산과 선언이 맞는지 봅니다. ONNX 로딩 단계에서 실패했다면 대상 런타임이 지원하는 opset과 연산자를 확인합니다. 모델은 열리지만 요청할 때 실패한다면 입력 이름·자료형·축별 크기를 실제 전달값과 대조합니다.

    verify=True 옵션은 ONNX Runtime 검증을 요청할 수 있지만, 서비스에서 받을 모든 크기를 대신 시험한 것은 아닙니다. 공식 검증 옵션과 별도로 경계 입력 목록을 유지해야 배치 크기 변경 후의 문제를 놓치지 않습니다.

    지금 배치 4에서 막혔다면 우선 저장된 모델이 기대하는 입력 shape를 확인하세요. 배치 축이 고정돼 있으면 내보내기 선언을 고치고, 이미 가변이라면 실패한 축과 연산을 좁혀 가면 됩니다. 특징 16을 유지한 채 배치 1·4·8의 출력까지 비교한 기록이 있어야 이 모델의 배치 크기를 바꿔 배포할 근거가 생깁니다.

    728x90
    반응형
Designed by Tistory.