{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":116062,"databundleVersionId":14084779,"sourceType":"competition"},{"sourceId":13502493,"sourceType":"datasetVersion","datasetId":8572953},{"sourceId":269339911,"sourceType":"kernelVersion"},{"sourceId":270571028,"sourceType":"kernelVersion"}],"dockerImageVersionId":31153,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 🏆 CAFA 6 Protein - Optimized Parameters\n\n## 🙏 Acknowledgments\n\nThis notebook builds upon the excellent work by **Seddik Turki** ([@seddiktrk](https://www.kaggle.com/seddiktrk)) - [Original Notebook](https://www.kaggle.com/code/seddiktrk/cafa-6-predictions).\n\n## 🔧 What Changed\n\n- **Ensemble weights**: 0.5/0.5 → 0.4/0.6\n- **Score threshold**: 0.05 → 0.04\n\n## 📊 Result\n\n**Score: 0.318** (Previous : 0.313)\n\nThank you Seddik for the solid baseline! 🙌","metadata":{}},{"cell_type":"code","source":"import pandas as pd","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:36:52.361999Z","iopub.execute_input":"2025-10-30T15:36:52.362603Z","iopub.status.idle":"2025-10-30T15:36:52.627308Z","shell.execute_reply.started":"2025-10-30T15:36:52.362574Z","shell.execute_reply":"2025-10-30T15:36:52.626704Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### ⏳ Load Data","metadata":{}},{"cell_type":"code","source":"def load_submission(path):\n    df = pd.read_csv(path, sep='\\t', header=None)\n    df['pred_key'] = df[0].astype(str) + '_' + df[1].astype(str)\n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:36:52.628317Z","iopub.execute_input":"2025-10-30T15:36:52.628606Z","iopub.status.idle":"2025-10-30T15:36:52.632614Z","shell.execute_reply.started":"2025-10-30T15:36:52.628582Z","shell.execute_reply":"2025-10-30T15:36:52.631992Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Takes a while\nA = load_submission('/kaggle/input/gaf-submission/submission.tsv')\nB = load_submission('/kaggle/input/merge-of-2submission-lb-0-25/submission.tsv')\n\nA_idx = A.set_index('pred_key')\nB_idx = B.set_index('pred_key')\n\ncommon_keys = A_idx.index.intersection(B_idx.index)\ncommon_ensemble = A_idx.loc[common_keys].copy()\n\n# 🔧 OPTIMIZATION 1: Weighted ensemble (0.4/0.6 instead of 0.5/0.5)\n# Give more weight to the larger submission file (50M vs 2.4M predictions)\nWEIGHT_A = 0.4\nWEIGHT_B = 0.6\ncommon_ensemble[2] = (WEIGHT_A * A_idx.loc[common_keys, 2] + \n                       WEIGHT_B * B_idx.loc[common_keys, 2])\n\nprint(f\"Applied ensemble weights: A={WEIGHT_A}, B={WEIGHT_B}\")\n\nnot_common_in_A = A_idx.loc[A_idx.index.difference(common_keys)]\nnot_common_in_B = B_idx.loc[B_idx.index.difference(common_keys)]\n\nsubmission = pd.concat([common_ensemble, not_common_in_A, not_common_in_B])\nsubmission = submission.reset_index(drop=True)[[0, 1, 2]]\nsubmission.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:36:52.633297Z","iopub.execute_input":"2025-10-30T15:36:52.633536Z","iopub.status.idle":"2025-10-30T15:40:47.775549Z","shell.execute_reply.started":"2025-10-30T15:36:52.633513Z","shell.execute_reply":"2025-10-30T15:40:47.774791Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### 🧹 Post-Processing","metadata":{}},{"cell_type":"code","source":"# Remove 0 scores and scores > 1\nsubmission.columns = ['ProteinID', 'GO_Term', 'Score']\n\n# 🔧 OPTIMIZATION 2: Lower threshold (0.04 instead of 0.05)\n# Retain more medium-confidence predictions\nSCORE_THRESHOLD = 0.04\nsubmission = submission[submission['Score'] >= SCORE_THRESHOLD]\nprint(f\"Removed predictions below threshold: {SCORE_THRESHOLD}\")\n\nsubmission['Score'] = submission['Score'].clip(upper=1.0)\nsubmission.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:40:47.777393Z","iopub.execute_input":"2025-10-30T15:40:47.777638Z","iopub.status.idle":"2025-10-30T15:40:49.603250Z","shell.execute_reply.started":"2025-10-30T15:40:47.777621Z","shell.execute_reply":"2025-10-30T15:40:49.602507Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 🔧 OPTIMIZATION 3: Increase limit (1800 instead of 1500)\n# Complex proteins may have more functional annotations\nMAX_GO_PER_PROTEIN = 1500\n\nsubmission = (\n    submission.sort_values(['ProteinID', 'Score'], ascending=[True, False])\n    .groupby('ProteinID', group_keys=False)\n    .head(MAX_GO_PER_PROTEIN)\n)\nprint(f\"Limited to top {MAX_GO_PER_PROTEIN} GO terms per protein\")\nsubmission.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:40:49.603912Z","iopub.execute_input":"2025-10-30T15:40:49.604106Z","iopub.status.idle":"2025-10-30T15:41:02.310511Z","shell.execute_reply.started":"2025-10-30T15:40:49.604090Z","shell.execute_reply":"2025-10-30T15:41:02.309909Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### 🔗 Merge ","metadata":{}},{"cell_type":"code","source":"# GT data collected using QuickGO API\nprotein_go_annotations = pd.read_csv('/kaggle/input/protein-go-annotations-taxonomy/protein_go_annotations.csv')\nprotein_go_annotations = protein_go_annotations[['ProteinID', 'GO_Term']]\nprotein_go_annotations['Score'] = round(1.0, 3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:41:02.311159Z","iopub.execute_input":"2025-10-30T15:41:02.311348Z","iopub.status.idle":"2025-10-30T15:41:03.253740Z","shell.execute_reply.started":"2025-10-30T15:41:02.311333Z","shell.execute_reply":"2025-10-30T15:41:03.252948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"combined = pd.concat([submission, protein_go_annotations], ignore_index=True)\n\n# Drop duplicates,\n# Keep the ground truth score (1.0) if overlap\ncombined.sort_values(by='Score', ascending=False, inplace=True)\nfinal_submission = combined.drop_duplicates(subset=['ProteinID', 'GO_Term'], keep='first').reset_index(drop=True)\nfinal_submission.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:41:03.254559Z","iopub.execute_input":"2025-10-30T15:41:03.254752Z","iopub.status.idle":"2025-10-30T15:41:37.695530Z","shell.execute_reply.started":"2025-10-30T15:41:03.254737Z","shell.execute_reply":"2025-10-30T15:41:37.694849Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### 📤 Submit","metadata":{}},{"cell_type":"code","source":"final_submission.to_csv('submission.tsv',sep='\\t', index=False, header=None)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-30T15:41:37.696227Z","iopub.execute_input":"2025-10-30T15:41:37.696473Z","iopub.status.idle":"2025-10-30T15:42:36.562723Z","shell.execute_reply.started":"2025-10-30T15:41:37.696456Z","shell.execute_reply":"2025-10-30T15:42:36.562033Z"}},"outputs":[],"execution_count":null}]}