Feature ablation for Swahili POS tagging — how much of the signal is morphology vs. context vs. word identity?
# Swahili POS Tagger — Feature Ablation Study
**Does a POS tagger for Swahili even need to see the word — or is the word's shape enough?**
Swahili loads a lot onto each word: a single verb can mark subject, object, tense, aspect, and negation through affixes. This is a controlled feature ablation on an averaged perceptron — from morphology only up to full lexicalization, one layer at a time — with a character BiLSTM for comparison, on MasakhaPOS Swahili.
**Finding:** morphology alone reaches 0.876 accuracy, within 2.6 points of the fully lexicalized model. Once a word's affixes and neighbours are known, its own identity adds almost nothing. A plain averaged perceptron also matches a character BiLSTM that overfits the small dataset.
## Requirements
- Python 3.10
- `numpy` — perceptron, BiLSTM helpers, results aggregation
- `torch` — character BiLSTM (`src/bilstm.py`, `src/aggregate_bilstm.py`)
- `scipy` — Wilcoxon signed-rank test (`src/wilcoxon_test.py`)
- `scikit-learn` — optional; only used as an independent cross-check in `verify_results.py` (skipped automatically if not installed)
- `matplotlib` — optional; only used by `make_figure.py` to render the per-tag F1 figure
```bash
pip install numpy torch scipy scikit-learn matplotlib
```
## Repo layout
```
.
├── data/ # MasakhaPOS swa splits, 2-column CoNLL. Read-only, never regenerate.
│ ├── train.txt # 693 sentences / 20898 tokens
│ ├── dev.txt # 138 sentences / 3817 tokens
│ └── test.txt # 553 sentences / 16074 tokens
├── src/
│ ├── reader.py # CoNLL reader
│ ├── featurecore.py # Shared feature extractor; nolex/morph configs are built on this
│ ├── features.py # Condition 1 — lexical: target word + affixes + neighbour words
│ ├── delex_features.py # Condition 2 — delex: affixes + neighbour words (no target word)
│ ├── nolex_features.py # Condition 3 — nolex: target affixes + neighb …