SageMaker에서 모델 학습의 기본 단위는 Training Job이다. 노트북에서 for epoch in ...을 직접 돌리는 대신 "이 데이터로, 이 컨테이너에서, 이 인스턴스로 학습해줘"라고 작업을 던지는 방식이다.
① 인스턴스 프로비저닝 (instance_type × instance_count) ▼② 컨테이너 실행 (ECR 이미지: 빌트인 / 프레임워크 / 커스텀) ▼③ 입력 데이터 로드 (S3 · FSx → File / Pipe / Fast File) ▼④ 학습 수행 ──▶ 체크포인트 ──▶ s3://.../checkpoints/ (Spot 중단 대비) ▼⑤ 모델 아티팩트 업로드 (model.tar.gz → output_path) ▼⑥ 인스턴스 자동 종료 (과금 중단)
단계
일어나는 일
놓치기 쉬운 점
① 프로비저닝
지정한 타입·개수만큼 EC2 인스턴스를 띄운다
여기서부터 과금이 시작된다
② 컨테이너 실행
알고리즘이 담긴 Docker 이미지(ECR)를 내려 실행
빌트인·프레임워크·커스텀 세 갈래
③ 입력 데이터 로드
S3(또는 FSx)에서 학습 데이터를 인스턴스로 가져옴
File 모드는 전부 받기 전까지 학습이 시작되지 않는다
④ 학습 수행
컨테이너가 데이터를 읽어 모델을 학습
지표는 로그로 방출되어야 튜닝·조기 종료가 작동
⑤ 아티팩트 저장
model.tar.gz를 output_path의 S3에 업로드
인스턴스가 사라져도 모델은 S3에 남는다
⑥ 인스턴스 종료
작업이 끝나면 자동으로 내린다
과금 중단. 상시 대기하는 엔드포인트와의 결정적 차이
핵심은 학습이 끝나면 인스턴스가 사라진다는 점이다. 추론 엔드포인트처럼 계속 떠 있지 않다. 그래서 학습은 본질적으로 "잠깐 쓰고 버리는" 배치성 작업이고, 이 특성이 뒤에 나올 Spot 학습과 잘 맞물린다.
이 구조는 "컴퓨팅과 스토리지의 분리"라는 클라우드 설계 원칙의 전형이다. 데이터는 영속적인 S3에 두고, 컴퓨팅은 필요할 때만 띄웠다 내린다. 덕분에 같은 데이터로 인스턴스 타입만 바꿔 여러 실험을 돌릴 수 있고, 학습이 끝난 뒤 비싼 GPU를 계속 켜두는 낭비가 사라진다. 온프레미스에서 GPU 서버를 사두면 안 쓸 때도 감가상각이 도는 것과 정반대다.
Python SDK에서 Training Job은 Estimator 객체로 정의한다. Estimator는 "무엇을, 어디서, 어떻게" 학습할지를 담은 설계도다.
무엇을: image_uri(알고리즘 컨테이너) 또는 entry_point(내 스크립트)
어디서: instance_type·instance_count·role
어떻게: set_hyperparameters()로 넘기는 알고리즘 손잡이
어디에: output_path(모델 아티팩트가 올라갈 S3 경로)
from sagemaker.estimator import Estimatorestimator = Estimator( image_uri=container, # 알고리즘 컨테이너(ECR 이미지) role=role, # SageMaker 실행 IAM 역할 instance_count=1, # 인스턴스 개수 instance_type='ml.m5.xlarge', # 인스턴스 타입 output_path='s3://my-bucket/output/', # 모델 저장 위치 sagemaker_session=session,)estimator.set_hyperparameters( max_depth=5, objective='binary:logistic', num_round=100,)
Estimator에는 크게 세 종류가 있고, 어느 쪽을 고르느냐가 시험에서 답이 갈리는 지점이다.
⚠️ 함정: "내가 쓴 PyTorch 스크립트를 SageMaker에서 학습시키려면?"의 답은 프레임워크 Estimator + entry_point다. 빌트인 컨테이너에 스크립트를 밀어 넣는 선택지가 자주 오답으로 나온다. 반대로 "빌트인에도 없고 프레임워크 컨테이너로도 못 담는 특수 의존성"이라야 커스텀 컨테이너로 내려간다.
from sagemaker.pytorch import PyTorchestimator = PyTorch( entry_point='train.py', # 내 학습 코드 role=role, framework_version='2.0', py_version='py310', instance_count=1, instance_type='ml.g5.xlarge', # GPU 인스턴스 hyperparameters={'epochs': 10, 'lr': 0.001},)
채널마다 데이터가 인스턴스로 어떻게 들어오는지(입력 모드)를 정할 수 있고, 이게 시험 범위에 든다.
입력 모드
동작
적합한 상황
File 모드 (기본)
데이터 전체를 인스턴스 디스크로 다운로드 후 학습 시작
데이터가 작아 디스크에 다 들어갈 때
Pipe 모드
S3에서 데이터를 스트리밍으로 흘려보냄(다운로드 대기 없음)
대용량 데이터, 시작 지연·디스크 절약
Fast File 모드
파일을 즉시 접근하되 필요한 만큼만 스트리밍
File의 편의 + 스트리밍 이점
데이터 저장소도 선택지가 있다.
저장소
성격
고르는 순간
S3
가장 일반적. 대부분의 학습 데이터 출발점
기본값. 데이터 규모가 보통이거나 반복 읽기가 적을 때
FSx for Lustre
초고성능 병렬 파일시스템. 한 번 올려두면 저지연 반복 접근
데이터가 매우 크고 여러 epoch에서 같은 데이터를 반복해 읽어 I/O가 병목일 때
EFS
공유 파일시스템을 마운트해 사용
이미 데이터가 EFS에 올라가 있을 때
⚠️ 함정: "수 TB 데이터를 매 epoch 반복해 읽는 대규모 분산 학습에서 데이터 로딩이 병목"이라는 시나리오가 나오면 답은 FSx for Lustre다. S3 File 모드는 시작 때 전부 다운로드하느라 느리고, Pipe 모드도 매 epoch마다 다시 스트리밍한다. FSx는 한 번 올려두면 저지연 병렬 접근이 되어 반복 읽기에 강하다. 반대로 데이터가 작으면 굳이 FSx를 쓸 필요 없이 S3 File 모드가 단순하고 충분하다.
인스턴스 선택은 비용과 속도를 동시에 좌우한다. 기본 원칙은 알고리즘 성격에 맞추는 것이다.
인스턴스 계열
성격
적합한 학습
ml.m5 (범용 CPU)
CPU·메모리 균형
XGBoost, Linear Learner 등 전통 ML의 기본값
ml.c5 (컴퓨트 최적화 CPU)
연산 성능 위주
CPU 연산이 지배적인 가벼운 학습
ml.g5 (GPU)
중급 GPU 단일/다중
중소형 딥러닝, 사전학습 모델 미세조정
ml.p4 (GPU)
대형 다중 GPU 노드
대형 신경망, 본격 분산 학습
분산 학습은 instance_count를 2 이상으로 주면 시작된다. 쪼개는 대상이 무엇이냐로 두 방식이 갈린다.
분산 방식
무엇을 쪼개나
쓰는 순간
데이터 병렬
데이터를 나눠 각 인스턴스가 같은 모델을 학습
모델은 GPU 한 대에 들어가는데 데이터가 많아 느릴 때
모델 병렬
모델 자체를 나눠 여러 GPU에 배치
모델이 GPU 한 대의 메모리에 안 들어갈 때
estimator = PyTorch( entry_point='train.py', role=role, instance_count=4, # 4대로 분산 학습 instance_type='ml.p4d.24xlarge', distribution={'torch_distributed': {'enabled': True}}, ...)
GPU가 딥러닝에서 빠른 이유는 신경망 학습의 핵심이 거대한 행렬 곱셈이고, GPU는 수천 개 코어로 이런 병렬 연산을 동시에 처리하기 때문이다. 반대로 트리 기반 알고리즘(XGBoost)은 분기 판단이 순차적이라 GPU 이득이 제한적이다(다만 XGBoost도 GPU 가속 옵션은 있다). "딥러닝이면 GPU, 전통 ML이면 CPU"가 기본값이고, 데이터·모델 크기가 한 대를 넘으면 분산을 고려한다는 순서로 외운다.
학습은 잠깐 쓰고 버리는 배치 작업이라 했다. 이 특성을 가장 잘 살리는 게 Managed Spot Training이다. Spot 인스턴스는 AWS의 남는 용량을 크게 할인해 쓰는 방식으로, 온디맨드 대비 최대 90%까지 저렴하다.
단점은 AWS가 용량을 회수하면 인스턴스가 중간에 종료(interruption)될 수 있다는 것이다. SageMaker는 이를 체크포인트로 해결한다. 학습 중간 상태를 주기적으로 S3에 저장해두면, 인스턴스가 회수돼 재시작돼도 마지막 체크포인트부터 이어서 학습한다.
estimator = Estimator( image_uri=container, role=role, instance_count=1, instance_type='ml.m5.xlarge', use_spot_instances=True, # Spot 학습 활성화 max_run=3600, # 최대 학습 시간(초) max_wait=7200, # Spot 대기 포함 최대 대기 시간(초) checkpoint_s3_uri='s3://my-bucket/checkpoints/', # 체크포인트 저장)
max_wait는 반드시 max_run보다 크거나 같아야 한다. Spot은 가용 용량을 기다리는 시간이 추가로 필요하기 때문이다.
checkpoint_s3_uri를 지정하지 않으면 중단 시 처음부터 다시 학습해 오히려 손해일 수 있다.
체크포인트는 저장만으로 끝나지 않는다. 학습 스크립트가 재시작 시 그 경로를 읽어 이어받도록 짜여 있어야 실제로 재개된다.
실제로 얼마나 아꼈는지는 작업 설명(describe)에서 확인한다. boto3로 학습 작업 상태와 과금 시간을 직접 조회할 수 있다.
import boto3sm = boto3.client('sagemaker')desc = sm.describe_training_job(TrainingJobName='my-training-job')print(desc['TrainingJobStatus']) # InProgress / Completed / Failedprint(desc['ModelArtifacts']['S3ModelArtifacts']) # model.tar.gz 위치print(desc['TrainingTimeInSeconds']) # 학습에 쓴 시간print(desc['BillableTimeInSeconds']) # 실제 과금된 시간
Spot을 켜면 BillableTimeInSeconds가 TrainingTimeInSeconds보다 크게 작아진다. 이 두 값의 차이가 곧 절감분이다.
"비용을 줄이되 학습이 중단되어도 손실 없이 재개돼야 한다"는 시나리오의 답은 Spot + 체크포인트다. Spot만 켜고 체크포인트를 안 두면 중단 시 진행분이 날아간다. 반대로 "학습이 절대 중단되면 안 되고 마감이 빡빡하다"면 온디맨드를 쓴다. Spot은 시간에 여유가 있고 재시작이 허용되는 학습에 적합하다는 점이 판단 기준이다.