Skip to content

7riangle/viterbi-syllabifier

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Viterbi Syllabifier

This is a small side project where I play with a classic HMM + Viterbi decoder to label phoneme / jamo sequences with syllable roles:

  • English: Onset / Nucleus / Coda (ONC)
  • Korean: 초성 / 중성 / 종성 (mapped to O / N / C)

The goal is not to build a production syllabifier, but to have a readable, linguistics-oriented demo that connects:

  • very simple phonotactic assumptions,
  • a tiny HMM implementation, and
  • visualisations of the Viterbi lattice.

What this repo does

English (ARPAbet-style phones)

  • Hand-written HMM with three states: O (Onset), N (Nucleus), C (Coda)
  • Emission preferences:
    • O / C prefer consonants
    • N prefers vowels
  • Transition preferences:
    • syllables tend to follow O → N → C
    • C → O opens up a new syllable
    • some onset/coda clusters are allowed

Typical usage:

from src.english.syllabifier_en import build_english_onc_hmm, syllabify_phones, STATES
from src.common.plotting import plot_viterbi_heatmap

phones = ["S", "T", "R", "AE", "N", "D"]  # e.g. "strand"
hmm = build_english_onc_hmm(phoneme_inventory=phones)

best_path, dp = hmm.viterbi(phones)

print("Phones:", phones)
print("ONC states:", best_path)

plot_viterbi_heatmap(
    dp,
    states=STATES,
    obs_seq=phones,
    best_path=best_path,
    title="English ONC decoding",
)

This prints an ONC sequence such as:

Phones: ['S', 'T', 'R', 'AE', 'N', 'D']
ONC states: ['O', 'O', 'O', 'N', 'C', 'C']

and shows a heatmap of the Viterbi DP table with the best path overlaid.

You can also plug in a real lexicon:

  • src/english/cmudict_loader.py contains a small helper to read a CMUdict-style pronunciation dictionary.
  • For a given word:
    1. look up its phoneme sequence,
    2. run it through syllabify_phones,
    3. inspect the ONC pattern and the lattice.

Korean (Hangul jamo)

Korean is a nice contrast case because syllable structure is visible in the writing system.

  • src/korean/hangul_utils.py implements Unicode-based decomposition of each Hangul syllable into 초성/중성/종성.
  • src/korean/syllabifier_ko.py defines a very small HMM over jamo:
    • O and C prefer consonant-type jamo,
    • N prefers vowel-type jamo,
    • transitions favour (C)V(C) patterns.

Example:

from src.korean.syllabifier_ko import build_korean_hmm, STATES
from src.korean.hangul_utils import decompose_word
from src.common.plotting import plot_viterbi_heatmap

word = "한국말"
jamo_seq = decompose_word(word)
hmm = build_korean_hmm(jamo_seq)

best_path, dp = hmm.viterbi(jamo_seq)

print("Word:", word)
print("Jamo:", jamo_seq)
print("States:", best_path)

plot_viterbi_heatmap(
    dp,
    states=STATES,
    obs_seq=jamo_seq,
    best_path=best_path,
    title="Korean ONC decoding",
)

Again, this prints the jamo sequence and a corresponding sequence of O/N/C labels, and visualises the Viterbi lattice.


Project structure

viterbi-syllabifier/
├── README.md
├── requirements.txt
├── src/
│   ├── common/
│   │   ├── viterbi.py          # generic ViterbiHMM implementation
│   │   └── plotting.py         # heatmap visualisation
│   ├── english/
│   │   ├── phonology_en.py     # tiny consonant/vowel inventory helpers
│   │   ├── syllabifier_en.py   # English ONC HMM
│   │   └── cmudict_loader.py   # CMUdict-style lexicon loader
│   └── korean/
│       ├── hangul_utils.py     # Unicode Hangul decomposition (초/중/종)
│       └── syllabifier_ko.py   # Korean ONC HMM over jamo
└── examples/
    ├── demo_english.py
    └── demo_korean.py
  • src/common/viterbi.py is a small, language-independent HMM + Viterbi decoder.
  • Language-specific files just define:
    • the state set,
    • transition log-probabilities, and
    • emission log-probabilities.

Installation

git clone https://github.com/<your-username>/viterbi-syllabifier.git
cd viterbi-syllabifier

python3 -m venv viterbi
source viterbi/bin/activate        # Windows: viterbi\Scripts\activate

pip install -r requirements.txt

Minimal requirements.txt:

matplotlib
numpy

(Jupyter or VS Code are convenient but not required.)


Running the demos

From the project root:

# English demo
python examples/demo_english.py

# Korean demo
python examples/demo_korean.py

Each script prints the decoded state sequence and pops up a matplotlib window with a lattice heatmap.


Design goals and limitations

This project is deliberately small:

  • It uses hand-crafted transition and emission scores, based on simple phonological intuitions:
    • onsets and codas like consonants,
    • nuclei like vowels,
    • syllables roughly follow O → N → C.
  • It is not tuned on real labelled syllabification data.
  • The output should be interpreted as:
    • “what this particular toy HMM thinks is the most plausible ONC pattern”
      rather than
    • “ground-truth syllabification”.

There is plenty of room to extend it, for example:

  • refine the state inventory (e.g. split O into O1, O2, or treat /s/-clusters separately),
  • estimate probabilities from an ONC-annotated corpus,
  • compare rule-based and probabilistic syllabifiers on the same lexicon,
  • treat the Viterbi path score as a simple phonotactic “well-formedness” score.

Credits and licences

This repository contains my own code, but it relies on some standard resources and ideas:

  • HMM + Viterbi
    The model and algorithm are standard textbook material in speech processing / NLP.
    The implementation here is a minimal version written for this project.

  • CMU Pronouncing Dictionary (optional data)
    If you add the CMUdict file under data/english/, please make sure to:

    • download it from the official CMUdict distribution, and
    • keep its original licence and copyright notice alongside the file.
      The helper cmudict_loader.py is written to work with the plain-text format.
  • Hangul decomposition
    The Hangul decomposition logic follows the algorithm described in the Unicode Standard (precomposed syllables mapped to (choseong, jungseong, jongseong) indices via simple arithmetic).

  • Python ecosystem
    This project uses standard libraries such as numpy and matplotlib.
    Their licences are provided by the respective projects.

You are free to reuse or modify the code in this repository under the terms of the licence below.


Licence

MIT License (or another licence you prefer — update this section if you change it).

About

Toy HMM + Viterbi syllabifier for English (ONC) and Korean (초성/중성/종성), with lattice visualisations.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages