월말 정리 (Month 2): 결과 표 하나로 Project 1·2를 포트폴리오로 묶는 법
오늘은 새로운 개념을 배우지 않고, 한 달간 만든 tiny-gpt(Project 1)와 sft-lora(Project 2)를 정리해 공개한다. 두 리포를 서로 링크하고, 실험 결과를 표 하나로 통합하고, 포트폴리오 인덱스를 갱신한다. 마지막으로 이번 달 틀린 알고리즘 문제를 다시 푼다.
By 송민성
오늘의 목표
Month 2까지 만든 Project 1(tiny-gpt)과 Project 2(sft-lora)를 "남이 열어봐도 이해되고 다시 돌려볼 수 있는" 상태로 정리해 공개한다. 두 리포를 서로 연결하고, 흩어진 실험 결과를 표 하나로 합치고, 포트폴리오 인덱스에 반영하는 것이 오늘의 전부다.
개념과 직관
오늘은 새로 배우는 개념이 없다. 대신 "정리"가 왜 연구 능력의 일부인지를 짚는다.
비유: 요리 레시피 노트. 요리를 잘해도 레시피를 적어두지 않으면 다음 주에 같은 맛을 못 낸다. 실험도 같다. 어떤 데이터로, 어떤 설정으로, 몇 번 돌렸더니 어떤 숫자가 나왔는지 적어두지 않으면 그 결과는 "기억"일 뿐 "증거"가 아니다.
재현성(reproducibility, 같은 코드와 설정으로 다시 돌리면 같은(비슷한) 결과가 나오는 성질) 이 오늘의 핵심 단어다. 이를 위해 리포에 최소한 아래가 있어야 한다.
- 한 줄 설명: 이 리포가 무엇인지
- 실행 방법: 설치부터 학습, 평가까지 복사해서 칠 수 있는 명령어
- 설정 기록: 시드(seed, 난수를 고정하는 값), 학습률, 배치 크기, 스텝 수 등
- 결과 표: 숫자와 그 숫자를 만든 조건
통합 결과 표의 직관. Project 1은 처음부터 작은 모델을 만들어 학습한 것이고, Project 2는 이미 학습된 모델을 SFT(지도 미세조정, 정답 예시를 보여주며 모델의 행동을 맞추는 학습)와 LoRA(원래 가중치는 얼리고 작은 추가 행렬만 학습하는 방법)로 조정한 것이다. 두 프로젝트의 지표가 서로 다를 수 있으므로, 표에는 "같은 열에 억지로 맞추기"보다 각 숫자가 무엇을 측정한 것인지를 명확히 적는 것이 중요하다.
코드로 직접 해보기
라이브러리 이전에, 정리의 원리는 "결과를 파일로 남기고 표로 합치는 것"이다. 단계별로 진행한다.
1단계. 각 프로젝트의 결과를 같은 형식의 파일로 모은다.
# results/project1.json, results/project2.json 형태로 저장해 둔다고 가정
import json
from pathlib import Path
def save_result(path, name, setting, metric_name, value, note=""):
Path(path).parent.mkdir(parents=True, exist_ok=True)
row = {"name": name, "setting": setting,
"metric": metric_name, "value": value, "note": note}
Path(path).write_text(json.dumps(row, ensure_ascii=False, indent=2))
save_result("results/p1_base.json", "tiny-gpt", "6 layers, seed=0",
"val_loss", 1.85, "내 실제 값으로 교체")값은 예시일 뿐이니, 반드시 본인이 실제로 측정한 숫자로 바꿔 넣어라.
2단계. 마크다운 표로 합친다.
import json
from pathlib import Path
rows = [json.loads(p.read_text()) for p in sorted(Path("results").glob("*.json"))]
lines = ["| 프로젝트 | 설정 | 지표 | 값 | 비고 |",
"|---|---|---|---|---|"]
for r in rows:
lines.append(f"| {r['name']} | {r['setting']} | {r['metric']} | {r['value']} | {r['note']} |")
Path("RESULTS.md").write_text("\n".join(lines), encoding="utf-8")
print("\n".join(lines))3단계. 두 리포를 공개하고 서로 링크한다.
- 각 리포 루트에서
git status로 커밋 안 된 파일이 없는지 확인한다. .gitignore에 체크포인트(*.pt,*.safetensors), 데이터 원본, 가상환경, API 키가 들어 있는 파일을 넣었는지 확인한다.- README 맨 위에 서로를 링크한다. 예:
- tiny-gpt README: "이 모델을 사전학습 모델로 쓰는 미세조정 실험은 sft-lora 참고"가 아니라, 실제 관계에 맞게 쓴다. (sft-lora가 tiny-gpt가 아닌 다른 모델을 썼다면 "다음 단계 프로젝트: sft-lora"처럼 사실대로만 적는다.) - sft-lora README: "from-scratch 구현 프로젝트: tiny-gpt"
- GitHub에서 Public으로 바꾸기 전, 깨끗한 폴더에
git clone후 README 명령어를 그대로 따라 쳐서 돌아가는지 확인한다.
4단계. 포트폴리오 인덱스 갱신. 인덱스(한 페이지짜리 목록)에 프로젝트당 한 줄로 적는다: 이름, 한 줄 요약, 핵심 결과 숫자 하나, 리포 링크.
오늘의 실험
이번 실험은 새 학습이 아니라 기존 결과의 통합과 검증이다.
- 바꾸는 것: 없음. 대신 "결과 표를 다른 사람이 읽을 수 있는가"를 점검한다.
- 관찰할 것:
- Project 1과 Project 2의 지표가 각각 무엇을 측정하는지 표에 명시했는가 - LoRA 설정(rank, 학습한 파라미터 수), 학습 스텝, 데이터 크기가 기록돼 있는가 - 베이스라인(미세조정 전 모델)과 비교 가능한 행이 있는가
- 기록 방법:
RESULTS.md에 표를 두고, 표 아래에 "관찰 3줄"을 쓴다. (1) 가장 잘된 설정과 이유 추정, (2) 예상과 달랐던 결과, (3) 다음에 해볼 실험 한 가지. 추정은 추정이라고 표시하고, 확인하지 않은 원인을 사실처럼 쓰지 않는다. - 재현 확인: 가능하면 가장 짧은 설정 하나를 다시 돌려, 표의 값과 크게 차이 나지 않는지 본다. 차이가 나면 그 차이도 비고에 적는다.
왜 이걸 배우나 (LLM / Post-training 연결)
LLM Post-training 업무는 SFT 같은 학습을 수없이 반복하고 설정별 결과를 비교하는 일이다. 그래서 결과를 일관된 표로 남기고 재현 가능하게 만드는 습관이 모델링 실력만큼 중요하다. 이 두 리포와 통합 표는 이후 Month 3에서 확장할 때 출발점이 되고, 면접에서 "내가 직접 해봤다"는 근거 자료가 된다.
초보자가 막히는 지점
- 큰 파일이 push되지 않는다. 체크포인트를 실수로 커밋하면 용량 제한에 걸린다.
.gitignore에 추가하고, 이미 커밋했다면 히스토리에서 제거해야 하므로 공개 전에git log --stat으로 확인한다. 어려우면 새 리포로 깨끗하게 다시 시작하는 편이 빠르다. - 비밀 정보 노출. 토큰이나 키가 코드·노트북 출력에 남아 있지 않은지 검색해 본다. 노출됐다면 공개 여부와 상관없이 키를 폐기하고 새로 발급한다.
- 내 컴퓨터에서만 돌아가는 README. 절대경로, 설치 안 적은 라이브러리가 흔한 원인이다. 깨끗한 환경에서 clone해서 따라 해보는 것이 유일하게 확실한 검증이다.
- 서로 다른 지표를 한 표에서 비교하려는 실수. loss와 정확도, 서로 다른 데이터셋의 값은 직접 비교할 수 없다. 비교하지 말고 "무엇을 측정했는지" 열을 두자.
- 기억에 의존한 숫자. 로그 파일에서 확인되지 않는 숫자는 표에 넣지 않는다.
- 완벽주의. 오늘은 정리하는 날이다. 새 실험을 추가하고 싶은 마음이 들면 "다음에 할 일" 목록에만 적어 두고 넘어간다.
알고리즘 (병행 1시간)
이번 달에 틀렸거나 막혔던 문제를 다시 푼다. 새 문제를 풀지 않는다.
- 이번 달 기록에서 오답·미해결 문제를 골라 목록으로 만든다 (3~5개 정도).
- 풀이를 보지 않고 처음부터 다시 푼다. 막히면 시간을 정해 두고(문제당 15분 정도) 그 후에 힌트를 본다.
- 풀이마다 아래 세 가지를 기록한다.
- 접근: 어떤 아이디어로 풀었는지 (예: 해시맵, 투 포인터, 정렬 후 탐색) - 시간복잡도: 입력 크기 n에 대해 얼마나 걸리는지와 그 이유 - 틀린 이유: 처음에 왜 틀렸는지 (조건을 놓침, 경계값 실수, 복잡도 초과, 개념 부족 등)
- 같은 유형의 이유가 두 번 이상 나오면, 그것이 다음 달에 집중해서 고칠 약점이다.