Views
No views yet
<target>, with up to two words before and two words after the target word.1import re
2import math
3import pandas as pd
4import torch
5from tqdm import tqdm
6from tqdm.auto import tqdm
7tqdm.pandas()
8
9from transformers import T5Tokenizer, T5ForConditionalGeneration
10
11DIALECT_MODELS = {
12 "glf": "CAMeL-Lab/GLF-S2S-lemmatizer",
13}
14
15def load_model(s2s_dialect: str):
16 model_name = DIALECT_MODELS[s2s_dialect]
17 tokenizer = T5Tokenizer.from_pretrained(model_name, use_fast=True, legacy=False)
18 model = T5ForConditionalGeneration.from_pretrained(model_name)
19 tokenizer.add_special_tokens({"additional_special_tokens": ["<target>"]})
20 model.resize_token_embeddings(len(tokenizer))
21 return tokenizer, model
22
23def predict(tokenizer, model, texts: list[str], device=None, batch_size: int = 16) -> list[str]:
24 if device is None:
25 device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
26 model.to(device).eval()
27 all_preds = []
28 total_batches = math.ceil(len(texts) / batch_size)
29 for i in tqdm(range(0, len(texts), batch_size), total=total_batches, desc="Predicting"):
30 batch = texts[i:i + batch_size]
31 enc = tokenizer(
32 batch,
33 return_tensors="pt",
34 padding=True,
35 truncation=True,
36 max_length=64
37 )
38 enc = {k: v.to(device) for k, v in enc.items()}
39 with torch.no_grad():
40 out = model.generate(
41 **enc,
42 max_length=50,
43 num_beams=1,
44 do_sample=False
45 )
46 all_preds.extend(tokenizer.batch_decode(out, skip_special_tokens=True))
47 return all_preds
48
49def get_context_window_fast(sentence_index, word_index, window_size=2):
50 words, indices = sentence_lookup[sentence_index]
51 target_pos = indices.index(word_index)
52
53 start_idx = max(0, target_pos - window_size)
54 end_idx = min(len(words), target_pos + window_size + 1)
55 context_words = words[start_idx:end_idx][:]
56 target_word_idx = target_pos - start_idx
57 context_words[target_word_idx] = f"<target>{context_words[target_word_idx]}<target>"
58
59 return f"lemmatize: {' '.join(context_words)}"
60
61
62# df should contain an input_text column with the target word marked using <target>
63# Example input: "أنا أبي <target>أروح<target> البيت الحين"
64
65# Sort df by sentence_index and word_index
66df = df.sort_values(by=["sentence_index", "word_index"])
67
68# Build a lookup dict: {sentence_index: (words_list, indices_list)}
69sentence_lookup = {
70 sid: (group['word'].astype(str).tolist(), group['word_index'].tolist())
71 for sid, group in df.sort_values('word_index').groupby('sentence_index')
72}
73
74df['input_text'] = df.progress_apply(
75 lambda row: get_context_window_fast(row['sentence_index'], row['word_index']), axis=1
76)
77
78tokenizer, model = load_model("glf")
79df["predicted_lex"] = predict(tokenizer, model, df["input_text"].tolist())1@inproceedings{saeed-habash-2025-lemmatizing,
2 title = {Lemmatizing Dialectal Arabic with Sequence-to-Sequence Models},
3 author = {Saeed, Mostafa and Habash, Nizar},
4 booktitle = {Proceedings of the Third Arabic Natural Language Processing Conference},
5 year = {2025},
6 address = {Suzhou, China},
7 url = {https://aclanthology.org/2025.arabicnlp-main.10/}
8}