{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":116062,"databundleVersionId":14084779,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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,"execution":{"iopub.status.busy":"2025-11-30T15:57:42.107032Z","iopub.execute_input":"2025-11-30T15:57:42.107847Z","iopub.status.idle":"2025-11-30T15:57:42.881492Z","shell.execute_reply.started":"2025-11-30T15:57:42.107816Z","shell.execute_reply":"2025-11-30T15:57:42.880725Z"}},"outputs":[{"name":"stdout","text":"/kaggle/input/cafa-6-protein-function-prediction/sample_submission.tsv\n/kaggle/input/cafa-6-protein-function-prediction/IA.tsv\n/kaggle/input/cafa-6-protein-function-prediction/Test/testsuperset.fasta\n/kaggle/input/cafa-6-protein-function-prediction/Test/testsuperset-taxon-list.tsv\n/kaggle/input/cafa-6-protein-function-prediction/Train/train_terms.tsv\n/kaggle/input/cafa-6-protein-function-prediction/Train/train_sequences.fasta\n/kaggle/input/cafa-6-protein-function-prediction/Train/train_taxonomy.tsv\n/kaggle/input/cafa-6-protein-function-prediction/Train/go-basic.obo\n","output_type":"stream"}],"execution_count":1},{"cell_type":"code","source":"import pandas as pd\nimport re\nimport numpy as np\nfrom sklearn.feature_extraction.text import TfidfVectorizer\nfrom sklearn.preprocessing import OneHotEncoder\nfrom scipy.sparse import hstack\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import f1_score, precision_score, recall_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:42.882596Z","iopub.execute_input":"2025-11-30T15:57:42.882947Z","iopub.status.idle":"2025-11-30T15:57:45.660093Z","shell.execute_reply.started":"2025-11-30T15:57:42.882924Z","shell.execute_reply":"2025-11-30T15:57:45.65943Z"}},"outputs":[],"execution_count":2},{"cell_type":"code","source":"#dataframe_test_file\ndef read_test_file(path):\n    proteins = []\n    seq_id = None\n    taxon_id = None\n    sequence = []\n\n    with open (path, \"r\") as f:\n        for line in f:\n            line = line.strip()\n            if line.startswith(\">\"):\n                if seq_id is not None:\n                    proteins.append({\n                        \"protein_id\" : seq_id,\n                        \"taxonomy_id\" : taxon_id,\n                        \"sequence\" : \"\".join(sequence)\n                    })\n                header = line[1:].split()\n                seq_id = header[0]\n                taxon_id = header[1] if len(header) >1 else None\n                sequence = []\n            else:\n                sequence.append(line)\n        if seq_id is not None:\n            proteins.append({\n                \"protein_id\" : seq_id,\n                \"taxonomy_id\" : taxon_id,\n                \"sequence\" : \"\".join(sequence)\n            })\n    return pd.DataFrame(proteins)\ntest_df = read_test_file(\"/kaggle/input/cafa-6-protein-function-prediction/Test/testsuperset.fasta\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:45.660971Z","iopub.execute_input":"2025-11-30T15:57:45.661362Z","iopub.status.idle":"2025-11-30T15:57:47.488384Z","shell.execute_reply.started":"2025-11-30T15:57:45.661333Z","shell.execute_reply":"2025-11-30T15:57:47.487314Z"}},"outputs":[],"execution_count":3},{"cell_type":"code","source":"test_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:47.490432Z","iopub.execute_input":"2025-11-30T15:57:47.49073Z","iopub.status.idle":"2025-11-30T15:57:47.512749Z","shell.execute_reply.started":"2025-11-30T15:57:47.490713Z","shell.execute_reply":"2025-11-30T15:57:47.512032Z"}},"outputs":[{"execution_count":4,"output_type":"execute_result","data":{"text/plain":"        protein_id taxonomy_id  \\\n0       A0A0C5B5G6        9606   \n1       A0A1B0GTW7        9606   \n2           A0JNW5        9606   \n3           A0JP26        9606   \n4           A0PK11        9606   \n...            ...         ...   \n224304      Q9Y7Q3      284812   \n224305      Q9Y7S3      284812   \n224306      Q9Y816      284812   \n224307      Q9ZB77      243273   \n224308      Q9ZB81      243273   \n\n                                                 sequence  \n0                                        MRWQEMGYIFYPRKLR  \n1       MLLLLLLLLLLPPLVLRVAASRCLHDETQKSVSLLRPPFSQLPSKS...  \n2       MAGIIKKQILKHLSRFTKNLSPDKINLSTLKGEGELKNLELDEEVL...  \n3       MVAEVCSMPAASAVKKPFDLRSKMGKWCHHRFPCCRGSGKSNMGTS...  \n4       MPGWFKKAWYGLASLLSFSSFILIIVALVVPHWLSGKILCQTGVDL...  \n...                                                   ...  \n224304  MHSSRRKYNDMWTARLLIRSDQKEEKYPSFKKNAGKAINAHLIPKL...  \n224305  MSTSYLCDENRKGENRKVEIQELVPYLYSVLLRGVPSRPVFDSRLK...  \n224306  MITEFIKSFLLFFFLPFFLSMPMIFATLGEFTDDQTHHYSTLPSCD...  \n224307  MLWSFNNHFVIDNSFKQEYDKPNITAFFNRSLQFFQENSLVLKPEL...  \n224308  MKVFKKLHNLNEILLLISIFFLVCIISLVGIGIIFDLIRKASLSAI...  \n\n[224309 rows x 3 columns]","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>protein_id</th>\n      <th>taxonomy_id</th>\n      <th>sequence</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>A0A0C5B5G6</td>\n      <td>9606</td>\n      <td>MRWQEMGYIFYPRKLR</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>A0A1B0GTW7</td>\n      <td>9606</td>\n      <td>MLLLLLLLLLLPPLVLRVAASRCLHDETQKSVSLLRPPFSQLPSKS...</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>A0JNW5</td>\n      <td>9606</td>\n      <td>MAGIIKKQILKHLSRFTKNLSPDKINLSTLKGEGELKNLELDEEVL...</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>A0JP26</td>\n      <td>9606</td>\n      <td>MVAEVCSMPAASAVKKPFDLRSKMGKWCHHRFPCCRGSGKSNMGTS...</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>A0PK11</td>\n      <td>9606</td>\n      <td>MPGWFKKAWYGLASLLSFSSFILIIVALVVPHWLSGKILCQTGVDL...</td>\n    </tr>\n    <tr>\n      <th>...</th>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n    </tr>\n    <tr>\n      <th>224304</th>\n      <td>Q9Y7Q3</td>\n      <td>284812</td>\n      <td>MHSSRRKYNDMWTARLLIRSDQKEEKYPSFKKNAGKAINAHLIPKL...</td>\n    </tr>\n    <tr>\n      <th>224305</th>\n      <td>Q9Y7S3</td>\n      <td>284812</td>\n      <td>MSTSYLCDENRKGENRKVEIQELVPYLYSVLLRGVPSRPVFDSRLK...</td>\n    </tr>\n    <tr>\n      <th>224306</th>\n      <td>Q9Y816</td>\n      <td>284812</td>\n      <td>MITEFIKSFLLFFFLPFFLSMPMIFATLGEFTDDQTHHYSTLPSCD...</td>\n    </tr>\n    <tr>\n      <th>224307</th>\n      <td>Q9ZB77</td>\n      <td>243273</td>\n      <td>MLWSFNNHFVIDNSFKQEYDKPNITAFFNRSLQFFQENSLVLKPEL...</td>\n    </tr>\n    <tr>\n      <th>224308</th>\n      <td>Q9ZB81</td>\n      <td>243273</td>\n      <td>MKVFKKLHNLNEILLLISIFFLVCIISLVGIGIIFDLIRKASLSAI...</td>\n    </tr>\n  </tbody>\n</table>\n<p>224309 rows × 3 columns</p>\n</div>"},"metadata":{}}],"execution_count":4},{"cell_type":"code","source":"import pandas as pd\nimport re\n\ndef read_train_file(path):\n    proteins = []\n    seq_id = None\n    taxon_id = None\n    sequence = []\n\n    with open(path, \"r\") as f:\n        for line in f:\n            line = line.strip()\n\n            if line.startswith(\">\"):\n                if seq_id is not None:\n                    proteins.append({\n                        \"protein_id\": seq_id,\n                        \"taxonomy_id\": taxon_id,\n                        \"sequence\": \"\".join(sequence)\n                    })\n                sequence = []\n                header = line[1:]\n                m_id = re.search(r\"sp\\|([^|]+)\\|\", header)\n                seq_id = m_id.group(1) if m_id else None\n                m_ox = re.search(r\"OX=(\\d+)\", header)\n                taxon_id = m_ox.group(1) if m_ox else None\n            else:\n                sequence.append(line)\n\n        # save last entry\n        if seq_id is not None:\n            proteins.append({\n                \"protein_id\": seq_id,\n                \"taxonomy_id\": taxon_id,\n                \"sequence\": \"\".join(sequence)\n            })\n\n    return pd.DataFrame(proteins)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:47.513458Z","iopub.execute_input":"2025-11-30T15:57:47.5137Z","iopub.status.idle":"2025-11-30T15:57:47.521763Z","shell.execute_reply.started":"2025-11-30T15:57:47.513683Z","shell.execute_reply":"2025-11-30T15:57:47.52109Z"}},"outputs":[],"execution_count":5},{"cell_type":"code","source":"train_df = read_train_file(\"/kaggle/input/cafa-6-protein-function-prediction/Train/train_sequences.fasta\")\ntrain_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:47.52242Z","iopub.execute_input":"2025-11-30T15:57:47.522628Z","iopub.status.idle":"2025-11-30T15:57:48.471961Z","shell.execute_reply.started":"2025-11-30T15:57:47.522604Z","shell.execute_reply":"2025-11-30T15:57:48.471286Z"}},"outputs":[{"execution_count":6,"output_type":"execute_result","data":{"text/plain":"       protein_id taxonomy_id  \\\n0      A0A0C5B5G6        9606   \n1          A0JNW5        9606   \n2          A0JP26        9606   \n3          A0PK11        9606   \n4          A1A4S6        9606   \n...           ...         ...   \n82399      Q9UTM1      284812   \n82400      Q9Y7I1      284812   \n82401      Q9Y7P7      284812   \n82402      Q9Y7Q3      284812   \n82403      Q9Y816      284812   \n\n                                                sequence  \n0                                       MRWQEMGYIFYPRKLR  \n1      MAGIIKKQILKHLSRFTKNLSPDKINLSTLKGEGELKNLELDEEVL...  \n2      MVAEVCSMPAASAVKKPFDLRSKMGKWCHHRFPCCRGSGKSNMGTS...  \n3      MPGWFKKAWYGLASLLSFSSFILIIVALVVPHWLSGKILCQTGVDL...  \n4      MGLQPLEFSDCYLDSPWFRERIRAHEAELERTNKFIKELIKDGKNL...  \n...                                                  ...  \n82399  MSKLKAQSALQKLIESQKNPNANEDGYFRRKRLAKKERPFEPKKLV...  \n82400  MSSNSNTDHSTGDNRSKSEKQTDLRNALRETESHGMPPLRGPAGFP...  \n82401  MRSNNSSLVHCCWVSPPSLTRLPAFPSPRILSPCYCYNKRIRPFRG...  \n82402  MHSSRRKYNDMWTARLLIRSDQKEEKYPSFKKNAGKAINAHLIPKL...  \n82403  MITEFIKSFLLFFFLPFFLSMPMIFATLGEFTDDQTHHYSTLPSCD...  \n\n[82404 rows x 3 columns]","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>protein_id</th>\n      <th>taxonomy_id</th>\n      <th>sequence</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>A0A0C5B5G6</td>\n      <td>9606</td>\n      <td>MRWQEMGYIFYPRKLR</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>A0JNW5</td>\n      <td>9606</td>\n      <td>MAGIIKKQILKHLSRFTKNLSPDKINLSTLKGEGELKNLELDEEVL...</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>A0JP26</td>\n      <td>9606</td>\n      <td>MVAEVCSMPAASAVKKPFDLRSKMGKWCHHRFPCCRGSGKSNMGTS...</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>A0PK11</td>\n      <td>9606</td>\n      <td>MPGWFKKAWYGLASLLSFSSFILIIVALVVPHWLSGKILCQTGVDL...</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>A1A4S6</td>\n      <td>9606</td>\n      <td>MGLQPLEFSDCYLDSPWFRERIRAHEAELERTNKFIKELIKDGKNL...</td>\n    </tr>\n    <tr>\n      <th>...</th>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n    </tr>\n    <tr>\n      <th>82399</th>\n      <td>Q9UTM1</td>\n      <td>284812</td>\n      <td>MSKLKAQSALQKLIESQKNPNANEDGYFRRKRLAKKERPFEPKKLV...</td>\n    </tr>\n    <tr>\n      <th>82400</th>\n      <td>Q9Y7I1</td>\n      <td>284812</td>\n      <td>MSSNSNTDHSTGDNRSKSEKQTDLRNALRETESHGMPPLRGPAGFP...</td>\n    </tr>\n    <tr>\n      <th>82401</th>\n      <td>Q9Y7P7</td>\n      <td>284812</td>\n      <td>MRSNNSSLVHCCWVSPPSLTRLPAFPSPRILSPCYCYNKRIRPFRG...</td>\n    </tr>\n    <tr>\n      <th>82402</th>\n      <td>Q9Y7Q3</td>\n      <td>284812</td>\n      <td>MHSSRRKYNDMWTARLLIRSDQKEEKYPSFKKNAGKAINAHLIPKL...</td>\n    </tr>\n    <tr>\n      <th>82403</th>\n      <td>Q9Y816</td>\n      <td>284812</td>\n      <td>MITEFIKSFLLFFFLPFFLSMPMIFATLGEFTDDQTHHYSTLPSCD...</td>\n    </tr>\n  </tbody>\n</table>\n<p>82404 rows × 3 columns</p>\n</div>"},"metadata":{}}],"execution_count":6},{"cell_type":"code","source":"#read_go_term\ndf_term = pd.read_csv(\"/kaggle/input/cafa-6-protein-function-prediction/Train/train_terms.tsv\", sep = \"\\t\")\n#check\nprint(df_term[\"EntryID\"].nunique())\nprint(df_term[\"term\"].nunique())\n#82404 unique EntryID in df_term\ndf_label = (df_term.groupby(\"EntryID\")[\"term\"].apply(list).reset_index())\n\ndf_train = train_df.merge(df_label, left_on = \"protein_id\", right_on = \"EntryID\", how = \"left\")\ndf_train = df_train.drop(columns = [\"EntryID\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:48.472825Z","iopub.execute_input":"2025-11-30T15:57:48.473138Z","iopub.status.idle":"2025-11-30T15:57:50.410482Z","shell.execute_reply.started":"2025-11-30T15:57:48.47311Z","shell.execute_reply":"2025-11-30T15:57:50.409822Z"}},"outputs":[{"name":"stdout","text":"82404\n26125\n","output_type":"stream"}],"execution_count":7},{"cell_type":"code","source":"df_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:50.411365Z","iopub.execute_input":"2025-11-30T15:57:50.411686Z","iopub.status.idle":"2025-11-30T15:57:50.42144Z","shell.execute_reply.started":"2025-11-30T15:57:50.411657Z","shell.execute_reply":"2025-11-30T15:57:50.420736Z"}},"outputs":[{"execution_count":8,"output_type":"execute_result","data":{"text/plain":"   protein_id taxonomy_id                                           sequence  \\\n0  A0A0C5B5G6        9606                                   MRWQEMGYIFYPRKLR   \n1      A0JNW5        9606  MAGIIKKQILKHLSRFTKNLSPDKINLSTLKGEGELKNLELDEEVL...   \n2      A0JP26        9606  MVAEVCSMPAASAVKKPFDLRSKMGKWCHHRFPCCRGSGKSNMGTS...   \n3      A0PK11        9606  MPGWFKKAWYGLASLLSFSSFILIIVALVVPHWLSGKILCQTGVDL...   \n4      A1A4S6        9606  MGLQPLEFSDCYLDSPWFRERIRAHEAELERTNKFIKELIKDGKNL...   \n\n                                                term  \n0  [GO:0001649, GO:0033687, GO:0005615, GO:000563...  \n1  [GO:0120013, GO:0034498, GO:0005769, GO:012000...  \n2                                       [GO:0005515]  \n3                           [GO:0007605, GO:0005515]  \n4  [GO:0005829, GO:0010008, GO:0005515, GO:000509...  ","text/html":"<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>protein_id</th>\n      <th>taxonomy_id</th>\n      <th>sequence</th>\n      <th>term</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>A0A0C5B5G6</td>\n      <td>9606</td>\n      <td>MRWQEMGYIFYPRKLR</td>\n      <td>[GO:0001649, GO:0033687, GO:0005615, GO:000563...</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>A0JNW5</td>\n      <td>9606</td>\n      <td>MAGIIKKQILKHLSRFTKNLSPDKINLSTLKGEGELKNLELDEEVL...</td>\n      <td>[GO:0120013, GO:0034498, GO:0005769, GO:012000...</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>A0JP26</td>\n      <td>9606</td>\n      <td>MVAEVCSMPAASAVKKPFDLRSKMGKWCHHRFPCCRGSGKSNMGTS...</td>\n      <td>[GO:0005515]</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>A0PK11</td>\n      <td>9606</td>\n      <td>MPGWFKKAWYGLASLLSFSSFILIIVALVVPHWLSGKILCQTGVDL...</td>\n      <td>[GO:0007605, GO:0005515]</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>A1A4S6</td>\n      <td>9606</td>\n      <td>MGLQPLEFSDCYLDSPWFRERIRAHEAELERTNKFIKELIKDGKNL...</td>\n      <td>[GO:0005829, GO:0010008, GO:0005515, GO:000509...</td>\n    </tr>\n  </tbody>\n</table>\n</div>"},"metadata":{}}],"execution_count":8},{"cell_type":"code","source":"df_train.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:50.422245Z","iopub.execute_input":"2025-11-30T15:57:50.422513Z","iopub.status.idle":"2025-11-30T15:57:50.463551Z","shell.execute_reply.started":"2025-11-30T15:57:50.42249Z","shell.execute_reply":"2025-11-30T15:57:50.462832Z"}},"outputs":[{"execution_count":9,"output_type":"execute_result","data":{"text/plain":"protein_id     0\ntaxonomy_id    0\nsequence       0\nterm           0\ndtype: int64"},"metadata":{}}],"execution_count":9},{"cell_type":"code","source":"# tao matrix multi label\nterms = sorted(df_term[\"term\"].unique())\n\nterm_to_idx = {t: i for i, t in enumerate(terms)}\nN = len(df_train)\nT = len(terms)\nprint(N)\nprint(T)\n\nY = np.zeros((N, T), dtype = np.int8)\nfor i, terms in enumerate(df_train[\"term\"]):\n    for t in terms:\n        Y[i, term_to_idx[t]] = 1\n\nX_sequences = df_train[\"sequence\"].tolist()\nX_taxonomy  = df_train[\"taxonomy_id\"].tolist()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:50.465951Z","iopub.execute_input":"2025-11-30T15:57:50.46629Z","iopub.status.idle":"2025-11-30T15:57:51.416018Z","shell.execute_reply.started":"2025-11-30T15:57:50.46627Z","shell.execute_reply":"2025-11-30T15:57:51.415179Z"}},"outputs":[{"name":"stdout","text":"82404\n26125\n","output_type":"stream"}],"execution_count":10},{"cell_type":"code","source":"# kmer - Tfidf\ndef get_kmer(seq, k=2):\n    return [seq[i:i+k] for i in range(len(seq)-k+1)]\n\ndef encode_taxo(tax_list):\n    return np.log1p(np.array(tax_list)).reshape(-1, 1)\n\n# 1. TF-IDF cho sequence\nX_kmers = [\" \".join(get_kmer(seq, k=2)) for seq in X_sequences]\nvectorizer = TfidfVectorizer(max_features=5000)\nX_seq_tfidf = vectorizer.fit_transform(X_kmers)\n\nprint(\"Shape của X_seq_tfidf:\", X_seq_tfidf.shape)\n\nX_taxonomy_int = np.array(X_taxonomy).astype(int)\n\n# Encode\nX_tax_encoded = encode_taxo(X_taxonomy_int)\n\nprint(\"Shape của X_tax_encoded:\", X_tax_encoded.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:57:51.416983Z","iopub.execute_input":"2025-11-30T15:57:51.417256Z","iopub.status.idle":"2025-11-30T15:58:15.861415Z","shell.execute_reply.started":"2025-11-30T15:57:51.417237Z","shell.execute_reply":"2025-11-30T15:58:15.860533Z"}},"outputs":[{"name":"stdout","text":"Shape của X_seq_tfidf: (82404, 480)\nShape của X_tax_encoded: (82404, 1)\n","output_type":"stream"}],"execution_count":11},{"cell_type":"code","source":"from scipy.sparse import hstack, csr_matrix\n\nX_tax_sparse = csr_matrix(X_tax_encoded)\n\nX_features = hstack([X_seq_tfidf, X_tax_sparse])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:58:15.862306Z","iopub.execute_input":"2025-11-30T15:58:15.862748Z","iopub.status.idle":"2025-11-30T15:58:16.092331Z","shell.execute_reply.started":"2025-11-30T15:58:15.86272Z","shell.execute_reply":"2025-11-30T15:58:16.091655Z"}},"outputs":[],"execution_count":12},{"cell_type":"code","source":"# Chia train/val\nX_train, X_val, Y_train, Y_val = train_test_split(X_features, Y, test_size=0.1, random_state=42)\n\nclass ProteinDataset(Dataset):\n    def __init__(self, X, Y):\n        self.X = X.tocsr() if hasattr(X, \"tocsr\") else X\n        self.Y = torch.tensor(Y, dtype=torch.float32)\n\n    def __len__(self):\n        return self.Y.shape[0]\n\n    def __getitem__(self, idx):\n        x = torch.tensor(self.X[idx].toarray(), dtype=torch.float32).squeeze(0) if hasattr(self.X, \"tocsr\") else torch.tensor(self.X[idx], dtype=torch.float32)\n        y = self.Y[idx]\n        return x, y\n\nbatch_size = 32\ntrain_dataset = ProteinDataset(X_train, Y_train)\nval_dataset   = ProteinDataset(X_val, Y_val)\n\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_loader   = DataLoader(val_dataset, batch_size=batch_size)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:58:16.093142Z","iopub.execute_input":"2025-11-30T15:58:16.09341Z","iopub.status.idle":"2025-11-30T15:58:20.434966Z","shell.execute_reply.started":"2025-11-30T15:58:16.093382Z","shell.execute_reply":"2025-11-30T15:58:20.434296Z"}},"outputs":[],"execution_count":13},{"cell_type":"code","source":"class MLPClassifier(nn.Module):\n    def __init__(self, input_dim, hidden_dim, output_dim):\n        super().__init__()\n        self.model = nn.Sequential(\n            nn.Linear(input_dim, hidden_dim),\n            nn.ReLU(),\n            nn.Dropout(0.1),\n            nn.Linear(hidden_dim, hidden_dim),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(hidden_dim, output_dim),\n        )\n\n    def forward(self, x):\n        return self.model(x)\n\ninput_dim = X_features.shape[1]\nhidden_dim = 124\noutput_dim = Y.shape[1]\n\nmodel = MLPClassifier(input_dim, hidden_dim, output_dim)\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr = 1e-3)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:58:20.435731Z","iopub.execute_input":"2025-11-30T15:58:20.436435Z","iopub.status.idle":"2025-11-30T15:58:22.251817Z","shell.execute_reply.started":"2025-11-30T15:58:20.436403Z","shell.execute_reply":"2025-11-30T15:58:22.251199Z"}},"outputs":[],"execution_count":14},{"cell_type":"code","source":"from sklearn.metrics import f1_score, precision_score, recall_score\nimport torch\n\nepochs = 2\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nmodel.to(device)\n\nthreshold = 0.1\n\nfor epoch in range(epochs):\n    model.train()\n    train_loss = 0\n    for X_batch, Y_batch in train_loader:\n        X_batch, Y_batch = X_batch.to(device), Y_batch.to(device)\n        optimizer.zero_grad()\n        output = model(X_batch)\n        loss = criterion(output, Y_batch)\n        loss.backward()\n        optimizer.step()\n        train_loss += loss.item() * X_batch.size(0)\n    train_loss /= len(train_loader.dataset)\n\n    model.eval()\n    val_loss = 0\n    all_targets = []\n    all_preds = []\n    with torch.no_grad():\n        for X_batch, Y_batch in val_loader:\n            X_batch, Y_batch = X_batch.to(device), Y_batch.to(device)\n            outputs = model(X_batch)\n            loss = criterion(outputs, Y_batch)\n            val_loss += loss.item() * X_batch.size(0)\n            \n            preds = (torch.sigmoid(outputs) >= threshold).int()\n            all_preds.append(preds.cpu())\n            all_targets.append(Y_batch.cpu())\n    \n    val_loss /= len(val_loader.dataset)\n    \n    # nối tất cả batch lại\n    all_preds = torch.cat(all_preds, dim=0).numpy()\n    all_targets = torch.cat(all_targets, dim=0).numpy()\n    \n    # tính metric\n    f1_micro = f1_score(all_targets, all_preds, average='micro',  zero_division=0)\n    \n    print(f\"Epoch {epoch+1}/{epochs} - Train Loss: {train_loss:.4f} - Val Loss: {val_loss:.4f}\")\n    print(f\"Val F1 Micro: {f1_micro:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T15:58:22.252592Z","iopub.execute_input":"2025-11-30T15:58:22.252957Z","iopub.status.idle":"2025-11-30T16:00:44.714344Z","shell.execute_reply.started":"2025-11-30T15:58:22.252939Z","shell.execute_reply":"2025-11-30T16:00:44.713469Z"}},"outputs":[{"name":"stdout","text":"Epoch 1/2 - Train Loss: 0.0072 - Val Loss: 0.0018\nVal F1 Micro: 0.1641\nEpoch 2/2 - Train Loss: 0.0019 - Val Loss: 0.0018\nVal F1 Micro: 0.1682\n","output_type":"stream"}],"execution_count":15},{"cell_type":"code","source":"# Lấy dữ liệu test\nX_test_sequence = test_df[\"sequence\"].tolist()\nX_test_taxonomy = test_df[\"taxonomy_id\"].astype(int).tolist()\n\n# 1. k-mer TF-IDF (dùng vectorizer đã fit từ train)\nX_test_kmers = [\" \".join(get_kmer(seq, k=2)) for seq in X_test_sequence]\nX_test_seq_tfidf = vectorizer.transform(X_test_kmers)\n\n# 2. Encode taxonomy_id bằng log1p giống train\nX_test_taxonomy = np.array(X_test_taxonomy).astype(int)\nX_test_tax_encoded = np.log1p(X_test_taxonomy).reshape(-1, 1)\n\n# 3. Ghép features\nX_test_features = hstack([X_test_seq_tfidf, X_test_tax_encoded]).tocsr()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T16:00:44.715285Z","iopub.execute_input":"2025-11-30T16:00:44.715524Z","iopub.status.idle":"2025-11-30T16:01:46.304491Z","shell.execute_reply.started":"2025-11-30T16:00:44.715505Z","shell.execute_reply":"2025-11-30T16:01:46.303783Z"}},"outputs":[],"execution_count":16},{"cell_type":"code","source":"model.eval()\nbatch_size = 32\nall_scores = []\n\nwith torch.no_grad():\n    for i in range(0, X_test_features.shape[0], batch_size):\n        batch_sparse = X_test_features[i : i + batch_size]   # OK (CSR support)\n        \n        # Convert only THIS batch to dense\n        batch_dense = batch_sparse.toarray()\n\n        batch_tensor = torch.tensor(batch_dense,\n                                    dtype=torch.float32).to(device)\n\n        output = model(batch_tensor)\n        score = torch.sigmoid(output).cpu().numpy()\n        all_scores.append(score)\n\nall_scores = np.vstack(all_scores)\nprint(\"Inference done:\", all_scores.shape)\n\n\n# --- Tạo file submission ---\nsubmission = []\nterms = sorted(df_term[\"term\"].unique())\n\nfor i, protein_id in enumerate(test_df[\"protein_id\"]):\n    for j, term in enumerate(terms):\n        submission.append([protein_id, term, all_scores[i, j]])\n\nsubmission_df = pd.DataFrame(submission, columns=[\"EntryID\", \"GO term\", \"Score\"])\nsubmission_df.to_csv(\"submission.tsv\", sep=\"\\t\", index=False)\n\nprint(\"Done! File 'submission.tsv' đã tạo xong.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T16:01:46.30536Z","iopub.execute_input":"2025-11-30T16:01:46.305592Z","execution_failed":"2025-11-30T16:02:16.218Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}