{"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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":121150,"databundleVersionId":15833391},{"sourceType":"datasetVersion","sourceId":15056958,"datasetId":9639587,"databundleVersionId":15937716}],"dockerImageVersionId":31286,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:34.826596Z","iopub.execute_input":"2026-03-03T11:29:34.826849Z","iopub.status.idle":"2026-03-03T11:29:36.693874Z","shell.execute_reply.started":"2026-03-03T11:29:34.826816Z","shell.execute_reply":"2026-03-03T11:29:36.693079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ntrain = pd.read_csv('/kaggle/input/competitions/deep-past-initiative-machine-translation/train.csv')\ntest = pd.read_csv('/kaggle/input/competitions/deep-past-initiative-machine-translation/test.csv')\n\nprint(train.shape)\nprint(train.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:36.695558Z","iopub.execute_input":"2026-03-03T11:29:36.695889Z","iopub.status.idle":"2026-03-03T11:29:36.79782Z","shell.execute_reply.started":"2026-03-03T11:29:36.695866Z","shell.execute_reply":"2026-03-03T11:29:36.796941Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['trans_len'] = train['transliteration'].str.split().apply(len)\ntrain['eng_len'] = train['translation'].str.split().apply(len)\n\ntrain[['trans_len', 'eng_len']].describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:36.798819Z","iopub.execute_input":"2026-03-03T11:29:36.799092Z","iopub.status.idle":"2026-03-03T11:29:36.861065Z","shell.execute_reply.started":"2026-03-03T11:29:36.799063Z","shell.execute_reply":"2026-03-03T11:29:36.86052Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(test.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:36.861993Z","iopub.execute_input":"2026-03-03T11:29:36.862225Z","iopub.status.idle":"2026-03-03T11:29:36.867863Z","shell.execute_reply.started":"2026-03-03T11:29:36.862205Z","shell.execute_reply":"2026-03-03T11:29:36.867266Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\ndef split_sentences(text):\n    return re.split(r'\\n+', text)\n\ntrain['sentences_src'] = train['transliteration'].apply(split_sentences)\ntrain['sentences_tgt'] = train['translation'].apply(lambda x: re.split(r'\\.\\s+', x))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:36.868818Z","iopub.execute_input":"2026-03-03T11:29:36.869064Z","iopub.status.idle":"2026-03-03T11:29:36.89451Z","shell.execute_reply.started":"2026-03-03T11:29:36.869045Z","shell.execute_reply":"2026-03-03T11:29:36.893853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lexicon = pd.read_csv('/kaggle/input/competitions/deep-past-initiative-machine-translation/OA_Lexicon_eBL.csv')\nlexicon.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:36.895431Z","iopub.execute_input":"2026-03-03T11:29:36.895708Z","iopub.status.idle":"2026-03-03T11:29:37.040753Z","shell.execute_reply.started":"2026-03-03T11:29:36.895681Z","shell.execute_reply":"2026-03-03T11:29:37.039906Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install sentencepiece","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:37.042901Z","iopub.execute_input":"2026-03-03T11:29:37.043455Z","iopub.status.idle":"2026-03-03T11:29:42.357805Z","shell.execute_reply.started":"2026-03-03T11:29:37.043429Z","shell.execute_reply":"2026-03-03T11:29:42.357097Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"!pip install -q sentencepiece transformers datasets sacrebleu accelerate","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:42.358997Z","iopub.execute_input":"2026-03-03T11:29:42.359254Z","iopub.status.idle":"2026-03-03T11:29:46.295301Z","shell.execute_reply.started":"2026-03-03T11:29:42.359229Z","shell.execute_reply":"2026-03-03T11:29:46.294642Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\nDATA_PATH = \"/kaggle/input/competitions/deep-past-initiative-machine-translation\"  # adjust if needed\n\ntrain = pd.read_csv(f\"{DATA_PATH}/train.csv\")\ntest = pd.read_csv(f\"{DATA_PATH}/test.csv\")\nlexicon = pd.read_csv(f\"{DATA_PATH}/OA_Lexicon_eBL.csv\")\nsentence_meta = pd.read_csv(f\"{DATA_PATH}/Sentences_Oare_FirstWord_LinNum.csv\")\n\nprint(\"Train shape:\", train.shape)\nprint(\"Test shape:\", test.shape)\nprint(\"Lexicon shape:\", lexicon.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.296506Z","iopub.execute_input":"2026-03-03T11:29:46.296761Z","iopub.status.idle":"2026-03-03T11:29:46.484061Z","shell.execute_reply.started":"2026-03-03T11:29:46.296735Z","shell.execute_reply":"2026-03-03T11:29:46.483324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.485164Z","iopub.execute_input":"2026-03-03T11:29:46.485482Z","iopub.status.idle":"2026-03-03T11:29:46.493213Z","shell.execute_reply.started":"2026-03-03T11:29:46.485451Z","shell.execute_reply":"2026-03-03T11:29:46.492624Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['src_len'] = train['transliteration'].str.split().apply(len)\ntrain['tgt_len'] = train['translation'].str.split().apply(len)\n\ntrain[['src_len','tgt_len']].describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.494705Z","iopub.execute_input":"2026-03-03T11:29:46.49491Z","iopub.status.idle":"2026-03-03T11:29:46.54269Z","shell.execute_reply.started":"2026-03-03T11:29:46.494891Z","shell.execute_reply":"2026-03-03T11:29:46.542162Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['len_ratio'] = train['tgt_len'] / train['src_len']\ntrain['len_ratio'].describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.54339Z","iopub.execute_input":"2026-03-03T11:29:46.543694Z","iopub.status.idle":"2026-03-03T11:29:46.551583Z","shell.execute_reply.started":"2026-03-03T11:29:46.543674Z","shell.execute_reply":"2026-03-03T11:29:46.550895Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"===== TRANSLITERATION =====\")\nprint(train.iloc[0]['transliteration'])\n\nprint(\"\\n===== TRANSLATION =====\")\nprint(train.iloc[0]['translation'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.552296Z","iopub.execute_input":"2026-03-03T11:29:46.552591Z","iopub.status.idle":"2026-03-03T11:29:46.563109Z","shell.execute_reply.started":"2026-03-03T11:29:46.552563Z","shell.execute_reply":"2026-03-03T11:29:46.562469Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"all_src_tokens = set()\nfor text in train['transliteration']:\n    all_src_tokens.update(text.split())\n\nprint(\"Unique source tokens:\", len(all_src_tokens))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.56389Z","iopub.execute_input":"2026-03-03T11:29:46.564105Z","iopub.status.idle":"2026-03-03T11:29:46.589297Z","shell.execute_reply.started":"2026-03-03T11:29:46.564086Z","shell.execute_reply":"2026-03-03T11:29:46.588783Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lexicon_forms = set(lexicon['form'].dropna())\n\ncoverage = len(all_src_tokens.intersection(lexicon_forms)) / len(all_src_tokens)\nprint(\"Lexicon coverage:\", coverage)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.59008Z","iopub.execute_input":"2026-03-03T11:29:46.590407Z","iopub.status.idle":"2026-03-03T11:29:46.610958Z","shell.execute_reply.started":"2026-03-03T11:29:46.590366Z","shell.execute_reply":"2026-03-03T11:29:46.610395Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.611702Z","iopub.execute_input":"2026-03-03T11:29:46.611937Z","iopub.status.idle":"2026-03-03T11:29:46.62426Z","shell.execute_reply.started":"2026-03-03T11:29:46.611917Z","shell.execute_reply":"2026-03-03T11:29:46.623615Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\ndef split_src(text):\n    return re.split(r'\\n+', text)\n\ndef split_tgt(text):\n    return re.split(r'\\.\\s+', text)\n\ntrain['src_sentences'] = train['transliteration'].apply(split_src)\ntrain['tgt_sentences'] = train['translation'].apply(split_tgt)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.624991Z","iopub.execute_input":"2026-03-03T11:29:46.625316Z","iopub.status.idle":"2026-03-03T11:29:46.651323Z","shell.execute_reply.started":"2026-03-03T11:29:46.625296Z","shell.execute_reply":"2026-03-03T11:29:46.650858Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[['src_sentences','tgt_sentences']].head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.652331Z","iopub.execute_input":"2026-03-03T11:29:46.652613Z","iopub.status.idle":"2026-03-03T11:29:46.669322Z","shell.execute_reply.started":"2026-03-03T11:29:46.652587Z","shell.execute_reply":"2026-03-03T11:29:46.6688Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mismatch = 0\nfor i,row in train.iterrows():\n    if len(row['src_sentences']) != len(row['tgt_sentences']):\n        mismatch += 1\n\nprint(\"Documents with sentence mismatch:\", mismatch)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.670124Z","iopub.execute_input":"2026-03-03T11:29:46.670416Z","iopub.status.idle":"2026-03-03T11:29:46.73696Z","shell.execute_reply.started":"2026-03-03T11:29:46.670388Z","shell.execute_reply":"2026-03-03T11:29:46.736274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lexicon['type'].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.737814Z","iopub.execute_input":"2026-03-03T11:29:46.73815Z","iopub.status.idle":"2026-03-03T11:29:46.747793Z","shell.execute_reply.started":"2026-03-03T11:29:46.738122Z","shell.execute_reply":"2026-03-03T11:29:46.747175Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from collections import Counter\n\ntoken_counts = Counter()\n\nfor text in train['transliteration']:\n    token_counts.update(text.split())\n\ntoken_counts.most_common(30)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.748854Z","iopub.execute_input":"2026-03-03T11:29:46.74915Z","iopub.status.idle":"2026-03-03T11:29:46.78202Z","shell.execute_reply.started":"2026-03-03T11:29:46.749122Z","shell.execute_reply":"2026-03-03T11:29:46.781366Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\ndef split_src(text):\n    lines = re.split(r'\\n+', text)\n    lines = [l.strip() for l in lines if len(l.strip()) > 3]\n    return lines","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.785706Z","iopub.execute_input":"2026-03-03T11:29:46.786118Z","iopub.status.idle":"2026-03-03T11:29:46.789721Z","shell.execute_reply.started":"2026-03-03T11:29:46.786092Z","shell.execute_reply":"2026-03-03T11:29:46.789063Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def split_tgt(text):\n    sents = re.split(r'(?<=[.?!])\\s+(?=[A-Z])', text)\n    sents = [s.strip() for s in sents if len(s.strip()) > 3]\n    return sents","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.790453Z","iopub.execute_input":"2026-03-03T11:29:46.790703Z","iopub.status.idle":"2026-03-03T11:29:46.803Z","shell.execute_reply.started":"2026-03-03T11:29:46.790675Z","shell.execute_reply":"2026-03-03T11:29:46.8025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['src_sents'] = train['transliteration'].apply(split_src)\ntrain['tgt_sents'] = train['translation'].apply(split_tgt)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.803715Z","iopub.execute_input":"2026-03-03T11:29:46.803951Z","iopub.status.idle":"2026-03-03T11:29:46.846262Z","shell.execute_reply.started":"2026-03-03T11:29:46.803922Z","shell.execute_reply":"2026-03-03T11:29:46.845763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"aligned_docs = train[\n    train['src_sents'].apply(len) == train['tgt_sents'].apply(len)\n]\n\nprint(\"Perfectly aligned docs:\", len(aligned_docs))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.846957Z","iopub.execute_input":"2026-03-03T11:29:46.847172Z","iopub.status.idle":"2026-03-03T11:29:46.85542Z","shell.execute_reply.started":"2026-03-03T11:29:46.847144Z","shell.execute_reply":"2026-03-03T11:29:46.854836Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_pairs = []\n\nfor _, row in aligned_docs.iterrows():\n    for s, t in zip(row['src_sents'], row['tgt_sents']):\n        sentence_pairs.append({\n            \"src\": s,\n            \"tgt\": t\n        })\n\nsent_df = pd.DataFrame(sentence_pairs)\nprint(sent_df.shape)\nsent_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.856164Z","iopub.execute_input":"2026-03-03T11:29:46.856451Z","iopub.status.idle":"2026-03-03T11:29:46.945682Z","shell.execute_reply.started":"2026-03-03T11:29:46.856431Z","shell.execute_reply":"2026-03-03T11:29:46.945119Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lex_map = {}\n\nfor _, row in lexicon.iterrows():\n    form = str(row['form'])\n    norm = str(row['norm'])\n    if form != \"nan\" and norm != \"nan\":\n        lex_map[form] = norm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:46.946412Z","iopub.execute_input":"2026-03-03T11:29:46.946642Z","iopub.status.idle":"2026-03-03T11:29:48.270522Z","shell.execute_reply.started":"2026-03-03T11:29:46.946612Z","shell.execute_reply":"2026-03-03T11:29:48.26994Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Lexicon entries:\", len(lex_map))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.271445Z","iopub.execute_input":"2026-03-03T11:29:48.271675Z","iopub.status.idle":"2026-03-03T11:29:48.275553Z","shell.execute_reply.started":"2026-03-03T11:29:48.271642Z","shell.execute_reply":"2026-03-03T11:29:48.274941Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def normalize_text(text):\n    tokens = text.split()\n    norm_tokens = []\n    \n    for tok in tokens:\n        if tok in lex_map:\n            norm_tokens.append(lex_map[tok])\n        else:\n            norm_tokens.append(tok)\n    \n    return \" \".join(norm_tokens)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.276274Z","iopub.execute_input":"2026-03-03T11:29:48.27658Z","iopub.status.idle":"2026-03-03T11:29:48.289067Z","shell.execute_reply.started":"2026-03-03T11:29:48.276548Z","shell.execute_reply":"2026-03-03T11:29:48.288405Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sent_df['src_norm'] = sent_df['src'].apply(normalize_text)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.289912Z","iopub.execute_input":"2026-03-03T11:29:48.290202Z","iopub.status.idle":"2026-03-03T11:29:48.305317Z","shell.execute_reply.started":"2026-03-03T11:29:48.290178Z","shell.execute_reply":"2026-03-03T11:29:48.304637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sent_df['src_combined'] = (\n    sent_df['src'] + \" <norm> \" + sent_df['src_norm']\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.306053Z","iopub.execute_input":"2026-03-03T11:29:48.306297Z","iopub.status.idle":"2026-03-03T11:29:48.317144Z","shell.execute_reply.started":"2026-03-03T11:29:48.306266Z","shell.execute_reply":"2026-03-03T11:29:48.316493Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"orig_tokens = set()\nnorm_tokens = set()\n\nfor text in sent_df['src']:\n    orig_tokens.update(text.split())\n\nfor text in sent_df['src_norm']:\n    norm_tokens.update(text.split())\n\nprint(\"Original unique:\", len(orig_tokens))\nprint(\"Normalized unique:\", len(norm_tokens))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.317998Z","iopub.execute_input":"2026-03-03T11:29:48.318499Z","iopub.status.idle":"2026-03-03T11:29:48.335077Z","shell.execute_reply.started":"2026-03-03T11:29:48.318478Z","shell.execute_reply":"2026-03-03T11:29:48.334404Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"aligned_docs = aligned_docs.reset_index(drop=True)\n\nsentence_rows = []\nfor _, row in aligned_docs.iterrows():\n    doc_id = row['oare_id']\n    for s, t in zip(row['src_sents'], row['tgt_sents']):\n        sentence_rows.append({\n            \"doc_id\": doc_id,\n            \"src\": s,\n            \"tgt\": t\n        })\n\nsent_df = pd.DataFrame(sentence_rows)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.335977Z","iopub.execute_input":"2026-03-03T11:29:48.336182Z","iopub.status.idle":"2026-03-03T11:29:48.367835Z","shell.execute_reply.started":"2026-03-03T11:29:48.336164Z","shell.execute_reply":"2026-03-03T11:29:48.367286Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import GroupKFold\n\ngkf = GroupKFold(n_splits=5)\n\nfor train_idx, val_idx in gkf.split(\n    sent_df,\n    groups=sent_df['doc_id']\n):\n    train_data = sent_df.iloc[train_idx]\n    val_data = sent_df.iloc[val_idx]\n    break\n\nprint(\"Train sentences:\", len(train_data))\nprint(\"Val sentences:\", len(val_data))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:48.36857Z","iopub.execute_input":"2026-03-03T11:29:48.368789Z","iopub.status.idle":"2026-03-03T11:29:49.144433Z","shell.execute_reply.started":"2026-03-03T11:29:48.368765Z","shell.execute_reply":"2026-03-03T11:29:49.14377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_rows = []\n\nfor _, row in aligned_docs.iterrows():\n    doc_id = row['oare_id']\n    for s, t in zip(row['src_sents'], row['tgt_sents']):\n        sentence_rows.append({\n            \"doc_id\": doc_id,\n            \"src\": s.strip(),\n            \"tgt\": t.strip()\n        })\n\nsent_df = pd.DataFrame(sentence_rows)\n\nprint(\"Total sentence pairs:\", len(sent_df))\nsent_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:49.145332Z","iopub.execute_input":"2026-03-03T11:29:49.14569Z","iopub.status.idle":"2026-03-03T11:29:49.174317Z","shell.execute_reply.started":"2026-03-03T11:29:49.145668Z","shell.execute_reply":"2026-03-03T11:29:49.173702Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lex_map = {}\nfor _, row in lexicon.iterrows():\n    form = str(row['form'])\n    norm = str(row['norm'])\n    if form != \"nan\" and norm != \"nan\":\n        lex_map[form] = norm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:49.175245Z","iopub.execute_input":"2026-03-03T11:29:49.175632Z","iopub.status.idle":"2026-03-03T11:29:50.538134Z","shell.execute_reply.started":"2026-03-03T11:29:49.175599Z","shell.execute_reply":"2026-03-03T11:29:50.537426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def normalize_text(text):\n    tokens = text.split()\n    norm_tokens = []\n    for tok in tokens:\n        if tok in lex_map:\n            norm_tokens.append(lex_map[tok])\n        else:\n            norm_tokens.append(tok)\n    return \" \".join(norm_tokens)\n\nsent_df['src_norm'] = sent_df['src'].apply(normalize_text)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:50.539195Z","iopub.execute_input":"2026-03-03T11:29:50.539739Z","iopub.status.idle":"2026-03-03T11:29:50.549076Z","shell.execute_reply.started":"2026-03-03T11:29:50.539713Z","shell.execute_reply":"2026-03-03T11:29:50.548575Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sent_df['src_combined'] = sent_df['src'] + \" <norm> \" + sent_df['src_norm']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:50.549871Z","iopub.execute_input":"2026-03-03T11:29:50.550125Z","iopub.status.idle":"2026-03-03T11:29:50.563273Z","shell.execute_reply.started":"2026-03-03T11:29:50.550104Z","shell.execute_reply":"2026-03-03T11:29:50.562644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sent_df[['src', 'src_norm', 'src_combined']].head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:50.564049Z","iopub.execute_input":"2026-03-03T11:29:50.564226Z","iopub.status.idle":"2026-03-03T11:29:50.581008Z","shell.execute_reply.started":"2026-03-03T11:29:50.56421Z","shell.execute_reply":"2026-03-03T11:29:50.580393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import GroupKFold\n\ngkf = GroupKFold(n_splits=5)\n\nfor train_idx, val_idx in gkf.split(\n    sent_df,\n    groups=sent_df['doc_id']\n):\n    train_data = sent_df.iloc[train_idx]\n    val_data = sent_df.iloc[val_idx]\n    break\n\nprint(\"Train sentences:\", len(train_data))\nprint(\"Val sentences:\", len(val_data))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:50.581763Z","iopub.execute_input":"2026-03-03T11:29:50.581993Z","iopub.status.idle":"2026-03-03T11:29:50.595768Z","shell.execute_reply.started":"2026-03-03T11:29:50.581974Z","shell.execute_reply":"2026-03-03T11:29:50.595167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:50.596775Z","iopub.execute_input":"2026-03-03T11:29:50.597404Z","iopub.status.idle":"2026-03-03T11:29:50.605583Z","shell.execute_reply.started":"2026-03-03T11:29:50.597375Z","shell.execute_reply":"2026-03-03T11:29:50.604965Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from datasets import Dataset\n\ntrain_dataset = Dataset.from_pandas(\n    train_data[['src_combined','tgt']].reset_index(drop=True)\n)\n\nval_dataset = Dataset.from_pandas(\n    val_data[['src_combined','tgt']].reset_index(drop=True)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:50.606267Z","iopub.execute_input":"2026-03-03T11:29:50.606525Z","iopub.status.idle":"2026-03-03T11:29:52.697548Z","shell.execute_reply.started":"2026-03-03T11:29:50.606498Z","shell.execute_reply":"2026-03-03T11:29:52.696933Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip uninstall -y transformers tokenizers\n!pip install transformers==4.40.2 tokenizers==0.19.1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:29:52.698431Z","iopub.execute_input":"2026-03-03T11:29:52.698832Z","iopub.status.idle":"2026-03-03T11:30:08.937982Z","shell.execute_reply.started":"2026-03-03T11:29:52.698795Z","shell.execute_reply":"2026-03-03T11:30:08.937257Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q --upgrade --force-reinstall \\\n    transformers==4.41.2 \\\n    tokenizers==0.19.1 \\\n    accelerate==0.30.1 \\\n    datasets==2.19.1 \\\n    sacrebleu==2.4.2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:30:08.939343Z","iopub.execute_input":"2026-03-03T11:30:08.939641Z","iopub.status.idle":"2026-03-03T11:31:21.108922Z","shell.execute_reply.started":"2026-03-03T11:30:08.939615Z","shell.execute_reply":"2026-03-03T11:31:21.108009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:42:58.346653Z","iopub.execute_input":"2026-03-03T11:42:58.347293Z","iopub.status.idle":"2026-03-03T11:42:58.35077Z","shell.execute_reply.started":"2026-03-03T11:42:58.347265Z","shell.execute_reply":"2026-03-03T11:42:58.35005Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nimport transformers\n\nprint(\"Transformers version:\", transformers.__version__)\nprint(\"Import successful ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:00.288257Z","iopub.execute_input":"2026-03-03T11:43:00.289028Z","iopub.status.idle":"2026-03-03T11:43:00.293145Z","shell.execute_reply.started":"2026-03-03T11:43:00.288993Z","shell.execute_reply":"2026-03-03T11:43:00.292565Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import AutoTokenizer, AutoModelForSeq2SeqLM\n\nmodel_name = \"google/mt5-small\"\n\ntokenizer = AutoTokenizer.from_pretrained(model_name)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:02.796225Z","iopub.execute_input":"2026-03-03T11:43:02.796906Z","iopub.status.idle":"2026-03-03T11:43:14.391109Z","shell.execute_reply.started":"2026-03-03T11:43:02.796875Z","shell.execute_reply":"2026-03-03T11:43:14.390501Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport re\n\nDATA_PATH = \"/kaggle/input/competitions/deep-past-initiative-machine-translation\"  # adjust if needed\n\ntrain = pd.read_csv(f\"{DATA_PATH}/train.csv\")\ntest = pd.read_csv(f\"{DATA_PATH}/test.csv\")\nlexicon = pd.read_csv(f\"{DATA_PATH}/OA_Lexicon_eBL.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:21.227968Z","iopub.execute_input":"2026-03-03T11:43:21.228764Z","iopub.status.idle":"2026-03-03T11:43:21.403803Z","shell.execute_reply.started":"2026-03-03T11:43:21.228731Z","shell.execute_reply":"2026-03-03T11:43:21.403086Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def split_src(text):\n    lines = re.split(r'\\n+', text)\n    return [l.strip() for l in lines if len(l.strip()) > 3]\n\ndef split_tgt(text):\n    sents = re.split(r'(?<=[.?!])\\s+(?=[A-Z])', text)\n    return [s.strip() for s in sents if len(s.strip()) > 3]\n\ntrain['src_sents'] = train['transliteration'].apply(split_src)\ntrain['tgt_sents'] = train['translation'].apply(split_tgt)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:27.95075Z","iopub.execute_input":"2026-03-03T11:43:27.951489Z","iopub.status.idle":"2026-03-03T11:43:27.993641Z","shell.execute_reply.started":"2026-03-03T11:43:27.951462Z","shell.execute_reply":"2026-03-03T11:43:27.993034Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"aligned_docs = train[\n    train['src_sents'].apply(len) == train['tgt_sents'].apply(len)\n].copy()\n\nprint(\"Aligned docs:\", len(aligned_docs))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:29.998937Z","iopub.execute_input":"2026-03-03T11:43:29.999251Z","iopub.status.idle":"2026-03-03T11:43:30.006984Z","shell.execute_reply.started":"2026-03-03T11:43:29.999224Z","shell.execute_reply":"2026-03-03T11:43:30.006247Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lex_map = {}\n\nfor _, row in lexicon.iterrows():\n    form = str(row['form'])\n    norm = str(row['norm'])\n    if form != \"nan\" and norm != \"nan\":\n        lex_map[form] = norm\n\nprint(\"Lexicon entries:\", len(lex_map))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:33.004204Z","iopub.execute_input":"2026-03-03T11:43:33.004533Z","iopub.status.idle":"2026-03-03T11:43:34.417713Z","shell.execute_reply.started":"2026-03-03T11:43:33.004503Z","shell.execute_reply":"2026-03-03T11:43:34.417066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_rows = []\n\nfor _, row in aligned_docs.iterrows():\n    doc_id = row['oare_id']\n    for s, t in zip(row['src_sents'], row['tgt_sents']):\n        sentence_rows.append({\n            \"doc_id\": doc_id,\n            \"src\": s.strip(),\n            \"tgt\": t.strip()\n        })\n\nsent_df = pd.DataFrame(sentence_rows)\n\nprint(\"Total sentence pairs:\", len(sent_df))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:38.61463Z","iopub.execute_input":"2026-03-03T11:43:38.615244Z","iopub.status.idle":"2026-03-03T11:43:38.63842Z","shell.execute_reply.started":"2026-03-03T11:43:38.615214Z","shell.execute_reply":"2026-03-03T11:43:38.637528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def normalize_text(text):\n    tokens = text.split()\n    norm_tokens = []\n    for tok in tokens:\n        if tok in lex_map:\n            norm_tokens.append(lex_map[tok])\n        else:\n            norm_tokens.append(tok)\n    return \" \".join(norm_tokens)\n\nsent_df['src_norm'] = sent_df['src'].apply(normalize_text)\nsent_df['src_combined'] = sent_df['src'] + \" <norm> \" + sent_df['src_norm']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:43.079603Z","iopub.execute_input":"2026-03-03T11:43:43.079903Z","iopub.status.idle":"2026-03-03T11:43:43.092061Z","shell.execute_reply.started":"2026-03-03T11:43:43.079877Z","shell.execute_reply":"2026-03-03T11:43:43.091278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import GroupKFold\n\ngkf = GroupKFold(n_splits=5)\n\nfor train_idx, val_idx in gkf.split(\n    sent_df,\n    groups=sent_df['doc_id']\n):\n    train_data = sent_df.iloc[train_idx]\n    val_data = sent_df.iloc[val_idx]\n    break\n\nprint(\"Train sentences:\", len(train_data))\nprint(\"Val sentences:\", len(val_data))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:43:46.62919Z","iopub.execute_input":"2026-03-03T11:43:46.629851Z","iopub.status.idle":"2026-03-03T11:43:46.643176Z","shell.execute_reply.started":"2026-03-03T11:43:46.629801Z","shell.execute_reply":"2026-03-03T11:43:46.642418Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"max_input_len = 256\nmax_target_len = 256\n\ndef preprocess(example):\n    model_inputs = tokenizer(\n        example[\"input_text\"],\n        max_length=max_input_len,\n        truncation=True,\n        padding=\"max_length\"\n    )\n\n    labels = tokenizer(\n        example[\"target_text\"],\n        max_length=max_target_len,\n        truncation=True,\n        padding=\"max_length\"\n    )\n\n    labels_ids = labels[\"input_ids\"]\n\n    # Mask padding tokens\n    labels_ids = [\n        [(l if l != tokenizer.pad_token_id else -100) for l in label]\n        for label in labels_ids\n    ]\n\n    model_inputs[\"labels\"] = labels_ids\n    return model_inputs\n\ntrain_dataset = train_dataset.map(preprocess, batched=True)\nval_dataset = val_dataset.map(preprocess, batched=True)\n\nprint(\"Tokenization complete ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:46:28.102744Z","iopub.execute_input":"2026-03-03T11:46:28.103399Z","iopub.status.idle":"2026-03-03T11:46:28.398374Z","shell.execute_reply.started":"2026-03-03T11:46:28.103338Z","shell.execute_reply":"2026-03-03T11:46:28.397582Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import Seq2SeqTrainingArguments\n\ntraining_args = Seq2SeqTrainingArguments(\n    output_dir=\"./mt5_oa\",\n    eval_strategy=\"epoch\",        # new name (no warning)\n    save_strategy=\"epoch\",        # MUST match eval_strategy\n    learning_rate=2e-4,\n    per_device_train_batch_size=4,\n    per_device_eval_batch_size=4,\n    num_train_epochs=40,\n    weight_decay=0.01,\n    logging_steps=5,\n    save_total_limit=2,\n    predict_with_generate=True,\n    load_best_model_at_end=True,\n    metric_for_best_model=\"geo_mean\",  # important\n    greater_is_better=True,\n    fp16=True,\n    report_to=\"none\"\n)\n\nprint(\"Training config fixed ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:46:33.919491Z","iopub.execute_input":"2026-03-03T11:46:33.92006Z","iopub.status.idle":"2026-03-03T11:46:33.9266Z","shell.execute_reply.started":"2026-03-03T11:46:33.920032Z","shell.execute_reply":"2026-03-03T11:46:33.925732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import Seq2SeqTrainer\n\ntrainer = Seq2SeqTrainer(\n    model=model,\n    args=training_args,\n    train_dataset=train_dataset,\n    eval_dataset=val_dataset,\n    tokenizer=tokenizer,\n    compute_metrics=compute_metrics\n)\n\ntrainer.train()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:46:37.323885Z","iopub.execute_input":"2026-03-03T11:46:37.324624Z","iopub.status.idle":"2026-03-03T11:46:37.389808Z","shell.execute_reply.started":"2026-03-03T11:46:37.324592Z","shell.execute_reply":"2026-03-03T11:46:37.388865Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q --force-reinstall \\\n    transformers==4.41.2 \\\n    accelerate==0.31.0 \\\n    peft==0.11.1 \\\n    tokenizers==0.19.1 \\\n    datasets==2.19.1 \\\n    sacrebleu==2.4.2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:46:41.985337Z","iopub.execute_input":"2026-03-03T11:46:41.985645Z","iopub.status.idle":"2026-03-03T11:49:07.758221Z","shell.execute_reply.started":"2026-03-03T11:46:41.985619Z","shell.execute_reply":"2026-03-03T11:49:07.757533Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q --force-reinstall \\\n    transformers==4.41.2 \\\n    accelerate==0.31.0 \\\n    peft==0.11.1 \\\n    tokenizers==0.19.1 \\\n    datasets==2.19.1 \\\n    sacrebleu==2.4.2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:44:14.925116Z","iopub.execute_input":"2026-03-03T11:44:14.925469Z","iopub.status.idle":"2026-03-03T11:45:46.185523Z","shell.execute_reply.started":"2026-03-03T11:44:14.92544Z","shell.execute_reply":"2026-03-03T11:45:46.1848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, Seq2SeqTrainer\nimport transformers, accelerate, peft\n\nprint(\"Transformers:\", transformers.__version__)\nprint(\"Accelerate:\", accelerate.__version__)\nprint(\"PEFT:\", peft.__version__)\nprint(\"Environment stable ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:49:14.095956Z","iopub.execute_input":"2026-03-03T11:49:14.0966Z","iopub.status.idle":"2026-03-03T11:49:14.21943Z","shell.execute_reply.started":"2026-03-03T11:49:14.096561Z","shell.execute_reply":"2026-03-03T11:49:14.21851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport pandas as pd\nimport numpy as np\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:50:16.393032Z","iopub.execute_input":"2026-03-03T11:50:16.393799Z","iopub.status.idle":"2026-03-03T11:50:16.397299Z","shell.execute_reply.started":"2026-03-03T11:50:16.393765Z","shell.execute_reply":"2026-03-03T11:50:16.39651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport pandas as pd\nimport numpy as np\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:52:26.543481Z","iopub.execute_input":"2026-03-03T11:52:26.544046Z","iopub.status.idle":"2026-03-03T11:52:26.54803Z","shell.execute_reply.started":"2026-03-03T11:52:26.544014Z","shell.execute_reply":"2026-03-03T11:52:26.547412Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df = pd.read_csv(\"/kaggle/input/YOUR_DATASET/expanded_sentence_pairs.csv\")\n\nprint(\"Total sentence pairs:\", sentence_df.shape)\nsentence_df.head()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from datasets import Dataset\n\ntrain_dataset = Dataset.from_pandas(\n    train_data[['src_combined','tgt']].reset_index(drop=True)\n)\n\nval_dataset = Dataset.from_pandas(\n    val_data[['src_combined','tgt']].reset_index(drop=True)\n)\n\ntrain_dataset = train_dataset.rename_column(\"src_combined\", \"input_text\")\ntrain_dataset = train_dataset.rename_column(\"tgt\", \"target_text\")\n\nval_dataset = val_dataset.rename_column(\"src_combined\", \"input_text\")\nval_dataset = val_dataset.rename_column(\"tgt\", \"target_text\")\n\nprint(\"Dataset ready ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:45:53.031736Z","iopub.execute_input":"2026-03-03T11:45:53.032269Z","iopub.status.idle":"2026-03-03T11:45:53.058258Z","shell.execute_reply.started":"2026-03-03T11:45:53.032243Z","shell.execute_reply":"2026-03-03T11:45:53.057582Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import AutoTokenizer, AutoModelForSeq2SeqLM\n\nmodel_name = \"google/mt5-small\"\n\ntokenizer = AutoTokenizer.from_pretrained(model_name)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_name)\n\nprint(\"Model loaded ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:45:55.921189Z","iopub.execute_input":"2026-03-03T11:45:55.921529Z","iopub.status.idle":"2026-03-03T11:46:01.125991Z","shell.execute_reply.started":"2026-03-03T11:45:55.9215Z","shell.execute_reply":"2026-03-03T11:46:01.125256Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"max_input_len = 256\nmax_target_len = 256\n\ndef preprocess(example):\n    model_inputs = tokenizer(\n        example[\"input_text\"],\n        max_length=max_input_len,\n        truncation=True,\n        padding=\"max_length\"\n    )\n\n    labels = tokenizer(\n        example[\"target_text\"],\n        max_length=max_target_len,\n        truncation=True,\n        padding=\"max_length\"\n    )\n\n    labels_ids = labels[\"input_ids\"]\n    labels_ids = [\n        [(l if l != tokenizer.pad_token_id else -100) for l in label]\n        for label in labels_ids\n    ]\n\n    model_inputs[\"labels\"] = labels_ids\n    return model_inputs\n\ntrain_dataset = train_dataset.map(preprocess, batched=True)\nval_dataset = val_dataset.map(preprocess, batched=True)\n\nprint(\"Tokenization complete ✅\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:46:05.343244Z","iopub.execute_input":"2026-03-03T11:46:05.343566Z","iopub.status.idle":"2026-03-03T11:46:05.720405Z","shell.execute_reply.started":"2026-03-03T11:46:05.343537Z","shell.execute_reply":"2026-03-03T11:46:05.719615Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import Seq2SeqTrainingArguments\n\ntraining_args = Seq2SeqTrainingArguments(\n    output_dir=\"./mt5_oa\",\n    eval_strategy=\"no\",          # disable evaluation during training\n    save_strategy=\"epoch\",\n    learning_rate=2e-4,\n    per_device_train_batch_size=4,\n    num_train_epochs=20,         # reduce for faster baseline\n    weight_decay=0.01,\n    save_total_limit=2,\n    fp16=True,\n    report_to=\"none\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:50:37.946076Z","iopub.execute_input":"2026-03-03T11:50:37.946403Z","iopub.status.idle":"2026-03-03T11:50:37.952822Z","shell.execute_reply.started":"2026-03-03T11:50:37.946346Z","shell.execute_reply":"2026-03-03T11:50:37.951941Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sacrebleu\nimport numpy as np\n\ndef compute_metrics(eval_preds):\n    preds, labels = eval_preds\n\n    decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True)\n\n    labels = np.where(labels != -100, labels, tokenizer.pad_token_id)\n    decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)\n\n    bleu = sacrebleu.corpus_bleu(decoded_preds, [decoded_labels]).score\n    chrf = sacrebleu.corpus_chrf(decoded_preds, [decoded_labels]).score\n    geo_mean = np.sqrt(bleu * chrf)\n\n    return {\n        \"bleu\": bleu,\n        \"chrf\": chrf,\n        \"geo_mean\": geo_mean\n    }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.153953Z","iopub.status.idle":"2026-03-03T11:31:46.154508Z","shell.execute_reply.started":"2026-03-03T11:31:46.15424Z","shell.execute_reply":"2026-03-03T11:31:46.154271Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nprint(\"CUDA available:\", torch.cuda.is_available())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.156287Z","iopub.status.idle":"2026-03-03T11:31:46.156738Z","shell.execute_reply.started":"2026-03-03T11:31:46.156517Z","shell.execute_reply":"2026-03-03T11:31:46.156545Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sacrebleu\nimport numpy as np\n\ndef compute_metrics(eval_preds):\n    preds, labels = eval_preds\n\n    # In newer versions, preds can be tuple\n    if isinstance(preds, tuple):\n        preds = preds[0]\n\n    # Convert to int if needed\n    preds = np.asarray(preds)\n    labels = np.asarray(labels)\n\n    # Replace -100 in labels\n    labels = np.where(labels != -100, labels, tokenizer.pad_token_id)\n\n    decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True)\n    decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)\n\n    bleu = sacrebleu.corpus_bleu(decoded_preds, [decoded_labels]).score\n    chrf = sacrebleu.corpus_chrf(decoded_preds, [decoded_labels]).score\n    geo_mean = np.sqrt(bleu * chrf)\n\n    return {\n        \"bleu\": bleu,\n        \"chrf\": chrf,\n        \"geo_mean\": geo_mean\n    }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.158505Z","iopub.status.idle":"2026-03-03T11:31:46.159372Z","shell.execute_reply.started":"2026-03-03T11:31:46.159115Z","shell.execute_reply":"2026-03-03T11:31:46.159144Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.160124Z","iopub.status.idle":"2026-03-03T11:31:46.160667Z","shell.execute_reply.started":"2026-03-03T11:31:46.160312Z","shell.execute_reply":"2026-03-03T11:31:46.160339Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"max_input_len = 192\nmax_target_len = 192","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.162785Z","iopub.status.idle":"2026-03-03T11:31:46.163503Z","shell.execute_reply.started":"2026-03-03T11:31:46.163207Z","shell.execute_reply":"2026-03-03T11:31:46.163261Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"per_device_train_batch_size=2,","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.164814Z","iopub.status.idle":"2026-03-03T11:31:46.165193Z","shell.execute_reply.started":"2026-03-03T11:31:46.165004Z","shell.execute_reply":"2026-03-03T11:31:46.165029Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.gradient_checkpointing_enable()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.165979Z","iopub.status.idle":"2026-03-03T11:31:46.166397Z","shell.execute_reply.started":"2026-03-03T11:31:46.166168Z","shell.execute_reply":"2026-03-03T11:31:46.166195Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.167157Z","iopub.status.idle":"2026-03-03T11:31:46.167638Z","shell.execute_reply.started":"2026-03-03T11:31:46.167395Z","shell.execute_reply":"2026-03-03T11:31:46.167423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nprint(\"GPU count:\", torch.cuda.device_count())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.169639Z","iopub.status.idle":"2026-03-03T11:31:46.170063Z","shell.execute_reply.started":"2026-03-03T11:31:46.169856Z","shell.execute_reply":"2026-03-03T11:31:46.169882Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ddp_find_unused_parameters=False,","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.170814Z","iopub.status.idle":"2026-03-03T11:31:46.171208Z","shell.execute_reply.started":"2026-03-03T11:31:46.170997Z","shell.execute_reply":"2026-03-03T11:31:46.171024Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import Seq2SeqTrainingArguments\n\ntraining_args = Seq2SeqTrainingArguments(\n    output_dir=\"./mt5_oa\",\n    eval_strategy=\"no\",\n    save_strategy=\"no\",\n    learning_rate=2e-4,\n    per_device_train_batch_size=2,\n    num_train_epochs=10,   # reduce for now\n    fp16=True,\n    gradient_checkpointing=True,\n    dataloader_pin_memory=False,\n    report_to=\"none\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.172998Z","iopub.status.idle":"2026-03-03T11:31:46.173668Z","shell.execute_reply.started":"2026-03-03T11:31:46.173465Z","shell.execute_reply":"2026-03-03T11:31:46.173492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nprint(torch.cuda.device_count())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.174825Z","iopub.status.idle":"2026-03-03T11:31:46.175471Z","shell.execute_reply.started":"2026-03-03T11:31:46.175203Z","shell.execute_reply":"2026-03-03T11:31:46.175232Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.176851Z","iopub.status.idle":"2026-03-03T11:31:46.177502Z","shell.execute_reply.started":"2026-03-03T11:31:46.177265Z","shell.execute_reply":"2026-03-03T11:31:46.177292Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import Seq2SeqTrainer\n\ntrainer = Seq2SeqTrainer(\n    model=model,\n    args=training_args,\n    train_dataset=train_dataset,\n    processing_class=tokenizer\n)\n\ntrainer.train()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.178608Z","iopub.status.idle":"2026-03-03T11:31:46.179016Z","shell.execute_reply.started":"2026-03-03T11:31:46.178788Z","shell.execute_reply":"2026-03-03T11:31:46.178816Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport sacrebleu\nimport numpy as np\n\nmodel.eval()\n\npredictions = []\nreferences = []\n\nfor row in val_data.itertuples():\n    inputs = tokenizer(\n        row.src_combined,\n        return_tensors=\"pt\",\n        truncation=True,\n        max_length=256\n    ).to(model.device)\n\n    with torch.no_grad():\n        output_ids = model.generate(\n            **inputs,\n            max_length=256,\n            num_beams=4\n        )\n\n    pred_text = tokenizer.decode(output_ids[0], skip_special_tokens=True)\n\n    predictions.append(pred_text)\n    references.append(row.tgt)\n\nbleu = sacrebleu.corpus_bleu(predictions, [references]).score\nchrf = sacrebleu.corpus_chrf(predictions, [references]).score\ngeo_mean = np.sqrt(bleu * chrf)\n\nprint(\"BLEU:\", bleu)\nprint(\"chrF:\", chrf)\nprint(\"GeoMean:\", geo_mean)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.179864Z","iopub.status.idle":"2026-03-03T11:31:46.180215Z","shell.execute_reply.started":"2026-03-03T11:31:46.180018Z","shell.execute_reply":"2026-03-03T11:31:46.18004Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\"\nprint(\"CUDA visibility forced to GPU 0\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.181037Z","iopub.status.idle":"2026-03-03T11:31:46.181457Z","shell.execute_reply.started":"2026-03-03T11:31:46.181218Z","shell.execute_reply":"2026-03-03T11:31:46.181242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nprint(\"GPU count:\", torch.cuda.device_count())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.183588Z","iopub.status.idle":"2026-03-03T11:31:46.183988Z","shell.execute_reply.started":"2026-03-03T11:31:46.183784Z","shell.execute_reply":"2026-03-03T11:31:46.183808Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\n\ndevice = torch.device(\"cuda:0\")\n\nmodel_name = \"google/mt5-small\"\ntokenizer = AutoTokenizer.from_pretrained(model_name)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_name)\n\nmodel.to(device)\nmodel.gradient_checkpointing_enable()\n\nprint(\"Model on:\", device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.185463Z","iopub.status.idle":"2026-03-03T11:31:46.185904Z","shell.execute_reply.started":"2026-03-03T11:31:46.185672Z","shell.execute_reply":"2026-03-03T11:31:46.185701Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\n\ndevice = torch.device(\"cuda:0\")\n\nmodel_name = \"google/mt5-small\"\ntokenizer = AutoTokenizer.from_pretrained(model_name)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_name)\n\nmodel.to(device)\nmodel.gradient_checkpointing_enable()\n\nprint(\"Model on:\", device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.186673Z","iopub.status.idle":"2026-03-03T11:31:46.187089Z","shell.execute_reply.started":"2026-03-03T11:31:46.186858Z","shell.execute_reply":"2026-03-03T11:31:46.186886Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\n\nclass TranslationDataset(Dataset):\n    def __init__(self, df, tokenizer, max_len=192):\n        self.df = df\n        self.tokenizer = tokenizer\n        self.max_len = max_len\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n\n        inputs = self.tokenizer(\n            row.src_combined,\n            max_length=self.max_len,\n            truncation=True,\n            padding=\"max_length\",\n            return_tensors=\"pt\"\n        )\n\n        targets = self.tokenizer(\n            row.tgt,\n            max_length=self.max_len,\n            truncation=True,\n            padding=\"max_length\",\n            return_tensors=\"pt\"\n        )\n\n        input_ids = inputs[\"input_ids\"].squeeze()\n        attention_mask = inputs[\"attention_mask\"].squeeze()\n        labels = targets[\"input_ids\"].squeeze()\n\n        labels[labels == tokenizer.pad_token_id] = -100\n\n        return {\n            \"input_ids\": input_ids,\n            \"attention_mask\": attention_mask,\n            \"labels\": labels\n        }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.188576Z","iopub.status.idle":"2026-03-03T11:31:46.18902Z","shell.execute_reply.started":"2026-03-03T11:31:46.188806Z","shell.execute_reply":"2026-03-03T11:31:46.188832Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = TranslationDataset(train_data, tokenizer)\nval_dataset = TranslationDataset(val_data, tokenizer)\n\ntrain_loader = DataLoader(train_dataset, batch_size=2, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.190237Z","iopub.status.idle":"2026-03-03T11:31:46.190851Z","shell.execute_reply.started":"2026-03-03T11:31:46.190718Z","shell.execute_reply":"2026-03-03T11:31:46.190736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from transformers import AdamW\n\noptimizer = AdamW(model.parameters(), lr=2e-4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.19264Z","iopub.status.idle":"2026-03-03T11:31:46.193045Z","shell.execute_reply.started":"2026-03-03T11:31:46.192852Z","shell.execute_reply":"2026-03-03T11:31:46.192878Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.gradient_checkpointing_disable()\nmodel.config.use_cache = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.193836Z","iopub.status.idle":"2026-03-03T11:31:46.194197Z","shell.execute_reply.started":"2026-03-03T11:31:46.19401Z","shell.execute_reply":"2026-03-03T11:31:46.194034Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 10\noptimizer = torch.optim.AdamW(model.parameters(), lr=5e-5)\n\nfor epoch in range(epochs):\n    model.train()\n    total_loss = 0\n\n    for batch in train_loader:\n        optimizer.zero_grad()\n\n        batch = {k: v.to(device) for k, v in batch.items()}\n\n        outputs = model(**batch)\n        loss = outputs.loss\n\n        if torch.isnan(loss):\n            print(\"NaN detected. Skipping batch.\")\n            continue\n\n        loss.backward()\n\n        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n\n        optimizer.step()\n\n        total_loss += loss.item()\n\n    avg_loss = total_loss / len(train_loader)\n    print(f\"Epoch {epoch+1} | Loss: {avg_loss:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.19655Z","iopub.status.idle":"2026-03-03T11:31:46.197012Z","shell.execute_reply.started":"2026-03-03T11:31:46.196772Z","shell.execute_reply":"2026-03-03T11:31:46.1968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sacrebleu\nimport numpy as np\n\nmodel.eval()\n\npredictions = []\nreferences = []\n\nwith torch.no_grad():\n    for row in val_data.itertuples():\n        inputs = tokenizer(\n            row.src_combined,\n            return_tensors=\"pt\",\n            truncation=True,\n            max_length=192\n        ).to(device)\n\n        output_ids = model.generate(\n            **inputs,\n            max_length=192,\n            num_beams=4\n        )\n\n        pred_text = tokenizer.decode(output_ids[0], skip_special_tokens=True)\n\n        predictions.append(pred_text)\n        references.append(row.tgt)\n\nbleu = sacrebleu.corpus_bleu(predictions, [references]).score\nchrf = sacrebleu.corpus_chrf(predictions, [references]).score\ngeo_mean = np.sqrt(bleu * chrf)\n\nprint(\"BLEU:\", bleu)\nprint(\"chrF:\", chrf)\nprint(\"GeoMean:\", geo_mean)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.197796Z","iopub.status.idle":"2026-03-03T11:31:46.198212Z","shell.execute_reply.started":"2026-03-03T11:31:46.197983Z","shell.execute_reply":"2026-03-03T11:31:46.198011Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport re\n\npublished = pd.read_csv(\"/kaggle/input/competitions/deep-past-initiative-machine-translation/published_texts.csv\")\npublications = pd.read_csv(\"/kaggle/input/competitions/deep-past-initiative-machine-translation/publications.csv\")\n\nprint(\"Published texts:\", published.shape)\nprint(\"Publications OCR:\", publications.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.20162Z","iopub.status.idle":"2026-03-03T11:31:46.201877Z","shell.execute_reply.started":"2026-03-03T11:31:46.201761Z","shell.execute_reply":"2026-03-03T11:31:46.201776Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def looks_like_english(text):\n    if pd.isna(text):\n        return False\n\n    # Reject transliteration-like lines\n    if re.search(r\"[A-Z]{2,}\\.|[a-z]-[a-z]\", text):\n        return False\n\n    # Must contain common English words\n    keywords = [\"the\", \"has\", \"seal\", \"silver\", \"son\", \"owe\", \"from\", \"to\"]\n    score = sum(word in text.lower() for word in keywords)\n\n    return score >= 2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.202861Z","iopub.status.idle":"2026-03-03T11:31:46.203771Z","shell.execute_reply.started":"2026-03-03T11:31:46.203548Z","shell.execute_reply":"2026-03-03T11:31:46.203578Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"candidate_translations = []\n\nfor row in publications.itertuples():\n    if looks_like_english(row.page_text):\n        candidate_translations.append({\n            \"pdf\": row.pdf_name,\n            \"text\": row.page_text\n        })\n\ncandidate_df = pd.DataFrame(candidate_translations)\n\nprint(\"English candidates:\", len(candidate_df))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.204511Z","iopub.status.idle":"2026-03-03T11:31:46.204892Z","shell.execute_reply.started":"2026-03-03T11:31:46.204686Z","shell.execute_reply":"2026-03-03T11:31:46.204711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"published['alias_list'] = published['aliases'].fillna(\"\").apply(\n    lambda x: [a.strip() for a in x.split(\"|\") if a.strip()]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.205616Z","iopub.status.idle":"2026-03-03T11:31:46.205987Z","shell.execute_reply.started":"2026-03-03T11:31:46.205785Z","shell.execute_reply":"2026-03-03T11:31:46.205809Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"alias_to_translit = {}\n\nfor row in published.itertuples():\n    if pd.isna(row.transliteration):\n        continue\n        \n    for alias in row.alias_list:\n        alias_to_translit[alias] = row.transliteration\n\nprint(\"Alias keys:\", len(alias_to_translit))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.206724Z","iopub.status.idle":"2026-03-03T11:31:46.209013Z","shell.execute_reply.started":"2026-03-03T11:31:46.208788Z","shell.execute_reply":"2026-03-03T11:31:46.208816Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\npattern = re.compile(\"|\".join(map(re.escape, alias_to_translit.keys())))\n\nexpanded_pairs = []\n\nfor row in candidate_df.itertuples():\n    matches = pattern.findall(row.text)\n    \n    for match in matches:\n        expanded_pairs.append({\n            \"src\": alias_to_translit[match],\n            \"tgt\": row.text\n        })\n\nexpanded_df = pd.DataFrame(expanded_pairs).drop_duplicates()\n\nprint(\"New parallel pairs:\", expanded_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.210087Z","iopub.status.idle":"2026-03-03T11:31:46.211116Z","shell.execute_reply.started":"2026-03-03T11:31:46.210787Z","shell.execute_reply":"2026-03-03T11:31:46.210814Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import re\n\ndef clean_translation(text):\n    text = re.sub(r\"\\n+\", \" \", text)\n    text = re.sub(r\"\\s+\", \" \", text)\n    text = re.sub(r\"\\[[^\\]]*\\]\", \"\", text)   # remove bracket notes\n    text = re.sub(r\"\\([^)]*\\)\", \"\", text)    # remove commentary\n    text = text.strip()\n    return text\n\nexpanded_df[\"tgt\"] = expanded_df[\"tgt\"].apply(clean_translation)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.212013Z","iopub.status.idle":"2026-03-03T11:31:46.212427Z","shell.execute_reply.started":"2026-03-03T11:31:46.212188Z","shell.execute_reply":"2026-03-03T11:31:46.212213Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"expanded_df = expanded_df[\n    (expanded_df.src.str.len() < 1000) &\n    (expanded_df.tgt.str.len() < 2000) &\n    (expanded_df.tgt.str.len() > 20)\n]\n\nprint(\"After cleaning:\", expanded_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.214057Z","iopub.status.idle":"2026-03-03T11:31:46.214564Z","shell.execute_reply.started":"2026-03-03T11:31:46.214317Z","shell.execute_reply":"2026-03-03T11:31:46.214344Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import nltk\nnltk.download('punkt')\nfrom nltk.tokenize import sent_tokenize\n\nsentence_pairs = []\n\nfor row in expanded_df.itertuples():\n    src_sents = re.split(r\"\\.\\s+\", row.src)\n    tgt_sents = sent_tokenize(row.tgt)\n    \n    min_len = min(len(src_sents), len(tgt_sents))\n    \n    for i in range(min_len):\n        sentence_pairs.append({\n            \"src\": src_sents[i].strip(),\n            \"tgt\": tgt_sents[i].strip()\n        })\n\nsentence_df = pd.DataFrame(sentence_pairs)\n\nprint(\"Sentence-level pairs:\", sentence_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.215921Z","iopub.status.idle":"2026-03-03T11:31:46.216454Z","shell.execute_reply.started":"2026-03-03T11:31:46.216201Z","shell.execute_reply":"2026-03-03T11:31:46.216229Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df = sentence_df[\n    (sentence_df.src.str.len() > 10) &\n    (sentence_df.tgt.str.len() > 10)\n]\n\nsentence_df = sentence_df.drop_duplicates()\n\nprint(\"Filtered sentence pairs:\", sentence_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.217907Z","iopub.status.idle":"2026-03-03T11:31:46.218436Z","shell.execute_reply.started":"2026-03-03T11:31:46.218196Z","shell.execute_reply":"2026-03-03T11:31:46.218223Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"full_df = pd.concat([\n    train_data[['src_combined','tgt']].rename(columns={'src_combined':'src'}),\n    sentence_df\n], ignore_index=True)\n\nfull_df = full_df.drop_duplicates()\n\nprint(\"Total training pairs:\", full_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.219976Z","iopub.status.idle":"2026-03-03T11:31:46.22077Z","shell.execute_reply.started":"2026-03-03T11:31:46.220546Z","shell.execute_reply":"2026-03-03T11:31:46.220573Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain_df, val_df = train_test_split(\n    full_df,\n    test_size=0.1,\n    random_state=42\n)\n\nprint(\"Train:\", train_df.shape)\nprint(\"Val:\", val_df.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.222016Z","iopub.status.idle":"2026-03-03T11:31:46.222446Z","shell.execute_reply.started":"2026-03-03T11:31:46.222214Z","shell.execute_reply":"2026-03-03T11:31:46.22224Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class TranslationDataset(Dataset):\n    def __init__(self, df, tokenizer, max_len=192):\n        self.df = df.reset_index(drop=True)\n        self.tokenizer = tokenizer\n        self.max_len = max_len\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n\n        inputs = self.tokenizer(\n            row.src,\n            max_length=self.max_len,\n            truncation=True,\n            padding=\"max_length\",\n            return_tensors=\"pt\"\n        )\n\n        targets = self.tokenizer(\n            row.tgt,\n            max_length=self.max_len,\n            truncation=True,\n            padding=\"max_length\",\n            return_tensors=\"pt\"\n        )\n\n        labels = targets[\"input_ids\"].squeeze()\n        labels[labels == tokenizer.pad_token_id] = -100\n\n        return {\n            \"input_ids\": inputs[\"input_ids\"].squeeze(),\n            \"attention_mask\": inputs[\"attention_mask\"].squeeze(),\n            \"labels\": labels\n        }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.22317Z","iopub.status.idle":"2026-03-03T11:31:46.223696Z","shell.execute_reply.started":"2026-03-03T11:31:46.223347Z","shell.execute_reply":"2026-03-03T11:31:46.2235Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = TranslationDataset(train_df, tokenizer)\nval_dataset = TranslationDataset(val_df, tokenizer)\n\ntrain_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.225665Z","iopub.status.idle":"2026-03-03T11:31:46.226055Z","shell.execute_reply.started":"2026-03-03T11:31:46.225848Z","shell.execute_reply":"2026-03-03T11:31:46.22587Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = torch.optim.AdamW(model.parameters(), lr=3e-5)\n\nepochs = 8\n\nfor epoch in range(epochs):\n    model.train()\n    total_loss = 0\n\n    for batch in train_loader:\n        optimizer.zero_grad()\n\n        batch = {k: v.to(device) for k, v in batch.items()}\n\n        outputs = model(**batch)\n        loss = outputs.loss\n\n        loss.backward()\n        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n        optimizer.step()\n\n        total_loss += loss.item()\n\n    print(f\"Epoch {epoch+1} | Loss: {total_loss/len(train_loader):.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-03T11:31:46.227655Z","iopub.status.idle":"2026-03-03T11:31:46.228011Z","shell.execute_reply.started":"2026-03-03T11:31:46.22783Z","shell.execute_reply":"2026-03-03T11:31:46.227853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport re\nfrom nltk.tokenize import sent_tokenize\nimport nltk\n\nnltk.download('punkt')\n\npublished = pd.read_csv(\"/kaggle/input/competitions/deep-past-initiative-machine-translation/published_texts.csv\")\npublications = pd.read_csv(\"/kaggle/input/competitions/deep-past-initiative-machine-translation/publications.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-05T14:58:07.418302Z","iopub.execute_input":"2026-03-05T14:58:07.41857Z","iopub.status.idle":"2026-03-05T14:58:19.649483Z","shell.execute_reply.started":"2026-03-05T14:58:07.418546Z","shell.execute_reply":"2026-03-05T14:58:19.648776Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def looks_like_english(text):\n    if pd.isna(text):\n        return False\n    if re.search(r\"[A-Z]{2,}\\.|[a-z]-[a-z]\", text):\n        return False\n    keywords = [\"the\", \"has\", \"seal\", \"silver\", \"son\", \"owe\", \"from\", \"to\"]\n    return sum(word in text.lower() for word in keywords) >= 2\n\ncandidate_df = publications[publications.page_text.apply(looks_like_english)]\ncandidate_df = candidate_df[['pdf_name','page_text']].rename(columns={'page_text':'text'})\n\nprint(\"English candidates:\", len(candidate_df))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:14:16.015361Z","iopub.execute_input":"2026-03-04T17:14:16.016024Z","iopub.status.idle":"2026-03-04T17:14:25.303961Z","shell.execute_reply.started":"2026-03-04T17:14:16.01599Z","shell.execute_reply":"2026-03-04T17:14:25.303189Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"published['alias_list'] = published['aliases'].fillna(\"\").apply(\n    lambda x: [a.strip() for a in x.split(\"|\") if a.strip()]\n)\n\nalias_to_translit = {}\n\nfor row in published.itertuples():\n    if pd.isna(row.transliteration):\n        continue\n    for alias in row.alias_list:\n        alias_to_translit[alias] = row.transliteration\n\nprint(\"Alias keys:\", len(alias_to_translit))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:14:58.8005Z","iopub.execute_input":"2026-03-04T17:14:58.801114Z","iopub.status.idle":"2026-03-04T17:14:58.842923Z","shell.execute_reply.started":"2026-03-04T17:14:58.801084Z","shell.execute_reply":"2026-03-04T17:14:58.842322Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pattern = re.compile(\"|\".join(map(re.escape, list(alias_to_translit.keys())[:8000])))\n\nexpanded_pairs = []\n\nfor row in candidate_df.itertuples():\n    matches = pattern.findall(row.text)\n    for match in matches:\n        if match in alias_to_translit:\n            expanded_pairs.append({\n                \"src\": alias_to_translit[match],\n                \"tgt\": row.text\n            })\n\nexpanded_df = pd.DataFrame(expanded_pairs).drop_duplicates()\n\nprint(\"Parallel pairs:\", expanded_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:16:43.159677Z","iopub.execute_input":"2026-03-04T17:16:43.160374Z","iopub.status.idle":"2026-03-04T17:21:13.586967Z","shell.execute_reply.started":"2026-03-04T17:16:43.160344Z","shell.execute_reply":"2026-03-04T17:21:13.586276Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def clean_translation(text):\n    text = re.sub(r\"\\n+\", \" \", text)\n    text = re.sub(r\"\\s+\", \" \", text)\n    text = re.sub(r\"\\[[^\\]]*\\]\", \"\", text)\n    text = re.sub(r\"\\([^)]*\\)\", \"\", text)\n    return text.strip()\n\nexpanded_df[\"tgt\"] = expanded_df[\"tgt\"].apply(clean_translation)\n\nsentence_pairs = []\n\nfor row in expanded_df.itertuples():\n    src_sents = re.split(r\"\\.\\s+\", row.src)\n    tgt_sents = sent_tokenize(row.tgt)\n\n    min_len = min(len(src_sents), len(tgt_sents))\n    for i in range(min_len):\n        sentence_pairs.append({\n            \"src\": src_sents[i].strip(),\n            \"tgt\": tgt_sents[i].strip()\n        })\n\nsentence_df = pd.DataFrame(sentence_pairs)\nsentence_df = sentence_df[\n    (sentence_df.src.str.len() > 10) &\n    (sentence_df.tgt.str.len() > 10)\n].drop_duplicates()\n\nprint(\"Final sentence pairs:\", sentence_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:21:27.839526Z","iopub.execute_input":"2026-03-04T17:21:27.839858Z","iopub.status.idle":"2026-03-04T17:21:34.20176Z","shell.execute_reply.started":"2026-03-04T17:21:27.839831Z","shell.execute_reply":"2026-03-04T17:21:34.200942Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df.to_csv(\"/kaggle/working/expanded_sentence_pairs.csv\", index=False)\nprint(\"Saved expanded dataset.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:21:41.363415Z","iopub.execute_input":"2026-03-04T17:21:41.364139Z","iopub.status.idle":"2026-03-04T17:21:41.537591Z","shell.execute_reply.started":"2026-03-04T17:21:41.364106Z","shell.execute_reply":"2026-03-04T17:21:41.53704Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Total sentence pairs:\", sentence_df.shape)\nsentence_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:23:35.534164Z","iopub.execute_input":"2026-03-04T17:23:35.53453Z","iopub.status.idle":"2026-03-04T17:23:35.55611Z","shell.execute_reply.started":"2026-03-04T17:23:35.534502Z","shell.execute_reply":"2026-03-04T17:23:35.555377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain_df, val_df = train_test_split(\n    sentence_df,\n    test_size=0.1,\n    random_state=42\n)\n\nprint(\"Train size:\", train_df.shape)\nprint(\"Validation size:\", val_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:23:44.649809Z","iopub.execute_input":"2026-03-04T17:23:44.650566Z","iopub.status.idle":"2026-03-04T17:23:44.658647Z","shell.execute_reply.started":"2026-03-04T17:23:44.650536Z","shell.execute_reply":"2026-03-04T17:23:44.658096Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\n\ndevice = torch.device(\"cuda:0\")\n\nmodel_name = \"google/mt5-small\"\n\ntokenizer = AutoTokenizer.from_pretrained(model_name)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_name)\n\nmodel.to(device)\n\n# disable cache during training\nmodel.config.use_cache = False\n\nprint(\"Model loaded on:\", device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:23:51.64972Z","iopub.execute_input":"2026-03-04T17:23:51.650404Z","iopub.status.idle":"2026-03-04T17:24:36.011415Z","shell.execute_reply.started":"2026-03-04T17:23:51.650373Z","shell.execute_reply":"2026-03-04T17:24:36.010514Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import Dataset\n\nclass TranslationDataset(Dataset):\n    def __init__(self, df, tokenizer, max_len=192):\n        self.df = df.reset_index(drop=True)\n        self.tokenizer = tokenizer\n        self.max_len = max_len\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n\n        inputs = tokenizer(\n            row.src,\n            max_length=self.max_len,\n            truncation=True,\n            padding=\"max_length\",\n            return_tensors=\"pt\"\n        )\n\n        targets = tokenizer(\n            row.tgt,\n            max_length=self.max_len,\n            truncation=True,\n            padding=\"max_length\",\n            return_tensors=\"pt\"\n        )\n\n        labels = targets[\"input_ids\"].squeeze()\n        labels[labels == tokenizer.pad_token_id] = -100\n\n        return {\n            \"input_ids\": inputs[\"input_ids\"].squeeze(),\n            \"attention_mask\": inputs[\"attention_mask\"].squeeze(),\n            \"labels\": labels\n        }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:24:58.656606Z","iopub.execute_input":"2026-03-04T17:24:58.657042Z","iopub.status.idle":"2026-03-04T17:24:58.665674Z","shell.execute_reply.started":"2026-03-04T17:24:58.657002Z","shell.execute_reply":"2026-03-04T17:24:58.664906Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\ntrain_dataset = TranslationDataset(train_df, tokenizer)\nval_dataset = TranslationDataset(val_df, tokenizer)\n\ntrain_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=4)\n\nprint(\"DataLoaders ready\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:26:04.292473Z","iopub.execute_input":"2026-03-04T17:26:04.293024Z","iopub.status.idle":"2026-03-04T17:26:04.30098Z","shell.execute_reply.started":"2026-03-04T17:26:04.292968Z","shell.execute_reply":"2026-03-04T17:26:04.300023Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = torch.optim.AdamW(model.parameters(), lr=3e-5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:26:18.19306Z","iopub.execute_input":"2026-03-04T17:26:18.193903Z","iopub.status.idle":"2026-03-04T17:26:18.199094Z","shell.execute_reply.started":"2026-03-04T17:26:18.193869Z","shell.execute_reply":"2026-03-04T17:26:18.198327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 3\n\nfor epoch in range(epochs):\n\n    model.train()\n    total_loss = 0\n\n    for step, batch in enumerate(train_loader):\n\n        optimizer.zero_grad()\n\n        batch = {k: v.to(device) for k, v in batch.items()}\n\n        outputs = model(**batch)\n        loss = outputs.loss\n\n        loss.backward()\n\n        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n        optimizer.step()\n\n        total_loss += loss.item()\n\n        if step % 300 == 0:\n            print(f\"Epoch {epoch+1} | Step {step}/{len(train_loader)} | Loss {loss.item():.4f}\")\n\n    avg_loss = total_loss / len(train_loader)\n\n    print(f\"\\nEpoch {epoch+1} finished | Avg Loss: {avg_loss:.4f}\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T17:40:58.530287Z","iopub.execute_input":"2026-03-04T17:40:58.531016Z","iopub.status.idle":"2026-03-04T18:34:54.724118Z","shell.execute_reply.started":"2026-03-04T17:40:58.530973Z","shell.execute_reply":"2026-03-04T18:34:54.723219Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save_pretrained(\"/kaggle/working/mt5_akkadian_model\")\ntokenizer.save_pretrained(\"/kaggle/working/mt5_akkadian_model\")\n\nprint(\"Model saved to /kaggle/working/\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T18:38:03.373312Z","iopub.execute_input":"2026-03-04T18:38:03.373613Z","iopub.status.idle":"2026-03-04T18:38:10.164747Z","shell.execute_reply.started":"2026-03-04T18:38:03.373586Z","shell.execute_reply":"2026-03-04T18:38:10.16378Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json\n\ndataset_metadata = {\n    \"title\": \"mt5-akkadian-model\",\n    \"id\": \"YOUR_KAGGLE_USERNAME/mt5-akkadian-model\",\n    \"licenses\": [{\"name\": \"CC0-1.0\"}]\n}\n\nwith open(\"/kaggle/working/dataset-metadata.json\", \"w\") as f:\n    json.dump(dataset_metadata, f)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T18:53:36.093278Z","iopub.execute_input":"2026-03-04T18:53:36.094118Z","iopub.status.idle":"2026-03-04T18:53:36.098401Z","shell.execute_reply.started":"2026-03-04T18:53:36.094084Z","shell.execute_reply":"2026-03-04T18:53:36.097644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!kaggle datasets create -p /kaggle/working","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T18:53:49.453341Z","iopub.execute_input":"2026-03-04T18:53:49.453662Z","iopub.status.idle":"2026-03-04T18:54:01.990203Z","shell.execute_reply.started":"2026-03-04T18:53:49.45362Z","shell.execute_reply":"2026-03-04T18:54:01.989412Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sacrebleu\nimport numpy as np\n\nmodel.eval()\n\npredictions = []\nreferences = []\n\nwith torch.no_grad():\n\n    for row in val_df.itertuples():\n\n        inputs = tokenizer(\n            row.src,\n            return_tensors=\"pt\",\n            truncation=True,\n            max_length=192\n        ).to(device)\n\n        output_ids = model.generate(\n            **inputs,\n            max_length=192,\n            num_beams=5,\n            length_penalty=0.8,\n            early_stopping=True\n        )\n\n        pred = tokenizer.decode(output_ids[0], skip_special_tokens=True)\n\n        predictions.append(pred)\n        references.append(row.tgt)\n\nbleu = sacrebleu.corpus_bleu(predictions, [references]).score\nchrf = sacrebleu.corpus_chrf(predictions, [references]).score\ngeo_mean = np.sqrt(bleu * chrf)\n\nprint(\"BLEU:\", bleu)\nprint(\"chrF:\", chrf)\nprint(\"GeoMean:\", geo_mean)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-04T19:17:04.67208Z","iopub.execute_input":"2026-03-04T19:17:04.672456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install sacrebleu\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:20:37.339854Z","iopub.execute_input":"2026-03-06T16:20:37.340113Z","iopub.status.idle":"2026-03-06T16:20:42.217946Z","shell.execute_reply.started":"2026-03-06T16:20:37.340084Z","shell.execute_reply":"2026-03-06T16:20:42.217122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport torch\nfrom datasets import Dataset\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nfrom torch.utils.data import DataLoader\nfrom torch.optim import AdamW\nimport sacrebleu","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:23:56.328274Z","iopub.execute_input":"2026-03-06T16:23:56.328604Z","iopub.status.idle":"2026-03-06T16:24:15.43201Z","shell.execute_reply.started":"2026-03-06T16:23:56.328578Z","shell.execute_reply":"2026-03-06T16:24:15.431474Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df = pd.read_csv(\"/kaggle/input/datasets/sagarred24b026/expanded-sentence-pairs/expanded_sentence_pairs.csv\")\n\nprint(sentence_df.shape)\nsentence_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:32:52.123673Z","iopub.execute_input":"2026-03-06T16:32:52.124574Z","iopub.status.idle":"2026-03-06T16:32:52.334181Z","shell.execute_reply.started":"2026-03-06T16:32:52.124545Z","shell.execute_reply":"2026-03-06T16:32:52.333488Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain_df, val_df = train_test_split(\n    sentence_df,\n    test_size=0.1,\n    random_state=42\n)\n\nprint(\"Train:\", train_df.shape)\nprint(\"Validation:\", val_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:32:55.723164Z","iopub.execute_input":"2026-03-06T16:32:55.723641Z","iopub.status.idle":"2026-03-06T16:32:55.75018Z","shell.execute_reply.started":"2026-03-06T16:32:55.723612Z","shell.execute_reply":"2026-03-06T16:32:55.749502Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_name = \"google/mt5-small\"\n\ntokenizer = AutoTokenizer.from_pretrained(model_name)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:32:58.307252Z","iopub.execute_input":"2026-03-06T16:32:58.307821Z","iopub.status.idle":"2026-03-06T16:33:07.981374Z","shell.execute_reply.started":"2026-03-06T16:32:58.307784Z","shell.execute_reply":"2026-03-06T16:33:07.980377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def tokenize(batch):\n\n    model_inputs = tokenizer(\n        batch[\"src\"],\n        max_length=128,\n        truncation=True,\n        padding=\"max_length\"\n    )\n\n    labels = tokenizer(\n        batch[\"tgt\"],\n        max_length=128,\n        truncation=True,\n        padding=\"max_length\"\n    )\n\n    model_inputs[\"labels\"] = labels[\"input_ids\"]\n\n    return model_inputs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:35:06.923236Z","iopub.execute_input":"2026-03-06T16:35:06.923881Z","iopub.status.idle":"2026-03-06T16:35:06.928204Z","shell.execute_reply.started":"2026-03-06T16:35:06.923853Z","shell.execute_reply":"2026-03-06T16:35:06.92732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = Dataset.from_pandas(train_df)\nval_dataset = Dataset.from_pandas(val_df)\n\ntrain_dataset = train_dataset.map(tokenize, batched=True)\nval_dataset = val_dataset.map(tokenize, batched=True)\n\ntrain_dataset.set_format(type=\"torch\")\nval_dataset.set_format(type=\"torch\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:35:11.297394Z","iopub.execute_input":"2026-03-06T16:35:11.29775Z","iopub.status.idle":"2026-03-06T16:35:17.746362Z","shell.execute_reply.started":"2026-03-06T16:35:11.297715Z","shell.execute_reply":"2026-03-06T16:35:17.74559Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:35:40.963219Z","iopub.execute_input":"2026-03-06T16:35:40.963826Z","iopub.status.idle":"2026-03-06T16:35:40.967519Z","shell.execute_reply.started":"2026-03-06T16:35:40.963797Z","shell.execute_reply":"2026-03-06T16:35:40.966947Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:35:44.185057Z","iopub.execute_input":"2026-03-06T16:35:44.185353Z","iopub.status.idle":"2026-03-06T16:35:45.096638Z","shell.execute_reply.started":"2026-03-06T16:35:44.185329Z","shell.execute_reply":"2026-03-06T16:35:45.095901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = AdamW(model.parameters(), lr=2e-4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:35:55.443131Z","iopub.execute_input":"2026-03-06T16:35:55.443915Z","iopub.status.idle":"2026-03-06T16:35:55.448928Z","shell.execute_reply.started":"2026-03-06T16:35:55.443885Z","shell.execute_reply":"2026-03-06T16:35:55.448136Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset.set_format(\n    type=\"torch\",\n    columns=[\"input_ids\", \"attention_mask\", \"labels\"]\n)\n\nval_dataset.set_format(\n    type=\"torch\",\n    columns=[\"input_ids\", \"attention_mask\", \"labels\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:35:58.922935Z","iopub.execute_input":"2026-03-06T16:35:58.923679Z","iopub.status.idle":"2026-03-06T16:35:58.92828Z","shell.execute_reply.started":"2026-03-06T16:35:58.923649Z","shell.execute_reply":"2026-03-06T16:35:58.927507Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\ntrain_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:36:03.643216Z","iopub.execute_input":"2026-03-06T16:36:03.643571Z","iopub.status.idle":"2026-03-06T16:36:03.647737Z","shell.execute_reply.started":"2026-03-06T16:36:03.643538Z","shell.execute_reply":"2026-03-06T16:36:03.646888Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import time\n\nepochs = 3\ntotal_steps = len(train_loader)\n\nstart_time = time.time()\n\nfor epoch in range(epochs):\n\n    model.train()\n    total_loss = 0\n\n    for step, batch in enumerate(train_loader):\n\n        batch = {k: v.to(device) for k, v in batch.items()}\n\n        optimizer.zero_grad()\n\n        outputs = model(**batch)\n\n        loss = outputs.loss\n\n        loss.backward()\n\n        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n\n        optimizer.step()\n\n        total_loss += loss.item()\n\n        # ---- LOGGING ----\n        if step % 100 == 0:\n\n            elapsed = time.time() - start_time\n            steps_done = epoch * total_steps + step + 1\n            steps_total = epochs * total_steps\n\n            speed = steps_done / elapsed\n            remaining = (steps_total - steps_done) / speed\n\n            print(\n                f\"Epoch {epoch+1}/{epochs} | \"\n                f\"Step {step}/{total_steps} | \"\n                f\"Loss {loss.item():.4f} | \"\n                f\"Speed {speed:.2f} step/s | \"\n                f\"ETA {remaining/60:.1f} min\"\n            )\n\n    avg_loss = total_loss / total_steps\n\n    print(f\"\\nEpoch {epoch+1} completed | Avg Loss {avg_loss:.4f}\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T16:46:12.654807Z","iopub.execute_input":"2026-03-06T16:46:12.655643Z","iopub.status.idle":"2026-03-06T17:30:31.713314Z","shell.execute_reply.started":"2026-03-06T16:46:12.655611Z","shell.execute_reply":"2026-03-06T17:30:31.712688Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sacrebleu\nimport numpy as np\n\nmodel.eval()\n\npredictions = []\nreferences = []\n\nwith torch.no_grad():\n\n    for row in val_df.itertuples():\n\n        inputs = tokenizer(\n            row.src,\n            return_tensors=\"pt\",\n            truncation=True,\n            max_length=192\n        ).to(device)\n\n        output_ids = model.generate(\n            **inputs,\n            max_length=192,\n            num_beams=5,\n            length_penalty=0.8,\n            early_stopping=True\n        )\n\n        pred = tokenizer.decode(output_ids[0], skip_special_tokens=True)\n\n        predictions.append(pred)\n        references.append(row.tgt)\n\nbleu = sacrebleu.corpus_bleu(predictions, [references]).score\nchrf = sacrebleu.corpus_chrf(predictions, [references]).score\ngeo_mean = np.sqrt(bleu * chrf)\n\nprint(\"BLEU:\", bleu)\nprint(\"chrF:\", chrf)\nprint(\"GeoMean:\", geo_mean)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T17:58:59.761303Z","iopub.execute_input":"2026-03-06T17:58:59.762021Z","iopub.status.idle":"2026-03-06T18:33:13.824959Z","shell.execute_reply.started":"2026-03-06T17:58:59.761992Z","shell.execute_reply":"2026-03-06T18:33:13.824155Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df[\"src_len\"] = sentence_df[\"src\"].str.split().apply(len)\nsentence_df[\"tgt_len\"] = sentence_df[\"tgt\"].str.split().apply(len)\n\nsentence_df[\"ratio\"] = sentence_df[\"tgt_len\"] / sentence_df[\"src_len\"]\n\nsentence_df = sentence_df[\n    (sentence_df[\"ratio\"] > 0.5) &\n    (sentence_df[\"ratio\"] < 2.5)\n]\n\nprint(sentence_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:38:34.901315Z","iopub.execute_input":"2026-03-06T18:38:34.902076Z","iopub.status.idle":"2026-03-06T18:38:35.015201Z","shell.execute_reply.started":"2026-03-06T18:38:34.902046Z","shell.execute_reply":"2026-03-06T18:38:35.01459Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df = sentence_df[\n    (sentence_df[\"src_len\"] > 3) &\n    (sentence_df[\"tgt_len\"] > 3)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:38:47.581273Z","iopub.execute_input":"2026-03-06T18:38:47.581585Z","iopub.status.idle":"2026-03-06T18:38:47.592207Z","shell.execute_reply.started":"2026-03-06T18:38:47.58156Z","shell.execute_reply":"2026-03-06T18:38:47.591495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sentence_df = sentence_df.drop_duplicates()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:38:57.056814Z","iopub.execute_input":"2026-03-06T18:38:57.057796Z","iopub.status.idle":"2026-03-06T18:38:57.074368Z","shell.execute_reply.started":"2026-03-06T18:38:57.057756Z","shell.execute_reply":"2026-03-06T18:38:57.073512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import time\n\nepochs = 3\ntotal_steps = len(train_loader)\n\nstart_time = time.time()\n\nfor epoch in range(epochs):\n\n    model.train()\n    total_loss = 0\n\n    for step, batch in enumerate(train_loader):\n\n        batch = {k: v.to(device) for k, v in batch.items()}\n\n        optimizer.zero_grad()\n\n        outputs = model(**batch)\n\n        loss = outputs.loss\n\n        loss.backward()\n\n        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n\n        optimizer.step()\n\n        total_loss += loss.item()\n\n        # ---- LOGGING ----\n        if step % 100 == 0:\n\n            elapsed = time.time() - start_time\n            steps_done = epoch * total_steps + step + 1\n            steps_total = epochs * total_steps\n\n            speed = steps_done / elapsed\n            remaining = (steps_total - steps_done) / speed\n\n            print(\n                f\"Epoch {epoch+1}/{epochs} | \"\n                f\"Step {step}/{total_steps} | \"\n                f\"Loss {loss.item():.4f} | \"\n                f\"Speed {speed:.2f} step/s | \"\n                f\"ETA {remaining/60:.1f} min\"\n            )\n\n    avg_loss = total_loss / total_steps\n\n    print(f\"\\nEpoch {epoch+1} completed | Avg Loss {avg_loss:.4f}\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:39:16.001814Z","iopub.execute_input":"2026-03-06T18:39:16.00211Z","iopub.status.idle":"2026-03-06T18:45:39.570717Z","shell.execute_reply.started":"2026-03-06T18:39:16.002085Z","shell.execute_reply":"2026-03-06T18:45:39.569773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df = pd.read_csv(\"/kaggle/input/competitions/deep-past-initiative-machine-translation/test.csv\")\n\nprint(test_df.shape)\ntest_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:47:14.84384Z","iopub.execute_input":"2026-03-06T18:47:14.84414Z","iopub.status.idle":"2026-03-06T18:47:14.857493Z","shell.execute_reply.started":"2026-03-06T18:47:14.844117Z","shell.execute_reply":"2026-03-06T18:47:14.856861Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\n\ntranslations = []\n\nwith torch.no_grad():\n\n    for row in test_df.itertuples():\n\n        inputs = tokenizer(\n            row.transliteration,\n            return_tensors=\"pt\",\n            truncation=True,\n            max_length=192\n        ).to(device)\n\n        output_ids = model.generate(\n            **inputs,\n            max_length=192,\n            num_beams=5\n        )\n\n        pred = tokenizer.decode(output_ids[0], skip_special_tokens=True)\n\n        translations.append(pred)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:47:33.238938Z","iopub.execute_input":"2026-03-06T18:47:33.239237Z","iopub.status.idle":"2026-03-06T18:47:44.887142Z","shell.execute_reply.started":"2026-03-06T18:47:33.239211Z","shell.execute_reply":"2026-03-06T18:47:44.886524Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"id\": test_df[\"id\"],\n    \"translation\": translations\n})\n\nsubmission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:47:58.943859Z","iopub.execute_input":"2026-03-06T18:47:58.944152Z","iopub.status.idle":"2026-03-06T18:47:58.951999Z","shell.execute_reply.started":"2026-03-06T18:47:58.944129Z","shell.execute_reply":"2026-03-06T18:47:58.951305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission.to_csv(\"/kaggle/working/submission.csv\", index=False)\n\nprint(\"Submission file saved!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T18:48:23.938652Z","iopub.execute_input":"2026-03-06T18:48:23.939203Z","iopub.status.idle":"2026-03-06T18:48:23.948204Z","shell.execute_reply.started":"2026-03-06T18:48:23.939175Z","shell.execute_reply":"2026-03-06T18:48:23.947505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"id\": test_df[\"id\"],\n    \"translation\": translations\n})\n\nsubmission.to_csv(\"/kaggle/working/submission.csv\", index=False)\n\nprint(\"Submission saved successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T19:03:05.002031Z","iopub.execute_input":"2026-03-06T19:03:05.002322Z","iopub.status.idle":"2026-03-06T19:03:05.009638Z","shell.execute_reply.started":"2026-03-06T19:03:05.002299Z","shell.execute_reply":"2026-03-06T19:03:05.008917Z"}},"outputs":[],"execution_count":null}]}