Wintersalmon | Blog

진짜 레버는 네트워크 크기가 아니라 학습률이었습니다

8 min read

실험은 승급보다 더 많은 것을 가르쳐 주었습니다

YINSH 보드게임 AI를 만드는 일은 이 프로젝트에서 실제 한계가 어디인지를 계속 가르쳐 주는 갈래입니다. 현재 챔피언인 gen-270 — 336만 개의 학습된 가중치를 가진 — 은 향상이 멈춰 있었습니다. 그것을 더 큰 신경망으로 키워 보려 했고, 왜 예상대로 되지 않는지 하룻밤을 들여 알아냈습니다. 승급은 없었습니다. 하지만 승급보다 더 많은 것을 배웠습니다. 우리가 생각조차 안 했던 숫자 하나, 학습률(learning rate) 이, 처음부터 조용히 아이디어를 망치고 있었습니다.

TL;DR

  • YINSH AI는 네 단계 루프로 향상됩니다: 스스로 대국, 새 신경망 학습, 챔피언과 대결, 이기면 승급.
  • gen-270(128채널 × 10블록, 3.36M 가중치)이 70세대 넘게 정체됐습니다. 더 큰 160×12 신경망(5.95M 가중치)이 돌파구처럼 보였습니다.
  • 처음부터 새로 학습한 큰 신경망은 승률 약 25–29%에서 멈췄습니다 — 챔피언을 모방할 뿐 뛰어넘지 못했습니다.
  • Net2Net이라는 기법으로 챔피언의 가중치를 큰 신경망에 옮겨 넣어 동률에서 출발했지만, 기본 학습률이 한 번의 학습 단계만에 그 이점을 지워 버렸습니다.
  • 학습률을 열 배 줄이자 결과가 +154 Elo 달라졌습니다 — “확실히 진다”에서 “거의 동률”로.
  • 최종 결과: gen-270을 이긴 것은 없습니다. 하지만 재사용 가능한 도구 셋과 다음에 무엇을 시도해야 할지에 대한 훨씬 명확한 그림을 얻었습니다.

엄격한 심판이 있는 자기 학습 루프

YINSH AI에게는 학습할 사람의 기보가 없습니다. 대신 세대를 거듭하며 반복되는 루프로 향상됩니다:

  1. 셀프플레이 — 챔피언이 스스로와 수천 판을 두되, 수읽기 탐색을 이용해 날 것의 직감보다 더 강한 수를 냅니다.
  2. 학습(Train) — 새 신경망이 그 대국들을 공부하며 챔피언의 최선의 선택을 따라 배웁니다.
  3. 게이트(Gate) — 새 신경망이 챔피언과 대국합니다. SPRT라는 통계 검정이 결과가 운이 아니라 실력 차이임이 확실해질 때까지 대국을 이어 갑니다.
  4. 승급(Promote) — 새 신경망이 확실하게 이기면 새 챔피언이 되고 루프가 다시 시작됩니다.

게이트는 한 방향 래칫입니다. 실력은 오르기만 할 수 있습니다. gen-270은 70세대에 걸친 모든 도전자를 이겨 왔습니다.

명인을 모방하면 가까워질 뿐입니다

첫 번째 시도: 무작위 가중치로 160×12 신경망을 새로 만들어 루프에 넣었습니다. 챔피언 대비 승률 약 25–29%까지 올라갔다가 멈췄습니다. 근처에도 가지 못했습니다.

이유는 구조적입니다. 모든 학습 데이터가 gen-270에서 나옵니다. 새 신경망의 임무는 오로지 챔피언의 수를 모방하는 것인데, 전문가를 모방하면 가까워질 뿐 사실상 넘어서지 못합니다. 전문가의 맹점을 그대로 물려받고 자신의 복제 오차까지 더하게 됩니다. 이것이 **증류 한계(distillation ceiling)**입니다(증류 distillation = “학생” 신경망이 “교사” 신경망을 흉내 내도록 학습시키는 기법). 셀프플레이 중 더 강한 수읽기 탐색을 써서 한계를 약간 높였지만(+58 Elo), 29%에서 다시 평평해졌습니다. 더 나은 모방일 뿐, 여전히 한계였습니다.

챔피언을 키워서 잃지 않는 방법

무작위에서 출발하면 처음부터 다시 배워야 한다면, 왜 무작위에서 출발해야 할까요?

