2026. 6. 16. 13:48ㆍDev
로컬 맥북에서 Gemma 4 12B 모델을 내려받고, 작은 데이터셋으로 LoRA 파인튜닝을 진행했다. 실험은 체스 다음 수를 맞히는 형태로 구성했다. 다만 목표는 체스 엔진을 만드는 것이 아니라, 모델이 정해진 출력 형식을 더 잘 따르게 만들 수 있는지 확인하는 것이었다.
이번 실험에서 사용한 출력 형식은 UCI 체스 표기다. 예를 들어 일반 체스 표기에서는 Nf3라고 쓰지만, UCI 표기에서는 출발 칸과 도착 칸을 모두 포함해 g1f3라고 쓴다.
프로그램에서 후처리하려면 Nf3보다 g1f3가 더 명확하다. 그래서 모델에게 “답은 UCI 형식으로만 출력하라”는 작은 규칙을 학습시키는 실험을 진행했다.
사용한 모델
사용한 모델은 MLX용 Gemma 4 12B 모델이다.
처음에 막힌 부분
처음에는 mlx-lm CLI만으로 바로 실행하려고 했다. 하지만 Gemma 4 12B의 gemma4_unified 모델 타입을 읽지 못하는 문제가 있었다.
이 문제는 프로젝트 전용 Python 가상환경을 만들고, mlx-optiq와 GitHub 최신 mlx-lm을 설치해서 해결했다.
설치 명령은 다음과 같다.
.venv/bin/python -m pip install -U mlx-optiq "mlx-lm @ git+https://github.com/ml-explore/mlx-lm.git"
핵심은 실행 코드에서 import optiq를 먼저 호출하는 것이었다. 이 import가 Gemma 4 unified 모델 타입을 등록해준다. 이 과정을 거친 뒤에는 모델 로딩과 생성이 정상 동작했다.
데이터셋 구성
데이터셋은 의도적으로 작게 만들었다. 큰 성능 실험이 아니라, 로컬 파인튜닝 파이프라인이 실제로 동작하는지 확인하는 목적이었기 때문이다.
구성은 다음과 같다.
- 학습 데이터: 32개
- 검증 데이터: 8개
- 테스트 데이터: 8개
- 전후 비교용 평가 데이터: 16개
데이터는 채팅 형식 JSONL로 만들었다. 한 줄은 하나의 학습 예제다.
예시는 다음과 같다.
{
"messages": [
{
"role": "system",
"content": "You are a chess next-move assistant. Return exactly one legal UCI move and no explanation."
},
{
"role": "user",
"content": "Chess drill italian_develop_knight. Moves so far: 1. e4 e5. Side to move: White. Plan: develop the king-side knight toward the center. Reply with the best next move in UCI."
},
{
"role": "assistant",
"content": "g1f3"
}
]
}
베이스라인 평가
파인튜닝 전 모델에 평가 질문 16개를 먼저 입력했다. 이 값을 베이스라인으로 사용했다.
결과는 0개 정답이었다.
베이스라인: 0/16 = 0.0%
이 결과만 보면 모델이 체스를 전혀 모르는 것처럼 보일 수 있다. 하지만 실제 출력은 그렇지 않았다.
예를 들어 정답이 g1f3인 문제에서 모델은 Nf3라고 답했다. 정답이 e7e6인 문제에서는 e6라고 답했다. 정답이 c7c6인 문제에서는 c6라고 답했다.
즉, 체스 수 자체는 어느 정도 맞췄지만, 내가 요구한 UCI 형식은 지키지 못했다. 이번 평가에서는 출력 형식을 엄격하게 봤기 때문에 Nf3, e6, c6는 모두 오답으로 처리했다.
LoRA 튜닝 설정
최종 실험에서는 다음 설정으로 LoRA 튜닝을 진행했다.
iters: 300
num_layers: 16
batch_size: 1
learning_rate: 1e-4
max_seq_length: 1024
mask_prompt: on
mask_prompt 옵션을 켠 것이 중요했다. 이 옵션은 질문 부분보다 assistant의 답변 부분에 학습을 집중하게 한다.
이번 실험의 목적은 질문을 외우게 하는 것이 아니라, 답을 UCI 형식으로 출력하게 만드는 것이었다. 그래서 mask_prompt를 켠 설정이 더 적합했다.
학습 가능한 파라미터는 전체 모델의 0.092%였다.
Trainable parameters: 0.092% (10.930M / 11907.350M)
걸린 시간
실행 시간은 다음과 같았다.
| 단계 | 시간 |
|---|---|
| 베이스라인 평가 | 8초 |
| LoRA 튜닝 | 84초 |
| LoRA 적용 후 평가 | 10초 |
| 전체 실행 | 214초 |
작은 데이터셋을 사용했기 때문에 학습 자체는 오래 걸리지 않았다.
튜닝 후 결과
LoRA 튜닝 후 같은 16개 평가 질문을 다시 입력했다.
결과는 다음과 같다.
LoRA 적용 후: 10/16 = 62.5%
베이스라인은 0/16이었고, LoRA 적용 후에는 10/16을 맞췄다.
0.0% -> 62.5%
표현을 바꿔서 물어본 평가 데이터에서도 8개 중 6개를 맞췄다. 단순히 학습 문장을 그대로 외운 결과만은 아니라고 볼 수 있다.
다만 모든 문제가 해결된 것은 아니다. French Defense나 English Opening 관련 일부 케이스에서는 여전히 다른 UCI 수를 출력했다.
결과 해석
이번 결과는 Gemma 4 12B의 체스 실력이 전반적으로 좋아졌다는 뜻은 아니다.
이번 실험에서 확인한 것은 더 좁은 내용이다.
작은 체스 지시 데이터에서, 모델이 UCI 형식으로 답하는 능력이 개선됐다.
베이스라인 모델은 체스적으로 그럴듯한 수를 일반 표기로 답하는 경우가 많았다. LoRA 튜닝 후에는 지정한 UCI 형식으로 답하는 비율이 올라갔다.
따라서 이 실험은 “체스 엔진 성능 개선”이 아니라 “출력 형식 교정” 실험으로 보는 것이 맞다.
한계
이번 실험에는 한계가 있다.
- 데이터셋이 작다.
- 오프닝 중심의 단순한 예제만 사용했다.
- 합법수 검증을 별도로 하지 않았다.
- Stockfish 같은 체스 엔진과 비교하지 않았다.
- 체스 실력 전체가 아니라 출력 형식만 평가했다.
정확한 체스 성능 평가를 하려면 더 큰 데이터셋과 별도 검증 환경이 필요하다.
정리
이번 실험에서는 로컬 Apple Silicon 환경에서 Gemma 4 12B LoRA 튜닝을 실제로 실행했다.
이번 실험은 작은 규모였지만, 로컬 맥북에서 모델 다운로드, 평가, LoRA 튜닝, 결과 비교까지 한 번에 진행할 수 있다는 점을 확인했다.
'Dev' 카테고리의 다른 글
| 하이드레이션과 렌더링 전략별 차이 (0) | 2026.07.06 |
|---|---|
| 우리는 모두 시스템 아키텍처 전문가가 되어야 한다 (0) | 2026.06.06 |
| Linear 앱의 초고속 성능을 가능하게 하는 핵심 웹 성능 최적화 방법 (0) | 2026.05.29 |
| Next.js 전환 후기 (0) | 2021.06.27 |
| Next.js meta 태그와 script 태그 다루기 (0) | 2021.06.17 |