표기 변형을 되돌릴 수 있는 opcode/operand로 분해해 토크나이저 어휘를 줄이는 Functionalizer
The Functionalizer: Lossless Functional Decomposition for Subword Tokenization
무엇인가
서브워드 토크나이저는 hello, Hello, HELLO, Héllo 같은 표기 변형을 서로 무관한 어휘 항목으로 취급한다. 그러면 표면형이 임베딩 슬롯을 중복 소비하고, Hello에 대한 그래디언트 업데이트가 hello에 간접적으로만 전달된다. 반대로 공격적인 소문자화와 발음구별기호 제거는 손실 압축이라 다운스트림 모델이 원래 정보를 복구할 수 없다. 이 논문은 제3의 경로인 무손실 함수 분해를 제안한다. 표면형을 외우거나 정보를 파괴하는 대신, 변형을 재사용 가능한 연산자로 분해해 하나의 정규 기저(canonical base)에 적용한다. 설계는 CPU 명령어 집합 구조(ISA)에서 직접 차용했다. CPU가 모든 상수마다 별도 명령(ADD_1, ADD_2...)을 두지 않고 연산(opcode)과 데이터(operand)를 분리하듯, 기저 토큰을 operand로, 변환 접두사를 opcode로 둔다.
어떻게 동작하나
구체적으로 Functionalizer는 토크나이즈 이전에 동작하는 프리토크나이저 프레임워크다. 명령은 PUA(Unicode Private Use Area) 코드포인트 시퀀스로 기저 토큰 앞에 붙는다. 숫자 파라미터는 U+E000–U+E0FF에 매핑되어 0–255 정수 값을 담고(값 = 코드포인트 − 0xE000), 연산자는 U+E100–U+EFFF를 쓰며 고정 개수의 파라미터를 소비한다. 나머지 평면은 향후 연산자를 위해 남겨둔다. 순서는 [opcode] → [base] 접두사 방식이다. 접미사 방식이 자기회귀 생성에서 의미 의도를 먼저 말할 수 있다는 장점이 있지만, 접두사 방식은 단어가 여러 BPE 서브워드(예: neuro, computation, al)로 쪼개질 때 포맷 연산자가 모든 구성 서브워드의 셀프 어텐션 층에서 계속 보인다는 구조적 이점이 있다고 저자들은 설명한다.
무엇과 다른가
현재 구현된 연산자는 대소문자(CAPITALIZE), 결합 발음구별기호 13개 전용 opcode(U+E100–U+E10D), 문자 반복(REPEAT, MULTIREPEAT)이다. 변환 파이프라인은 완전 전단사다. 인코딩은 결합 발음구별기호를 직렬화 연산자로 추출하고, CAPITALIZE를 위해 대문자 인덱스를 찾고, 결합 표시를 제거하고, 남은 문자를 소문자로 만든 뒤 연산자 접두사를 정규 기저 앞에 붙인다. 디코딩은 연산자를 역순으로 적용해 발음구별기호와 대소문자를 복원한 뒤 접두사를 제거해 원문을 정확히 되돌린다. 반복 연산자는 디코딩 순서에서 마지막에 실행되고, 위치 파라미터는 반복 확장 이전의 개별 조각 내 인덱스를 가리킨다. Abcabcabc처럼 대소문자가 뒤섞인 반복은 분해하지 않고 그대로 둔다. 파이프라인에서는 원시 텍스트가 아니라 1차 정규식 분할기(Llama Split) 이후의 조각에 적용하는 것을 전제로 한다. 이렇게 하면 pos ≤ 255라는 국소 좌표계가 생겨 파라미터가 1바이트 범위를 넘지 않는다. 기본값은 연산자를 기저 단어와 분리된 독립 접두사 토큰으로 내보내는 split_operators = true이고, 이 경우 기저 토큰 임베딩이 모든 대소문자 변형에서 공유되는 대신 시퀀스 길이가 늘어난다. 반대로 split_operators = false로 두면 BPE나 SentencePiece가 자주 쓰이는 대소문자 형태를 적응적으로 병합할 수 있다.
어떻게 쓰나
실험은 자연어 산문(Wikitext, FineWeb-Edu)과 소스코드(Python-Codes-25k, GitHub-Code-Python)에서 수행했다. 데이터셋당 최대 100,000개 문서를 샘플링하고, 목표 어휘 예산을 사실상 무제한(4096k)으로 둔 BPE를 학습시켜 병합 후보가 완전히 고갈될 때까지 돌렸다. 이 조건에서 Functionalizer는 모든 코퍼스에 대해 더 작은 어휘로 완전한 코퍼스 커버리지를 달성했고, 필요한 어휘 슬롯을 14.61%에서 19.72%까지 줄였다(데이터셋 평균 17.16% 감소, FineWeb-Edu에서 −19.72%로 최대). 대신 연산자를 독립 접두사 토큰으로 내보내기 때문에 검증 데이터에서 Chars/Token이 −12.88%에서 −17.73% 변했다. 즉 토큰이 늘어나는 시퀀스 길이 비용을 지불하고 표현 공유와 구문 충실도를 얻는 맞바꿈이다.
전제와 한계
다운스트림 평가는 GPT-2 Small 구조(12층, 은닉 768, 어텐션 헤드 12, 컨텍스트 512, 임베딩 타이, 어휘 16k, 약 98M 파라미터)를 5개 시드로 FineWeb-Edu와 GitHub-Code-Python에서 50,000 스텝 학습해 수행했다. AdamW, 학습률 4e-4, 1,000 스텝 워밍업 후 선형 감쇠, 가중치 감쇠 0.01, 유효 배치 32를 썼다. 문자 단위 퍼플렉시티(Char PPL)는 GitHub-Code-Python에서 1.5328로 베이스라인 1.5697보다 낮았고, 교차 엔트로피도 0.6525 대 0.8056으로 낮았다. FineWeb-Edu 산문에서는 2.2656 대 2.2662로 사실상 동등했다. 탐욕 디코딩으로 데이터셋당 1,000개 검증 프롬프트에서 생성한 결과, Python 문법 성공률은 9.12%로 베이스라인 7.70%보다 높았고(상대 18.4% 개선) 시드 간 분산도 작았다. 중복 n-gram 반복은 FineWeb-Edu에서 66.0%에서 55.8%로, GitHub-Code-Python에서 25.5%에서 17.9%로 줄었다. 저자들은 공백과 식별자의 구조적 분해가 기여했다고 본다. 표준 BPE는 들여쓰기를 임의의 공백 청크로 쪼개지만, REPEAT 연산자는 공백 블록이 같은 기저 문자를 공유하고 서수 카운트만 다른 산술 관계로 파라미터화한다는 것이다. 다만 이 규모에서는 독립 접두사가 디코딩 비용을 만들기도 해서 산문에서 빈 시퀀스가 7.1% 나왔고, 그중 일부는 연산자만 있는 시퀀스였다.
개발자 관점에서 이 논문은 토크나이저 어휘 크기와 시퀀스 길이 사이의 트레이드오프를 다루는 도구로 읽힌다. 다국어·코드·대소문자 혼용 텍스트를 다루면서 어휘 폭발이나 발음구별기호 손실 중 하나를 골라야 했던 팀이라면, 되돌릴 수 있는 결정론적 규칙 기반 분해라는 선택지를 검토할 만하다. 외부 사전이나 빈도 임계값이 필요 없고, Hugging Face BPE 같은 표준 토크나이저 위에서 동작하며, 인코딩·디코딩이 전단사라 원문 복원이 보장된다는 점이 실무적으로 중요하다. 다만 기본 설정이 연산자를 독립 토큰으로 내보내 시퀀스가 늘어나고 KV 캐시 메모리와 어텐션 연산이 증가하므로, 실제 배포에서는 자주 쓰이는 대소문자 형태를 융합하는 설정(split_operators = false)이나 융합 임계값을 먼저 벤치마크해야 한다. 또한 생성 시 연산자만 남는 고아 시퀀스가 나올 수 있어 제약 디코딩이나 접두사 마스킹 같은 대비가 필요하다.
저자들이 밝힌 한계는 명확하다. 다운스트림 평가가 약 98M 파라미터, 50,000 스텝 고정 예산에서 이뤄졌고, 독립 접두사로 인한 시퀀스 확장 때문에 Functionalizer가 사전학습 중 베이스라인보다 약 8–16% 적은 원시 바이트를 처리했다. 표현 이득과 시퀀스 길이 차이를 분리하려면 동일한 wall-clock 및 문자/바이트 예산으로 학습한 수십억 파라미터 규모의 평가가 필요하다. 접두사 융합 확장(어휘 빈도 구간별 하이브리드 융합 임계값, 접두사 인식 어텐션 최적화)은 프레임워크에 일부 존재하지만 이 논문 범위에서는 평가하지 않았다. 파라미터 인덱싱은 프리토크나이즈된 조각 내 pos ≤ 255로 제한되고, 발음구별기호는 13개 결합 표시로 한정된다. 향후 확장으로 범위/블록 대소문자([ALL_CAPS]), 비라틴 문자, 교착어를 위한 형태소 표제어 폴딩, 숫자·날짜 템플릿이 제안된다. 마지막으로 다운스트림 실험은 CAPITALIZE와 발음구별기호, REPEAT를 합친 복합 파이프라인만 평가했고, 대소문자와 구조적 공백 반복 각각의 기여를 분리하는 절제 실험은 남은 과제다.