Net2Net은 학습된 신경망을 받아 똑같은 함수를 계산하는 더 큰 신경망을 만드는 기법입니다 — 같은 입력, 같은 출력, 부동소수점 반올림 범위까지. 챔피언 대비 −576 Elo의 신선한 160×12 신경망 대신, gen-270 그 자체인 160×12를 얻습니다. 격차가 0인 상태에서 출발하는 것입니다. 늘어난 용량은 공짜 여유 공간입니다.

두 가지 연산으로 구현됩니다. 넓히기(채널 추가): 기존 채널의 가중치를 새 슬롯에 복사하고, 다음 층에서 그 복사본들에 대한 가중치를 복사 횟수로 나눕니다 — 그러면 복사본들이 원래 기여도로 합산됩니다. 출력은 그대로입니다. 깊게 하기(층 추가): “우회로(detour)“가 태어날 때부터 0으로 음소거된 블록을 삽입해 순수한 통과(pass-through)로 만듭니다. 학습이 진행되면서 음소거가 서서히 풀리고, 우회로가 깨어나 무언가를 기여하는 법을 배웁니다. 무작위 입력에서의 출력 차이를 확인한 패리티 검사 결과: 0.000001 이내. 파라미터 3.36M → 5.95M, 동일한 수.

웜스타트를 지운 숫자 하나

gen-270을 160×12로 키워 학습을 시작했습니다. 한 세대 만에 다시 ~25%로 떨어졌습니다 — 처음부터 시작한 것과 같은 결과. 키운 것이 아무 소용이 없어 보였습니다.

범인은 **학습률(LR)**이었습니다. 학습은 신경망의 가중치를 조정할 때 실력을 개선하는 방향으로 조금씩 걸음을 내딛습니다. LR은 그 걸음의 크기입니다. 가능한 모든 가중치 설정의 공간을 높이가 실력인 지형이라고 상상해 보세요. gen-270의 가중치는 좁은 봉우리 위에 있습니다. 웜스타트로 그 자리에서 시작하면 봉우리 위에 선 것입니다. LR이 그 봉우리에 머무를지를 정합니다:

  • LR = 1e-3 (기본값): 무작위에서 출발하는 학습에 맞게 설정된 값으로, 거기선 크고 탐험적인 걸음이 바람직합니다. 이미 봉우리 위에 있는 신경망에 적용하면 첫 걸음에 봉우리에서 뛰어내립니다. 웜스타트가 즉시 지워집니다.
  • LR = 1e-4 (파인튜닝): 열 배 작습니다. 신경망이 봉우리 근처에 머물며 조금씩 조정합니다. 챔피언의 실력이 보존됩니다.
학습률 1세대 실력 (챔피언 대비)
LR = 1e-3 (기본값) −195 Elo (승률 24.5%)
LR = 1e-4 (파인튜닝) −41 Elo (승률 44%)

