lf.wtf
연구 노트 01

AI 연구 · SmolLM2-135M

회로 이식

Claude Opus 5.5와 함께 쓰고 만들었어요

135M 모델의 뉴런에 작은 회로를 이식했어요. 경사 학습은 쓰지 않았어요. 모델은 SmolLM2-135M이고, 원래 가중치는 하나도 바뀌지 않았어요. 봉인한 홀드아웃 문제에서 곱셈 점수가 21.3%에서 83.1%로 올랐어요.

SmolLM2-135M 안에서 이식이 놓이는 곳텍스트는 토큰으로 들어와 뉴런으로 된 30개 층을 지나고, 출력 헤드가 다음 토큰을 골라요. 이식은 층 옆에 덧붙인 작은 회로예요. 20층을 읽고, 출력 헤드 바로 앞에 있는 마지막 층인 29층에 밀어 주기를 더해요. 원래 뉴런은 바뀌지 않아요.0142021290층에서 29층. 점은 각 층의 일부이며, 실제 비율이 아니에요.토큰입력출력헤드다음토큰이식25,270에서 121,198개가중치 추가,0.1% 미만132원래 뉴런, 변경 없음이식, 층 옆에 추가 SmolLM2-135M 안에서 이식이 놓이는 곳텍스트는 토큰으로 들어와 뉴런으로 된 30개 층을 지나고, 출력 헤드가 다음 토큰을 골라요. 이식은 층 옆에 덧붙인 작은 회로예요. 20층을 읽고, 출력 헤드 바로 앞에 있는 마지막 층인 29층에 밀어 주기를 더해요. 원래 뉴런은 바뀌지 않아요.토큰 입력014202129출력 헤드다음 토큰이식25,270에서 121,198개가중치 추가,0.1% 미만132원래 뉴런, 변경 없음이식, 층 옆에 추가점은 각 층의 일부이며, 실제 비율이 아니에요.
이식이 놓이는 곳. SmolLM2-135M은 30개 층으로 되어 있고, 각 층은 어텐션 블록(헤드 9개)과 그 뒤의 MLP 블록으로 이루어져 있으며, 폭이 숫자 576개인 은닉 상태를 다뤄요. 가중치는 모두 약 134.5M개예요. 이식은 우회로처럼 층 옆에 덧붙인 작은 회로예요. 원래 뉴런이나 가중치는 하나도 바뀌지 않아요.
  1. 읽기와 두 스위치는 모델이 다음 답 자릿수를 쓰려는 위치에서, 20층 MLP의 입력에 있는 은닉 상태를 가져와요.
  2. 이식의 밀어 주기는 같은 위치에서 마지막 층인 29층의 MLP 출력에 더해져요. 출력 헤드가 다음 토큰을 고르기 바로 전이에요.
  3. 세 자리 덧셈에서는 읽기에 14층과 21층도 합쳐요(모두 숫자 1,728개). 쓰기는 여전히 마지막 층에 들어가요.
곱셈, 홀드아웃
21.3% → 83.1%
바뀐 원래 가중치
0
가장 큰 이식의 모델 대비 비율
0.09%
같은 크기 경사 학습 이식 대비 앞선 포인트
+57.9

출발점

규칙 하나가 많은 사실에 쓰일 수 있다

작은 오픈 모델을 무거운 학습 없이, 가중치를 직접 편집하고 새 부품을 이식하는 것만으로 프런티어 수준에 얼마나 가깝게 끌어올릴 수 있는지 알아보고 싶어요. 보통은 학습을 해요. 수십억 개의 질문과 답을 모델에 통과시키면 경사 하강법이 스스로 규칙을 찾아내요. 그런데 모델을 열어서 문제를 푸는 도중에 무엇을 갖고 있는지 읽고, 그걸 바꿀 수도 있어요. 그렇다면 그 규칙 중 일부를 손으로 써 넣을 수 있을까요?

제 작업 가설은 추론의 상당 부분이 규칙 세트로 돌아가고, 규칙 하나가 많은 사실에 쓰인다는 거예요. 가장 단순한 예가 1을 받아올리는 거예요. 모든 덧셈을 외우는 사람은 없어요. 받아올림 규칙 하나가 모든 자리에서 모든 덧셈을 처리하니까요. 메모에는 이렇게 적었어요.

