Use pretrained embedding vocab to decide which punctuation to keep, split, or remove before tokenization
Scanned 9/12/2026
Install to Claude Code
npx -y skills add wenmin-wu/ds-skills --skill embedding-aware-punct-normalization --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Embedding Aware Punct Normalization?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/wenmin-wu-embedding-aware-punct-normalization)More formats (shields.io, HTML) on the badges page.
---
name: nlp-embedding-aware-punct-normalization
description: Use pretrained embedding vocab to decide which punctuation to keep, split, or remove before tokenization
---
## Overview
Different pretrained embeddings tokenize punctuation differently. GoogleNews has a vector for `&` but not for `?`. GloVe has vectors for `!` and `?`. Instead of applying uniform punctuation rules, query the embedding vocab to decide: (1) keep as a token if it has an embedding, (2) split around characters that act as word boundaries, (3) remove characters with no vector. This routinely pushes text coverage from ~90% to >99%.
## Quick Start
```python
def clean_text(x):
x = str(x)
# Split punctuation the embedding treats as word boundaries
# (so 'foo/bar' becomes two tokens 'foo bar')
for punct in "/-'":
x = x.replace(punct, ' ')
# Keep tokens known to have embeddings (surround with spaces so tokenizer splits them)
for punct in '&':
x = x.replace(punct, f' {punct} ')
# Remove punctuation with no embedding coverage
strip_chars = '?!.,"#$%\'()*+-/:;<=>@[\\]^_`{|}~' + '\u201c\u201d\u2018\u2019'
for punct in strip_chars:
x = x.replace(punct, '')
return x
```
## Workflow
1. Build a dataset vocab frequency dict and check coverage against the pretrained embedding
2. For each frequent OOV punctuation character, test: does the pretrained index contain it?
3. Partition punctuation into 3 sets: keep-as-token, split-as-separator, remove
4. Apply `clean_text` before tokenization
5. Re-run coverage check — aim for > 99% text coverage
## Key Decisions
- **Per-embedding rules**: GloVe, FastText, and Paragram have different punctuation vocabs. Write one `clean_text` per embedding, or use the intersection.
- **Order matters**: Split separators first, then keep-tokens, then strip. Otherwise you may split characters you wanted to keep.
- **vs. blanket removal**: Removing all punctuation loses real signal (e.g., `&` in `R&D`). Embedding-aware rules preserve it.
- **vs. lowercase**: Lowercase aggressively too — most pretrained vocabs are lowercased except for named-entity embeddings.
## References
- [How to: Preprocessing when using embeddings](https://www.kaggle.com/code/christofhenkel/how-to-preprocessing-when-using-embeddings)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!