{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391},{"sourceType":"kernelVersion","sourceId":301427874}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Deep Past Initiative – Machine Translation (Inference Notebook)\n\nThis notebook is a **starter / baseline** for this Kaggle competition.\n\nTraining Code is [here](https://www.kaggle.com/code/takamichitoda/dpc-starter-train).","metadata":{}},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport torch\nimport re\nfrom torch.utils.data import DataLoader, Dataset\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom tqdm.auto import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:07.238367Z","iopub.execute_input":"2026-03-04T15:21:07.239014Z","iopub.status.idle":"2026-03-04T15:21:07.242786Z","shell.execute_reply.started":"2026-03-04T15:21:07.238983Z","shell.execute_reply":"2026-03-04T15:21:07.242013Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# MODEL_PATH = \"/kaggle/input/notebooks/theflashylucario/dpc-starter-train-oa-lexicon\"\n\nMODEL_PATH = \"/kaggle/input/notebooks/theflashylucario/dpc-starter-train-oa-lexicon/byt5-akkadian-model\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:07.243888Z","iopub.execute_input":"2026-03-04T15:21:07.244170Z","iopub.status.idle":"2026-03-04T15:21:07.367442Z","shell.execute_reply.started":"2026-03-04T15:21:07.244138Z","shell.execute_reply":"2026-03-04T15:21:07.366808Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Own code\ndef implement_lexicon(transliteration_text):\n    INPUT_DIR = \"/kaggle/input/deep-past-initiative-machine-translation\"\n    df = pd.read_csv(f\"{INPUT_DIR}/OA_Lexicon_eBL.csv\")\n    \n    # names_list = df.loc[df['type'] == 'PN', 'form'].dropna().unique().tolist()\n    # names_list = [str(n) for n in names_list]\n    # names_list.sort(key=len, reverse=True)\n    # print(names_list)\n\n    subset_df = df.loc[df['type'] == 'PN', ['form', 'lexeme']].dropna()\n    names_list = subset_df.drop_duplicates().values.tolist()\n    names_list = [[str(item) for item in pair] for pair in names_list]\n    names_list.sort(key=lambda x: len(x[0]), reverse=True)\n    \n    name_map = {}\n    processed_text = transliteration_text\n    \n    counter = 0\n    for form, lexeme in names_list:\n        if form in processed_text:\n            placeholder = f\"PN_{counter}\"\n            name_map[placeholder] = lexeme\n            \n            pattern = re.compile(rf'(?<!\\S){re.escape(form)}(?!\\S)')\n            processed_text = pattern.sub(placeholder, processed_text)\n            \n            counter += 1\n            \n    return processed_text, name_map\n\ndef restore_names(translated_text, name_map):\n    restored_text = translated_text\n    for placeholder, original_name in name_map.items():\n        restored_text = restored_text.replace(placeholder, original_name)\n    return restored_text\n\n# End of own code","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:07.368496Z","iopub.execute_input":"2026-03-04T15:21:07.368817Z","iopub.status.idle":"2026-03-04T15:21:07.381057Z","shell.execute_reply.started":"2026-03-04T15:21:07.368783Z","shell.execute_reply":"2026-03-04T15:21:07.380295Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TEST_DATA_PATH = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\nBATCH_SIZE = 16\nMAX_LENGTH = 512\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\n# --- Model Loading ---\nprint(f\"Loading model from {MODEL_PATH}...\")\ntokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(MODEL_PATH).to(DEVICE)\nmodel.eval()\n\n# --- Data Preparation ---\ntest_df = pd.read_csv(TEST_DATA_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:07.382675Z","iopub.execute_input":"2026-03-04T15:21:07.383106Z","iopub.status.idle":"2026-03-04T15:21:07.893269Z","shell.execute_reply.started":"2026-03-04T15:21:07.383065Z","shell.execute_reply":"2026-03-04T15:21:07.892649Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"PREFIX = \"translate Akkadian to English: \"\n\n# class InferenceDataset(Dataset):\n#     def __init__(self, df, tokenizer):\n#         self.texts = df['transliteration'].astype(str).tolist()\n#         self.texts = [PREFIX + i for i in self.texts]\n#         self.tokenizer = tokenizer\n        \n#     def __len__(self):\n#         return len(self.texts)\n    \n#     def __getitem__(self, idx):\n#         text = self.texts[idx]\n#         inputs = self.tokenizer(\n#             text, \n#             max_length=MAX_LENGTH, \n#             padding=\"max_length\", \n#             truncation=True, \n#             return_tensors=\"pt\"\n#         )\n#         return {\n#             \"input_ids\": inputs[\"input_ids\"].squeeze(0),\n#             \"attention_mask\": inputs[\"attention_mask\"].squeeze(0)\n#         }\n\nclass InferenceDataset(Dataset):\n    def __init__(self, df, tokenizer):\n        self.tokenizer = tokenizer\n        self.raw_texts = df['transliteration'].astype(str).tolist()\n        \n        # New: Lists to store processed text and their corresponding maps\n        self.processed_texts = []\n        self.name_maps = []\n        \n        print(\"Applying lexicon to test data...\")\n        for text in self.raw_texts:\n            # 1. Apply the lexicon masking\n            masked_text, n_map = implement_lexicon(text)\n            \n            # 2. Add the prefix for the model\n            final_input = PREFIX + masked_text\n            \n            self.processed_texts.append(final_input)\n            self.name_maps.append(n_map)\n        \n    def __len__(self):\n        return len(self.processed_texts)\n    \n    def __getitem__(self, idx):\n        text = self.processed_texts[idx]\n        inputs = self.tokenizer(\n            text, \n            max_length=MAX_LENGTH, \n            padding=\"max_length\", \n            truncation=True, \n            return_tensors=\"pt\"\n        )\n        return {\n            \"input_ids\": inputs[\"input_ids\"].squeeze(0),\n            \"attention_mask\": inputs[\"attention_mask\"].squeeze(0),\n            \"index\": idx  # Return index to retrieve the correct name_map later\n        }\n\ntest_dataset = InferenceDataset(test_df, tokenizer)\ntest_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)\n\n# --- Inference Loop ---\nprint(\"Starting Inference...\")\nall_predictions = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:07.894207Z","iopub.execute_input":"2026-03-04T15:21:07.894486Z","iopub.status.idle":"2026-03-04T15:21:08.300843Z","shell.execute_reply.started":"2026-03-04T15:21:07.894455Z","shell.execute_reply":"2026-03-04T15:21:08.300166Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# with torch.no_grad():\n#     for batch in tqdm(test_loader):\n#         input_ids = batch[\"input_ids\"].to(DEVICE)\n#         attention_mask = batch[\"attention_mask\"].to(DEVICE)\n  \n#         outputs = model.generate(\n#             input_ids=input_ids,\n#             attention_mask=attention_mask,\n#             max_length=MAX_LENGTH,\n#             num_beams=4,\n#             early_stopping=True\n#         )\n        \n#         decoded = tokenizer.batch_decode(outputs, skip_special_tokens=True)\n#         all_predictions.extend([d.strip() for d in decoded])\n\nwith torch.no_grad():\n    for batch in tqdm(test_loader):\n        input_ids = batch[\"input_ids\"].to(DEVICE)\n        attention_mask = batch[\"attention_mask\"].to(DEVICE)\n        indices = batch[\"index\"].tolist() # Get indices for this batch\n  \n        outputs = model.generate(\n            input_ids=input_ids,\n            attention_mask=attention_mask,\n            max_length=MAX_LENGTH,\n            num_beams=4,\n            early_stopping=True\n        )\n        \n        decoded = tokenizer.batch_decode(outputs, skip_special_tokens=True)\n        \n        # --- Restore Names Step ---\n        for i, translation in enumerate(decoded):\n            current_index = indices[i]\n            current_map = test_dataset.name_maps[current_index]\n            \n            # Swap placeholders back to original ancient names\n            restored_text = restore_names(translation, current_map)\n            all_predictions.append(restored_text.strip())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:08.301614Z","iopub.execute_input":"2026-03-04T15:21:08.301922Z","iopub.status.idle":"2026-03-04T15:21:14.042406Z","shell.execute_reply.started":"2026-03-04T15:21:08.301875Z","shell.execute_reply":"2026-03-04T15:21:14.041472Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- Submission ---\nsubmission = pd.DataFrame({\n    \"id\": test_df[\"id\"],\n    \"translation\": all_predictions\n})\n\nsubmission[\"translation\"] = submission[\"translation\"].apply(lambda x: x if len(x) > 0 else \"broken text\")\n\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"Submission file saved successfully!\")\nsubmission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T15:21:14.044019Z","iopub.execute_input":"2026-03-04T15:21:14.044525Z","iopub.status.idle":"2026-03-04T15:21:14.068112Z","shell.execute_reply.started":"2026-03-04T15:21:14.044485Z","shell.execute_reply":"2026-03-04T15:21:14.067500Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}