This repository explores using a fine-tuned T5 language model to resolve abbreviated,
misspelled, or partially-written person names against a list of known candidate names,
using embeddings derived from the model's encoder and cosine similarity. The core
experiment (Fuzzy Matching.ipynb) fine-tunes t5-base on a small, hand-written
synthetic dataset of "sentence completion" examples where shortened/garbled name
mentions (e.g. "Z F and K P") must be expanded to full names (e.g. "Zikun Fu and Ken
Pu"), then uses the fine-tuned model's encoder hidden states as name embeddings to rank
candidate names by cosine similarity. Two related notebooks in the repo explore adjacent
sub-problems: Entity Extraction.ipynb fine-tunes the same t5-base architecture to tag
entity spans in sentences (a possible preprocessing step for locating which tokens to
fuzzy-match), and Bird.ipynb is a separate, non-ML, rule-based utility that parses SQL
queries and masks/classifies entities (tables, columns, aliases, literal values) using
sqlparse and regex.
Fuzzy Matching.ipynb— main fuzzy-matching-via-embeddings experiment (12 cells).Entity Extraction.ipynb— T5 fine-tuning for entity-span tagging (9 cells).Bird.ipynb— rule-based SQL entity extraction/masking script (6 cells), not related to embeddings.train.json/train_tables.json— text-to-SQL data (question/SQL pairs and database schemas) consumed byBird.ipynb.test.ipynb— empty notebook, no content.
- Model:
t5-base, loaded viatransformers.T5Tokenizerandtransformers.T5ForConditionalGeneration, fine-tuned with the Hugging FaceTrainerAPI for 20 epochs (TrainingArguments(num_train_epochs=20, per_device_train_batch_size=8, ...)). - Data: a synthetic, hand-written dataset embedded directly in the notebook — 61
training examples and 21 test examples, each an
{"input": ..., "output": ...}pair. Inputs give a bracketed list of candidate full names plus a sentence containing abbreviated/garbled versions of those names (e.g."[Zikun Fu, Nick Yang, Ken Pu] Complete the sentence: Z F and K P should meet N.Y."); outputs are the sentence with full names restored. - Embedding/similarity approach: after fine-tuning,
get_embedding()runs text through the fine-tuned T5 encoder and mean-poolslast_hidden_stateacross tokens to produce a fixed-size vector.compare()usessklearn.metrics.pairwise.cosine_similarityto score an input phrase's embedding against the embeddings of each candidate name and prints the candidates sorted by similarity (highest first). - Separately, the fine-tuned model is also used generatively via
model.generate()(complete_sentence()) to directly produce the disambiguated sentence, independent of the embedding/cosine-similarity path.
- Fine-tunes
t5-base(same tokenizer/model classes as above) for 5 epochs to convert a sentence into a version where named-entity tokens are replaced with<ENT>(entity start) /<CONT>(entity continuation) markers. - Data: the Hugging Face dataset
rjac/kaggle-entity-annotated-corpus-ner-dataset(loaded withdatasets.load_dataset), sampled down to 2,000 rows (df.sample(n=2000, random_state=42)). The notebook computes a 70/15/15 train/validation/test split withsklearn.model_selection.train_test_split(intotrain_df/val_data/test_data), but the subsequent tokenization cell buildstrain_datasetfrom the original, unsplit 2,000-rowtrain_datavariable rather than from the 70%train_dfsplit, so the model is trained on all 2,000 examples while validation/test use the 300/300-row splits drawn from that same pool.
- A non-ML, rule-based script that uses
sqlparseand regex to walk the tokens of a SQL query and classify each name token as anAlias,Table,Column, orValue(usingtrain_tables.jsonschema metadata to distinguish table vs. column names), then reconstructs a "masked" version of the query with placeholder tokens (<extra_id_0..3>). It readstrain.json(9,428 question/SQL records, each withdb_id,question,evidence,SQLfields) andtrain_tables.json(per-database schema info) as input data. This notebook does not use any embedding model.
The notebooks record actual executed outputs rather than a held-out benchmark evaluation; the concrete numbers below are copied verbatim from those outputs.
Fuzzy Matching.ipynb: after 20 epochs of fine-tuning, the final logged training
metrics were train_loss: 4.403097397089004, and the final per-epoch evaluation showed
eval_loss: 0.05864345282316208 (epoch 20.0). On one worked example (candidate names
["Emily Brown", "Elsa Betty", "David Grass", "David Green", "Finny Blade", "Fiona Black"], input mentioning "Em B and David G ... with Fi Blac"), the model's
complete_sentence() generation correctly output "Emily Brown and David Green are
chatting with Fiona Black," but the separate cosine-similarity ranking over the same
candidates returned:
Elsa Betty: 0.5508
David Grass: 0.5338
Fiona Black: 0.5298
Finny Blade: 0.4101
David Green: 0.2918
Emily Brown: 0.2574
Note the embedding-based cosine-similarity ranking did not put the correct matches (David Green, Emily Brown) at the top for this example, even though generation-based decoding got the sentence right — i.e. the mean-pooled encoder embedding used for similarity ranking underperformed direct generation on this single example.
Entity Extraction.ipynb: after 5 epochs on the 2,000-example sampled dataset, the
final logged metrics were train_loss: 0.7479060190320015 and a final eval_loss: 0.007703553885221481 (epoch 5.0). Two qualitative generation examples are shown in the
notebook; for input "Ken Pu is going to meet Zikun Fu and Chen Yang on Sunday morning." the model output was "ENT> CONT> is going to meet ENT> CONT> and ENT> CONT> on ENT> morning." — the model detects entity spans but does not reproduce the leading
< character of each tag correctly.
Bird.ipynb produces illustrative (non-numeric) output: for a sample query against
the movie_platform database it correctly lists extracted entities such as
ratings/movies (Table), movie_title/movie_id/rating_timestamp_utc (Column),
T1/T2 (Alias), and numeric literals (Value), and prints the corresponding masked SQL
string.
There is no requirements.txt in this repository. Based on the imports used across the
notebooks, install:
pip install pandas torch transformers datasets scikit-learn sqlparse jupyter
Then, from the repository root:
jupyter notebook
Fuzzy Matching.ipynb: self-contained — its training/test data is defined inline in the notebook. Run cells top to bottom.Entity Extraction.ipynb: downloads its dataset automatically from the Hugging Face Hub (rjac/kaggle-entity-annotated-corpus-ner-dataset) on first run; requires internet access. Run cells top to bottom.Bird.ipynb: requirestrain.jsonandtrain_tables.json, which are already present in the repository root. Run cells top to bottom.test.ipynbis empty and has no content to run.
Fuzzy Matching.ipynb and Entity Extraction.ipynb (the two notebooks that load a
model) select cuda automatically if a GPU is available
(torch.device('cuda' if torch.cuda.is_available() else 'cpu')), otherwise they fall
back to CPU. Bird.ipynb does not use PyTorch or a GPU — it is a pure Python/regex/
sqlparse script.