hyunsu blog

홈강좌LAYA 결정 모델 24편 중 7편째

맥북에서 LAYA 미세조정 — 학습 과정의 로그를 한 줄씩 읽는다

목차 · 4
  1. 01명령 한 줄
  2. 02학습 로그 읽기
  3. 03만들어진 파일
  4. 04실습 — 걸린 시간과 메모리

laya-train 한 줄로 맥북의 GPU(MPS)에서 LAYA 를 학습시킨다. 처음 사람이 라벨을 붙인 150건으로 학습했고, 약 1분이 걸렸다. 이 편은 학습이 출력하는 로그를 한 줄씩 읽는다. 학습이 잘 됐는지 판단하는 재료가 모두 이 로그에 있다.

01 명령 한 줄

6편의 학습용 600건 가운데 처음 150건(first-150.jsonl)만 쓴다. 실제로도 처음에는 사람이 라벨을 붙인 데이터가 많지 않다. 나머지는 9편부터 "운영에서 모으는" 데이터로 쓴다.

bash
laya-train --data first-150.jsonl --base multilingual \
  --out checkpoints/v1 --eval tickets-eval.jsonl
  • --base multilingual — 한국어를 읽는 다국어 체크포인트에서 시작한다(4편).
  • --out checkpoints/v1 — 학습한 모델을 저장할 곳. 첫 판이라 v1 이다.
  • --eval tickets-eval.jsonl — 학습 전후를 같은 평가 데이터로 비교한다. 이것을 빼면 학습용에서 떼어 낸 몇십 건으로만 재는데, 8편에서 보듯 그 숫자는 믿을 수 없다.

02 학습 로그 읽기