어쩌면 한 사실의 규칙이 다른 사실의 규칙과 일치할지도 모른다.

작은 모델에게 사실은 저장하기에 비싸고, 규칙은 싸요. 이 노트의 첫 번째 곱셈 회로는 2 × 10부터 9 × 99까지 모든 문제를 위해 만들었고, 가중치는 25,270개예요.

같은 대화에서 첫 번째 생각과 짝을 이루는 두 번째 아이디어도 나왔어요. 이미 아는 걸 적용하는 논리 규칙과 함께, 새로운 걸 익히기 위한 학습 규칙 세트가 있다는 거예요. 이 노트는 논리 쪽을 다뤄요.

모델이 이미 가진 것

숫자는 이미 안에 있다

무언가를 만들기 전에, SmolLM2가 답을 쓰기 시작하는 순간 무엇을 갖고 있는지 살펴봤어요. 답 위치의 은닉 상태를 최소제곱법으로 맞춘 선형 읽기로 읽으면, 두 수의 각 자릿수가 거의 완벽하게 나와요. 세 자리 덧셈은 한 층으로는 부족했지만, 14, 20, 21층을 합치면 새 문제에서 모든 자릿수를 99%로 읽어 내요.

자릿수는 어디에 있나

세 자리 덧셈. 선형 읽기가 두 수의 여섯 자릿수를 모두 맞게 읽어 낸 새 문제의 비율이에요. 한 번에 한 층씩 읽은 경우와, 14, 20, 21층을 합친 경우예요. 각 읽기는 1,500문제로 맞췄어요.

76.6% 단일 층 중 최고, 21층

11.8% 마지막 층, 29층

97.9% 14, 20, 21층을 합친 경우, 그 읽기를 3,000문제로 맞추면 99.2%

30개 층 전체를 표로
층여섯 자릿수 모두 맞음
00.0%
14.3%
226.0%
350.1%
452.2%
547.1%
631.4%
720.4%
818.8%
918.2%
1027.1%
1127.9%
1239.1%
1347.2%
1474.8%
1570.1%
1664.0%
1763.0%
1864.2%
1963.5%
2072.9%
2176.6%
2271.5%
2362.9%
2448.8%
2530.5%
2619.0%
2713.9%
2811.7%
2911.8%

즉, 모델은 문제를 읽었어요. 모델이 안정적으로 못 하는 건 자릿수를 결합하는 일이에요. 받아올림, 받아내림, 구구단 같은 거요. 그 결합 단계를 저희가 채워 넣어요.

이식의 작동 방식

네 가지 부품, 어느 것도 경사 하강법으로 학습하지 않았다

  1. 읽기두 수의 각 자릿수마다, 모델 자신의 은닉 상태에서 가져오는 선형 읽기예요.
  2. 규칙답의 자릿수마다 있는 작은 조회 표예요. 일의 자리는 두 수의 일의 자리에서 나오고, 십의 자리는 두 수의 십의 자리와 받아올림에서 나오는 식으로 위로 올라가요.
  3. 쓰기모델의 마지막 층에서 맞는 숫자 토큰 쪽으로 밀어 줘요. 답은 여전히 모델이 직접 써요. 이식은 다음에 어떤 숫자가 올지만 살짝 기울여요.
  4. 스위치맞춰 둔 스위치 두 개가 이식을 언제 켤지 정해요. 이런 종류의 문제에 답을 쓰는 동안에만 켜지고, 다른 수학, 문장제, 코드, 일반 텍스트에서는 꺼져 있도록 맞췄어요.

읽기와 스위치는 닫힌 형식의 최소제곱법으로 맞추고, 규칙 표는 프로그램이 써 내요(첫 번째 곱셈 이식은 손으로 썼어요). 기본 모델 파일은 전혀 건드리지 않아요. 각 이식은 그 옆에 덧붙여요.

