Kaggle NVIDIA Nemotron 추론 대회 동메달: 공개 어댑터로도, 개인적으로도 패배했던 베이스라인이 승리한 이야기
요약
Kaggle의 NVIDIA Nemotron Model Reasoning Challenge에 참가하여 동메달을 획득한 경험을 공유합니다. 이 대회는 LoRA를 활용해 LLM으로 논리 퍼즐 정답률을 높이는 것이 목표였습니다. 공개 환경에서 패배했던 베이스라인이 private 테스트에서 역전승하며 메달을 따낸 과정을 상세히 설명합니다.
핵심 포인트
- LoRA 미세 조정 및 검증 기반 구축의 중요성
- 공개/비공개 데이터셋 간의 차이를 이해해야 함
- 문제 유형별 정답률 분석으로 약점 파악 가능
- 기존 베이스라인을 충실히 재현하는 것이 핵심
서론
Kaggle의 NVIDIA Nemotron Model Reasoning Challenge에 참가하여 4,348팀 중 262위로 동메달을 획득했습니다(private 0.856).
LoRA도 LLM (대규모 언어 모델) 미세 조정도 처음이었고, 남은 기간이 2주밖에 없었습니다. 복잡한 해법은 아닙니다. 다만 마지막에 '공개 환경에서도, 개인적인 검증에서도 패배했던 베이스라인이 private에서 승리하며 메달을 따는' 역전극이 벌어졌기 때문에 그 이야기를 중심으로 정리했습니다.
대회 개요
LLM을 LoRA로 미세 조정하여 논리 퍼즐의 정답률을 높이는 대회입니다.
- 모델:
nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16
(30B MoE (Mixture of Experts)로 구동되는 것은 3B이며, Mamba와 Transformer의 혼성 구조) - 제출: LoRA 어댑터(rank 32 이하)만
submission.zip으로 제출합니다. 추론은 운영 측의 vLLM으로 진행됩니다. - 데이터: train.csv 9,500행.
id, prompt, answer만 포함되어 있고, 사고 과정(CoT: Chain of Thought)은 포함되어 있지 않습니다. - 문제 유형: 비트 연산, 암호, 중력, 숫자 표기, 단위 환산, 복면 산수, 수식 등 9가지. 유형은 prompt의 템플릿에서 판별할 수 있습니다.
- 채점: 출력된
oxed{}안의 내용이 정답과 일치하는 비율(수치는 상대적으로 1%까지 허용). - 계산 자원: Kaggle이 Blackwell GPU (RTX PRO 6000급, 약 96 GB)를 제공했기 때문에, 30B 모델을 bf16 상태 그대로 Kaggle의 노트북에서 학습할 수 있었습니다.
public LB(Leaderboard)는 약 100문제밖에 없습니다. 공개 어댑터를 그대로 제출한 팀들이 0.86 근처에 약 1,200팀이 몰려 있어, 메달권의 차이는 public 환경에서는 파악하기 어려운 상태였습니다.
진행 과정
1. 먼저 성실한 검증 기반을 구축하다
학습을 시작하기 전에 다음 검증 기반을 만들었습니다.
- 공개 CoT 데이터는 train 문제에서 만들어졌기 때문에, 아무 생각 없이 사용하면 held-out(분리된) 문제가 학습에 섞이게 됩니다. held-out의 id는 CoT 데이터 생성과 학습 데이터 모두에서 제외했습니다.
- 채점 함수는 공개되었던 검증 노트북(huikang님)의 동작을 이식했습니다.
- 전체 정답률뿐만 아니라, 유형별 정답률을 반드시 확인했습니다. 약점을 즉시 파악할 수 있습니다.
2. 채점의 특징
수치로 읽을 수 있는 답은 허용 오차를 두고 비교됩니다.
import math
def verify(gold: str, pred: str) -> bool:
try:
...
앞에 0이 붙는 2진수도 10진수로 읽히기 때문에, 비트 연산 문제는 하위 비트를 틀려도 정답이 될 수 있습니다. 상위 비트가 맞는지 여부만 중요하기 때문에, 하위 비트의 정확도를 높여도 점수가 되지 않습니다.
3. 공개 레시피를 충실히 재현한 베이스라인
dgxchen님의 공개 레시피를 가능한 한 그대로 재현했습니다.
- Unsloth, LoRA r32 (q/k/v/o와 Mamba의 in/out, MLP의 up/down)
- 공개 CoT 데이터 7,029건(held-out 제외 후), 1 에포크, 학습률 2e-4
- Blackwell에서 약 7시간. 어댑터가 MoE의 128 expert 전체에 붙기 때문에 약 3 GB (8.8억 파라미터)
held-out 결과는 **86.6 %**였습니다(학습 전 모델은 22 %).
| 유형 | 정답률 |
|---|---|
| 숫자 표기 / 중력 / 단위 환산 | 99~100 % |
| ... |
학습 전 모델은 오래 생각하다가 oxed{} 안에 도달하지 못하는 경우가 많았고, 학습을 통해 익힌 것은 주로 '간결하게 생각해서 답을 상자에 넣는' 것이었습니다.
| 실험 | held-out | public | private |
|---|---|---|---|
| 베이스라인(dgxchen 레시피 재현) | 86.6 % | 0.844 | 0.856 |
| 공개 어댑터(kienngx 님의 tinker)를 그대로 | 88.2 % | 0.864 | 0.844 |
| 베이스라인 + 합성의 가면 계산 CoT | 86.8 %(가면 계산 0 %) | ||
| LoRA의 모델 수프(공개 어댑터 2개의 가중치 평균) | 65.5 % | ||
| 베이스에서 재학습하고, 비트 연산・가면 계산을 자체 솔버의 CoT로 교체 | 77.9 % | ||
| 공개 어댑터부터 추가 학습(비트 연산에 대한 상세한 CoT, 학습률 5e-5) | 81.2 % |
자체 개선안은 모두 베이스라인과 공개 어댑터에도 미치지 못했습니다.
효과가 없었던 것들
합성 CoT(가면 계산・비트 연산)
가면 계산은 문제마다 기호와 숫자의 대응이 무작위로 바뀌는 암호화된 계산입니다. 몇 개의 예시로부터 대응을 해독할 필요가 있어, 올바른 절차의 CoT를 합성하여 학습시켜도 가면 계산은 0%에 머물렀습니다.
비트 연산은 자체 솔버(held-out에서 86% 해결 가능)로 올바른 CoT를 만들어서 학습시켰습니다. 베이스에서 재학습하자 85.6% → **36.2%**로 무너졌고, 공개 어댑터부터 추가 학습하자, **학습하지 않은 암호의 정답률까지 100% → 74.7%**로 떨어졌습니다.
정답이 맞더라도 CoT를 작성하는 방식이 모델 자체 추론 방식과 다르면, 모델은 형식만 따라 하려다 계산을 할 수 없게 됩니다. 커뮤니티에서도 '5만 건의 올바른 합성 CoT로 학습했더니 LB 0.46'이라는 보고가 있었는데, 같은 현상이라고 생각합니다.
LoRA의 모델 수프
공개 어댑터 2개의 가중치를 평균하자 65.5%로 무너졌습니다. LoRA의 업데이트량은 B×A이므로, A와 B를 따로따로 평균해도 업데이트량의 평균이 되지 않습니다.
평균하려면 모듈별로 업데이트량 BA를 평균한 다음 rank 32로 자르는 것이 필요합니다.
warm-start 시 키 이름 불일치
공개 어댑터부터 추가 학습한 첫 버전은, 8 스텝밖에 학습하지 않았는데 public이 0.56이었습니다. 공개 어댑터와 PEFT에서 키 이름 지정 방식이 달라 가중치가 거의 로드되지 않고 초기값 그대로 진행되었던 것이 원인이었습니다. PEFT는 경고만 내보낼 뿐 멈추지 않습니다. 키 이름을 대응시켜 재조정하자, 12,010개의 텐서 전체가 로드되었습니다. warm-start 할 때는, 로드된 텐서 수를 assert로 확인하는 것을 추천합니다.
마지막 역전
마감 전에 보였던 지표로는 모두 공개 어댑터가 우세했습니다.
| 제출 | public | held-out | private |
|---|---|---|---|
| 공개 어댑터 | 0.864 | 88.2 % | 0.844 |
| 자체 베이스라인 | 0.844 | 86.6 % | 0.856 |
최종 제출은 2개 선택이 가능하여, 공개 어댑터와 베이스라인 둘 다를 선택했습니다. private에서는 순위가 바뀌어, 베이스라인이 메달을 가져갔습니다.
이 역전은 마감 전 데이터로는 예측할 수 없었다고 생각합니다. held-out은 train에서 분리되었기 때문에, 보이는 분포에 너무 치우친 어댑터는 발견하기 어렵습니다. held-out과 public 모두에서 공개 어댑터가 우세했던 것은 같은 분포로 측정했기 때문입니다.
교훈
교훈
마지막 2개 중 1개는 손대지 않은 순수한 베이스라인으로 남겨두기. 보이는 분포에 대한 과적합(overfitting)에 대비하는 저렴한 보험이 됩니다.
- train에서 분리해낸 held-out은 나쁜 아이디어를 버리기는 충분하지만, 좋은 아이디어들 간의 순위 매기기에는 불충분합니다. Soup나 Solver CoT는 올바르게 기각할 수 있었지만, 공개 어댑터의 과적합은 발견하지 못했습니다. 추론(inference) 태스크의 합성 CoT는 답의 정확성보다 작성 방식이 모델에 적합한지가 중요합니다.
- public LB는 정답 확인 정도만 사용하고 최적화 목표로 삼지 마세요. 약 100문제의 public은 메달권에서는 거의 정보가 없었습니다.
- Kaggle의 kernel-metadata에는 작성하지 않으면 P100이 할당되고, 데이터를 로드한 후 CUDA 에러가 발생합니다. 데이터 버그처럼 보이지만 실제로는
machine_shape을 반드시 적어야 합니다.
공개한 것
검증 기반(validation infrastructure) 부분을 CPU만으로 구동되는 노트북으로 만들어 공개했습니다 (채점 함수, 채점 습관 데모, 종류 판별, ID 기반 계층 분할 및 누수 체크).
맺음말
처음 LLM 미세 조정 대회에서 동메달을 딸 수 있었던 것은 복잡한 기교가 아니라, 검증 시스템을 먼저 만들고 순수한 베이스라인을 남겨두었기 덕분이었습니다.
학습 레시피와 CoT 데이터를 공개해주신 dgxchen 님, 채점 로직과 해법을 공개해주신 Tong Hui Kang(huikang) 님, 비교에 사용하게 해주신 어댑터를 공개해주신 kienngx 님, 그리고 NVIDIA와 Kaggle에 감사드립니다.
토론

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn ML의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기