숫자 하나, +154 Elo 차이. LR은 학습 스크립트에 하드코딩돼 있어 설정할 방법이 없었습니다. 그것을 설정 가능한 플래그로 노출하는 것이 전부였습니다(PR #1439). 웜스타트와 학습률은 쌍을 이룹니다: 좋은 출발점에서 시작하는 것은 보폭이 그 근처에 머물 만큼 작아야만 도움이 됩니다.

앞으로 무엇이 달라지나

파인튜닝 LR 덕분에 키운 신경망은 승률 약 45–49%에 안착했습니다 — 챔피언과 대등하지만 이기지는 못했습니다. 한 가지 레버를 더 시도했습니다. 셀프플레이를 얼어붙은 챔피언 대신 최신 신경망으로 전환하는 것입니다. AlphaZero가 출발점을 진짜로 뛰어넘는 방식입니다 — 스스로의 점점 나아지는 대국으로 학습합니다. 하지만 우리 신경망은 동률 바로 아래에 있었고, 그 대국들은 챔피언의 것보다 약간 약했습니다. 그것으로 학습하자 신경망이 아래로 표류했습니다(~40%로). 자기 향상으로의 전환은 신경망이 교사와 진정으로 동등하거나 그 이상이 된 다음에야 효과가 있습니다.

gen-270이 챔피언으로 남습니다. 성장 유틸리티(PR #1436), LR 플래그(PR #1439), 그리고 한 판의 느린 대국을 기다리느라 세대 전체가 지연되지 않도록 하는 낙오자 배리어(PR #1444) — 이 세 가지 도구를 얻었습니다. 신경망이 파인튜닝 LR 아래에서 진정한 동률을 다시 넘어서면, warm=latest 전환이 다음에 당길 레버입니다.

핵심 용어

  • Self-play — AI가 스스로와 게임을 두어 사람의 기보 없이 자신의 학습 예제를 만드는 것.
  • Champion(챔피언) — 현재 최강 신경망. 새 후보는 통계 대국에서 이겨야 챔피언을 교체합니다.
  • Gate / SPRT — 결과가 운이 아닌 실력 차이임이 확실해질 때까지만 대국하는 통계 검정.
  • Elo — 실력 점수. +100 Elo 차이는 강한 쪽이 약 64% 이긴다는 뜻.
  • Generation(세대) — 루프 한 바퀴: 셀프플레이, 학습, 게이트, 채택 또는 폐기.
  • Distillation ceiling(증류 한계) — 얼어붙은 “교사”를 모방하는 “학생” 신경망이 도달하는 한계. 교사의 실력에 수렴할 뿐 좀처럼 넘어서지 못합니다.
  • Net2Net — 학습된 신경망을 같은 함수를 계산하는 더 큰 신경망으로 키우는 기법. 더 큰 모델이 처음부터 시작하는 대신 작은 모델의 기술을 물려받습니다.
  • Learning rate(학습률) — 학습이 신경망의 가중치를 조정할 때 내딛는 걸음의 크기. 웜스타트한 신경망에 너무 큰 학습률을 쓰면 웜스타트가 첫 걸음에 지워집니다.
  • Warm-start(웜스타트) — 무작위 초기화 대신 기존 신경망의 가중치에서 학습을 시작하는 것.
  • Residual block(잔차 블록) — 현대 신경망의 표준 구성 블록. 입력을 그대로 통과시키는 “급행 차선”과 더할 보정값을 계산하는 “우회로” 두 경로로 이루어집니다.

참고 자료

  • training/yinsh-ai/src/net2net.py, training/yinsh-ai/tests/test_net2net.py — 성장 유틸리티와 패리티 테스트. PR #1436.
  • packages/yinsh-ai-core/scripts/iterate.ts, training/yinsh-ai/run-campaign-k3s.sh--lr 플래그 배선. PR #1439.
  • PR #1444 — 셀프플레이 낙오자 soft-barrier: 제 시간에 끝난 95%의 대국으로 학습하고 나머지는 건너뜁니다.
  • docs/task-log/20260717-ai-training-improvement/02-next-levers.md — 모든 설정과 Elo 수치가 담긴 실험 전체 표.
  • docs/task-log/20260717-ai-training-improvement/03-how-ai-training-works.md — 이 글이 바탕으로 한 주니어 AI 엔지니어용 교육 문서.
  • [[2026-07-14-clever-tricks-lost-to-capacity]] — 270세대 회고; 이번 실험이 뚫으려 한 용량 정체 구간.
  • [[2026-06-29-capacity-was-the-limiter]] — 첫 번째 용량 천장 돌파(96×8 → 128×10, +113 Elo)의 과정.
  • AlphaZero (DeepMind, 2017) — 이 파이프라인이 본뜬 self-play + search + train 루프.
  • Net2Net: Accelerating Learning via Knowledge Transfer (Chen et al., 2016) — 성장 기법의 원본 논문.

AI 작업 노트

원본 자료(03-how-ai-training-works.md)는 모든 실험이 완료된 후 주니어 AI 엔지니어를 위한 교육 문서로 먼저 작성됐습니다. 이것을 비엔지니어를 위한 블로그 글로 전환하는 작업은 일반 독자가 처음부터 끝까지 따라갈 수 있는 두세 개의 아이디어(루프, 증류 한계, 학습률 함정)를 선별하고, 교육용 발판(“주니어 핵심” 박스, 기울기 흐름 상세)을 제거하는 것을 의미했습니다. Net2Net 절이 가장 번역하기 어려웠습니다. “복사 후 공 나누기”와 “볼륨 0의 우회로”는 원본 문서에서는 정확하지만 두 개념이 동시에 도착하기 때문입니다. 이를 해결하기 위해 메커니즘보다 유추(좁은 봉우리)를 먼저 제시했습니다. 학습률 절은 거의 그대로 전환됐습니다 — 원본 문서의 머릿속 그림이 이미 비엔지니어에게 읽힐 만한 것이었기 때문입니다.

#ai #yinsh #self-play


Hungjoon

I'm Hungjoon, a software engineer based in South Korea. This is my long-form notebook — homelab, Kubernetes, AI infra, and whatever else keeps me up at night.