이식의 내부, 38 + 47의 경우자릿수를 읽고, 규칙을 적용하고, 맞는 숫자를 밀어 줘요. 밀어 주기를 언제 켤지는 두 스위치가 정해요. 밀어 주기는 29층에서 더해지고, 모델은 85를 써요.1읽기첫째 수: 3, 8둘째 수: 4, 7남은 답 자릿수: 22규칙일의 자리: 8 + 7 = 155를 쓰고, 1 받아올림십의 자리: 3 + 4 + 1 = 83쓰기답의 첫 자릿수:8을 밀어 줌답의 다음 자릿수:5를 밀어 줌4스위치밀어 주기 × 스위치 × 스위치켜짐: 이 답을 쓰는 동안꺼짐: 다른 텍스트29층에서 더해져요. 모델은 85를 써요. 이식의 내부, 38 + 47의 경우자릿수를 읽고, 규칙을 적용하고, 맞는 숫자를 밀어 줘요. 밀어 주기를 언제 켤지는 두 스위치가 정해요. 밀어 주기는 29층에서 더해지고, 모델은 85를 써요.1읽기첫째 수: 3, 8둘째 수: 4, 7남은 답 자릿수: 22규칙일의 자리: 8 + 7 = 155를 쓰고, 1 받아올림십의 자리: 3 + 4 + 1 = 83쓰기답의 첫 자릿수: 8을 밀어 줌답의 다음 자릿수: 5를 밀어 줌4스위치밀어 주기 × 스위치 × 스위치켜짐: 이 답을 쓰는 동안꺼짐: 다른 텍스트29층에서 더해져요. 모델은 85를 써요.
이식의 내부, 38 + 47을 예로 든 그림이에요. 읽기는 3, 8, 4, 7과 함께, 답 자릿수가 두 개 남았다는 것을 찾아요. 규칙에 따르면 8 + 7 = 15이므로 일의 자리는 5이고 1을 받아올리며, 십의 자리는 3 + 4 + 1 = 8이에요. 첫 번째 답 위치에서 이식은 8을 밀어 주고, 다음 위치에서는 5를 밀어 줘요. 밀어 주기의 크기는 자리마다 조정돼요. 두 스위치가 밀어 주기에 곱해지기 때문에, 모델이 이런 종류의 문제에 답을 쓰는 동안에만 켜져요. 답은 여전히 모델이 직접 써요.

어떻게 커졌나

이식 하나에서 파이프라인으로

  1. 뉴런 이식첫 시도에서는 두 자리 덧셈의 받아올림을 채우려고 마지막 층에 새 뉴런 24개를 추가했어요. 봉인된 문제에서도 효과가 유지됐고, +19.7포인트였어요. 이건 모델 자체의 계산을 살짝 거드는 방식이었기 때문에, 다음 단계는 계산을 아예 직접 하는 거였어요.
  2. 손으로 연결한 회로곱셈에서는 규칙 표를 손으로 쓰고, 모델 자신의 자릿수 읽기를 입력으로 넣었어요. 첫 버전은 봉인된 홀드아웃 문제에서 83.5%를 기록했어요. 원래는 21.3%였어요. 스위치를 개선한 두 번째 버전은 83.1%였고, 다른 수학에서 가장 크게 나빠진 폭은 −0.75포인트였어요.
  3. 프로그램이 찾은 규칙규칙을 찾는 프로그램에 풀이가 있는 문제 340개를 자릿수와 답의 형태로 줬어요. 프로그램은 답의 각 자릿수마다 그 자릿수를 결정하는 가장 작은 입력 집합을 찾았어요. 덧셈의 받아올림, 뺄셈의 받아내림, 곱셈의 받아올림 연쇄를 스스로 찾아냈어요. 십의 자리가 일의 자리 규칙을 십의 자리 숫자에 다시 쓴 것에 받아올림 단계를 더한 것이라는 것도 찾았어요. 규칙 하나가 여러 자릿수에 쓰이는 거죠. 이 작업의 출발점이 된 바로 그 생각이에요. 이 프로그램의 곱셈 회로는 홀드아웃에서 82.7%를 기록해, 손으로 연결한 회로와 0.5포인트 이내였어요.
  4. 같은 파이프라인, 새로운 능력뺄셈과 두 자리 덧셈은 곱셈의 설정을 그대로 복사해, 조정 없이 같은 스크립트에 넣었어요. 세 자리 덧셈은 세 가지를 고쳐야 했고, 각각 홀드아웃 세트를 열기 전에 테스트했어요. 세 층을 합친 읽기, 두 번째 스위치, 자리마다 따로 정한 밀어 주기 강도예요.
