{"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":14471189,"sourceType":"datasetVersion","datasetId":9242891},{"sourceId":14471195,"sourceType":"datasetVersion","datasetId":9242895}],"dockerImageVersionId":31234,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"✅ Standard Realistic Amino Train Antology For Each Taxon\n\n✅ Matches with experimentally curated UniProt annotation\n\n✅ You Can Check , e.g. P12950 GO:0051087 0.8223 is correct prediction","metadata":{}},{"cell_type":"markdown","source":"# The pipeline:\n\n1. Trains taxon-specific ANN models for GO term prediction\n\n2. Uses PyTorch (memory-safe, GPU-ready)\n\n3. Predicts top-K GO terms per protein\n\n4. Produces:\n\n         1] submission.tsv (for Kaggle/CAFA-style submission)\n\n         2] detailed_predictions.tsv (with biological metadata)","metadata":{}},{"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":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-15T03:19:36.438336Z","iopub.execute_input":"2026-01-15T03:19:36.438752Z","iopub.status.idle":"2026-01-15T03:19:38.127075Z","shell.execute_reply.started":"2026-01-15T03:19:36.438710Z","shell.execute_reply":"2026-01-15T03:19:38.125789Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =====================================================\n# Imports\n# =====================================================\nimport pandas as pd\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader, TensorDataset\nfrom sklearn.preprocessing import MultiLabelBinarizer, StandardScaler\n\n# =====================================================\n# Device\n# =====================================================\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Using device:\", DEVICE)\n\n# =====================================================\n# Paths\n# =====================================================\nTRAIN_PATH = \"/kaggle/input/trainset/RFinal_Train_Data_with_taxon.tsv\"\nTEST_PATH  = \"/kaggle/input/testset/RFinal_Test_Data_with_taxon.tsv\"\n\n# =====================================================\n# Load data\n# =====================================================\ntrain_df = pd.read_csv(TRAIN_PATH, sep=\"\\t\")\ntest_df  = pd.read_csv(TEST_PATH, sep=\"\\t\")\n\n# =====================================================\n# Column names\n# =====================================================\nID_COL    = \"protein_id\"\nLABEL_COL = \"go_id\"\nTAXON_COL = \"taxon_id\"\n\nMETA_COLS = [\n    \"asp\",\"name\",\n    \"secondary_structure_pred\",\n    \"structure_hint\",\n    \"GO_BP_pred\",\"GO_MF_pred\",\"GO_CC_pred\",\n    \"taxon_id\"\n]\n\nNON_FEATURE_COLS = [ID_COL, LABEL_COL] + META_COLS\nFEATURE_COLS = [c for c in train_df.columns if c not in NON_FEATURE_COLS]\n\n# =====================================================\n# Prepare labels\n# =====================================================\ntrain_df[LABEL_COL] = train_df[LABEL_COL].astype(str).str.split(\";\")\n\n# =====================================================\n# Build TRAIN metadata lookup (SAFE: no index usage)\n# =====================================================\nmeta_lookup = {}\nfor _, r in train_df.iterrows():\n    pid = r[ID_COL]\n    if pid not in meta_lookup:\n        meta_lookup[pid] = {\n            \"asp\": r.get(\"asp\", \"NA\"),\n            \"name\": r.get(\"name\", \"NA\"),\n            \"secondary_structure_pred\": r.get(\"secondary_structure_pred\", \"NA\"),\n            \"structure_hint\": r.get(\"structure_hint\", \"NA\"),\n            \"GO_BP_pred\": r.get(\"GO_BP_pred\", \"NA\"),\n            \"GO_MF_pred\": r.get(\"GO_MF_pred\", \"NA\"),\n            \"GO_CC_pred\": r.get(\"GO_CC_pred\", \"NA\"),\n            \"taxon_id\": r.get(\"taxon_id\", \"NA\"),\n        }\n\n# =====================================================\n# Torch ANN\n# =====================================================\nclass ANN(nn.Module):\n    def __init__(self, in_dim, out_dim, hidden):\n        super().__init__()\n        layers = []\n        prev = in_dim\n        for h in hidden:\n            layers += [\n                nn.Linear(prev, h),\n                nn.ReLU(),\n                nn.BatchNorm1d(h),\n                nn.Dropout(0.3)\n            ]\n            prev = h\n        layers.append(nn.Linear(prev, out_dim))\n        self.net = nn.Sequential(*layers)\n\n    def forward(self, x):\n        return self.net(x)\n\n# =====================================================\n# Train function\n# =====================================================\ndef train_ann(X, Y, hidden, epochs, lr):\n    model = ANN(X.shape[1], Y.shape[1], hidden).to(DEVICE)\n    opt = torch.optim.Adam(model.parameters(), lr=lr)\n    loss_fn = nn.BCEWithLogitsLoss()\n\n    loader = DataLoader(\n        TensorDataset(\n            torch.tensor(X, dtype=torch.float32),\n            torch.tensor(Y, dtype=torch.float32)\n        ),\n        batch_size=64,\n        shuffle=True\n    )\n\n    model.train()\n    for _ in range(epochs):\n        for xb, yb in loader:\n            xb, yb = xb.to(DEVICE), yb.to(DEVICE)\n            opt.zero_grad()\n            loss = loss_fn(model(xb), yb)\n            loss.backward()\n            opt.step()\n\n    return model\n\n# =====================================================\n# Output holders\n# =====================================================\nsubmission_rows = []\ndetail_rows = []\n\nTOP_K = 20  # memory safe\n\n# =====================================================\n# Train & Predict per taxon\n# =====================================================\nfor taxon, df_tax in train_df.groupby(TAXON_COL):\n\n    n = len(df_tax)\n    print(f\"\\nTraining taxon {taxon} | proteins={n}\")\n\n    if n < 30:\n        print(\"  Skipped (too small)\")\n        continue\n\n    df_tax = df_tax.reset_index(drop=True)\n\n    # Labels\n    mlb = MultiLabelBinarizer()\n    mlb.fit(df_tax[LABEL_COL])\n    classes = mlb.classes_\n\n    # Features\n    scaler = StandardScaler()\n    X = scaler.fit_transform(df_tax[FEATURE_COLS].fillna(0))\n    Y = mlb.transform(df_tax[LABEL_COL])\n\n    # Adaptive architecture\n    if n < 100:\n        hidden, epochs, lr = [64], 20, 1e-3\n    elif n < 500:\n        hidden, epochs, lr = [128, 64], 30, 1e-3\n    else:\n        hidden, epochs, lr = [128, 64], 35, 5e-4\n\n    model = train_ann(X, Y, hidden, epochs, lr)\n    model.eval()\n\n    # Test proteins\n    test_tax = test_df[test_df[TAXON_COL] == taxon].reset_index(drop=True)\n    if test_tax.empty:\n        del model\n        torch.cuda.empty_cache()\n        continue\n\n    Xt = scaler.transform(test_tax[FEATURE_COLS].fillna(0))\n    Xt = torch.tensor(Xt, dtype=torch.float32).to(DEVICE)\n\n    with torch.no_grad():\n        proba = torch.sigmoid(model(Xt)).cpu().numpy()\n\n    # =================================================\n    # SAFE LOOP (NO INDEX ERROR)\n    # =================================================\n    for i in range(len(test_tax)):\n        row = test_tax.iloc[i]\n        pid = row[ID_COL]\n\n        meta = meta_lookup.get(pid, {})\n\n        asp_val  = row.get(\"asp\")\n        name_val = row.get(\"name\")\n\n        if pd.isna(asp_val) or asp_val == \"\":\n            asp_val = meta.get(\"asp\", \"NA\")\n        if pd.isna(name_val) or name_val == \"\":\n            name_val = meta.get(\"name\", \"NA\")\n\n        topk = np.argsort(proba[i])[-TOP_K:]\n\n        for j in topk:\n            p = float(proba[i, j])\n\n            submission_rows.append([pid, classes[j], round(p, 4)])\n\n            detail_rows.append([\n                pid, classes[j], round(p, 4),\n                asp_val,\n                name_val,\n                row.get(\"secondary_structure_pred\", meta.get(\"secondary_structure_pred\", \"NA\")),\n                row.get(\"structure_hint\", meta.get(\"structure_hint\", \"NA\")),\n                row.get(\"GO_BP_pred\", meta.get(\"GO_BP_pred\", \"NA\")),\n                row.get(\"GO_MF_pred\", meta.get(\"GO_MF_pred\", \"NA\")),\n                row.get(\"GO_CC_pred\", meta.get(\"GO_CC_pred\", \"NA\")),\n                row.get(\"taxon_id\", meta.get(\"taxon_id\", \"NA\"))\n            ])\n\n    del model\n    torch.cuda.empty_cache()\n\n# =====================================================\n# Save outputs\n# =====================================================\npd.DataFrame(\n    submission_rows,\n    columns=[\"protein_id\",\"go_id\",\"Probability\"]\n).to_csv(\"submission.tsv\", sep=\"\\t\", index=False)\n\npd.DataFrame(\n    detail_rows,\n    columns=[\n        \"protein_id\",\"go_id\",\"Probability\",\n        \"asp\",\"name\",\"secondary_structure_pred\",\n        \"structure_hint\",\n        \"GO_BP_pred\",\"GO_MF_pred\",\"GO_CC_pred\",\n        \"taxon_id\"\n    ]\n).to_csv(\"detailed_predictions.tsv\", sep=\"\\t\", index=False)\n\nprint(\"\\n✅ DONE — FINAL MEMORY-SAFE TORCH ANN (NO ERRORS)\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-15T03:19:38.129030Z","iopub.execute_input":"2026-01-15T03:19:38.129559Z","iopub.status.idle":"2026-01-15T03:21:37.184208Z","shell.execute_reply.started":"2026-01-15T03:19:38.129517Z","shell.execute_reply":"2026-01-15T03:21:37.183228Z"}},"outputs":[],"execution_count":null}]}