먼저 학습 방식을 정한다
최적화의 출발점은 "어떤 방식으로 학습할 것인가"이다. 일반적인 SFT라면 먼저 QLoRA를 기본값으로 검토한다. QLoRA는 원본 모델을 4비트로 불러오고 LoRA 어댑터만 학습하므로, VRAM이 적은 환경에서도 실험을 시작하기 쉽다. Unsloth 공식 가이드도 대부분의 경우 작은 instruct 모델과 QLoRA로 시작하라고 권한다1.
16비트 LoRA는 4비트보다 메모리를 더 쓰지만 수치 안정성이 필요한 실험에서 유리할 수 있다. Full fine-tuning은 모델 전체를 바꾸므로 조정 폭은 크지만 비용이 높다. FP8 학습은 지원 하드웨어와 런타임 조건이 맞을 때 속도와 메모리 면에서 매력적이지만, 모든 환경의 기본 선택지는 아니다2. 처음에는 load_in_4bit=True, dtype=None, max_seq_length=2048 같은 보수적인 설정으로 기준선을 만든다.
AI 생성 이미지
Unsloth가 빠른 이유를 측정한다
Unsloth의 장점은 단순히 설정값을 줄이는 데 있지 않다. RoPE와 MLP 연산을 위한 커스텀 Triton 커널, padding 낭비를 줄이는 packing 최적화가 학습 처리량과 VRAM 사용량에 영향을 준다. 공식 자료에서는 새 RoPE·MLP 커널과 smart auto packing으로 일반적으로 더 빠른 학습과 VRAM 절감을 기대할 수 있다고 설명한다3.
하지만 중요한 것은 내 환경에서의 숫자다. 같은 모델, 같은 데이터, 같은 시드, 같은 배치 조건으로 비교해야 한다. 기록할 값은 네 가지면 충분하다.
| 항목 | 확인할 내용 |
|---|---|
| 처리량 | 초당 학습 토큰 수 또는 step 시간 |
| 메모리 | nvidia-smi 기준 최대 VRAM |
| 품질 | train loss와 검증 프롬프트 응답 |
| 안정성 | loss 급등, 반복 답변, 형식 붕괴 여부 |
한 번에 여러 설정을 바꾸면 원인을 알 수 없다. 기준 실험을 먼저 저장하고, 이후 하나씩 바꾼다.
긴 컨텍스트는 단계적으로 늘린다
모델이 32K나 128K 컨텍스트를 지원한다고 해서 처음부터 최대 길이로 학습할 필요는 없다. 긴 시퀀스는 VRAM과 시간이 빠르게 늘어난다. 문서 요약, 긴 규정 검색, 장문 대화처럼 실제로 긴 문맥이 필요한 작업이 아니라면 2048부터 시작한다. 이후 4096, 8192처럼 단계적으로 늘리며 평가 점수가 실제로 좋아지는지 확인한다.
긴 컨텍스트가 필요하지만 메모리가 부족하다면 use_gradient_checkpointing="unsloth"를 우선 검토한다. 이 방식은 중간 활성값을 더 효율적으로 관리해 VRAM을 줄이는 대신 약간의 시간 오버헤드가 생길 수 있다. Unsloth는 이 기능으로 더 긴 컨텍스트 학습을 지원한다고 설명한다4. 따라서 "가능한 최대 길이"가 아니라 "품질 향상 대비 비용이 맞는 길이"를 찾는 것이 핵심이다.
짧은 샘플이 많으면 packing을 확인한다
데이터셋에 짧은 질의응답이 많으면 padding 때문에 계산이 낭비된다. 예를 들어 최대 길이가 2048인데 실제 샘플 대부분이 200토큰이라면, 빈 공간을 계산하는 셈이다. 이때 packing=True를 쓰면 여러 짧은 샘플을 한 시퀀스로 묶어 처리량을 높일 수 있다.
다만 packing은 샘플 경계를 다루는 방식이 중요하다. 대화 데이터라면 EOS 토큰이 빠지지 않았는지, assistant 답변에만 loss가 걸리는지, 이전 샘플의 내용이 다음 샘플로 새지 않는지 확인해야 한다. Unsloth의 padding-free 및 smart packing은 이런 경계를 보존하도록 설계되어 있지만, 최종 검증은 사용자의 데이터로 해야 한다3.
하이퍼파라미터는 실험표로 관리한다
배치 크기와 gradient accumulation은 함께 봐야 한다. 유효 배치 크기는 대략 per_device_train_batch_size × gradient_accumulation_steps × GPU 수로 계산한다. VRAM이 부족하면 per-device batch를 줄이고 accumulation을 늘려 비슷한 유효 배치를 맞춘다.
학습률은 QLoRA SFT에서 2e-4 전후로 시작하고, 불안정하면 1e-4, 5e-5처럼 낮춘다. optimizer는 메모리 절약을 위해 adamw_8bit가 자주 쓰인다. BF16을 지원하는 GPU라면 BF16을, 아니면 FP16을 사용해 시작할 수 있다5.
마지막으로 다음 표처럼 실험을 남긴다.
| run | seq | batch | accum | lr | packing | 시간 | 최대 VRAM | 평가 |
|---|---|---|---|---|---|---|---|---|
| base | 2048 | 2 | 4 | 2e-4 | false | |||
| pack | 2048 | 2 | 4 | 2e-4 | true | |||
| long | 4096 | 1 | 8 | 1e-4 | true |
좋은 설정은 loss가 가장 낮은 설정이 아니다. 같은 시간과 메모리 안에서 평가 프롬프트에 안정적으로 답하고, 원하는 형식을 지키며, 재현 가능한 설정이 좋은 설정이다.
참고
1Fine-tuning LLMs Guide | Unsloth Documentation
3⚡3x Faster LLM Training with Unsloth Kernels + Packing
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.