{"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":"none","dataSources":[{"sourceId":121150,"databundleVersionId":15061024,"sourceType":"competition"}],"dockerImageVersionId":31234,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Data Inspection","metadata":{}},{"cell_type":"code","source":"import os\n\nfor dirname, _, filenames in os.walk('/kaggle/input/deep-past-initiative-machine-translation'):\n    print(f\"\\nDirectory: {dirname}\")\n    for filename in filenames:\n        print(\"  \", filename)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## bibliography.csv - Scholarly bibliographic metadata ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/bibliography.csv\"\nbib = pd.read_csv(path)\n\nprint(\"Shape:\", bib.shape)\nprint(\"\\nColumns:\")\nprint(bib.columns.tolist())\n\nbib.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:55:43.027460Z","iopub.execute_input":"2026-01-19T09:55:43.027693Z","iopub.status.idle":"2026-01-19T09:55:43.288028Z","shell.execute_reply.started":"2026-01-19T09:55:43.027676Z","shell.execute_reply":"2026-01-19T09:55:43.287463Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Sentences_Oare_FirstWord_LinNum.csv - Keep as reference / analysis","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/Sentences_Oare_FirstWord_LinNum.csv\"\nsent = pd.read_csv(path)\n\nprint(\"Shape:\", sent.shape)\nprint(\"\\nColumns:\")\nprint(sent.columns.tolist())\n\nsent.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:55:48.270093Z","iopub.execute_input":"2026-01-19T09:55:48.270751Z","iopub.status.idle":"2026-01-19T09:55:48.329816Z","shell.execute_reply.started":"2026-01-19T09:55:48.270731Z","shell.execute_reply":"2026-01-19T09:55:48.329234Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## published_texts.csv - contains FULL Akkadian transliterations","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/published_texts.csv\"\npub = pd.read_csv(path)\n\nprint(\"Shape:\", pub.shape)\nprint(\"\\nColumns:\")\nprint(pub.columns.tolist())\n\npub.head(5)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:55:52.572939Z","iopub.execute_input":"2026-01-19T09:55:52.573329Z","iopub.status.idle":"2026-01-19T09:55:52.791552Z","shell.execute_reply.started":"2026-01-19T09:55:52.573294Z","shell.execute_reply":"2026-01-19T09:55:52.790938Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## train.csv ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/train.csv\"\ntrain = pd.read_csv(path)\n\nprint(\"Shape:\", train.shape)\nprint(\"\\nColumns:\")\nprint(train.columns.tolist())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:55:57.396846Z","iopub.execute_input":"2026-01-19T09:55:57.397063Z","iopub.status.idle":"2026-01-19T09:55:57.436735Z","shell.execute_reply.started":"2026-01-19T09:55:57.397046Z","shell.execute_reply":"2026-01-19T09:55:57.436175Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:01.115918Z","iopub.execute_input":"2026-01-19T09:56:01.116149Z","iopub.status.idle":"2026-01-19T09:56:01.122718Z","shell.execute_reply.started":"2026-01-19T09:56:01.116130Z","shell.execute_reply":"2026-01-19T09:56:01.122159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for col in train.columns:\n    print(f\"\\n=== Column: {col} ===\")\n    sample = train[col].dropna().astype(str).head(5).tolist()\n    for s in sample:\n        print(\" \", s[:250])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:08.068558Z","iopub.execute_input":"2026-01-19T09:56:08.068789Z","iopub.status.idle":"2026-01-19T09:56:08.074858Z","shell.execute_reply.started":"2026-01-19T09:56:08.068772Z","shell.execute_reply":"2026-01-19T09:56:08.074302Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def looks_akkadian(text):\n    if not isinstance(text, str):\n        return False\n    return any(ch in text for ch in ['-', 'š', 'ṣ', 'ṭ', '{', '}', 'ḫ'])\n\nfor col in pub.columns:\n    hits = pub[col].dropna().astype(str).apply(looks_akkadian).sum()\n    print(f\"{col}: {hits} Akkadian-like rows\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:11.823218Z","iopub.execute_input":"2026-01-19T09:56:11.823479Z","iopub.status.idle":"2026-01-19T09:56:11.910565Z","shell.execute_reply.started":"2026-01-19T09:56:11.823461Z","shell.execute_reply":"2026-01-19T09:56:11.909979Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for col in train.columns:\n    if train[col].dtype == 'object':\n        char_len = train[col].astype(str).str.len()\n        word_len = train[col].astype(str).str.split().str.len()\n        print(f\"\\nColumn: {col}\")\n        print(\"Char length:\")\n        print(char_len.describe())\n        print(\"Word length:\")\n        print(word_len.describe())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:15.567061Z","iopub.execute_input":"2026-01-19T09:56:15.567774Z","iopub.status.idle":"2026-01-19T09:56:15.605891Z","shell.execute_reply.started":"2026-01-19T09:56:15.567748Z","shell.execute_reply":"2026-01-19T09:56:15.605273Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\nmarkers = ['!', '?', '/', ':', '[', ']', '{', '}', '<', '>', '˹', '˺']\n\nfor col in train.columns:\n    if train[col].dtype == 'object':\n        print(f\"\\nMarkers in column: {col}\")\n        for m in markers:\n            count = train[col].astype(str).str.contains(re.escape(m)).sum()\n            if count > 0:\n                print(f\"  '{m}' → {count}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:20.687228Z","iopub.execute_input":"2026-01-19T09:56:20.687761Z","iopub.status.idle":"2026-01-19T09:56:20.727701Z","shell.execute_reply.started":"2026-01-19T09:56:20.687739Z","shell.execute_reply":"2026-01-19T09:56:20.727056Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def has_all_caps_word(text):\n    return any(tok.isupper() and len(tok) > 1 for tok in str(text).split())\n\nfor col in train.columns:\n    caps = train[col].astype(str).apply(has_all_caps_word).sum()\n    print(f\"{col}: {caps} rows with ALL-CAPS tokens\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:24.378776Z","iopub.execute_input":"2026-01-19T09:56:24.379001Z","iopub.status.idle":"2026-01-19T09:56:24.406159Z","shell.execute_reply.started":"2026-01-19T09:56:24.378984Z","shell.execute_reply":"2026-01-19T09:56:24.405511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.dropna().sample(5, random_state=42)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:28.078612Z","iopub.execute_input":"2026-01-19T09:56:28.078839Z","iopub.status.idle":"2026-01-19T09:56:28.090224Z","shell.execute_reply.started":"2026-01-19T09:56:28.078822Z","shell.execute_reply":"2026-01-19T09:56:28.089667Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## publications.csv ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/publications.csv\"\npubs = pd.read_csv(path)\n\nprint(\"Shape:\", pubs.shape)\nprint(\"\\nColumns:\")\nprint(pubs.columns.tolist())\n\npubs.head(10)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:30.966728Z","iopub.execute_input":"2026-01-19T09:56:30.966957Z","iopub.status.idle":"2026-01-19T09:56:38.559054Z","shell.execute_reply.started":"2026-01-19T09:56:30.966940Z","shell.execute_reply":"2026-01-19T09:56:38.558458Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## resources.csv -  ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/resources.csv\"\nres = pd.read_csv(path)\n\nprint(\"Shape:\", res.shape)\nprint(\"\\nColumns:\")\nprint(res.columns.tolist())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:45.635150Z","iopub.execute_input":"2026-01-19T09:56:45.635710Z","iopub.status.idle":"2026-01-19T09:56:45.651391Z","shell.execute_reply.started":"2026-01-19T09:56:45.635686Z","shell.execute_reply":"2026-01-19T09:56:45.650883Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"res.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:49.055138Z","iopub.execute_input":"2026-01-19T09:56:49.055779Z","iopub.status.idle":"2026-01-19T09:56:49.067671Z","shell.execute_reply.started":"2026-01-19T09:56:49.055759Z","shell.execute_reply":"2026-01-19T09:56:49.066539Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## eBL_Dictionary.csv ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/eBL_Dictionary.csv\"\nebl = pd.read_csv(path)\n\nprint(\"Shape:\", ebl.shape)\nprint(\"\\nColumns:\")\nprint(ebl.columns.tolist())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:52.819978Z","iopub.execute_input":"2026-01-19T09:56:52.820214Z","iopub.status.idle":"2026-01-19T09:56:52.867847Z","shell.execute_reply.started":"2026-01-19T09:56:52.820195Z","shell.execute_reply":"2026-01-19T09:56:52.867306Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ebl.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:56.228195Z","iopub.execute_input":"2026-01-19T09:56:56.228457Z","iopub.status.idle":"2026-01-19T09:56:56.236401Z","shell.execute_reply.started":"2026-01-19T09:56:56.228438Z","shell.execute_reply":"2026-01-19T09:56:56.235771Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## OA_Lexicon_eBL.csv ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/OA_Lexicon_eBL.csv\"\noa_lex = pd.read_csv(path)\n\nprint(\"Shape:\", oa_lex.shape)\nprint(\"\\nColumns:\")\nprint(oa_lex.columns.tolist())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:56:59.100040Z","iopub.execute_input":"2026-01-19T09:56:59.100290Z","iopub.status.idle":"2026-01-19T09:56:59.187381Z","shell.execute_reply.started":"2026-01-19T09:56:59.100239Z","shell.execute_reply":"2026-01-19T09:56:59.186776Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"oa_lex.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:01.912141Z","iopub.execute_input":"2026-01-19T09:57:01.912813Z","iopub.status.idle":"2026-01-19T09:57:01.921524Z","shell.execute_reply.started":"2026-01-19T09:57:01.912794Z","shell.execute_reply":"2026-01-19T09:57:01.921030Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## test.csv ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath = \"/kaggle/input/deep-past-initiative-machine-translation/test.csv\"\ntest = pd.read_csv(path)\n\nprint(\"Shape:\", test.shape)\nprint(\"\\nColumns:\")\nprint(test.columns.tolist())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:04.860010Z","iopub.execute_input":"2026-01-19T09:57:04.860280Z","iopub.status.idle":"2026-01-19T09:57:04.868011Z","shell.execute_reply.started":"2026-01-19T09:57:04.860237Z","shell.execute_reply":"2026-01-19T09:57:04.867414Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Preprocessing","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\nbase_path = \"/kaggle/input/deep-past-initiative-machine-translation\"\n\ntrain = pd.read_csv(f\"{base_path}/train.csv\")\ntest  = pd.read_csv(f\"{base_path}/test.csv\")\n\nprint(train.shape, test.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:08.328160Z","iopub.execute_input":"2026-01-19T09:57:08.328428Z","iopub.status.idle":"2026-01-19T09:57:08.356146Z","shell.execute_reply.started":"2026-01-19T09:57:08.328410Z","shell.execute_reply":"2026-01-19T09:57:08.355512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\ndef preprocess_akkadian(text):\n    if not isinstance(text, str):\n        return text\n\n    # Normalize determinatives (consistency only)\n    text = re.sub(r'\\(d\\)', '{d}', text)\n    text = re.sub(r'\\(m\\)', '{m}', text)\n\n    # Remove editorial square brackets, keep content\n    # [KÙ.BABBAR] → KÙ.BABBAR\n    text = re.sub(r'\\[([^\\]]+)\\]', r'\\1', text)\n\n    # Normalize whitespace\n    text = re.sub(r'\\s+', ' ', text).strip()\n\n    return text\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:11.301415Z","iopub.execute_input":"2026-01-19T09:57:11.301651Z","iopub.status.idle":"2026-01-19T09:57:11.306230Z","shell.execute_reply.started":"2026-01-19T09:57:11.301633Z","shell.execute_reply":"2026-01-19T09:57:11.305476Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preprocess_english(text):\n    if not isinstance(text, str):\n        return text\n\n    # Remove editorial brackets, keep content\n    # [silver] → silver, <added> → added\n    text = re.sub(r'\\[([^\\]]+)\\]', r'\\1', text)\n    text = re.sub(r'<([^>]+)>', r'\\1', text)\n\n    # Remove stray braces (very rare OCR noise)\n    text = text.replace('}', '')\n\n    # Normalize repeated quotes\n    text = re.sub(r'\"\"+', '\"', text)\n\n    # Normalize whitespace\n    text = re.sub(r'\\s+', ' ', text).strip()\n\n    return text\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:16.209574Z","iopub.execute_input":"2026-01-19T09:57:16.210067Z","iopub.status.idle":"2026-01-19T09:57:16.213838Z","shell.execute_reply.started":"2026-01-19T09:57:16.210048Z","shell.execute_reply":"2026-01-19T09:57:16.213294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train\ntrain[\"src\"] = train[\"transliteration\"].apply(preprocess_akkadian)\ntrain[\"tgt\"] = train[\"translation\"].apply(preprocess_english)\n\n# Test (only source)\ntest[\"src\"] = test[\"transliteration\"].apply(preprocess_akkadian)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:19.813619Z","iopub.execute_input":"2026-01-19T09:57:19.813922Z","iopub.status.idle":"2026-01-19T09:57:19.915327Z","shell.execute_reply.started":"2026-01-19T09:57:19.813896Z","shell.execute_reply":"2026-01-19T09:57:19.914637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[[\"transliteration\", \"src\"]].head(3)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:23.525591Z","iopub.execute_input":"2026-01-19T09:57:23.525823Z","iopub.status.idle":"2026-01-19T09:57:23.536358Z","shell.execute_reply.started":"2026-01-19T09:57:23.525804Z","shell.execute_reply":"2026-01-19T09:57:23.535708Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[[\"translation\", \"tgt\"]].head(3)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:26.985935Z","iopub.execute_input":"2026-01-19T09:57:26.986502Z","iopub.status.idle":"2026-01-19T09:57:26.993203Z","shell.execute_reply.started":"2026-01-19T09:57:26.986483Z","shell.execute_reply":"2026-01-19T09:57:26.992622Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Empty src rows:\", (train[\"src\"].str.len() == 0).sum())\nprint(\"Empty tgt rows:\", (train[\"tgt\"].str.len() == 0).sum())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:30.058212Z","iopub.execute_input":"2026-01-19T09:57:30.058453Z","iopub.status.idle":"2026-01-19T09:57:30.064350Z","shell.execute_reply.started":"2026-01-19T09:57:30.058436Z","shell.execute_reply":"2026-01-19T09:57:30.063788Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_out = train[[\"oare_id\", \"src\", \"tgt\"]]\ntest_out  = test[[\"id\", \"src\"]]\n\ntrain_out.to_csv(\"/kaggle/working/train_preprocessed.csv\", index=False)\ntest_out.to_csv(\"/kaggle/working/test_preprocessed.csv\", index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:32.749994Z","iopub.execute_input":"2026-01-19T09:57:32.750224Z","iopub.status.idle":"2026-01-19T09:57:32.789131Z","shell.execute_reply.started":"2026-01-19T09:57:32.750206Z","shell.execute_reply":"2026-01-19T09:57:32.788529Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Tokenization","metadata":{}},{"cell_type":"code","source":"!pip install -q sentencepiece","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:38.357949Z","iopub.execute_input":"2026-01-19T09:57:38.358187Z","iopub.status.idle":"2026-01-19T09:57:41.948153Z","shell.execute_reply.started":"2026-01-19T09:57:38.358168Z","shell.execute_reply":"2026-01-19T09:57:41.947473Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nos.makedirs(\"/kaggle/working/spm\", exist_ok=True)\n\n# Write Akkadian source text\nwith open(\"/kaggle/working/spm/src.txt\", \"w\", encoding=\"utf-8\") as f:\n    for s in train[\"src\"]:\n        f.write(s + \"\\n\")\n\n# Write English target text\nwith open(\"/kaggle/working/spm/tgt.txt\", \"w\", encoding=\"utf-8\") as f:\n    for s in train[\"tgt\"]:\n        f.write(s + \"\\n\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:46.058081Z","iopub.execute_input":"2026-01-19T09:57:46.058347Z","iopub.status.idle":"2026-01-19T09:57:46.070499Z","shell.execute_reply.started":"2026-01-19T09:57:46.058326Z","shell.execute_reply":"2026-01-19T09:57:46.069911Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!wc -l /kaggle/working/spm/src.txt\n!wc -l /kaggle/working/spm/tgt.txt\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:49.655650Z","iopub.execute_input":"2026-01-19T09:57:49.656328Z","iopub.status.idle":"2026-01-19T09:57:49.907662Z","shell.execute_reply.started":"2026-01-19T09:57:49.656310Z","shell.execute_reply":"2026-01-19T09:57:49.906993Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Train Akkadian SentencePiece Model","metadata":{}},{"cell_type":"code","source":"import sentencepiece as spm\n\nspm.SentencePieceTrainer.train(\n    input=\"/kaggle/working/spm/src.txt\",\n    model_prefix=\"/kaggle/working/spm/akkadian\",\n    vocab_size=8000,\n    model_type=\"unigram\",\n    character_coverage=1.0,\n    normalization_rule_name=\"identity\",\n    split_by_whitespace=True,\n    split_by_unicode_script=False,\n    allow_whitespace_only_pieces=True\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:57:53.348463Z","iopub.execute_input":"2026-01-19T09:57:53.349276Z","iopub.status.idle":"2026-01-19T09:57:53.744157Z","shell.execute_reply.started":"2026-01-19T09:57:53.349234Z","shell.execute_reply":"2026-01-19T09:57:53.743581Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Train English SentencePiece Model","metadata":{}},{"cell_type":"code","source":"spm.SentencePieceTrainer.train(\n    input=\"/kaggle/working/spm/tgt.txt\",\n    model_prefix=\"/kaggle/working/spm/english\",\n    vocab_size=5000,\n    model_type=\"unigram\",\n    character_coverage=1.0,\n    normalization_rule_name=\"identity\",\n    split_by_whitespace=True,\n    split_by_unicode_script=False,\n    allow_whitespace_only_pieces=True\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:00.088548Z","iopub.execute_input":"2026-01-19T09:58:00.088792Z","iopub.status.idle":"2026-01-19T09:58:00.427538Z","shell.execute_reply.started":"2026-01-19T09:58:00.088775Z","shell.execute_reply":"2026-01-19T09:58:00.426798Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Encode the Data with SentencePiece","metadata":{}},{"cell_type":"code","source":"import sentencepiece as spm\n\nsp_src = spm.SentencePieceProcessor()\nsp_tgt = spm.SentencePieceProcessor()\n\nsp_src.load(\"/kaggle/working/spm/akkadian.model\")\nsp_tgt.load(\"/kaggle/working/spm/english.model\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:05.228513Z","iopub.execute_input":"2026-01-19T09:58:05.228744Z","iopub.status.idle":"2026-01-19T09:58:05.245959Z","shell.execute_reply.started":"2026-01-19T09:58:05.228727Z","shell.execute_reply":"2026-01-19T09:58:05.245423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def encode_src(text):\n    return sp_src.encode(text, out_type=int)\n\ndef encode_tgt(text):\n    return sp_tgt.encode(text, out_type=int)\n\ntrain[\"src_ids\"] = train[\"src\"].apply(encode_src)\ntrain[\"tgt_ids\"] = train[\"tgt\"].apply(encode_tgt)\n\ntest[\"src_ids\"] = test[\"src\"].apply(encode_src)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:08.296211Z","iopub.execute_input":"2026-01-19T09:58:08.296457Z","iopub.status.idle":"2026-01-19T09:58:08.472819Z","shell.execute_reply.started":"2026-01-19T09:58:08.296440Z","shell.execute_reply":"2026-01-19T09:58:08.472296Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train[\"src_ids\"].iloc[0][:20])\nprint(train[\"tgt_ids\"].iloc[0][:20])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:11.718877Z","iopub.execute_input":"2026-01-19T09:58:11.719122Z","iopub.status.idle":"2026-01-19T09:58:11.723312Z","shell.execute_reply.started":"2026-01-19T09:58:11.719104Z","shell.execute_reply":"2026-01-19T09:58:11.722706Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"MAX_SRC_LEN = 256\nMAX_TGT_LEN = 320\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:14.934522Z","iopub.execute_input":"2026-01-19T09:58:14.935072Z","iopub.status.idle":"2026-01-19T09:58:14.938225Z","shell.execute_reply.started":"2026-01-19T09:58:14.935050Z","shell.execute_reply":"2026-01-19T09:58:14.937593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def truncate(ids, max_len):\n    return ids[:max_len]\n\ntrain[\"src_ids\"] = train[\"src_ids\"].apply(lambda x: truncate(x, MAX_SRC_LEN))\ntrain[\"tgt_ids\"] = train[\"tgt_ids\"].apply(lambda x: truncate(x, MAX_TGT_LEN))\n\ntest[\"src_ids\"] = test[\"src_ids\"].apply(lambda x: truncate(x, MAX_SRC_LEN))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:18.154815Z","iopub.execute_input":"2026-01-19T09:58:18.155049Z","iopub.status.idle":"2026-01-19T09:58:18.165569Z","shell.execute_reply.started":"2026-01-19T09:58:18.155031Z","shell.execute_reply":"2026-01-19T09:58:18.164767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q transformers datasets accelerate sacrebleu\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T09:58:21.179166Z","iopub.execute_input":"2026-01-19T09:58:21.179411Z","iopub.status.idle":"2026-01-19T10:01:12.335966Z","shell.execute_reply.started":"2026-01-19T09:58:21.179394Z","shell.execute_reply":"2026-01-19T10:01:12.335174Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from datasets import Dataset\n\ntrain_ds = Dataset.from_dict({\n    \"input_ids\": train[\"src_ids\"].tolist(),\n    \"labels\": train[\"tgt_ids\"].tolist()\n})\n\ntest_ds = Dataset.from_dict({\n    \"input_ids\": test[\"src_ids\"].tolist(),\n    \"id\": test[\"id\"].tolist()\n})\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T10:01:16.442568Z","iopub.execute_input":"2026-01-19T10:01:16.442804Z","iopub.status.idle":"2026-01-19T10:01:22.786547Z","shell.execute_reply.started":"2026-01-19T10:01:16.442785Z","shell.execute_reply":"2026-01-19T10:01:22.785950Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import BertConfig, EncoderDecoderConfig, EncoderDecoderModel\n\nencoder_config = BertConfig(\n    vocab_size=sp_src.get_piece_size(),\n    hidden_size=256,\n    num_hidden_layers=4,\n    num_attention_heads=4,\n    intermediate_size=1024,\n    max_position_embeddings=MAX_SRC_LEN,\n    hidden_dropout_prob=0.2,\n    attention_probs_dropout_prob=0.2\n)\n\ndecoder_config = BertConfig(\n    vocab_size=sp_tgt.get_piece_size(),\n    hidden_size=256,\n    num_hidden_layers=4,\n    num_attention_heads=4,\n    intermediate_size=1024,\n    max_position_embeddings=MAX_TGT_LEN,\n    hidden_dropout_prob=0.2,\n    attention_probs_dropout_prob=0.2,\n    is_decoder=True,\n    add_cross_attention=True\n)\n\nconfig = EncoderDecoderConfig.from_encoder_decoder_configs(\n    encoder_config,\n    decoder_config\n)\n\nmodel = EncoderDecoderModel(config)\n\nmodel.config.decoder_start_token_id = 1\nmodel.config.eos_token_id = 2\nmodel.config.pad_token_id = 0\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T10:01:27.235423Z","iopub.execute_input":"2026-01-19T10:01:27.235781Z","iopub.status.idle":"2026-01-19T10:01:50.607034Z","shell.execute_reply.started":"2026-01-19T10:01:27.235763Z","shell.execute_reply":"2026-01-19T10:01:50.606433Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import TrainingArguments\n\ntraining_args = TrainingArguments(\n    output_dir=\"/kaggle/working/mt_model\",\n    do_train=True,\n    do_eval=False,              # <-- IMPORTANT\n    per_device_train_batch_size=4,\n    gradient_accumulation_steps=4,\n    learning_rate=5e-4,\n    warmup_steps=100,\n    num_train_epochs=20,\n    fp16=True,\n    logging_steps=50,\n    save_total_limit=2,\n    report_to=\"none\"\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T10:04:32.485757Z","iopub.execute_input":"2026-01-19T10:04:32.486382Z","iopub.status.idle":"2026-01-19T10:04:32.530429Z","shell.execute_reply.started":"2026-01-19T10:04:32.486358Z","shell.execute_reply":"2026-01-19T10:04:32.529650Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T10:04:35.457636Z","iopub.execute_input":"2026-01-19T10:04:35.457877Z","iopub.status.idle":"2026-01-19T10:04:35.461928Z","shell.execute_reply.started":"2026-01-19T10:04:35.457858Z","shell.execute_reply":"2026-01-19T10:04:35.461299Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def collate_fn(batch):\n    # Extract sequences\n    input_ids = [torch.tensor(x[\"input_ids\"], dtype=torch.long) for x in batch]\n    labels    = [torch.tensor(x[\"labels\"], dtype=torch.long) for x in batch]\n\n    # Pad source\n    input_ids = torch.nn.utils.rnn.pad_sequence(\n        input_ids,\n        batch_first=True,\n        padding_value=model.config.pad_token_id\n    )\n\n    # Pad target (labels) — use -100 so loss ignores padding\n    labels = torch.nn.utils.rnn.pad_sequence(\n        labels,\n        batch_first=True,\n        padding_value=-100\n    )\n\n    return {\n        \"input_ids\": input_ids,\n        \"labels\": labels\n    }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T10:04:39.571754Z","iopub.execute_input":"2026-01-19T10:04:39.572005Z","iopub.status.idle":"2026-01-19T10:04:39.576718Z","shell.execute_reply.started":"2026-01-19T10:04:39.571986Z","shell.execute_reply":"2026-01-19T10:04:39.576058Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import Trainer\n\ntrainer = Trainer(\n    model=model,\n    args=training_args,\n    train_dataset=train_ds,\n    data_collator=collate_fn   # <-- THIS IS THE FIX\n)\n\ntrainer.train()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-19T10:04:42.243711Z","iopub.execute_input":"2026-01-19T10:04:42.243987Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Generate Translations (Inference)","metadata":{}},{"cell_type":"code","source":"UNK_ID = 0   # <unk>\nBOS_ID = 1   # <s>\nEOS_ID = 2   # </s>\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\n\ndef generate_translation(src_ids):\n    input_ids = torch.tensor([src_ids], dtype=torch.long).to(trainer.model.device)\n\n    with torch.no_grad():\n        output_ids = trainer.model.generate(\n            input_ids=input_ids,\n            decoder_start_token_id=BOS_ID,   # 🔥 FORCE IT HERE\n            bos_token_id=BOS_ID,\n            eos_token_id=EOS_ID,\n            pad_token_id=UNK_ID,\n            max_length=MAX_TGT_LEN,\n            num_beams=4,\n            length_penalty=1.1,\n            early_stopping=True\n        )[0]\n\n    return sp_tgt.decode(output_ids.tolist())\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(generate_translation(train[\"src_ids\"].iloc[0]))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T14:26:35.253838Z","iopub.execute_input":"2026-01-16T14:26:35.254217Z","iopub.status.idle":"2026-01-16T14:26:38.570384Z","shell.execute_reply.started":"2026-01-16T14:26:35.254187Z","shell.execute_reply":"2026-01-16T14:26:38.569520Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"trainer.model.eval()\n\ntest[\"translation\"] = test[\"src_ids\"].apply(generate_translation)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T14:31:46.912577Z","iopub.execute_input":"2026-01-16T14:31:46.913636Z","iopub.status.idle":"2026-01-16T14:32:00.205638Z","shell.execute_reply.started":"2026-01-16T14:31:46.913546Z","shell.execute_reply":"2026-01-16T14:32:00.204698Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = test[[\"id\", \"translation\"]]\nsubmission.to_csv(\"/kaggle/working/submission.csv\", index=False)\n\nsubmission\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T14:32:14.706981Z","iopub.execute_input":"2026-01-16T14:32:14.707343Z","iopub.status.idle":"2026-01-16T14:32:14.737739Z","shell.execute_reply.started":"2026-01-16T14:32:14.707310Z","shell.execute_reply":"2026-01-16T14:32:14.736939Z"}},"outputs":[],"execution_count":null}]}