CoolFace
Datasetpublic

mehedihasanbijoy/BanglaSEC

BanglaSEC A 1.18M-pair parallel corpus for Bangla spelling error correction, with character-level error masks across 14 error types. BanglaSEC is the corpus introduced in A transformer based spelling error correction framework for Bangla and resource scarce Indic languages (Bijoy, Hossain, Islam & Shatabda, Computer Speech & Language 89:101703, 2025). Each row pairs a correct Bangla word with an erroneous form, labelled by error type and annotated with a binary mask marking… See the full description on the dataset page: https://huggingface.co/datasets/mehedihasanbijoy/BanglaSEC.

sourceHugging Facemitupdated 13d agoView on Hugging Face
0likes106downloads
Dataset Card

BanglaSEC

A 1.18M-pair parallel corpus for Bangla spelling error correction, with character-level error masks across 14 error types.

BanglaSEC is the corpus introduced in *A transformer based spelling error correction framework for Bangla and resource scarce Indic languages* (Bijoy, Hossain, Islam & Shatabda, Computer Speech & Language 89:101703, 2025). Each row pairs a correct Bangla word with an erroneous form, labelled by error type and annotated with a binary mask marking exactly which characters are wrong.

This repository provides the official train / validation / test splits used by DPCSpell.


Quick start

python
from datasets import load_dataset

ds = load_dataset("mehedihasanbijoy/BanglaSEC")

print(ds)
# DatasetDict({
#     train:      Dataset({num_rows: 957746, ...})
#     validation: Dataset({num_rows:  50414, ...})
#     test:       Dataset({num_rows: 177919, ...})
# })

print(ds["test"][0])
# {'Word': 'ঠানকা', 'Error': 'ঠনকা', 'ErrorType': 'Typo Deletion', 'Flag': 0,
#  'Mask': '[0, 1, 0, 0]', 'ErrorBlanks': "['ঠ', '_', 'ক', 'া']", 'MaskFlag': 1}

Stream it instead of downloading the full 184 MB:

python
ds = load_dataset("mehedihasanbijoy/BanglaSEC", split="train", streaming=True)
for row in ds.take(3):
    print(row["Error"], "→", row["Word"])

Dataset structure

Splits

SplitRowsShare
train957,74680.75%
validation50,4144.25%
test177,91915.00%
Total1,186,079

Fields

FieldTypeDescription
WordstringThe correct Bangla word — the target.
ErrorstringThe misspelled form — the source.
ErrorTypestringOne of 14 categories (see below).
MaskstringPer-character binary mask over Word; 1 marks an incorrect character. Serialised as a Python list literal.
ErrorBlanksstringWord as a character list with masked positions replaced by _. Serialised as a Python list literal.
FlagintCorrectness flag. Always 0 — every row is an error pair.
MaskFlagintMask-validity flag. Always 1.

Mask and ErrorBlanks are stored as strings for CSV round-tripping. Parse them with ast.literal_eval:

python
import ast

row = ds["train"][0]
mask   = ast.literal_eval(row["Mask"])         # [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
blanks = ast.literal_eval(row["ErrorBlanks"])  # ['ন', 'ি', 'ত', '্', 'য', 'ন', 'ৈ', '_', ...]

wrong_positions = [i for i, m in enumerate(mask) if m == 1]

Error types

Error typeCountExample (`Error` → `Word`)
Split-word Error (Random)124,895চু ষিয়া → চুষিয়া
Run-on Error124,895পূজিলখাতাঞ্জি → পূজিল
Typo Insertion124,807ঐরাবততেরে → ঐরাবতেরে
Typo Transposition123,245আবর্িজত → আবর্জিত
Typo (Bijoy) Substituition119,864সানাৎসার → সারাৎসার
Typo (Avro) Substituition119,573এাখাল্ → রাখাল্
Visual Error117,391উভযতোমুখ → উভয়তোমুখ
Typo Deletion115,767ক্বপ → ক্বিপ
Cognitive Error108,227ফ্রহরা → প্রহরা
Split-word Error (Left)62,890গোল্ লা → গোল্লা
Visual Error (Combined Character)17,617ত্তস্তাদের → ওস্তাদের
Split-word Error (Right)13,985গৃহ গোধা → গৃহগোধা
Split-word Error (both)12,800নিন্ দিতা → নিন্দিতা
Homonym Error123স্ব:হিত → সহিত

Every error type appears in all three splits in proportion to its corpus share (within 0.01 percentage points).


Configurations

default — the full corpus

All seven columns, one row per error instance. Use this for almost everything.

python
ds = load_dataset("mehedihasanbijoy/BanglaSEC")

detector — DPCSpell detector-network format

Exactly what DPCSpell's detector.py writes to ./Dataset/{train,valid,test}.csv: two columns, space-separated at the character level, ready to drop into the detector's TabularDataset.

python
ds = load_dataset("mehedihasanbijoy/BanglaSEC", "detector")