text
eval items 400 from tickets-eval.jsonl (skipped {}, 0 overlapping training/calibration items)
train items 270, calibration items 30, eval items 400 (tickets-eval.jsonl), skipped {}, device mps
optimizer budget: 270 train item(s), effective batch up to 64 (micro_batch 8 x grad_accum 8), 20 optimizer updates over 4 epoch(s)
epoch 1/4 mean loss 0.3581
epoch 2/4 mean loss -0.0395
epoch 3/4 mean loss 0.0608
epoch 4/4 mean loss -0.0695
.venv/lib/python3.12/site-packages/laya/train_cli.py:221: RuntimeWarning: laya.train: choice calibration: fitted on only 14 calibration items
  summary = finetune(
.venv/lib/python3.12/site-packages/laya/train_cli.py:221: RuntimeWarning: laya.train: choice calibration: the fit came back unchanged at 1.0 (accuracy 1.00, mean confidence 1.000 on the calibration items), which usually means they gave it nothing to correct; this type's confidences are uncalibrated
  summary = finetune(
.venv/lib/python3.12/site-packages/laya/train_cli.py:221: RuntimeWarning: laya.train: noul calibration: fitted on only 16 calibration items
  summary = finetune(
.venv/lib/python3.12/site-packages/laya/train_cli.py:221: RuntimeWarning: laya.train: noul calibration: the fitted temperature 0.5 is on the [0.5, 5] clamp
  summary = finetune(

=== Evaluation (before vs after fine-tuning on 400 held-out items from tickets-eval.jsonl) ===
Metric                 Before         After          Delta         
-----------------------------------------------------------------
Accuracy               0.6050         0.8750         +0.2700       
Loss                   1.1901         0.7915         -0.3986       
ECE                    0.2664         0.1034         -0.1630       
Brier (multi-class)    0.6079         0.2188         -0.3891       
Brier (top-1)          0.2897         0.1081         -0.1816       
Mean Confidence        0.8714         0.9769         +0.1055       
-----------------------------------------------------------------

Training complete! Model saved to checkpoints/v1
그림 1.v1 학습 손실 — 에폭마다
mean loss−0.10.00.10.20.30.412341: 0.35812: −0.03953: 0.06084: −0.06950.3581−0.0695mean loss−0.10.00.10.20.30.412341: 0.35812: −0.03953: 0.06084: −0.06950.3581−0.0695

RLCD 손실은 음수도 나온다 — 크게 줄어드는 흐름을 본다

숫자로 보기
항목mean loss
10.3581
2-0.0395
30.0608
4-0.0695

1. 준비(1~3번째 줄)

  • 평가 400건 — 평가 문의 200건 × 질문 2개다. 학습·보정 데이터와 겹치는 것이 0건이라고 확인해 준다.
  • 학습 270건·보정 30건 — 150건 × 질문 2개 = 300건 가운데 10% 를 보정용으로 먼저 떼어 둔다. device mps 가 맥의 GPU 로 돌고 있다는 표시다.
  • 업데이트 20번 — 8건씩 8번 모아 한 번 고치니(유효 배치 64) 한 바퀴(에폭)에 5번, 4바퀴에 20번 모델을 고친다.

2. 에폭마다 손실(4~7번째 줄)

손실(loss)은 "얼마나 틀렸나" 를 나타내는 값이다. 0.3581 → -0.0395 → 0.0608 → -0.0695 로 크게 줄었다. 음수가 나오는 것은 정상이다. LAYA 의 기본 학습 방식(RLCD)은 맞힐수록 보상을 주는 강화학습 항이 손실에 들어가서, 일반적인 분류 손실처럼 0 에서 멈추지 않는다. 손실은 위아래로 흔들려도 크게 줄어드는 흐름이면 된다.

3. 보정 경고(8~15번째 줄)

학습이 끝나면 떼어 둔 보정용 30건으로 "확신을 얼마나 낮출지(온도)" 를 맞춘다(1편의 보정). 경고가 넷 나왔다.

  • choice(팀) 보정에 14건뿐이다(fitted on only 14).
  • 그 14건을 모두 확신 1.000 으로 맞혀서, 고칠 것이 없어 온도가 1.0 그대로다. 그래서 팀 질문의 확신은 보정되지 않았다(uncalibrated).
  • noul(서두름) 보정도 16건뿐이고, 맞춘 온도가 허용 범위 끝(0.5)에 걸렸다.

데이터가 적으면 보정이 제대로 안 된다는 뜻이다. 이 경고를 무시하면 9편에서 실제로 대가를 치른다.

4. 전후 비교 표(17~26번째 줄)

지표뜻학습 전 → 후
Accuracy맞힌 비율0.6050 → 0.8750
Loss정답에 준 확률의 로그 손실(작을수록 좋다)1.1901 → 0.7913
ECE확신과 실제 정답률의 차이(작을수록 좋다)0.2664 → 0.1034
Brier확률의 오차 제곱(작을수록 좋다)0.6079 → 0.2188
Mean Confidence평균 확신0.8714 → 0.9769

모든 지표가 좋아졌다. 다만 이 표는 팀과 서두름 두 질문을 합친 숫자다. 서두름은 말끝("빨리 확인 부탁드려요.")만 보면 되는 쉬운 질문이라 합친 정확도를 끌어올린다. 팀만 따로 보는 것은 다음 편에서 한다.

03 만들어진 파일

bash
cd checkpoints/v1 && du -sh * | sort -k2
text
647M	checkpoint_latest
4.0K	encoder
614M	model.safetensors
4.0K	questions.json
8.0K	rl_agent_config.json
 33M	tokenizer
4.0K	train_report.json
  • model.safetensors(614MB) — 학습한 가중치. 이것이 모델 본체다.
  • encoder/·tokenizer/·rl_agent_config.json — 모델 구조·글자 쪼개는 규칙·설정(보정 온도 포함).
  • questions.json — 학습에 쓴 질문 모양. 서비스에서 똑같이 물어야 한다(6편).
  • train_report.json — 이 로그의 숫자들을 기록한 파일. 9~11편에서 판(版)을 비교할 때 쓴다.
  • checkpoint_latest/(647MB) — 에폭이 끝날 때마다 덮어쓰는 백업이다. 학습이 중간에 끊겨도 한 에폭만 잃게 해 준다. 학습이 끝난 뒤에는 필요 없어서, 배포할 때 빼면 크기가 절반으로 준다(14편).

04 실습 — 걸린 시간과 메모리

같은 학습을 한 번 더 돌려 걸린 시간과 가장 많이 쓴 메모리를 쟀다.

text
       59.77 real        18.13 user         6.93 sys
         10559965896  peak memory footprint

Apple Silicon 맥북에서 약 1분, 메모리는 가장 많을 때 약 10GB 였다(real 은 초, peak memory footprint 는 바이트). 데이터가 늘면 시간은 거의 건수에 비례해 는다. 메모리는 배치 크기(--micro-batch)와 문장 길이(--max-len)에 좌우되니, 메모리가 16GB 인 맥에서 모자라면 --micro-batch 4 로 줄인다.

이제 학습 데이터 150건으로 v1 이 생겼다. 다음 편에서 팀 질문만 따로 재고, 데이터가 적을 때·라벨이 틀렸을 때·너무 오래 학습했을 때 어떻게 되는지 실제로 돌려 본다.