Other Projects

Other interesting projects

Scroll to explore
AI · NLP

Jamo Tokenization Translator

Korean morpheme boundaries often fall inside a syllable, where character-level BPE can't cut. This project decomposes each syllable into its jamo (initial, medial, final) before applying BPE — yielding fewer, more morphologically aligned tokens — and measures the effect by training an identical Korean→English Seq2Seq Transformer on each tokenizer.

Role
Main researcher & implementer (co-author: Ju-ve Chankasemporn)
Focus
Korean tokenization · Seq2Seq translation
Stack
PyTorch · HuggingFace tokenizers · kss/jamo · Streamlit
Motivation

The morpheme boundary lives inside the syllable

Standard tokenizers — BPE, WordPiece, SentencePiece — treat the character or byte as the smallest unit. Korean breaks that assumption: in 노랫말 (lyrics) the interfix ㅅ sits inside the syllable 랫, and in 먹었어요 the past-tense ㅆ is fused into 었. A character tokenizer can never split those apart.

The hypothesis: decompose each Hangul syllable into its jamo first, then let BPE merge. Sub-syllable structure becomes visible, so the tokenizer can land on morpheme-aligned pieces and represent the language with fewer tokens — especially at small vocabularies and on out-of-domain text.

Core — Tokenization

Two tokenizers, one idea: decompose, then merge

01

Reversible jamo decomposition

Hangul syllables (U+AC00–U+D7A3) decompose by S = ((init × 21) + med) × 28 + fin + 0xAC00. Using kss's h2hcj / hcj2h, text round-trips losslessly between syllables and compatibility jamo, so any tokenization is fully reversible.

02

JamoBPE — from scratch

A pure-Python BPE: build word-frequency tuples, count adjacent pair statistics, merge the most frequent pair, repeat until the vocab target or a min-frequency floor. Written for conceptual clarity over the whole train→merge loop.

03

HFJamoBPE — production

A HuggingFace tokenizers build on the Rust backend with end_of_word_suffix "</w>", trained on millions of CC-100 Korean lines at 32k and 16k vocabularies — the version used for the real experiments.

04

Lossless decoding

Decoding rejoins tokens, turns </w> back into spaces, and reconstructs Hangul with hcj2h() — so the jamo round-trip is invisible to anything downstream.

Translation Model

An identical Transformer behind each tokenizer

Korean is split into jamo and BPE-merged, then an identical ~89M-param encoder–decoder Transformer (d_model 512 · 8 heads · 4 + 4 layers · FFN 1024) translates to English — only the Korean tokenizer changes between runs.
Jamo decomposition
강 → ㄱ ㅏ ㅇ · reversible (kss h2hcj)
HFJamoBPE
vocab 32,768 / 16,384 · end-of-word "</w>"
Encoder
src emb × √512
+ sinusoidal PE
× 4 layers
Self-attn · FFN
8 heads · 512 / 1024
→ memory
Decoder
tgt emb + PE
GPT-2 tokenizer (~50k)
× 4 layers
Masked self-attn
causal
cross-attn ← memory
FFN
512 / 1024
→ generator
Generator
Linear → EN vocab
Greedy decode → English
AdamW · inv-sqrt warmup 1k · label-smooth 0.1 · bf16
Findings

Clear token savings, an honest downstream caveat

Fewer tokens off-domain

On small or domain-mismatched text, jamo uses 30–50% fewer tokens than character BPE — BTS's 봄날 came to 530 tokens vs 953 — with the gap converging to ~1.6% on large general CC-100 text.

Tighter at small vocab

At a 16k vocabulary, jamo averaged ~5.5% fewer tokens and showed lower variance, so the representation is both shorter and more consistent.

Morpheme-aligned splits

Qualitatively, jamo segmentation exposes morpheme boundaries inside syllables (interfix ㅅ, past-tense ㅆ) that character BPE structurally cannot reach.

No free lunch downstream

At this model scale the jamo and character training-loss curves were nearly identical (<1%) — the efficiency gain did not translate into measurably better translation, stated plainly as a limitation.

Demo

Tokenize and translate, live

A Streamlit app lets you pick a dataset (small / large / large-16k) and a mode (jamo / full character), type Korean, and see the tokenization and token count side by side — with live Korean→English translation on the large models. It made the comparison between approaches something you can feel rather than just read off a table.

Stack

What it's built on

Tokenization
jamokssHuggingFace tokenizerstiktoken (baseline)
Modeling
PyTorchSeq2Seq TransformerSinusoidal PEGreedy decode
Data
CC-100 (ko)AI Hub ko–endatasets
Demo & infra
StreamlitPython 3.12bfloat16

Carried end to end — the tokenizer design, the translation model and training, the quantitative and qualitative evaluation, and the live demo — to probe an underexplored direction in Korean tokenization.