print(ds["test"][0])
# {'Error': 'ঠ ন ক া', 'ErrorBlanks': 'ঠ _ ক া'}
The DPCSpell purificator and corrector networks train on detector_preds.csv and purificator_preds.csv, which are generated by running each preceding stage's trained model over the corpus. They cannot be derived from the corpus alone and are not included here — produce them by running detector.py and purificator.py from the DPCSpell repo.

Example usage

Fine-tune a seq2seq corrector (ByT5)

Character-level models suit this task well, since errors are character edits.

python
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

ds = load_dataset("mehedihasanbijoy/BanglaSEC")
tok = AutoTokenizer.from_pretrained("google/byt5-small")
model = AutoModelForSeq2SeqLM.from_pretrained("google/byt5-small")

def preprocess(batch):
    enc = tok(batch["Error"], max_length=64, truncation=True)
    enc["labels"] = tok(batch["Word"], max_length=64, truncation=True)["input_ids"]
    return enc

tokenized = ds.map(preprocess, batched=True, remove_columns=ds["train"].column_names)

Evaluate per error type

The headline number hides a lot — split-word and run-on errors are much harder than single-character typos.

python
test = load_dataset("mehedihasanbijoy/BanglaSEC", split="test")

for etype in sorted(set(test["ErrorType"])):
    subset = test.filter(lambda r: r["ErrorType"] == etype)
    preds = my_model.correct(subset["Error"])
    acc = sum(p == g for p, g in zip(preds, subset["Word"])) / len(subset)
    print(f"{etype:<36} n={len(subset):>6}  exact-match={acc:.4f}")

Train on a single error type

python
typos = ds.filter(lambda r: r["ErrorType"].startswith("Typo"))
print(len(typos["train"]))  # 487,124

Use the character masks for error detection

Treat the task as token classification — predict which characters are wrong — rather than generation.

python
import ast

def to_tagging(row):
    return {
        "chars": list(row["Word"]),
        "labels": ast.literal_eval(row["Mask"]),   # 1 = character is misspelled
    }

tagging = ds["train"].map(to_tagging)

Few-shot prompting with an LLM

python
train = load_dataset("mehedihasanbijoy/BanglaSEC", split="train")
shots = train.shuffle(seed=0).select(range(8))

prompt = "Correct the Bangla spelling error.\n\n"
for s in shots:
    prompt += f"Input: {s['Error']}\nOutput: {s['Word']}\n\n"
prompt += f"Input: {test[0]['Error']}\nOutput:"

How the splits were made

Splitting follows train_valid_test_df in DPCSpell's utils.py, as called from detector.py:

python
train_valid_test_df(df, test_size=0.15, valid_size=0.05)

Within each ErrorType independently — so the split is stratified:

python
train_tmp, test  = train_test_split(etype_df, test_size=0.15)
train,     valid = train_test_split(train_tmp, test_size=0.05)

giving 0.85 × 0.95 = 80.75% train, 0.85 × 0.05 = 4.25% validation, 15% test.

The original code leaves train_test_split unseeded, so the exact row assignment of the published runs is unrecoverable. These files were generated with random_state=1234 (the seed DPCSpell sets for torch) so the split is reproducible from here on. Proportions and stratification match the paper exactly; row-level membership is a fresh draw. Regenerate with the included make_splits.py.


Limitations and caveats

Please read these before reporting numbers on this dataset.

  • —Duplicate pairs straddle splits. The corpus contains 51,732 duplicate (Word, Error) rows, because different error-generation processes can land on the same surface form. The paper's procedure splits rows, not unique pairs, so 12,511 test rows (7.0% of the test split) have an identical pair somewhere in train. This is preserved for comparability with published results — deduplicate yourself if you want a stricter evaluation.
  • —Word-level overlap is by design. Each correct word appears with many different errors, so 97,712 of the 98,090 distinct test words also occur in train. This benchmarks error correction, not generalisation to unseen vocabulary.
  • —Split-word and run-on errors contain spaces. 214,570 Error strings contain a space. DPCSpell's word2char + whitespace tokenizer silently drops it, so the detector config does not preserve the word boundary. The default config keeps raw strings intact — prefer it if boundaries matter to you.
  • —`Homonym Error` is tiny — 123 rows, splitting to 98 / 6 / 19. Per-type metrics for this category are very noisy; don't read much into them.
  • —Errors are synthetically generated, not harvested from human writing. The generation processes are modelled on real Bangla error patterns (Avro/Bijoy keyboard layouts, visual confusability, cognitive substitution), but the distribution is not a natural error distribution.
  • —`Flag` and `MaskFlag` are constant (0 and 1). They are retained for schema compatibility with the DPCSpell codebase and carry no information.

Citation

bibtex
@article{hossain2024panini,
  title={Panini: a transformer-based grammatical error correction method for bangla},
  author={Hossain, Nahid and Bijoy, Mehedi Hasan and Islam, Salekul and Shatabda, Swakkhar},
  journal={Neural Computing and Applications},
  volume={36},
  number={7},
  pages={3463--3477},
  year={2024},
  publisher={Springer}
}

License

MIT, matching the DPCSpell reference implementation.