A spaCy-compatible Scottish Gaelic NLP pipeline with POS tagging and a POS-aware lemmatizer.
Project description
Scottish Gaelic Lemmatizer – CSRI Research Project
This project is part of an ongoing collaborative research initiative between the Cornell College Computer Science Department and Napier University in Edinburgh, Scotland. The goal is to build tools that enable deeper text analysis for the Scottish Gaelic language — a low-resource language with limited computational tools.
Project Context
- Year 1: A team of students created a cleaned corpus of Scottish Gaelic text and a tokenizer.
- Year 2 (Current): Focused on developing a rule-based lemmatizer, generating word frequency statistics, and implementing preprocessing techniques specific to Scottish Gaelic grammar and spelling.
What This Tool Does
This lemmatizer reduces inflected Scottish Gaelic word forms to their base forms (lemmas) using:
- A manually curated irregular dictionary for unpredictable wordforms (e.g.,
chunnaic → faic) - A set of carefully tested suffix rules for regular morphological patterns (e.g.,
taighean → taigh) - Preprocessing steps that handle accents, emphatic suffixes, prosthetic consonants, and lenition
- Frequency-guided refinement: rules and dictionary are informed by analysis of the most common words
- Output in a simple, editable format for future researchers to reuse or expand
Tree-like Folder Structure
lemmatizer_gaelic/
├── lemmatizer.py # Main lemmatization script using spaCy custom component
├── irregular_dict.json # Irregular word → lemma mappings
├── Latest_Corpus.txt # Cleaned corpus with "word source" format
├── lemmatized_output.txt # Output from previous lemmatizer version / reference output
├── lemmatized_output_pos_aware_example.txt # Example output from the new POS-aware lemmatizer
├── compare_lemmas.py # Script to compare two lemmatizer output files
├── word_frequency.py # Word frequency analysis script (by source)
├── stopWords.txt # List of Gaelic stop words (excluded from stats)
├── CorpusBySource.py # Exports per-source texts from the raw corpus
└── README.md # Project documentation
How It Works
1. Corpus Preparation
- The input corpus (
Latest_Corpus.txt) contains lines in the format: - Only the first word of each line is used for lemmatization.
2. Preprocessing Steps
- Replace acute accents with grave accents
- Remove emphatic suffixes:
-sa,-se,-san,-ne - Strip prosthetic consonants:
t-,h-,n-(at beginning) - Remove lenition marker:
has second letter (e.g.,bhean → bean)
3. Lemmatization Logic (lemmatizer.py)
- Apply preprocessing to each token
- If token exists in irregular dictionary → use its mapped lemma
- If not, apply suffix rules (
-ean,-an,-achadh, etc.) - If no rules match, return preprocessed token (unless it's too short)
Code Flowchart
Load input corpus file
↓
Process text with spaCy pipeline (Tokenizer -> POS Tagger -> Custom Lemmatizer)
↓ (This step assigns POS tags to tokens)
For each token in the spaCy `Doc` object:
↓
Get lowercased raw text
Initialize lemma with raw text
↓
1. Check if raw token text exists in irregular dictionary
├─ Yes → Use lemma from irregulars (e.g., "deach" → "rach") and SKIP further steps for this token
└─ No → Proceed to preprocessing
↓
2. Preprocess token text (e.g., "chuala" → "cuala", "bhean" → "bean"):
├─ Replace acute accents with grave accents
├─ Remove emphatic suffixes
├─ Remove prosthetic consonants
└─ Remove lenition marker
↓
3. Check if preprocessed token text exists in irregular dictionary
├─ Yes → Use lemma from irregulars (e.g., "cuala" → "cluinn") and SKIP further steps
└─ No → Proceed to POS-informed suffix rules
↓
4. Apply POS-informed suffix rules (based on `token.pos_`):
├─ If `token.pos_ == "NOUN"`:
│ ├─ Apply longest noun suffixes first (e.g., "-aichean" -> "", "-annan" -> "", "-ean" -> "", "-an" -> "")
│ └─ Examples: "eileanan" → "eilean", "stàitean" → "stàit", "lochan" → "loch"
├─ If `token.pos_ == "VERB"`:
│ ├─ Apply longest verb suffixes first (e.g., "-eachadh" -> "-ich", "-eadh" -> "", "-te" -> "", "-ta" -> "")
│ └─ Examples: "atharrachadh" → "atharraich", "stèidheachadh" → "stèidhich", "aonaichte" → "aonaich", "sònraichte" → "sònraich"
├─ If `token.pos_ == "ADJ"`:
│ ├─ Apply adjective-specific rules
│ └─ Examples: (comparatives, superlatives, ensuring base forms like "cumanta" remain unchanged)
└─ If no POS-specific rule matched:
↓
5. Fallback: If preprocessing changed the word and no rule applied, use preprocessed word as lemma.
If lemma length is 1 or less (and not an irregular), revert to original raw text.
↓
Assign final lemma to token in spaCy `Doc` object
↓
Repeat for all tokens
↓
Output results:
├─ Print token → lemma to console
└─ Save results to `lemmatized_output_pos_aware_example.txt`
↓
Print summary:
├─ Changed by irregulars
├─ Changed by preprocessing
├─ Changed by suffix
├─ Total changed / unchanged words
└─ Total operations applied
4. Word Frequency Analysis (word_frequency.py)
- Computes the top 100 most frequent words by source
- Excludes stopwords (
stopWords.txt) - Guides rule updates and dictionary development
Future Work
- Integrate a robust Gaelic POS tagger to improve lemmatizer accuracy
- Expand suffix rules and irregulars using linguistic input from Napier University
- Group frequent words by part of speech (noun, verb, adj) for better rule targeting
- Evaluate lemmatizer accuracy using a manually verified gold standard
Status
Work in Progress — June 2025
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gd_core_web_sm-0.1.2.tar.gz.
File metadata
- Download URL: gd_core_web_sm-0.1.2.tar.gz
- Upload date:
- Size: 24.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aff38607b19e7aa45f481de7912c934ff8052dcaa1e2bbff9e97b6752b41f9ca
|
|
| MD5 |
d9f974be442a16e2a18e002cf40a2ddd
|
|
| BLAKE2b-256 |
0137af8121e3ea7886979adbf874f036bf2c420ac2242c5e5e43f9375cca2e25
|
File details
Details for the file gd_core_web_sm-0.1.2-py3-none-any.whl.
File metadata
- Download URL: gd_core_web_sm-0.1.2-py3-none-any.whl
- Upload date:
- Size: 24.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab1805e8f8346523d595db2a8f42519f4e89a3a72154f4c8d40b868bffb9265b
|
|
| MD5 |
0de261a95561e2c8265acde1c1d6af87
|
|
| BLAKE2b-256 |
f2e0cdbea91b68afe435a8fb0169ee07d46d20de16564d92dc0283b2e8941d17
|