규칙 찾기 프로그램의 작동 방식풀이가 있는 문제 340개가 들어가요. 프로그램은 답의 각 자릿수마다 그 자릿수를 결정하는 가장 작은 입력 집합을 찾고, 십의 자리가 일의 자리 규칙을 다시 쓰고 받아올림을 더한 것임을 찾아내고, 규칙을 조회 표로 컴파일해요.풀이가 있는 문제 340개38 + 47 = 8516 + 29 = 4552 + 31 = 83...답 자릿수별 최소 입력일의 자리 ← 두 수의 일의 자리십의 자리 ← 두 수의 십의 자리+ 일의 자리에서 받아올림일의 자리 규칙을 한 자리 위에서 다시 씀조회 표8, 7 → 5, 받아올림 16, 9 → 5, 받아올림 12, 1 → 3, 받아올림 0... 규칙 찾기 프로그램의 작동 방식풀이가 있는 문제 340개가 들어가요. 프로그램은 답의 각 자릿수마다 그 자릿수를 결정하는 가장 작은 입력 집합을 찾고, 십의 자리가 일의 자리 규칙을 다시 쓰고 받아올림을 더한 것임을 찾아내고, 규칙을 조회 표로 컴파일해요.풀이가 있는 문제 340개38 + 47 = 8516 + 29 = 4552 + 31 = 83...답 자릿수별 최소 입력일의 자리 ← 두 수의 일의 자리십의 자리 ← 두 수의 십의 자리+ 일의 자리에서 받아올림일의 자리 규칙을 한 자리 위에서 다시 씀조회 표8, 7 → 5, 받아올림 16, 9 → 5, 받아올림 12, 1 → 3, 받아올림 0...
규칙 찾기 프로그램. 풀이가 있는 문제 340개를 자릿수와 답의 형태로 받아요. 답의 각 자릿수마다 그 자릿수를 결정하는 가장 작은 입력 집합을 찾아요. 일의 자리는 두 수의 일의 자리에만 달려 있어요. 십의 자리가 일의 자리 규칙을 다시 쓰고 받아올림을 더한 것임을 찾아내고, 규칙을 조회 표로 컴파일해요. 예시 행은 설명을 위한 거예요.

효과가 있었던 이유

프로그램이 규칙을 찾을 수 있었던 이유

규칙은 모델에서 나온 게 아니에요. 모델 밖의 별도 프로그램이 풀이가 있는 예제 340개에서 찾았어요. 모델이 맡은 일은 숫자를 제공하는 것이고, 이식은 그 숫자를 모델의 은닉 상태에서 읽어요. 이걸 가능하게 한 건 네 가지예요.

  1. 문제를 자릿수로 나누기정수 그대로 보면 7 × 48 = 336은 가능한 문제 720개 중 하나의 사실일 뿐이에요. 자릿수로 나누면 패턴이 보여요. 답의 마지막 자릿수는 7과 8에만 달려 있어요. 이게 가장 중요한 선택이었고, 각 숫자를 별도 토큰으로 저장하는 SmolLM2와도 잘 맞아요.
  2. 가장 단순한 설명 찾기프로그램은 답의 각 자릿수마다 그 자릿수를 항상 결정하는 가장 작은 입력 자릿수 묶음을 찾고, 모든 예제에서 성립할 때만 그 규칙을 남겨요. 두 자릿수에 기반한 규칙은 가능한 항목이 약 100개이고, 예제 340개로 거의 다 채워져요. 그래서 같은 쌍을 다시 쓰는 새 문제에서도 통해요. 외우려면 모든 입력 자릿수를 다 써야 하는데, 그 조합은 예제 340개로는 턱없이 모자라요.
  3. 이미 찾은 규칙 다시 쓰기한 자리 위에서는 일의 자리 규칙을 다시 시도하고, 남는 부분을 설명하는 추가 신호가 하나 있는지 확인해요. 그 신호가 받아올림이었어요. 아무도 프로그램에 그 말을 알려 주지 않았어요. 데이터가 변수 하나를 필요로 했기 때문에 그 변수를 찾은 거예요. 백의 자리에서 같은 단계를 반복하면 받아올림의 연쇄가 나와요.
  4. 처음 보는 문제로 확인하기규칙은 본 적 없는 문제로 테스트한 다음, 이식 안의 조회 표로 컴파일했어요.

