{"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":14084779,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.multioutput import MultiOutputClassifier\nfrom sklearn.feature_extraction.text import TfidfVectorizer\nfrom sklearn.preprocessing import MultiLabelBinarizer\nimport os\n\nBASE_DIR = \"/kaggle/input/cafa-6-protein-function-prediction\"\nTRAIN_DIR = os.path.join(BASE_DIR, \"Train\")\nTEST_DIR = os.path.join(BASE_DIR, \"Test\")\n\n# Step 1: Load train sequences (correct ID extraction)\nprint(\"Step 1: Loading train sequences...\")\ntrain_seqs = {}\nwith open(os.path.join(TRAIN_DIR, \"train_sequences.fasta\")) as f:\n    for line in f:\n        if line.startswith(\">\"):\n            header = line[1:].strip()\n            if '|' in header:\n                seq_id = header.split('|')[1]\n            else:\n                seq_id = header.split()[0]\n            train_seqs[seq_id] = \"\"\n        else:\n            train_seqs[seq_id] += line.strip()\n\ntrain_seq_df = pd.DataFrame({\n    'Protein ID': list(train_seqs.keys()),\n    'Sequence': list(train_seqs.values())\n})\nprint(f\"Loaded {len(train_seq_df)} training sequences.\")\n\n# Step 2: Load train labels\nprint(\"Step 2: Loading train annotations...\")\ntrain_labels = pd.read_csv(os.path.join(TRAIN_DIR, \"train_terms.tsv\"), sep=\"\\t\")\n\ntop_n = 1000\ngo_counts = train_labels['term'].value_counts()\ntop_go_terms = go_counts.head(top_n).index.tolist()\nprint(f\"Using top {len(top_go_terms)} GO terms.\")\n\ntrain_labels = train_labels[train_labels['term'].isin(top_go_terms)]\n\n# Group by EntryID (which is UniProt ID like P21802)\ngrouped = train_labels.groupby('EntryID')['term'].apply(list).reset_index()\ntrain_df = pd.merge(train_seq_df, grouped, left_on='Protein ID', right_on='EntryID', how='inner')\nprint(f\"Training on {len(train_df)} labeled proteins.\")  # Should be > 0 now!\n\n# Step 3: Vectorize\nprint(\"Step 3: Vectorizing sequences...\")\nvectorizer = TfidfVectorizer(\n    analyzer='char',\n    ngram_range=(1, 3),\n    lowercase=False,\n    stop_words=None\n)\nX = vectorizer.fit_transform(train_df['Sequence'])\nprint(f\"Feature matrix shape: {X.shape}\")\n\n# Step 4: Labels\nmlb = MultiLabelBinarizer(classes=top_go_terms)\ny = mlb.fit_transform(train_df['term'])\n\n# Step 5: Train\nprint(\"Step 5: Training model...\")\nmodel = MultiOutputClassifier(\n    LogisticRegression(max_iter=500, random_state=42),\n    n_jobs=-1\n)\nmodel.fit(X, y)\n\n# Step 6: Load test sequences (same ID extraction!)\nprint(\"Step 6: Loading test sequences...\")\ntest_seqs = {}\nwith open(os.path.join(TEST_DIR, \"testsuperset.fasta\")) as f:\n    for line in f:\n        if line.startswith(\">\"):\n            header = line[1:].strip()\n            if '|' in header:\n                seq_id = header.split('|')[1]\n            else:\n                seq_id = header.split()[0]\n            test_seqs[seq_id] = \"\"\n        else:\n            test_seqs[seq_id] += line.strip()\n\ntest_seq_df = pd.DataFrame({\n    'Protein ID': list(test_seqs.keys()),\n    'Sequence': list(test_seqs.values())\n})\nprint(f\"Loaded {len(test_seq_df)} test sequences.\")\n\n# Step 7-9: Predict and submit\nX_test = vectorizer.transform(test_seq_df['Sequence'])\ny_pred_proba = np.array([estimator.predict_proba(X_test)[:, 1] for estimator in model.estimators_]).T\n\nprint(\"Generating submission...\")\nsubmission_rows = []\nthreshold = 0.01\nfor i, protein_id in enumerate(test_seq_df['Protein ID']):\n    scores = y_pred_proba[i]\n    for j, go_term in enumerate(mlb.classes_):\n        score = float(scores[j])\n        if score >= threshold:\n            submission_rows.append([protein_id, go_term, score])\n\nsubmission_df = pd.DataFrame(submission_rows, columns=[\"Protein Id\", \"GO Term Id\", \"Prediction\"])\nsubmission_df.to_csv(\"submission.tsv\", sep=\"\\t\", index=False, header=True)\nprint(f\"✅ Done! {len(submission_df)} predictions saved.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}