{"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":"none","dataSources":[{"sourceId":116062,"databundleVersionId":14875579,"sourceType":"competition"},{"sourceId":6180004,"sourceType":"datasetVersion","datasetId":3546496},{"sourceId":285859586,"sourceType":"kernelVersion"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\ndef read_submission(path: str) -> pd.DataFrame:\n    df = pd.read_csv(\n        path, sep=\"\\t\", header=None,\n        names=[\"Id\", \"GO term\", \"Confidence\"],\n        dtype={\"Id\": str, \"GO term\": str}\n    )\n    df[\"Confidence\"] = pd.to_numeric(df[\"Confidence\"], errors=\"coerce\").fillna(0.0).astype(np.float32)\n\n    # Nếu có dòng trùng (Id, GO term) thì lấy score lớn nhất\n    df = df.groupby([\"Id\", \"GO term\"], as_index=False)[\"Confidence\"].max()\n    return df\n\n# === paths ===\nsub1_path = \"/kaggle/input/nnn-kmer-tfidf/submission.tsv\"\nsub2_path = \"/kaggle/input/cafa5-055923-pred/submission.tsv\"\n\nsub1 = read_submission(sub1_path)\nsub2 = read_submission(sub2_path)\n\nmerged = sub1.merge(\n    sub2, on=[\"Id\", \"GO term\"], how=\"outer\",\n    suffixes=(\"_1\", \"_2\")\n)\n\nmerged[\"Confidence_1\"] = merged[\"Confidence_1\"].fillna(0.0).astype(np.float32)\nmerged[\"Confidence_2\"] = merged[\"Confidence_2\"].fillna(0.0).astype(np.float32)\n\n# ===== CHỌN 1 TRONG 3 CÁCH DƯỚI ĐÂY =====\n\n# (A) Priority/backfill (KHÔNG phải ensemble): ưu tiên sub2 nếu có, thiếu thì lấy sub1\n# merged[\"Confidence\"] = np.where(merged[\"Confidence_2\"] > 0, merged[\"Confidence_2\"], merged[\"Confidence_1\"])\n\n# (B) Max ensemble: lấy score lớn hơn giữa 2 model\nmerged[\"Confidence\"] = merged[[\"Confidence_1\", \"Confidence_2\"]].max(axis=1)\n\n# (C) Weighted average ensemble: hợp lý nhất nếu bạn biết model nào mạnh hơn\n# w = 0.7  # w lớn hơn cho model tốt hơn (ví dụ sub1 mạnh hơn)\n# merged[\"Confidence\"] = (w * merged[\"Confidence_1\"] + (1 - w) * merged[\"Confidence_2\"])\n\nmerged[\"Confidence\"] = merged[\"Confidence\"].clip(0.0, 1.0)\n\n# (khuyến nghị) giữ lại top-K per protein để file không quá lớn + giảm nhiễu\nTOPK_PER_PROTEIN = 200  # đặt giống config của bạn, hoặc tăng 500 nếu muốn\nfinal = (\n    merged.sort_values([\"Id\", \"Confidence\"], ascending=[True, False])\n          .groupby(\"Id\", as_index=False)\n          .head(TOPK_PER_PROTEIN)\n          .loc[:, [\"Id\", \"GO term\", \"Confidence\"]]\n)\n\nout_path = \"/kaggle/working/submission.tsv\"\nfinal.to_csv(out_path, sep=\"\\t\", header=False, index=False)\n\nprint(\"sub1 rows:\", len(sub1), \"| sub2 rows:\", len(sub2))\nprint(\"merged rows:\", len(merged), \"| final rows:\", len(final))\nprint(\"saved to:\", out_path)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-13T07:48:09.524637Z","iopub.execute_input":"2025-12-13T07:48:09.524929Z","iopub.status.idle":"2025-12-13T07:51:49.631672Z","shell.execute_reply.started":"2025-12-13T07:48:09.524908Z","shell.execute_reply":"2025-12-13T07:51:49.630816Z"}},"outputs":[],"execution_count":null}]}