{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":121150,"databundleVersionId":15061024,"sourceType":"competition"},{"sourceId":726890,"sourceType":"modelInstanceVersion","modelInstanceId":553350,"modelId":565899},{"sourceId":728404,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":554661,"modelId":567224}],"dockerImageVersionId":31260,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"################################################################################\n# OPTION A: PARAMETER SWEEP - 3 SUBMISSIONS\n################################################################################\n\nimport pandas as pd\nimport torch\nfrom transformers import MBartForConditionalGeneration, MBart50TokenizerFast\n\n# ============================================================================\n# CONFIGURATION\n# ============================================================================\nMODEL_PATH = \"/kaggle/input/2628/pytorch/default/1\"\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nprint(\"=\"*80)\nprint(\"SINGLE CONFIG TEST - BASELINE\")\nprint(\"=\"*80)\n\n# ============================================================================\n# LOAD MODEL ONCE\n# ============================================================================\ntokenizer = MBart50TokenizerFast.from_pretrained(MODEL_PATH)\nmodel = MBartForConditionalGeneration.from_pretrained(MODEL_PATH).to(DEVICE)\nmodel.eval()\nprint(f\"✓ Model loaded on {DEVICE}\")\n\n# ============================================================================\n# LOAD TEST DATA\n# ============================================================================\ntest_df = pd.read_csv(\"/kaggle/input/deep-past-initiative-machine-translation/test.csv\")\nprint(f\"✓ Test samples: {len(test_df)}\")\n\n# ============================================================================\n# GENERATION CONFIG - baseline matching your 25.0 score\n# ============================================================================\ngen_config = {\n    \"max_length\": 256,\n    \"num_beams\": 5,\n    \"length_penalty\": 2.0,\n    \"repetition_penalty\": 1.8,\n    \"no_repeat_ngram_size\": 3,\n    \"early_stopping\": True,\n}\n\n# ============================================================================\n# GENERATE\n# ============================================================================\ndef translate_batch(texts, batch_size=4):\n    outputs = []\n    for i in range(0, len(texts), batch_size):\n        batch = texts[i:i+batch_size]\n        \n        enc = tokenizer(\n            batch,\n            return_tensors=\"pt\",\n            padding=True,\n            truncation=True,\n            max_length=512\n        ).to(DEVICE)\n        \n        with torch.no_grad():\n            gen_ids = model.generate(\n                **enc,\n                forced_bos_token_id=tokenizer.lang_code_to_id[\"en_XX\"],\n                **gen_config,\n            )\n        \n        preds = tokenizer.batch_decode(gen_ids, skip_special_tokens=True)\n        outputs.extend(preds)\n    \n    return outputs\n\npredictions = translate_batch(test_df[\"transliteration\"].tolist())\n\nprint(f\"✓ Generated {len(predictions)} predictions\")\nprint(f\"✓ Avg length: {sum(len(p) for p in predictions) / len(predictions):.1f} chars\")\n\n# ============================================================================\n# CREATE SUBMISSION\n# ============================================================================\nsubmission = pd.DataFrame({\n    \"id\": test_df[\"id\"],\n    \"translation\": predictions,\n})\n\nsubmission.to_csv(\"/kaggle/working/submission.csv\", index=False)\n\nprint(\"=\"*80)\nprint(\"✓ SAVED: submission.csv\")\nprint(\"=\"*80)\nprint(\"\\nFirst prediction:\")\nprint(submission.loc[0, \"translation\"])\n\n# Load model ONCE\ntokenizer = MBart50TokenizerFast.from_pretrained(MODEL_PATH)\nmodel = MBartForConditionalGeneration.from_pretrained(MODEL_PATH).to(DEVICE)\nmodel.eval()\nprint(f\"✓ Model loaded on {DEVICE}\\n\")\n\n# Load test data\ntest_df = pd.read_csv('/kaggle/input/deep-past-initiative-machine-translation/test.csv')\nprint(f\"✓ Test samples: {len(test_df)}\\n\")\n\n# === DEFINE 3 CONFIGS ===\nconfigs = [\n    {\n        'name': 'conservative',\n        'description': 'Lower beams, shorter, safer',\n        'params': {\n            'max_length': 200,\n            'num_beams': 3,\n            'length_penalty': 1.5,\n            'repetition_penalty': 1.8,\n            'no_repeat_ngram_size': 3,\n            'early_stopping': True\n        }\n    },\n    {\n        'name': 'aggressive',\n        'description': 'Higher beams, longer, more exploratory',\n        'params': {\n            'max_length': 300,\n            'num_beams': 8,\n            'length_penalty': 2.5,\n            'repetition_penalty': 1.5,\n            'no_repeat_ngram_size': 2,\n            'early_stopping': True\n        }\n    },\n    {\n        'name': 'balanced_strong_antirep',\n        'description': 'Baseline with stronger repetition control',\n        'params': {\n            'max_length': 256,\n            'num_beams': 5,\n            'length_penalty': 2.0,\n            'repetition_penalty': 2.2,  # ← Increased from 1.8\n            'no_repeat_ngram_size': 4,   # ← Increased from 3\n            'early_stopping': True\n        }\n    }\n]\n\n# === GENERATION FUNCTION ===\ndef translate_batch(texts, config_params, batch_size=4):\n    \"\"\"Generate translations with specified config\"\"\"\n    outputs = []\n    \n    for i in range(0, len(texts), batch_size):\n        batch = texts[i:i+batch_size]\n        \n        enc = tokenizer(\n            batch,\n            return_tensors=\"pt\",\n            padding=True,\n            truncation=True,\n            max_length=512\n        ).to(DEVICE)\n        \n        with torch.no_grad():\n            gen_ids = model.generate(\n                **enc,\n                forced_bos_token_id=tokenizer.lang_code_to_id[\"en_XX\"],\n                **config_params\n            )\n        \n        preds = tokenizer.batch_decode(gen_ids, skip_special_tokens=True)\n        outputs.extend(preds)\n    \n    return outputs\n\n# === GENERATE 3 SUBMISSIONS ===\nprint(\"=\" * 80)\nprint(\"GENERATING PREDICTIONS\")\nprint(\"=\" * 80)\n\nall_submissions = {}\n\nfor i, config in enumerate(configs, 1):\n    print(f\"\\n--- Config {i}/3: {config['name']} ---\")\n    print(f\"Description: {config['description']}\")\n    print(f\"Parameters: {config['params']}\")\n    \n    # Generate\n    predictions = translate_batch(\n        test_df['transliteration'].tolist(),\n        config['params']\n    )\n    \n    # Create submission\n    submission = pd.DataFrame({\n        'id': test_df['id'],\n        'translation': predictions\n    })\n    \n    # Stats\n    avg_len = submission['translation'].str.len().mean()\n    avg_words = submission['translation'].str.split().str.len().mean()\n    \n    print(f\"✓ Generated {len(predictions)} predictions\")\n    print(f\"  Avg length: {avg_len:.1f} chars\")\n    print(f\"  Avg words: {avg_words:.1f}\")\n    \n    # Save\n    filename = f'/kaggle/working/submission_{config[\"name\"]}.csv'\n    submission.to_csv(filename, index=False)\n    print(f\"✓ Saved: {filename}\")\n    \n    # Store for comparison\n    all_submissions[config['name']] = submission\n\n# === COMPARISON TABLE ===\nprint(\"\\n\" + \"=\" * 80)\nprint(\"COMPARISON SUMMARY\")\nprint(\"=\" * 80)\n\ncomparison = []\nfor name, sub in all_submissions.items():\n    comparison.append({\n        'Config': name,\n        'Avg Chars': f\"{sub['translation'].str.len().mean():.1f}\",\n        'Avg Words': f\"{sub['translation'].str.split().str.len().mean():.1f}\",\n        'Max Length': sub['translation'].str.len().max(),\n        'Min Length': sub['translation'].str.len().min()\n    })\n\ncomp_df = pd.DataFrame(comparison)\nprint(comp_df.to_string(index=False))\n\n# === SIDE-BY-SIDE EXAMPLES ===\nprint(\"\\n\" + \"=\" * 80)\nprint(\"SAMPLE PREDICTIONS (First Example)\")\nprint(\"=\" * 80)\n\nprint(f\"\\nSource: {test_df.loc[0, 'transliteration'][:80]}...\\n\")\n\nfor name, sub in all_submissions.items():\n    pred = sub.loc[0, 'translation']\n    print(f\"{name.upper():25} ({len(pred)} chars)\")\n    print(f\"  {pred[:120]}...\\n\")\n\nprint(\"\\n\" + \"=\" * 80)\nprint(\"READY TO SUBMIT\")\nprint(\"=\" * 80)\nprint(\"Download these 3 files and submit to Kaggle:\")\nfor name in all_submissions.keys():\n    print(f\"  ✓ /kaggle/working/submission_{name}.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T18:41:54.941649Z","iopub.execute_input":"2026-02-04T18:41:54.942232Z","iopub.status.idle":"2026-02-04T18:45:21.395725Z","shell.execute_reply.started":"2026-02-04T18:41:54.942192Z","shell.execute_reply":"2026-02-04T18:45:21.394194Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# FINAL STEP: Copy conservative config to submission.csv for Kaggle compliance\n# ============================================================================\nimport shutil\n\n# Copy conservative to submission.csv (Kaggle's expected output file)\nshutil.copy(\n    \"/kaggle/working/submission_balanced_strong_antirep.csv\",\n    \"/kaggle/working/submission.csv\"\n)\n\nprint(\"=\"*80)\nprint(\"✓ FINAL SUBMISSION: submission.csv (antirep)\")\nprint(\"=\"*80)\n\n# Verify\nimport pandas as pd\nfinal = pd.read_csv(\"/kaggle/working/submission.csv\")\nprint(f\"Rows: {len(final)}\")\nprint(f\"Columns: {list(final.columns)}\")\nprint(f\"\\nFirst prediction:\")\nprint(final.loc[0, 'translation'])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-04T18:45:21.398283Z","iopub.execute_input":"2026-02-04T18:45:21.398649Z","iopub.status.idle":"2026-02-04T18:45:21.411589Z","shell.execute_reply.started":"2026-02-04T18:45:21.398617Z","shell.execute_reply":"2026-02-04T18:45:21.410560Z"}},"outputs":[],"execution_count":null}]}