모델 학습 설정과 라우트
model_training 블록의 모든 키, 실행이 대기열에 들어가 점수가 매겨지고 저장되는 방식, 관리자 및 에이전트 라우트, 흔한 실행 오류의 해결 방법을 설명합니다.
v2.14.0의 새 기능
이 페이지는 Potato 설정의 model_training 블록과 실행을 시작한 뒤 그 실행에 일어나는 일을 다루는 레퍼런스입니다. 연구를 운영하면서 실행 횟수를 제한하거나, 실행을 다른 머신으로 보내거나, 모델의 예측을 어노테이터에게 보여 주거나, 스크립트에서 학습을 시작하려는 사람을 위해 쓴 페이지입니다. 아래의 모든 키, 기본값, 라우트, 메시지는 Potato의 코드와 대조해 확인했습니다. 첫 실행은 첫 모델 학습시키기부터 시작하십시오. 트레이너와 트레이너의 파라미터는 트레이너에 나열되어 있습니다.
전체 설정 예시
아래 설정은 상품 리뷰로 감성 분류기를 학습시킵니다. auto_retrain은 새 어노테이션 25개마다 sklearn-text를 다시 맞춥니다. 기본 TF-IDF 특징을 쓰는 sklearn-text는 CPU에서 학습하며 기본 Potato 설치 외에 아무것도 필요 없습니다. 따라서 잦은 자동 실행도 비용이 거의 들지 않습니다. 되쓰기는 신뢰도가 0.8 이상인 모든 예측을 어노테이터에게 보여 줍니다. include_unlabeled를 지정하면 실행은 아직 아무도 레이블을 달지 않은 리뷰도 예측합니다. hf-text-classification 기본값과 gpu-server 백엔드는 Training 페이지에서 직접 시작한 실행에 쓰입니다.
annotation_task_name: "Review sentiment with model training"
task_dir: "."
data_files:
- "data/reviews.json"
item_properties:
id_key: "id"
text_key: "text"
output_annotation_dir: "annotation_output"
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: "radio"
name: "sentiment"
description: "Is this review positive or negative?"
labels: ["positive", "negative"]
model_training:
enabled: true
split_seed: 0
splits: {train: 0.7, val: 0.15, test: 0.15}
aggregation: consensus
retain_runs: 5
queue_max: 10
max_wall_seconds: 3600
max_ram_mb: 8192
num_threads: 4
trainer_params:
sklearn-text:
classifier: sklearn.linear_model.LogisticRegression
classifier_kwargs: {max_iter: 1000}
hf-text-classification:
model_name: answerdotai/ModernBERT-base
epochs: 4
lora: true
auto_retrain:
enabled: true
trainer: sklearn-text
schemas: [sentiment]
min_interval_s: 600
update_frequency: 25
writeback:
schemas: [sentiment]
min_confidence: 0.8
include_unlabeled: true
backends:
gpu-server:
type: ssh
host: gpu-server
python: /opt/conda/bin/python3
gpus: auto
min_free_gpu_mb: 4000split_seed는 연구가 지속되는 동안 고정해 두십시오. 시드를 바꾸면 모든 항목이 다시 배정되어, 홀드아웃이던 항목이 학습에 들어가고 이후 점수를 이전 점수와 비교할 수 없게 됩니다. min_confidence의 하한 0.8은 출발점일 뿐이며, 알맞은 값은 첫 홀드아웃 점수에 따라 달라집니다. 사전 레이블은 어노테이터를 모델의 답에 고착시키므로, 그 점수가 사전 레이블을 보여 줘도 좋다고 뒷받침할 때 include_unlabeled를 켜십시오.
model_training의 키
모든 키는 model_training 아래에 있습니다.
| 키 | 기본값 | 의미 |
|---|---|---|
enabled | false | Training 페이지, /admin/training 아래의 라우트, /api/training 아래의 에이전트 라우트를 등록합니다. enabled: true가 없으면 라우트가 존재하지 않습니다. |
retain_runs | 5 | 실행 원장에 남겨 두는 완료된 실행의 수입니다. 실행의 예측이 아직 저장되어 있지 않다면 오래된 실행은 원장에서 빠집니다. 실행 디렉터리는 디스크에 남습니다. |
grace_seconds | 20 | 취소된 실행이 Potato가 프로세스를 강제 종료하기 전에 종료할 수 있는 시간(초)입니다. 0 이상이며, 작업과 함께 ssh, slurm, agent 유형의 백엔드로 전송됩니다. |
queue_max | 10 | 진행 중인 실행 뒤에서 기다릴 수 있는 실행의 수입니다. |
split_seed | 0 | 항목을 train, val, test 분할에 배정하는 시드입니다. |
splits | {train: 0.7, val: 0.15, test: 0.15} | 분할 비율이며 합이 1이 되도록 정규화됩니다. 이름은 train, val, test이고 train은 필수입니다. |
aggregation | consensus | 한 항목에 여러 어노테이터가 단 레이블을 하나의 레이블로 만드는 방법입니다. consensus는 연구에 어노테이터가 둘 이상이면 Dawid-Skene 모델을 맞추고, 맞추기에 실패하면 다수결로 되돌아갑니다. majority는 다수결을 택합니다. |
max_wall_seconds | 설정 안 됨 | 실행 하나의 시간 제한입니다. Potato는 로컬 실행을 실행이 이벤트를 보고할 때마다, ssh나 에이전트 실행을 1초마다 확인합니다. |
max_ram_mb | 설정 안 됨 | setrlimit으로 설정하는 학습 프로세스의 주소 공간 제한입니다. 이 제한이 없는 플랫폼에서는 실행이 경고를 로그에 남기고 계속됩니다. |
device | auto | auto, cpu, cuda, cuda:N, mps 중 하나입니다. auto는 CUDA, Apple의 Metal, CPU 순서로 선택합니다. |
num_threads | 설정 안 됨 | 환경에서 이미 설정하지 않았다면 실행에 대해 OMP_NUM_THREADS, MKL_NUM_THREADS, OPENBLAS_NUM_THREADS를 설정합니다. |
auto_retrain | 꺼짐 | 어노테이션이 들어오는 대로 재학습합니다. auto_retrain을 참고하십시오. |
writeback | 없음 | 예측을 사전 레이블로 게시합니다. writeback을 참고하십시오. |
backend | local | 다른 백엔드를 지정하지 않은 실행의 백엔드입니다. |
backends | 없음 | 이름을 붙인 ssh, slurm, agent 백엔드입니다. 백엔드를 참고하십시오. |
max_predictions_mb | 512 | 원격 에이전트가 업로드할 수 있는 predictions.jsonl의 최대 크기입니다. |
trainer_params | 없음 | 트레이너 이름을 키로 하는 파라미터 기본값입니다. |
tiling | enabled: auto | 검출과 분할 트레이너를 위해 큰 이미지를 타일로 자릅니다. tiling을 참고하십시오. |
실행 자체의 params는 trainer_params를 덮어쓰고, 이 값은 다시 트레이너의 기본값을 덮어씁니다. 트레이너가 받지 않는 파라미터 이름은 trainer_params 아래에 있으면 서버를 시작할 때, 그 밖의 경우에는 실행이 시작될 때 거부됩니다. 트레이너가 순서를 예시와 함께 알려 줍니다.
auto_retrain
자동 재학습은 어노테이션을 저장할 때마다 새 실행이 필요한지 점검합니다.
| 키 | 기본값 | 의미 |
|---|---|---|
enabled | false | 점검을 켭니다. |
trainer | 없음 | 트레이너 이름입니다. 필수입니다. |
schemas | 없음 | 학습시킬 스키마입니다. 필수입니다. |
min_interval_s | 600 | 다른 실행이 시작되기 전에 마지막 실행이 끝난 뒤 지나야 하는 시간(초)입니다. |
update_frequency | 25 | 다른 실행이 시작되기 전에 마지막 자동 실행 이후 들어와야 하는 새 어노테이션의 수입니다. |
params | {} | API 실행의 params와 같은 트레이너 파라미터입니다. |
backend | model_training.backend | 자동 실행의 백엔드입니다. |
accept_licence | false | 확인이 필요한 트레이너(ultralytics-detect, ultralytics-segment, layoutlmv3)의 라이선스를 확인합니다. 확인하지 않으면 그 트레이너의 자동 실행은 건너뜁니다. |
점검이 실행하지 않기로 하면 그 이유가 GET /admin/training/api/status의 skip_reason 필드에 나타나며, 예를 들면 "waiting for 3 more annotation(s)"나 "a run is already in progress"입니다. 자동 실행은 실행 대기열에 들어가지 않습니다. 대기열이 비고 나서 저장되는 다음 어노테이션이 다시 점검하며, 그때는 학습할 어노테이션이 더 많습니다. Potato는 어노테이션 수를 메모리에 보관하므로, 재시작 뒤에는 이전에 학습한 적이 있는 프로젝트도 재시작 이후의 새 어노테이션부터 셉니다.
writeback
되쓰기는 어노테이터가 어떤 예측을 보는지 정합니다.
| 키 | 기본값 | 의미 |
|---|---|---|
schemas | [] | 예측을 어노테이터에게 보여 줄 스키마입니다. 빈 목록은 아무것도 보여 주지 않습니다. |
min_confidence | 0.0 | 이 기준에 못 미치는 예측은 저장되지만 보이지 않습니다. 신뢰도가 없는 예측은 통과합니다. |
field | predictions | 사전 레이블을 쓰는 항목 필드입니다. |
include_unlabeled | false | 아무도 레이블을 달지 않은 항목도 예측하고 그 항목에 사전 레이블을 붙입니다. include_unlabeled가 없으면 실행은 그 실행 자신의 val 항목과 test 항목만 예측합니다. |
tiling
검출과 분할 트레이너는 각 이미지를 몇백 픽셀로 줄입니다. 그 크기에서는 전체 슬라이드 이미지나 위성 장면의 객체가 사라집니다. 그래서 image_annotation, microscopy, geo_annotation 스키마에서 Potato는 실행의 학습 데이터를 만들 때 각 큰 이미지를 타일로 자릅니다. 이미지의 분할은 이미지를 자르기 전에 결정되므로 한 슬라이드의 타일이 두 분할에 나뉘어 들어가는 일은 없습니다. 예측은 전체 이미지에 다시 대응되고, 홀드아웃 점수는 전체 이미지에서 계산됩니다. 비전 튜토리얼이 슬라이드와 지도를 실제로 다룹니다.
| 키 | 기본값 | 의미 |
|---|---|---|
enabled | auto | auto는 슬라이드 형식(.svs, .ndpi, .mrxs, .scn 등)과 긴 변이 auto_min_side 이상인 이미지를 타일로 자릅니다. true는 모든 이미지를, false는 아무것도 자르지 않습니다. |
auto_min_side | 4096 | auto가 이미지를 타일로 자르기 시작하는 긴 변의 길이(픽셀)입니다. |
tile_size | 1024 | 트레이너가 보는 픽셀 단위의 타일 한 변의 길이입니다. |
overlap | 128 | 이웃한 타일이 공유하는 픽셀 수이며, 최대 tile_size의 절반입니다. 겹침은 객체 크기 이상으로 유지하십시오. 그렇지 않으면 큰 객체가 조각으로 검출됩니다. |
downsample | 1 | 타일 픽셀 하나당 원본 해상도 픽셀의 수입니다. |
mpp | 없음 | 타일 픽셀당 마이크론입니다. 해상도가 기록된 슬라이드에서는 downsample보다 우선합니다. |
background | 0.25 | 객체가 있는 타일마다 표집하는 빈 타일의 수입니다. 일부만 어노테이션된 슬라이드에는 background: 0을 지정하십시오. |
max_predict_tiles | 2000 | 이미지당 예측하는 타일의 최대 수입니다. 조직이 가장 많은 타일이 남습니다. |
min_visible | 0.4 | 객체가 그 타일에서 학습되려면 타일 안에 있어야 하는 객체의 비율입니다. |
tissue_threshold | 0.05 | 모델이 슬라이드 타일에서 예측하려면 타일에서 조직이 차지해야 하는 비율입니다. |
슬라이드는 학습 데이터를 만드는 머신에서 pip install "potato-annotation[wsi]"로 설치하는 openslide로 읽습니다. 원격 백엔드는 타일을 내려받으며 슬라이드는 내려받지 않습니다.
실행 대기열
한 번에 하나의 실행만 실행됩니다. 다른 실행이 진행 중일 때 Training 페이지나 API에서 시작한 실행은 거부되지 않고 기다립니다. 시작 요청은 queued: true와 실행의 position이 담긴 202를 반환하고, 실행 표는 그 실행을 Cancel run 버튼이 있는 waiting #N으로 나열합니다. 진행 중인 실행이 끝나면 가장 오래 기다린 실행이 시작됩니다.
기다리는 실행은 실행 원장의 레코드이므로 대기열은 재시작 후에도 유지되고, 서버가 돌아오면 첫 번째 대기 실행이 시작됩니다. 이전 서버가 진행하던 실행은 같은 시점에 interrupted로 표시됩니다. 기다리는 실행의 학습 데이터는 실행이 시작될 때 만들어지므로, 실행은 그 순간에 있는 어노테이션으로 학습합니다. 알 수 없는 스키마를 지정한 시작처럼 거부될 시작은 순서가 돌아올 때가 아니라 즉시 거부됩니다. 기다리는 동안 스키마나 트레이너가 설정에서 사라진 실행은 invalid_when_dequeued로 실패하고 다음 실행이 시작됩니다.
대기열의 자리 대신 409를 받으려면 요청 본문에 "queue": false를 보내십시오. 이미 queue_max개의 실행이 기다리고 있으면 새 시작은 429를 받습니다. GET /admin/training/api/status는 기다리는 실행을 순서대로 queue 아래에 나열합니다.
실행 전 점검
potato validate는 model_training 블록의 모든 문제를 한꺼번에 보고하며, 서버도 같은 문제에서 시작을 거부합니다.
potato validate config.yaml --strict점검이 다루는 경우는 다음과 같습니다.
train,val,test이외의 이름이 있는splits, 0보다 작거나 숫자가 아닌 비율, 합이 0인 비율, 또는train이 없는 경우.writeback이나auto_retrain에 없는 키, 스키마가 아닌writeback.schemas항목, 또는 0에서 1을 벗어난min_confidence.accept_license는accept_licence의 오타로 보고됩니다.field가writeback.field와 다른, 켜져 있는pre_annotation블록. 그런 블록 아래에서는 학습 사전 레이블이 보이지 않습니다.auto_retrain.enabled일 때, 존재하지 않는 트레이너나 스키마, 트레이너가 학습할 수 없는 스키마, 트레이너가 받지 않거나 타입이 틀린 파라미터,backends에 없는backend, 또는local이 아닌 백엔드의decision-calibrate.trainer_params아래의 트레이너가 받지 않거나 타입이 틀린 파라미터.dp안에서는 각 키와 키의 범위도 검사합니다.- 0보다 작거나 숫자가 아닌
grace_seconds, 또는 0보다 작거나 정수가 아닌retain_runs나split_seed. backends아래에서type이 없거나 알 수 없는 경우, 그 type에 없는 키,host가 없는 ssh 백엔드,auto,none, GPU 인덱스 이외의gpus값, 이름이local인 원격 백엔드, 또는 정의되지 않은model_training.backend.
potato training check는 실행이 백엔드를 쓰기 전에 백엔드 하나를 점검합니다. local의 경우 이 명령은 실행이 쓸 장치를 출력하며, 예를 들어 Apple silicon Mac에서는 local: this machine, Apple Metal (mps)를 출력합니다. ssh 백엔드의 경우 이 명령은 Python 버전, 모든 GPU와 각 GPU의 여유 메모리, 실행이 받을 GPU, 원격 인터프리터에 없는 학습 패키지를 보고합니다. Training 페이지의 Check 버튼도 같은 점검을 실행하고, --json은 보고서를 JSON으로 출력합니다.
potato training check local config.yaml
potato training check gpu-server config.yamlTraining 페이지나 API에서 시작한 실행은 시작될 때 다시 점검됩니다. 상태 코드는 라우트에 나열되어 있습니다.
백엔드
실행은 백엔드에서 실행되며, Training 페이지의 Runs on 메뉴는 설정된 백엔드를 나열합니다. model_training.backend가 기본값을 정하고, API 실행이나 auto_retrain은 backend로 다른 백엔드를 지정할 수 있습니다. Potato의 백엔드 type은 네 가지입니다.
| Type | 트레이너가 실행되는 곳 | 트레이너를 시작하는 주체 |
|---|---|---|
local | 이 머신의 서브프로세스. 항상 사용할 수 있으며 기본값입니다. | Potato |
ssh | GPU 서버처럼 Potato가 ssh로 접속할 수 있는 다른 머신. | Potato가 ssh로 |
slurm | 배치 작업으로 실행되는 클러스터의 컴퓨트 노드. | Potato가 로그인 노드에 ssh로 접속한 뒤 sbatch로 |
agent | NAT 뒤의 워크스테이션처럼 Potato가 접속할 수 없는 머신. | 사람이 potato training agent로 |
ssh 백엔드는 BatchMode를 켠 키 기반 인증을 사용하므로, 비밀번호 프롬프트는 멈추지 않고 실패합니다. slurm 백엔드는 sbatch, squeue, scancel만 쓰며 scontrol을 제공하는 클러스터에서는 scontrol도 씁니다. 또한 컴퓨트 노드가 공유하는 스토리지의 remote_dir이 필요합니다. 에이전트가 모든 연결을 열기 때문에 agent 백엔드는 인바운드 포트가 필요 없습니다. local이라는 이름은 이 머신 전용으로 예약되어 있으며, decision-calibrate는 local에서만 실행됩니다. GPU 서버, SLURM 클러스터, NAT 뒤의 머신에서 학습하기는 원격 type 세 가지를 모두 각 키와 함께 단계별로 안내합니다.
홀드아웃 점수
모든 실행은 그 실행 자신의 예측에 val 항목과 test 항목에서 사람이 통합한 레이블과 비교해 점수를 매깁니다. 지표 이름에는 val_macro_f1이나 test_f1처럼 분할이 들어갑니다. 레이블은 있는데 예측이 없는 항목은 틀린 것으로 계산되므로, 어려운 항목을 빼서 트레이너의 점수를 올릴 수 없습니다. <split>_coverage는 예측이 붙은 항목의 비율을 보고합니다.
대표 점수는 실행 표의 Held-out score 열에 나타나며, 분할과 지표는 툴팁에 나옵니다. 대표 점수는 val과 test 중 항목이 있는 첫 분할에서 첫 번째 스키마의 대표 지표를 말합니다. 트레이너가 val 점수로 최적 체크포인트를 골랐다면 트레이너가 이미 val 점수를 보았으므로 Potato는 test를 먼저 시도합니다. hf-text-classification, torchvision-detect, llm-sft처럼 최적 에포크를 유지하는 파인튜닝 트레이너는 대표 점수를 test에서 가져옵니다. sklearn-text, setfit, rdkit-property, 결정 모델 트레이너, 추론 브리지는 val에서 아무것도 고르지 않으며, 이 트레이너들의 실행은 val에 항목이 있으면 언제든 대표 점수를 val에서 가져옵니다. val 항목도 test 항목도 없는 실행은 "not scored"로 표시됩니다.
대표 지표는 스키마의 어노테이션 유형에 따라 달라지며, 아래 표는 흔한 유형을 보여 줍니다.
| 어노테이션 유형 | 대표 지표 |
|---|---|
radio, select, likert | macro-F1(정확도도 함께, 숫자형 likert 레이블은 평균 절대 오차도 함께) |
multiselect | micro-F1(macro-F1과 완전 일치도 함께) |
span | 시작, 끝, 레이블이 일치하는 스팬에 대한 F1 |
text | 토큰 F1(완전 일치도 함께) |
binary 모드의 pairwise | 동점으로 답하지 않은 항목에 대한 정확도 |
ranking | Kendall의 tau |
image_annotation, microscopy, geo_annotation | IoU 0.5에서의 COCO mAP(map_50), map_50_95도 함께 기록 |
audio_annotation | IoU 0.5 이상에서 레이블이 같은 구간에 대한 F1 |
speech_transcript | word_accuracy, 1에서 단어 오류율을 뺀 값 |
volume_annotation | mean_dice |
토큰 F1은 올바른 단어를 틀린 순서로 쓴 답에도 점수를 주므로, 토큰 F1은 완전 일치와 함께 읽으십시오. 같은 객체에 대해 두 어노테이터가 그린 박스가 IoU 0.9로 겹치는 일은 드물기 때문에, 검출의 대표 지표는 0.5에서 0.95까지의 평균이 아니라 IoU 0.5를 씁니다. 업스트림의 홀드아웃 점수 표는 모든 어노테이션 유형의 지표를 나열합니다.
되쓰기
실행이 성공하면 Potato는 실행의 예측을 저장하고, 네 가지 점검을 통과한 예측을 각 항목의 predictions 필드나 writeback.field가 지정한 필드에 씁니다. 점검은 이 순서로 실행되며, 실행의 되쓰기 보고서는 건너뛴 수를 점검별로 셉니다.
- train 분할 항목에는 사전 레이블이 붙지 않습니다. 이 점검은 원장에 남아 있는 모든 실행의 train 분할을 대상으로 하며, 이전 실행이 항목에 남긴 사전 레이블은 이후 실행이 그 항목으로 학습할 때 내려집니다.
writeback.schemas에 있는 스키마만 게시됩니다. 이 목록은 기본적으로 비어 있으므로, 학습을 켜도 어노테이터에게 보이는 화면은 달라지지 않습니다.- 거부된 쌍은 건너뜁니다. 모델 검토에서
reject판정을 받은 항목과 스키마의 쌍은 다시 보이지 않습니다. - 최소 신뢰도가 적용됩니다.
min_confidence에 못 미치는 예측은 저장되지만 게시되지 않습니다.
예측은 항목 데이터에 들어가고 어노테이션은 각 어노테이터의 사용자 상태에 있으므로, 되쓰기는 사람이 단 레이블을 바꾸지 않습니다. 사전 레이블은 어노테이터가 수정할 수 있는 미리 채워진 답으로 보이며, 예를 들어 선택형은 선택된 옵션으로, 자유 텍스트 답은 스키마의 텍스트 상자에 채워지고, pre_annotation 블록은 필요 없습니다. 사전 레이블이 어노테이터의 답이 되는 때는 어노테이터가 사전 레이블을 수정하거나 다음으로 넘어갈 때뿐입니다. 따라서 아무도 수정하지 않았거나 넘어가지 않은 사전 레이블은 학습 레이블이 되지 않습니다. ai_support.holdout이 연구의 지원 없는 비교 그룹에 넣은 어노테이터와 항목의 쌍에는 사전 레이블이 보이지 않으며, 그 쌍에 보내는 항목 데이터에는 writeback.field와 pre_annotation.field가 모두 빠집니다. 되쓰기 보고서는 GET /admin/training/api/status의 writeback 필드이고, 보고서의 summary가 실행이 아무것도 게시하지 않은 이유를 알려 줍니다.
Potato는 항목과 스키마마다 예측을 하나만 보관하며, 새 실행의 예측이 이전 실행의 예측을 대체합니다. 새 예측이 min_confidence에 못 미치거나 비어 있거나 거부되어 저장만 되고 보이지 않는 경우에는, 이전 실행의 사전 레이블이 항목에서 즉시 내려지고 되쓰기 보고서는 그 항목을 n_superseded_cleared에 셉니다. 데이터와 함께 제공된 사전 레이블은 그대로 둡니다. 시작할 때 writeback.schemas의 스키마에 저장된 예측은 같은 네 가지 점검을 거쳐 항목 데이터로 다시 되써지므로, 사전 레이블은 재시작 후에도 유지됩니다. 실행의 사전 레이블을 철회하려면 DELETE /admin/training/api/runs/<run_id>/predictions를 보내십시오. 이 요청은 저장된 예측을 제거하고 항목에서 사전 레이블을 내립니다.
수정된 항목과 고정된 항목은 항상 학습에 쓰입니다
두 종류의 항목은 안정적인 분할에서의 위치와 상관없이 이후 모든 실행의 train 분할로 갑니다.
- 검토자가 수정한 항목. 모델 검토의
correct판정은 사람이 모델의 답을 고쳤다는 뜻입니다. 수정은 모델이 가장 못하던 항목에서 나오므로,val이나test에 있는 수정된 항목으로는 모델의 자체 실수를 표본으로 삼아 점수를 매기게 됩니다.accept와reject판정은 항목을 원래 자리에 둡니다. - 고정된 항목. Catalog 페이지에서 슬라이스 옆의 Train on these는 그 슬라이스에 일치하는 항목(예: 기본 제공되는
model-found-nothing슬라이스)을 고정합니다. 고정된 항목은 누군가 레이블을 단 뒤에 학습에 쓰입니다.
홀드아웃 항목을 train으로 옮긴 실행은 그 수와 함께 경고를 로그에 남깁니다. 그 실행의 홀드아웃 점수는 그 항목들을 빼고 계산되므로 이전 실행의 점수와 직접 비교할 수 없습니다. 개수는 학습 데이터의 manifest.json에서 stats.forced_train 아래에 있습니다.
분할을 데이터셋 버전으로 저장하기
실행 페이지의 Keep this split as a dataset은 실행의 val, test, train 항목을 통합된 사람 레이블과 함께 데이터셋의 새 버전으로 저장합니다. 데이터셋 버전은 이후에 바뀌지 않으므로, 나중에 만든 모델과 LLM 프롬프트를 정확히 같은 항목에서 비교할 수 있습니다. 이 기능에는 datasets.enabled: true가 필요합니다. 저장된 각 버전은 분할 하나를 담으며 데이터셋의 마지막 버전에 더하지 않고 새로 시작합니다. 실행 2의 val 항목을 실행 1의 것에 더하면 실행 2가 학습한 항목이 들어가기 때문입니다. 각 예시의 inputs에는 사전 레이블 필드가 빠지므로, 평가에서 모델의 답을 읽을 수 없습니다.
사전 레이블이 어디서 왔는지
GET /admin/model-review는 학습 실행이 사전 레이블을 쓴 검토 대기열의 각 항목에 provenance를 포함합니다. 스키마마다 그 항목은 실행 id, 트레이너, 실행의 홀드아웃 점수를 알려 줍니다. 데이터와 함께 제공된 사전 레이블에는 항목이 없습니다.
실행이 저장되는 곳
각 실행에는 <task_dir>/<output_annotation_dir>/training/runs/<run_id>/에 디렉터리가 있습니다.
| 경로 | 내용 |
|---|---|
bundle/ | 학습 데이터. train.jsonl, val.jsonl, test.jsonl, include_unlabeled일 때의 unlabeled.jsonl, labels.json, manifest.json, media/. |
artifacts/ | model_card.json, predictions.jsonl, 그리고 모델. 예를 들어 sklearn-text는 model.pkl, 트랜스포머 트레이너는 model/ 디렉터리입니다. |
spec.json | 실행에 요청된 내용. |
events.jsonl, stdout.log, stderr.log | 실행의 진행 이벤트와 출력. |
agent.log | ssh 백엔드에서 원격 에이전트 자체의 출력. |
bundle.tar.gz | 원격 백엔드에서 에이전트가 내려받은 그대로의 학습 데이터(미디어 포함). |
실행 원장은 프로젝트 데이터베이스 <task_dir>/project.sqlite에 있으며, 실행, 실행마다 각 항목의 분할, 학습에 고정된 항목, 저장된 예측, 에이전트 토큰, Hugging Face Hub 푸시를 기록합니다. retain_runs는 원장을 정리하되 예측이 아직 저장되어 있는 실행은 정리하지 않으므로, 모든 사전 레이블은 그것을 쓴 실행까지 추적할 수 있습니다. 정리해도 실행 디렉터리는 디스크에 남습니다.
LoRA 실행은 수 메가바이트에서 수백 메가바이트의 어댑터만 저장하고, 실행이 예측할 때 model_name으로 베이스 모델을 불러옵니다. 전체 파인튜닝은 모델 전체를 저장합니다. POTATO_MODEL_CACHE 환경 변수에 디렉터리를 지정하면, 학습 프로세스는 HF_HOME, TRANSFORMERS_CACHE, SENTENCE_TRANSFORMERS_HOME이 이미 설정되어 있지 않은 한 그 디렉터리를 이 변수들에 사용합니다. 에어갭 머신에서는 트레이너가 지정하는 모델을 미리 그 디렉터리에 넣어 두십시오.
라우트
Training 페이지와 페이지의 JSON 라우트는 /admin/training 아래에 있으며 관리자 권한이 필요합니다. 관리자 권한은 관리자 세션이나 X-API-Key 헤더를 뜻합니다. 브라우저에서 보내는 POST와 DELETE 요청은 동일 출처여야 합니다. Potato의 OpenAPI 명세는 학습 작업 26개 모두에 x-potato-requires-config: model_training.enabled: true를 표시합니다.
| 라우트 | 용도 |
|---|---|
GET /admin/training | 실행 양식, 실행 목록, 트레이너가 있는 Training 페이지. |
GET /admin/training/runs/<run_id> | 상태, 지표, 이벤트, 각 항목의 분할이 있는 실행 하나의 페이지. |
GET /admin/training/api/trainers | 모든 트레이너와 트레이너의 종류, 모달리티, 라이선스, 설치 상태. |
GET /admin/training/api/schemas | 연구의 스키마, 각 스키마의 종류, 각 스키마에 맞는 트레이너. |
GET /admin/training/api/status | 상태, 진행률, 지표, 경고, skip_reason, writeback, queue가 있는 현재 또는 마지막 실행. |
GET /admin/training/api/runs | 실행 이력. ?limit=의 기본값은 50이고 최대는 500입니다. |
POST /admin/training/api/runs | 실행을 시작합니다. 실행이 시작되면 200, 실행이 기다리면 queued: true와 position이 담긴 202. |
GET /admin/training/api/runs/<run_id> | 실행 하나의 레코드와 함께, 검토 판정 아래의 실행 예측 정밀도인 review. |
GET /admin/training/api/runs/<run_id>/events | 실행의 이벤트 로그. ?limit=의 기본값은 200입니다. |
POST /admin/training/api/runs/<run_id>/cancel | 진행 중인 실행이나 대기 중인 실행을 취소합니다. 다른 실행 id에는 400. |
DELETE /admin/training/api/runs/<run_id>/predictions | 실행의 저장된 예측과 사전 레이블을 철회합니다. |
POST /admin/training/api/runs/<run_id>/push-to-hub | 실행의 모델을 Hugging Face Hub에 게시합니다. Hugging Face Hub에 게시하기를 참고하십시오. |
POST /admin/training/api/runs/<run_id>/pin-split | 본문 {"dataset": name, "split": "val"}로 분할을 데이터셋 버전으로 저장합니다. |
GET /admin/training/api/backends | 설정된 백엔드. |
POST /admin/training/api/backends/<name>/check | potato training check처럼 백엔드를 점검합니다. |
GET /admin/training/api/pinned | 이유별로 묶은 고정된 항목. |
POST /admin/training/api/pinned | {"slice": name}이나 {"instance_ids": [...]}로 항목을 train에 고정합니다. |
DELETE /admin/training/api/pinned | 나열한 instance_ids의 고정을 해제하며, 본문에 아무것도 없으면 고정된 모든 항목을 해제합니다. |
실행 요청은 trainer, schemas(목록 또는 이름 하나), params, backend, accept_licence, queue를 받습니다. 모든 트레이너는 지정된 첫 번째 스키마만 학습합니다. 아래 요청은 예시의 sentiment 스키마에서 sklearn-text 실행을 시작합니다.
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
http://localhost:8000/admin/training/api/runs \
-d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'거부된 시작은 error에 이유를 담습니다.
| 상태 | 발생 조건 |
|---|---|
400 | 본문에 트레이너나 스키마가 없음, 알 수 없는 트레이너나 스키마, 트레이너가 학습할 수 없는 스키마, 프로젝트가 실행할 수 없는 트레이너, 또는 라이선스 확인이 필요한 트레이너(요청이 accept_licence: true를 지정할 때까지 needs_licence_ack: true와 함께) |
409 | 트레이너가 받지 않거나 타입이나 범위가 틀린 파라미터, 알 수 없는 백엔드, local이 아닌 백엔드의 decision-calibrate, 또는 "queue": false일 때 이미 진행 중인 실행 |
429 | 이미 queue_max개의 실행이 기다리는 중 |
에이전트 프로토콜
model_training.enabled는 학습 에이전트가 호출하는 라우트도 /api/training 아래에 등록합니다. 에이전트는 에이전트의 토큰을 Authorization: Bearer <token>으로 보내며, 토큰이 없거나 유효하지 않으면 401을 받습니다. 백엔드를 등록하는 데에는 관리자 API 키가 대신 쓰입니다. potato/training/protocol.py는 새 에이전트를 작성하는 사람을 위해 프로토콜을 설명하고, potato/training/agent.py는 참조 구현입니다.
| 라우트 | 용도 |
|---|---|
POST /api/training/backends/register | X-API-Key로 백엔드 이름에 대한 에이전트 토큰을 발급합니다. potato training register가 이 라우트를 호출합니다. |
POST /api/training/backends/<name>/heartbeat | 유휴 에이전트가 살아 있음을 보고합니다. 다른 백엔드에 발급된 토큰은 403. |
GET /api/training/jobs/next?wait=30 | 롱 폴링. 작업이 있으면 200, wait초 안에 작업이 오지 않으면 204. |
GET /api/training/jobs/<run_id> | 작업, 작업의 spec, 작업이 취소되었는지 여부. |
GET /api/training/jobs/<run_id>/bundle | 미디어를 포함한 tar.gz 학습 데이터. 이 라우트는 Range 요청에 응답하므로 에이전트는 끊어진 다운로드를 최대 다섯 번까지 이어 받습니다. 번들이 사라지면 410. |
POST /api/training/jobs/<run_id>/progress | 진행 이벤트. 취소는 응답으로 돌아옵니다. |
POST /api/training/jobs/<run_id>/predictions | predictions.jsonl. max_predictions_mb를 넘으면 413. |
POST /api/training/jobs/<run_id>/complete | 종료 코드와 마지막 이벤트. |
QLoRA
llm-sft, llm-dpo, hf-text-classification, vlm-sft, reward-model은 QLoRA(Dettmers et al., 2023)의 구성인 lora: {quantize: 4bit}를 받습니다. 베이스 모델은 4비트 NF4 가중치와 이중 양자화로 불러오고, GPU가 bf16을 지원하면 그 위에서 bf16으로 LoRA 어댑터를 학습시킵니다. quantize: 8bit는 중간 단계의 옵션이며, 예측도 베이스 모델을 같은 방식으로 불러옵니다.
model_training:
trainer_params:
llm-sft:
model_name: Qwen/Qwen2.5-7B-Instruct
lora: {quantize: 4bit}4비트에서는 베이스 가중치가 같은 가중치를 bf16으로 둘 때의 4분의 1 메모리를 차지하며, 여기에 활성화, 어댑터, 옵티마이저 상태가 더해집니다. Potato는 GPU에서 QLoRA 실행의 메모리를 아직 측정하지 않았으므로, 실행 자체의 "Peak GPU memory" 줄을 보고 계획하십시오. 모든 트랜스포머 실행은 끝날 때 그 줄을 로그에 남깁니다. QLoRA에는 CUDA GPU와 그 머신의 CUDA에 맞는 bitsandbytes 빌드가 필요합니다. 실행은 모델을 불러오기 전에 GPU에서 숫자 몇 개를 양자화해 보며 둘을 모두 점검하고, 두 버전이 맞지 않으면 오류가 두 버전을 모두 알려 줍니다. LLM 파인튜닝 튜토리얼은 SFT와 DPO 실행에 QLoRA를 적용합니다.
Hugging Face Hub에 게시하기
모델이 Potato 서버에 있는 성공한 실행에는 실행 페이지에 Publish to the Hugging Face Hub가 있습니다. 푸시하면 모델과, 트레이너, 베이스 모델과 어댑터, 스키마와 레이블, 분할 크기, 홀드아웃 점수와 그 점수를 측정한 분할, 실행 id와 번들 id를 적은, 실행에서 작성한 README.md 모델 카드가 업로드됩니다. dp 실행의 카드에는 목표 대비 소진한 epsilon, delta, 보장이 적용되는 train 분할이 담긴 "Differential privacy" 행도 있습니다. 실행이 목표나 delta 값을 기록하지 않았으면 행에서 해당 값을 뺍니다.
업로드는 artifacts/ 디렉터리 전체가 아니라 정해진 파일 목록입니다. 목록에는 .safetensors, .bin, .pt, .pkl 같은 가중치 파일, 저장된 model/ 디렉터리의 설정 및 토크나이저 파일, 로컬 경로를 파일 이름으로 바꾼 model_card.json, calibration.json이 들어갑니다. 프로젝트 항목에 대한 모델의 답(predictions.jsonl, 결정 모델은 raw_answers.jsonl)은 서버에 남습니다. 체크포인트, 옵티마이저 상태, 일부 트레이너가 만드는 학습 데이터 사본(yolo_data/, wev_data/, laya_data/), artifacts/ 밖을 가리키는 모든 심볼릭 링크도 제외됩니다.
양식에는 실수나 공개 푸시를 막는 장치가 여러 가지 있습니다.
- 저장소 이름을 두 번 입력하며, 두 이름이 일치할 때만 푸시가 진행됩니다.
- Private은 기본으로 체크되어 있습니다. Private이 체크된 동안 Potato는 이미 존재하는 공개 저장소에는 푸시하지 않으며, API는
409로 응답합니다. - 양식은 Hugging Face 쓰기 토큰을 담은 서버의 환경 변수 이름을 지정하며 기본값은
HF_TOKEN입니다. 토큰 자체는 페이지에 입력하지 않습니다. 변수 이름에는TOKEN이 들어 있거나HF_로 시작해야 하고 값은hf_로 시작해야 하므로, 다른 변수의 값은 Hub에 도달할 수 없습니다. - Hub가 저장소의 존재 여부를 알려 주지 못하면 아무것도 푸시되지 않으며, 푸시가 만든 저장소는 이후 업로드가 실패하면 다시 삭제됩니다.
- 모델 카드의 라이선스는 지정한 Hub 라이선스 id이며
apache-2.0같은 값입니다. 지정하지 않으면 카드에는 베이스 모델의 라이선스가 적용된다고 적힙니다.ultralytics-detect(AGPL-3.0)처럼 라이선스 확인이 필요한 트레이너는 푸시에도 같은 확인이 필요합니다. fetch_artifacts: false인 원격 호스트에 남아 있거나 에이전트 백엔드에서 학습한 모델은 서버에서 푸시할 수 없으며, 오류가 모델이 있는 위치를 알려 줍니다.
푸시 한 번은 커밋 하나입니다. 실행 페이지는 모든 푸시를 저장소, 공개 범위, 커밋과 함께 나열하고, 원장은 누가 푸시했는지 기록합니다. API로는 POST /admin/training/api/runs/<run_id>/push-to-hub의 본문이 repo_id, confirm_repo_id, private(기본값 true), token_env(기본값 HF_TOKEN), licence, accept_licence를 받습니다. 이 라우트는 커밋과 함께 201을 반환하고, 불일치, 없는 토큰 변수, 모델 파일 없음, 확인되지 않은 라이선스에는 400을, Hub가 거부하면 502를 반환합니다.
문제 해결
아래 항목은 첫 설정에서 가장 가능성이 높은 오류를 다룹니다. 업스트림 문제 해결 목록은 GPU 드라이버, CUDA 빌드, 트레이너별 메시지를 다룹니다.
/admin/training이 404를 반환합니다.model_training.enabled가true가 아니며, Potato는 이 키가true일 때만 라우트를 등록합니다.- "Only N items in the train split". 항목을 더 어노테이션하거나 실행의
params에서min_instances를 낮추십시오. train 분할은 기본적으로 레이블이 달린 항목의 70%를 차지합니다. - "Schema 'x' has 1 distinct label(s) in the data". 분류기에는 실제로 쓰인 레이블이 최소 두 개 필요합니다.
- "No resolved annotations to train on". 실행에 지정한 스키마가 어노테이션 중인 스키마와 다르거나, 아직 아무도 어노테이션하지 않았습니다.
- 실행이 사전 레이블을 게시하지 않았습니다.
GET /admin/training/api/status의writeback보고서를 읽으십시오. "No predictions were published: write-back is not enabled for any schema"는writeback.schemas가 비어 있다는 뜻이며, 건너뛴 수는 각 점검이 예측을 몇 개씩 제거했는지 보여 줍니다. <trainer> does not take <name>. 실행이나trainer_params아래의 파라미터가 오타이거나 다른 트레이너의 것입니다. 메시지가 트레이너가 받는 이름을 나열합니다.- 머신의 메모리가 부족해 실행이 강제 종료되었습니다. 프로세스가 SIGKILL로 종료되었으며, 보통은 메모리 부족 킬러 때문입니다. 더 작은 모델을 쓰거나 항목을 줄이거나,
max_ram_mb를 지정해 실행이 자신의 제한 안에서 실패하게 하십시오. - "Stopped: the run took longer than model_training.max_wall_seconds". 실행이 시간 제한에 도달했습니다.
max_wall_seconds를 올리거나 더 적은 항목으로 학습시키십시오. - "The GPU ran out of memory". 유효 배치를 유지하도록
batch_size를 낮추고gradient_accumulation을 올리거나,lora: true또는lora: {quantize: 4bit}를 지정하거나,llm-sft에서는gradient_checkpointing: true를 지정하거나 더 작은 모델을 고르십시오. - "ssh to host failed: Permission denied". Potato는
ssh를BatchMode=yes로 실행하므로ssh <host> true가 서버 계정에서 프롬프트 없이 성공해야 합니다. 패스프레이즈가 있는 키는ssh-agent가 그 키를 가지고 있으면 동작합니다. - 에이전트 백엔드의 실행이 대기 상태로 남아 있습니다. 그 백엔드 이름으로 폴링하는 에이전트가 없습니다.
potato training agent --backend <name>으로 에이전트를 시작하고, Training 페이지의 Check로 토큰을 점검하십시오.
더 읽어보기
- 내 어노테이션으로 모델 학습하기: 학습 루프, Training 페이지, 빠른 시작.
- 트레이너: 모든 트레이너, 각 트레이너가 학습하는 스키마, 설치 명령.
- GPU 서버, SLURM 클러스터, NAT 뒤의 머신에서 학습하기: ssh, SLURM, 폴링 에이전트 백엔드를 단계별로.
- 루프 안의 모델: 연구 하나에서 되쓰기, 검토,
auto_retrain, 데이터셋 버전. - 능동 학습: 모델 불확실성으로 항목 순서 정하기.
- 무심코 승인된 사전 레이블 찾아내기: 어노테이터가 사전 레이블을 읽지 않고 수락하는지 확인하기.
- 업스트림 레퍼런스: 모든 트레이너의 전체 파라미터 표.
참고 문헌
- Dawid, A. P., and Skene, A. M. (1979). Maximum Likelihood Estimation of Observer Error-Rates Using the EM Algorithm. Applied Statistics, 28(1). https://doi.org/10.2307/2346806
- Dettmers, T., Pagnoni, A., Holtzman, A., and Zettlemoyer, L. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. Advances in Neural Information Processing Systems 36 (NeurIPS 2023). https://proceedings.neurips.cc/paper_files/paper/2023/hash/1feb87871436031bdc0f2beaa62a049b-Abstract-Conference.html