Correcting post-lemmatization spelling errors
Project description
🧬 lemma-corrector
Treating text corpora like sequenced genomes to fix lemmatization artifacts.
Standard NLP lemmatizers often propagate spelling errors, resulting in corrupted, non-existent lemmas (e.g., happi instead of happy, or runn instead of run). lemma-corrector bypasses traditional rigid dictionary lookups by applying graph-based error-correction algorithms inspired by bioinformatics to your text corpus.
By treating lemmas as nodes in a similarity graph, this library uses Louvain community detection and PageRank consensus to identify and repair misspelled lemmas without relying on pre-defined dictionaries.
✨ Features
- Graph-Based Correction: Maps lemmas into a NetworkX graph based on Damerau-Levenshtein edit distance.
- Smart Community Detection: Uses the Louvain algorithm to cluster morphologically similar lemmas together.
- Consensus Leader Election: Identifies the correct spelling by finding the node that is both the most frequent and the most central (PageRank) in its community.
- Vocabulary Guardrails: Optionally accepts a set of known correct words to prevent over-correcting valid, domain-specific terminology.
- Length-Aware Weighting: Edge weights scale with string length, recognizing that a single typo in a long word is statistically more likely to be an error than a single character difference between two short words.
🚀 Quick Start
from collections import Counter
from lemma_corrector import LemmaCorrector
# 1. Create a bag of lemmata (e.g., from your NLP pipeline)
# Notice the misspelled/over-lemmatized words: "happi", "runn", "quikly"
bag_of_lemmata = Counter({
"happy": 150,
"happi": 12, # Misspelling
"run": 200,
"runn": 8, # Misspelling
"quickly": 90,
"quikly": 5, # Misspelling
"the": 1000,
"a": 800,
})
# 2. Initialize the corrector
corrector = LemmaCorrector(bag_of_lemmata)
# 3. Get the corrections
corrections = corrector.get_corrections()
print(corrections)
# Output: {'happi': 'happy', 'runn': 'run', 'quikly': 'quickly'}
Using a Known Vocabulary
If you have domain-specific jargon that looks like a typo but is actually correct, pass a vocabulary set to protect those words:
# "foo" and "bar" are domain-specific variables, not typos
vocabulary = {"foo", "bar", "baz"}
corrector = LemmaCorrector(bag_of_lemmata, vocabulary=vocabulary)
🧠 How It Works
The algorithm operates in four distinct phases:
-
Graph Construction: Each unique lemma becomes a node, weighted by its normalized frequency (frequency divided by the max frequency in the corpus). Edges are drawn between lemmas that have a Damerau-Levenshtein distance of exactly 1. Edge weights are calculated as
1.0 - (1.0 / max_length), meaning longer strings with a single edit get stronger connections. -
Community Detection: The Louvain algorithm partitions the graph into communities. Lemmas that are structurally similar and connected are grouped together.
-
Leader Election (Consensus): For each community, the algorithm looks for a "leader" (the correct spelling). To be chosen as the leader, a lemma must satisfy two conditions simultaneously:
- It must be the most frequent lemma in the community (highest node weight).
- It must be the most central lemma in the community (highest PageRank). If the most frequent and most central lemmas are different, the community is deemed ambiguous and skipped.
-
Vocabulary Validation: If a vocabulary is provided, the algorithm enforces two rules:
- Edges are never created between two known, correct words.
- A community leader cannot be an unknown word if a known word already exists in that community.
📖 API Reference
LemmaCorrector
The main class for correcting lemmas.
__init__(bag_of_lemmata, vocabulary=None, epsilon=1.0e-6)
bag_of_lemmata(Counter[str]): A Counter mapping lemmas to their frequencies.vocabulary(set[str] | None): Optional set of known correct words to protect from correction.epsilon(float): Tolerance threshold for Louvain and PageRank algorithms.
get_corrections() -> dict[str, str]
Computes and returns a dictionary mapping misspelled lemmas to their corrected leaders.
🤝 Contributing
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
📄 License
This project is licensed under the MIT License.
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 lemma_corrector-1.0.0.tar.gz.
File metadata
- Download URL: lemma_corrector-1.0.0.tar.gz
- Upload date:
- Size: 5.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c1aa8789443623915007eb8545c2f9de8c780555084201df31f50ee0b6ed159
|
|
| MD5 |
07e678cffe605213df5837e169864e4f
|
|
| BLAKE2b-256 |
f60a9b028180cfc762dc92c385cb5975df8dfa8000cff36121eecf3d171b5ff6
|
File details
Details for the file lemma_corrector-1.0.0-py3-none-any.whl.
File metadata
- Download URL: lemma_corrector-1.0.0-py3-none-any.whl
- Upload date:
- Size: 6.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f4df3e2f64ff1b8ab5e31bfa8d1e2e919b41c32c16b41a9eb428d07cf0b34bc
|
|
| MD5 |
a6d847f2941fbbe3a87d81d638a20c6a
|
|
| BLAKE2b-256 |
302a0361d1843abd5db4854b52dc0ab9b8c7917cfa879ccb99b6f650fc93576e
|