Skip to main content
Grammar checking, homophone disambiguation, and context-aware suggestions all depend on knowing each word’s grammatical role. The POS tagging system provides this through a pluggable backend architecture where you choose the accuracy/cost tradeoff that fits your deployment, from a zero-dependency rule engine to a transformer model.

Introduction

What is POS Tagging?

Part-of-Speech tagging assigns grammatical categories (noun, verb, adjective, etc.) to words:

Why Use POS Tagging?

  • Improved Accuracy: Context-aware spell checking (model-level accuracy of 85-93%, depending on tagger and training data)
  • Better Suggestions: Grammatically appropriate correction suggestions
  • Disambiguation: Distinguish between homonyms based on context
  • Validation: Detect grammatical errors and inconsistencies

Integration Points

The POS tagger integrates at two levels:
  1. Build-Time: The inference engine assigns POS tags when building your dictionary from corpus
  2. Runtime: On-the-fly tagging for OOV (out-of-vocabulary) words during spell checking

Supported Tags

Two Tag Systems

mySpellChecker has two POS sources that produce different tag granularities:
  • Inference Engine (rule-based): Produces granular particle tags (P_SUBJ, P_OBJ, P_SENT, P_MOD, P_LOC) by analyzing suffixes and morphology. Used during dictionary building and for OOV word fallback.
  • Transformer Model (HuggingFace): Produces coarse particle tags (PPM, PART) because the underlying model was trained on a coarser tag set. Used for high-accuracy runtime tagging.
The transformer model does not distinguish between particle types; it outputs PPM (postpositional marker) or PART (general particle) for all particles. Granular particle tags (P_SUBJ, P_OBJ, etc.) come from the inference engine and the dictionary.

Complete POS Tag Set

Core Tags (all systems)

Granular Particle Tags (inference engine only)

These tags are produced by the rule-based inference engine and stored in the dictionary. The transformer model cannot distinguish between particle types and uses coarse tags instead.

Coarse / Transformer-Only Tags

These tags come from the HuggingFace transformer model. They are broader categories that don’t distinguish particle subtypes.

Transformer Tag Mapping

The HuggingFace model (chuuhtetnaing/myanmar-pos-model) outputs lowercase tags. The TransformerPOSTagger maps them to the internal uppercase convention via HF_TO_INTERNAL_TAG_MAP:

Tag Disambiguation Guidelines

Many Myanmar words can have multiple POS tags depending on context. Here are common ambiguities:

1. Noun vs. Verb Ambiguity

Some words function as both nouns and verbs: Resolution rule: If followed by ကို/အား, it’s likely a noun. If followed by တယ်/ပြီ, it’s a verb.

2. Adjective vs. Verb Ambiguity

Myanmar adjectives often function as stative verbs: Resolution rule: With modifier particle (သော, တဲ့) → ADJ. As predicate → V.

3. Particle Disambiguation

Particles require careful context analysis:

Annotation Guidelines

When annotating Myanmar text for POS tagging:
  1. Segment first: Ensure proper word boundaries before tagging
  2. Context matters: Always consider surrounding words for disambiguation
  3. Particle chains: Tag each particle in a chain separately
    • Example: သွားပါမယ် = V(သွား) + P_POL(ပါ) + P_SENT(မယ်)
  4. Compound words: Tag as single unit if dictionary entry exists
    • Example: ကျောင်းသား (student) = N (not N + N)
  5. Numbers: Use NUM for digits and number words
  6. Punctuation: Exclude from POS tagging (handled separately)

Common Annotation Errors to Avoid


Quick Start

Default Configuration (Rule-Based)

No setup required - works out of the box with zero dependencies:

Upgrading to Transformer (High Accuracy)

Install transformers package and configure:

Using Custom Models

Point to your fine-tuned HuggingFace model:

Tagger Types

1. Rule-Based (Default)

Best for: Quick setup, no dependencies, production environments with tight resource constraints Characteristics:
  • Fast suffix-based morphological analysis
  • Produces granular particle tags (P_SUBJ, P_OBJ, P_SENT, P_MOD, P_LOC)
  • No external dependencies
  • Fork-safe for multiprocessing
  • Lowest memory footprint
Performance:
  • Speed: Very Fast
  • Accuracy: ~70%
  • Memory: Very Low
  • Dependencies: None
How it works:
Fallback chain:
  1. Check pos_map (if provided)
  2. Morphological suffix analysis
  3. Return “UNK” for unknown words

2. Transformer (Highest Accuracy)

Best for: Maximum accuracy, when GPU is available, offline processing Characteristics:
  • Pre-trained neural models from HuggingFace
  • Context-aware sequence tagging
  • Produces coarse particle tags (PPM, PART), mapped from HF lowercase tags
  • Requires GPU for optimal speed
  • Not fork-safe (CUDA limitations)
Performance:
  • Speed: Slow (CPU), Fast (GPU)
  • Accuracy: ~93%
  • Memory: ~500 MB (model) + ~100 MB (buffer)
  • Dependencies: transformers>=4.30.0, torch>=2.0.0