경사 학습에는 가장 단순한 설명으로 끌리는 성질이 내장돼 있지 않고, 예제가 적으면 외워 버렸어요. 곱셈에서 같은 크기의 경사 학습 이식은 자기 학습 문제에서 72.7%, 개발용 문제 140개에서 25.1%였어요. 회로는 만들 때 쓴 문제에서 94.7%, 같은 개발용 문제에서 88.7%였어요.

자릿수로 나누는 틀은 우리가 정했고, 프로그램은 그 안에서 규칙을 찾아요. 산수를 넘어서는 기술로 가는 다음 단계는 문제를 나누는 올바른 방법까지 스스로 찾는 프로그램이에요.

결과

아무도 조정에 쓰지 않은 문제에서 다섯 가지 능력

각 능력의 홀드아웃 문제는 무언가를 만들기 전에 따로 떼어 두었고, 그 문제로는 아무것도 조정하지 않았어요. 모든 점수는 시드 두 개, 문제당 네 번 실행한 결과이고, 모델 단독일 때와 이식했을 때 같은 샘플링 설정을 썼어요. 곱셈 세트는 첫 번째 손으로 연결한 버전 때 한 번, 마지막 두 버전 때 한 번 더 열었어요.

홀드아웃 정확도, SmolLM2-135M

정확히 맞힌 문제의 비율. 곱셈은 140문제, 나머지는 500문제.

  • SmolLM2 단독
  • 이식 적용
  • 같은 이식, 배선 섞음
곱셈7 × 48, 규칙은 손으로 연결
21.3% → 83.1%+61.8
곱셈7 × 48, 규칙은 프로그램이 찾음
21.3% → 82.7%+61.3
뺄셈, 두 자리83 − 27, 규칙은 프로그램이 찾음
11.3% → 68.3%+57.1
덧셈, 두 자리38 + 47, 규칙은 프로그램이 찾음
49.7% → 86.5%+36.8
덧셈, 세 자리347 + 285, 규칙은 프로그램이 찾음
26.1% → 83.7%+57.6
같은 결과를 표로
능력문제 수SmolLM2 단독이식 적용향상, 포인트(95% 하한)배선 섞음추가 가중치
곱셈, 규칙은 손으로 연결7 × 4814021.3%83.1%+61.8 (+56.1)2.4%25,2700.019%
곱셈, 규칙은 프로그램이 찾음7 × 4814021.3%82.7%+61.3 (+55.5)6.3%32,5190.024%
뺄셈, 두 자리83 − 2750011.3%68.3%+57.1 (+54.0)7.8%32,4460.024%
덧셈, 두 자리38 + 4750049.7%86.5%+36.8 (+33.8)16.7%32,4760.024%
덧셈, 세 자리347 + 28550026.1%83.7%+57.6 (+54.6)21.4%121,1980.090%
  • 원래 가중치는 하나도 바뀌지 않았고, 경사 학습도 없었어요. 각 이식은 가중치를 25,270개에서 121,198개 더하고, 이는 모델의 0.019%에서 0.090%예요. 스스로 정한 상한은 0.1%였어요.
  • 배선 섞음 대조군은 같은 이식에서 배선만 뒤섞은 거예요. 모든 능력에서 모델 단독과 같거나 그보다 낮은 2.4%에서 21.4%를 기록했으니, 맞는 규칙이 없으면 추가 가중치는 아무 역할도 못 해요.
  • 두 자리 이식 세 개(곱셈, 뺄셈, 덧셈)는 한 모델에서 함께 돌릴 수도 있고, 가중치는 모두 92,496개예요. 각각 개발용 문제에서 향상을 유지했어요. 다른 수학에서 가장 크게 나빠진 폭은 −0.25포인트였고, 관련 없는 프롬프트 200개 중 200개가 이전과 같은 답을 냈어요.

향상은 문제별로 짝지어 계산했고, 단측 95% 부트스트랩 하한을 썼어요. 부작용 점검은 다른 산수와 문장제 세트 8개에 GSM8K와 코드를 더한 거예요. 관련 없는 프롬프트는 IFEval 프롬프트 200개이고, 탐욕적 디코딩으로 답하게 했어요. 모든 실행의 규칙과 예측은 결과가 나오기 전에 적어 뒀어요.

경사 학습과 비교

세 번의 맞대결

능력을 추가하는 표준 방법은 경사 학습이라서, 그걸 경쟁자로 돌렸어요. 각 경사 학습 이식은 테스트 전에 설정 그리드에서 조정했어요.

곱셈, 봉인된 홀드아웃

140문제, 시드 2개, 각 4회 실행. 첫 번째 손으로 연결한 회로와 조정을 마친 경사 학습 이식 두 개의 비교.

SmolLM2 단독
21.3%
경사 학습 이식, 같은 크기뉴런 14개
25.6%
경사 학습 이식, 0.1% 상한뉴런 77개
23.7%
회로 이식가중치 25,270개, 경사 학습 없음
83.5%

회로가 57.9포인트와 59.8포인트 앞섰어요.

곱셈, LoRA 파인튜닝과 비교

개발용 문제 140개, 시드 2개, 각 4회 실행. LoRA는 그리드 탐색에서 가장 좋았던 설정을 사용.

SmolLM2 단독
28.5%
LoRA 파인튜닝학습한 가중치 115,200개
39.4%
회로 이식가중치 25,270개, 경사 학습 없음
88.7%

49.3포인트 앞섰고, 95% 하한은 +42.8이에요. 가중치는 4분의 1도 안 썼어요.

두 자리 뺄셈

개발용 문제 500개, 시드 2개, 각 4회 실행. 회로의 설정은 곱셈에서 그대로 가져왔고 조정하지 않았어요.

SmolLM2 단독
11.35%
경사 학습 이식, 뉴런 14개
48.15%
경사 학습 이식, 뉴런 77개가중치 133,056개, 조정함
65.0%
회로 이식가중치 32,446개, 조정 없음
64.98%

네 배 크기의 경사 학습 이식과는 동점이고, 뉴런 14개짜리보다는 약 17포인트 앞섰어요.

회로의 뺄셈 규칙은 340문제에서 나왔어요. 경사 학습 이식은 1,500문제로 학습했는데, 회로의 자릿수 읽기를 맞출 때 쓴 것과 같은 1,500문제예요.

진행 중

더 큰 모델에서 옮겨 오기

더 큰 모델에서 능력을 옮겨 오는 것도 시도하고 있어요. Qwen3.5-4B는 저희 확인에서 이 곱셈 문제를 300개 중 300개 맞혔기 때문에, 그 뉴런 일부를 SmolLM2로 변환해 옮겨 보려고 했어요. 이와 별도로, 초등학교 수준 문장제에서 Qwen3.5-4B의 보정 신호를 Qwen3.5-0.8B로 매핑했어요. 둘 다 아직 성공하지 못했고, 둘 다 아직 진행 중이에요. 지금까지는 큰 모델이 작은 모델이 어디서 무너지는지 알려 주는 길잡이로 가장 쓸모가 있었어요.

이식이란

모델 자신의 읽기를 입력으로 쓰는 계산기

계산은 모델이 이미 갖고 있는 숫자를 가지고 이식이 직접 해요. SmolLM2가 곱셈을 배우는 건 아니에요. 이식은 문제의 단순한 형태("347 + 285는 얼마인가요?")에서 작동하고, 문장제에서는 스위치가 일부러 꺼 둬요. 지금까지는 모두 한 모델에서의 결과예요.

이 방법은 새로운 능력에도 그대로 이어져요. 규칙은 예시 340개에서 프로그램이 찾고, 표로 컴파일한 뒤, 능력마다 같은 설정으로 배치해요. 다음은 학습 쪽이에요. 프롬프트로 건네받은 사실을 SmolLM2가 활용하게 만드는 거예요.