Default model: chuuhtetnaing/myanmar-pos-model (XLM-RoBERTa-based, 93.37% accuracy) How it works:

3. Viterbi HMM

Best for: Context-aware tagging without GPU, balanced accuracy/speed Characteristics:
  • Hidden Markov Model with Viterbi algorithm
  • Uses trigram transition probabilities
  • Requires pre-built probability tables
  • Fork-safe
Performance:
  • Speed: Fast
  • Accuracy: ~85% (with probability tables), ~70% (fallback to morphology)
  • Memory: ~50 MB (probability tables)
  • Dependencies: None (pure Python + optional Cython)
Database Requirements: The Viterbi tagger requires POS probability tables in the database: Building database with POS probabilities:
Note: If probability tables are empty, Viterbi falls back to morphological analysis with reduced accuracy (~70%).
How it works:

4. Custom Tagger

Best for: Domain-specific requirements, research experiments Implement your own tagger by inheriting from POSTaggerBase:

Configuration

POSTaggerConfig

Central configuration for POS tagger system:

Environment Variables

Configure via environment variables (useful for deployment):

Configuration Priority

  1. Explicit config in code (highest priority)
  2. Environment variables
  3. Default values (lowest priority)

Build-Time Usage

CLI - Building Dictionaries

Default (Rule-Based)

With Transformer Tagger

With Custom Model

Python API - Building Dictionaries


Runtime Usage

SpellChecker Configuration

Default (Rule-Based)

With Transformer

OOV Word Handling

The POS tagger provides fallback for out-of-vocabulary words:
Fallback chain:
  1. Database lookup
  2. Stemming + root lookup
  3. POS tagger
  4. Morphology analyzer (backward compatibility)
  5. Return None or “UNK”

Performance Comparison

Comparison

Recommendation Matrix


Troubleshooting

Missing Dependencies

Error: ImportError: transformers required Solution:
Verification:

CUDA Errors

Error: RuntimeError: CUDA out of memory Solutions:
  1. Reduce batch size:
  1. Use CPU:
  1. Clear GPU cache:
Error: RuntimeError: CUDA error: device-side assert triggered Solution: Usually model/data mismatch. Verify:

Model Loading Failures

Error: OSError: Can't load model from 'nonexistent/model' Solutions:
  1. Verify model exists:
  1. Check internet connection (for HuggingFace downloads):
  1. Use cache directory:
  1. Download manually:

Fork-Safety Issues

Error: RuntimeError: Cannot re-initialize CUDA in forked subprocess Cause: Transformer models use CUDA which is not fork-safe. Solution: Use rule-based or Viterbi tagger for multiprocessing:
Alternative: Use spawn instead of fork:

Performance Issues

Slow tagging with transformer:
  1. Use GPU:
  1. Increase batch size:
  1. Use quantization (trade accuracy for speed):

Joint Segmentation and Tagging

Overview

Joint segmentation and tagging is an advanced mode that performs word segmentation and POS tagging simultaneously in a single Viterbi pass. This is different from the default sequential approach where text is first segmented, then tagged. Default Behavior (Sequential Mode):
Joint Mode:

Why It’s Disabled by Default

Joint mode is disabled by default (config.joint.enabled=False) for several important reasons:

When to Enable Joint Mode

Joint mode may provide benefits in specific scenarios:

Configuration

Enable Joint Mode

Using SpellCheckerConfig

JointConfig Parameters

Performance Comparison

Note: Performance varies based on text complexity and hardware.

Usage Example

Technical Details

The joint decoder uses a unified Viterbi algorithm that optimizes:
State representation: (position, word_start, current_tag, prev_tag) Scoring components:
  1. Word score: log P(word | prev_word) - N-gram language model
  2. Transition score: log P(tag | prev_tags) - POS tag sequence model
  3. Emission score: log P(tag | word) - Word-to-tag emission probability

Limitations

  1. Requires probability tables: Joint mode needs bigram/trigram probabilities in the database
  2. Not all segmenters support it: Only JointSegmentTagger implements joint mode
  3. Base segmenters raise NotImplementedError: Individual segmenters don’t support joint mode; use SpellChecker.segment_and_tag() instead

Advanced Topics

Fine-Tuning Custom Models

Train your own Myanmar POS tagger on domain-specific data:

Extending with Custom Taggers

Create domain-specific taggers:

Combining Multiple Taggers

Ensemble approach for higher accuracy:

Caching Strategies

Optimize performance with intelligent caching:

Acknowledgments

Transformer POS Model

The default transformer-based POS tagger uses the myanmar-pos-model by Chuu Htet Naing: This model was trained specifically for Myanmar/Burmese Part-of-Speech tagging and provides state-of-the-art accuracy for the language. Citation: If you use the transformer POS tagger in your research, please cite the original model:
We express our gratitude to Chuu Htet Naing for making this model publicly available, which significantly enhances the accuracy of Myanmar language processing in mySpellChecker.

See Also