{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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"},"colab":{"provenance":[{"file_id":"1URGWtlGrdpaRFi9m7Sky9ADXZdfHkiBh","timestamp":1764297238819}],"gpuType":"T4"},"accelerator":"GPU","widgets":{"application/vnd.jupyter.widget-state+json":{"eee963e53de546f5970307bdf6ca88d3":{"model_module":"@jupyter-widgets/controls","model_name":"VBoxModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"VBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"VBoxView","box_style":"","children":["IPY_MODEL_bdfb4c3886d44f3cbf4bc783b11360f6","IPY_MODEL_cd3c3654d0484c43bb8bad63f2d10a9e","IPY_MODEL_273835834af4428290a98ad682a8e996"],"layout":"IPY_MODEL_19d8b02ee1e841d3a2ba65e259b8b916"}},"d304ab6904bc4a83bb759e8fa85faa30":{"model_module":"@jupyter-widgets/controls","model_name":"HTMLModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_3391f990829d4fd9bb1be970d7a9f992","placeholder":"​","style":"IPY_MODEL_9876220000684d98bf49141c2dc05fc9","value":"<center> <img\nsrc=https://www.kaggle.com/static/images/site-logo.png\nalt='Kaggle'> <br> Create an API token from <a\nhref=\"https://www.kaggle.com/settings/account\" target=\"_blank\">your Kaggle\nsettings page</a> and paste it below along with your Kaggle username. <br> </center>"}},"6a897aa61c5248ce8655cecf1d038324":{"model_module":"@jupyter-widgets/controls","model_name":"TextModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"TextModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"TextView","continuous_update":true,"description":"Username:","description_tooltip":null,"disabled":false,"layout":"IPY_MODEL_754cebcd4d0d42edaf99d6c8546935e4","placeholder":"​","style":"IPY_MODEL_ea453c2d990d447583627fcdc6ee5901","value":"minhnv"}},"b4bdb0ceceb74d75ad895a47e9dbe514":{"model_module":"@jupyter-widgets/controls","model_name":"PasswordModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"PasswordModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"PasswordView","continuous_update":true,"description":"Token:","description_tooltip":null,"disabled":false,"layout":"IPY_MODEL_06376152d1de4b699ac0f5fd833ed4da","placeholder":"​","style":"IPY_MODEL_1058672674b740849b3eaf30e1e5bd98","value":""}},"d261ce42f3a546d9aad5d9613eea83a3":{"model_module":"@jupyter-widgets/controls","model_name":"ButtonModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ButtonModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ButtonView","button_style":"","description":"Login","disabled":false,"icon":"","layout":"IPY_MODEL_d049ed9b85c7475da4173902b38737c6","style":"IPY_MODEL_87765ac53b4e4e1f96575cccf0f1992c","tooltip":""}},"ff38edc803864c3391a330f638be2e41":{"model_module":"@jupyter-widgets/controls","model_name":"HTMLModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_22fa38aef8314df6ade1d05119ce2581","placeholder":"​","style":"IPY_MODEL_dee589a99b6d43a8ba3c3fa48ece2375","value":"\n<b>Thank You</b></center>"}},"19d8b02ee1e841d3a2ba65e259b8b916":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":"center","align_self":null,"border":null,"bottom":null,"display":"flex","flex":null,"flex_flow":"column","grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":"50%"}},"3391f990829d4fd9bb1be970d7a9f992":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"9876220000684d98bf49141c2dc05fc9":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"754cebcd4d0d42edaf99d6c8546935e4":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"ea453c2d990d447583627fcdc6ee5901":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"06376152d1de4b699ac0f5fd833ed4da":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"1058672674b740849b3eaf30e1e5bd98":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"d049ed9b85c7475da4173902b38737c6":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"87765ac53b4e4e1f96575cccf0f1992c":{"model_module":"@jupyter-widgets/controls","model_name":"ButtonStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ButtonStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","button_color":null,"font_weight":""}},"22fa38aef8314df6ade1d05119ce2581":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"dee589a99b6d43a8ba3c3fa48ece2375":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"f651e4093b07414286536faf3dd86062":{"model_module":"@jupyter-widgets/controls","model_name":"LabelModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"LabelModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"LabelView","description":"","description_tooltip":null,"layout":"IPY_MODEL_3e237845b86549d8a142e39b1102d7ca","placeholder":"​","style":"IPY_MODEL_c12200d78edd4ebda6683ec827ed953d","value":"Connecting..."}},"3e237845b86549d8a142e39b1102d7ca":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"c12200d78edd4ebda6683ec827ed953d":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"bdfb4c3886d44f3cbf4bc783b11360f6":{"model_module":"@jupyter-widgets/controls","model_name":"LabelModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"LabelModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"LabelView","description":"","description_tooltip":null,"layout":"IPY_MODEL_08b255405d0c4a9abe67e1e7a2bc7fc7","placeholder":"​","style":"IPY_MODEL_be0bf46075c048589fcf391ad1d18167","value":"401 Client Error."}},"cd3c3654d0484c43bb8bad63f2d10a9e":{"model_module":"@jupyter-widgets/controls","model_name":"LabelModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"LabelModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"LabelView","description":"","description_tooltip":null,"layout":"IPY_MODEL_9a4f81e955f342c5b64211edab88f97d","placeholder":"​","style":"IPY_MODEL_b4ff3ca9c0224638b45ce1efef31150d","value":"You don't have permission to access resource at URL: https://www.kaggle.com/api/v1/hello. The server reported the following issues: Unauthenticated"}},"273835834af4428290a98ad682a8e996":{"model_module":"@jupyter-widgets/controls","model_name":"LabelModel","model_module_version":"1.5.0","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"LabelModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"LabelView","description":"","description_tooltip":null,"layout":"IPY_MODEL_af0da47c81864260a8fb8d1b86cf53a3","placeholder":"​","style":"IPY_MODEL_83bc78a567c4472a8e42a715d2f714dc","value":"Please make sure you are authenticated if you are trying to access a private resource or a resource requiring consent."}},"08b255405d0c4a9abe67e1e7a2bc7fc7":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"be0bf46075c048589fcf391ad1d18167":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"9a4f81e955f342c5b64211edab88f97d":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"b4ff3ca9c0224638b45ce1efef31150d":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}},"af0da47c81864260a8fb8d1b86cf53a3":{"model_module":"@jupyter-widgets/base","model_name":"LayoutModel","model_module_version":"1.2.0","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"83bc78a567c4472a8e42a715d2f714dc":{"model_module":"@jupyter-widgets/controls","model_name":"DescriptionStyleModel","model_module_version":"1.5.0","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}}}},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":116062,"databundleVersionId":14875579,"sourceType":"competition"},{"sourceId":13905557,"sourceType":"datasetVersion","datasetId":8859656},{"sourceId":14148019,"sourceType":"datasetVersion","datasetId":9016779}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q biopython","metadata":{"id":"4jPWLC0MBe8Y","executionInfo":{"status":"ok","timestamp":1764317766947,"user_tz":-420,"elapsed":13293,"user":{"displayName":"minh Nguyen","userId":"14294519645000511864"}},"outputId":"da5205be-6f2b-4c87-b9a0-0ac37eb56fac","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:42:44.890525Z","iopub.execute_input":"2025-12-14T04:42:44.891614Z","iopub.status.idle":"2025-12-14T04:42:50.230262Z","shell.execute_reply.started":"2025-12-14T04:42:44.891594Z","shell.execute_reply":"2025-12-14T04:42:50.228739Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout\nfrom tensorflow.keras.optimizers import Adam\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom collections import Counter\n\nfrom Bio import SeqIO","metadata":{"id":"34bbcd40","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:42:50.232256Z","iopub.execute_input":"2025-12-14T04:42:50.232875Z","iopub.status.idle":"2025-12-14T04:43:05.188284Z","shell.execute_reply.started":"2025-12-14T04:42:50.23284Z","shell.execute_reply":"2025-12-14T04:43:05.187707Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Read files and extract training information (ProteinID, Sequence) - (Terms)\n\n## 1. Filter outlier sequence length\n\n## 2. Filter out low-frequency terms","metadata":{"id":"yPgjd3e1cOF7"}},{"cell_type":"code","source":"def create_seq_df(data_folder: str, mode: str = \"Train\", seq_type: str = \"list\"):\n    \"\"\"\n    Load sequences. Mode can be 'Train' or 'Test'.\n    Assumes structure:\n       - data_folder/Train/train_sequences.fasta\n       - data_folder/Test/testsuperset.fasta\n    \"\"\"\n    filename = 'train_sequences.fasta' if mode == 'Train' else 'testsuperset.fasta'\n    path = f'{data_folder}/{mode}/{filename}'\n\n    print(f\"--- Reading {path} ---\")\n    try:\n        records = list(SeqIO.parse(path, format='fasta'))\n        seq_df = pd.DataFrame([\n            {\"ID\": rec.id.split(\"|\")[1] if \"|\" in rec.id else rec.id,\n             \"Sequence\": list(rec.seq) if seq_type==\"list\" else str(rec.seq)}\n            for rec in records\n        ])\n        print(f\"Loaded {mode} sequences: {len(seq_df)}\")\n        return seq_df\n    except FileNotFoundError:\n        print(f\"Error: File not found at {path}\")\n        return pd.DataFrame()\n\ndef create_term_df(data_folder):\n    term_path = f'{data_folder}/Train/train_terms.tsv'\n    print(f'--- Reading {term_path} ---')\n    train_term_df = pd.read_csv(term_path, sep='\\t')\n    train_term = train_term_df.groupby(\"EntryID\", as_index=False)['term'].apply(list)\n    print(f\"Loaded Term labels for {len(train_term)} proteins\")\n    return train_term\n\ndef create_train_df(seq_df: pd.DataFrame, term_df: pd.DataFrame):\n    # Using INNER join to automatically remove IDs that don't exist in both clean sets\n    train_df = seq_df.merge(term_df, how=\"inner\", left_on=\"ID\", right_on=\"EntryID\")\n    train_df = train_df.drop(columns=[\"EntryID\"])\n    print(f\"Final Merged Training Size: {len(train_df)}\")\n    return train_df\n\n# --- 2. FILTERING LOGIC ---\n\ndef remove_seq_outliers(seq_df: pd.DataFrame, prob_keep: int = 99, plot: bool = False):\n    seq_lengths = seq_df[\"Sequence\"].apply(len)\n    cutoff = np.percentile(seq_lengths, prob_keep)\n\n    print(f\"[Filter Seq] Cutoff length (Top {prob_keep}%): {cutoff:.2f}\")\n\n    filtered_df = seq_df[seq_lengths < cutoff].copy()\n\n    if plot:\n        plt.figure(figsize=(6, 4))\n        sns.histplot(filtered_df[\"Sequence\"].apply(len), bins=50)\n        plt.title(f\"Sequence Lengths (< {cutoff:.0f})\")\n        plt.show()\n\n    print(f\"[Filter Seq] Dropped {len(seq_df) - len(filtered_df)} sequences.\")\n    return filtered_df, cutoff\n\ndef remove_term_by_freq(term_df: pd.DataFrame, freq_threshold: int = 10):\n    allterms = [t for sub_term in term_df[\"term\"] for t in sub_term]\n    cnt = Counter(allterms)\n    valid_terms = set([t for t, count in cnt.items() if count > freq_threshold])\n\n    print(f\"[Filter Term] Keeping terms with freq > {freq_threshold}. Valid terms: {len(valid_terms)}/{len(cnt)}\")\n\n    # Filter terms in each row\n    term_df[\"term\"] = term_df[\"term\"].apply(lambda x: [t for t in x if t in valid_terms])\n\n    # Remove rows that became empty\n    filtered_term = term_df[term_df['term'].map(len) > 0].copy()\n\n    print(f\"[Filter Term] Dropped {len(term_df) - len(filtered_term)} proteins (became empty labels).\")\n    return filtered_term","metadata":{"id":"KsFgFAq6E89t","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:43:05.189627Z","iopub.execute_input":"2025-12-14T04:43:05.190001Z","iopub.status.idle":"2025-12-14T04:43:05.200196Z","shell.execute_reply.started":"2025-12-14T04:43:05.189984Z","shell.execute_reply":"2025-12-14T04:43:05.199382Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Function for train-test preparation","metadata":{"id":"VYkj36LsOPK-"}},{"cell_type":"code","source":"def prepare_train_dataset(data_folder: str, seq_prob: int = 99, term_threshold: int = 10):\n    \"\"\"\n    1. Load Seq & Term\n    2. Filter Seq Outliers (Length)\n    3. Filter Term Outliers (Rare frequency)\n    4. Merge -> (ID, Sequence, ListOfTerms)\n    Returns: DataFrame, max_seq_len (to use for test set)\n    \"\"\"\n    print(\"\\n=== PREPARING TRAIN DATASET ===\")\n    # 1. Load\n    seq_df = create_seq_df(data_folder, mode=\"Train\")\n    term_df = create_term_df(data_folder)\n\n    # 2. Filter Seq\n    seq_clean, max_len_cutoff = remove_seq_outliers(seq_df, prob_keep=seq_prob, plot=True)\n\n    # 3. Filter Term\n    term_clean = remove_term_by_freq(term_df, freq_threshold=term_threshold)\n\n    # 4. Merge\n    train_df = create_train_df(seq_clean, term_clean)\n\n    return train_df, max_len_cutoff\n\ndef prepare_test_dataset(data_folder: str):\n    \"\"\"\n    1. Load Test Seq\n    \"\"\"\n    print(\"\\n=== PREPARING TEST DATASET ===\")\n    # 1. Load\n    test_df = create_seq_df(data_folder, mode=\"Test\")\n\n    print(f\"Final Test Size: {len(test_df)}\")\n\n    return test_df","metadata":{"id":"WKKsj65IFAkd","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:43:05.206192Z","iopub.execute_input":"2025-12-14T04:43:05.206464Z","iopub.status.idle":"2025-12-14T04:43:05.239615Z","shell.execute_reply.started":"2025-12-14T04:43:05.206439Z","shell.execute_reply":"2025-12-14T04:43:05.23873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_path = \"/kaggle/input/cafa-6-protein-function-prediction\"\n\ntrain_df, cutoff_len = prepare_train_dataset(data_path, seq_prob=99, term_threshold=10)\n\n# 2. Tạo tập Test (áp dụng ngưỡng độ dài từ tập train)\ntest_df = prepare_test_dataset(data_path)\n\nprint(train_df.head(3))\nprint(\"\\n\"*2)\nprint(test_df.head(3))","metadata":{"id":"7HStsS08OlX0","executionInfo":{"status":"ok","timestamp":1764302417760,"user_tz":-420,"elapsed":6097,"user":{"displayName":"minh Nguyen","userId":"14294519645000511864"}},"outputId":"7b2ddd8a-e25b-4deb-c0da-dd27397b3e2f","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:51:42.485763Z","iopub.execute_input":"2025-12-14T04:51:42.48649Z","iopub.status.idle":"2025-12-14T04:51:54.947185Z","shell.execute_reply.started":"2025-12-14T04:51:42.486464Z","shell.execute_reply":"2025-12-14T04:51:54.946402Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Embedding T5","metadata":{}},{"cell_type":"code","source":"path = '/kaggle/input/cafa6-esm2-embedding-dataset/test_ids.npy'\ndata = np.load(path, allow_pickle=True)\n\nprint(\"Number of embedded protein:\", data.shape)","metadata":{"id":"uRfvucCzSZRt","executionInfo":{"status":"ok","timestamp":1764299561340,"user_tz":-420,"elapsed":29,"user":{"displayName":"minh Nguyen","userId":"14294519645000511864"}},"outputId":"001722d7-f387-47cf-d7bf-656954ed3ec1","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:57:50.055587Z","iopub.execute_input":"2025-12-14T04:57:50.055872Z","iopub.status.idle":"2025-12-14T04:57:50.09376Z","shell.execute_reply.started":"2025-12-14T04:57:50.05585Z","shell.execute_reply":"2025-12-14T04:57:50.092809Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_embedding_dict():\n    \"\"\"\n    Load .npz file and return a dictionary {ID: Embedding_Vector}\n    \"\"\"\n    print(f\"Loading embeddings\")\n    ids = np.load(\"/kaggle/input/cafa6-esm2-embedding-dataset/test_ids.npy\", allow_pickle=True)\n    embs = np.load(\"/kaggle/input/cafa6-esm2-embedding-dataset/test_embeddings.npy\")\n\n    print(f\"IDs key: - Count: {ids.shape}\")\n    print(f\"Embeddings key: - Shape: {embs.shape}\")\n\n    # Mapping IDs(str) -> Embedded sequence(list)\n    embedding_map = dict(zip(ids, embs))\n\n    return embedding_map\n\ndef add_embedding_to_df(df: pd.DataFrame, embedding_map: dict):\n    \"\"\"\n    Thêm cột 'Embedding' vào DataFrame dựa trên cột 'ID'\n    \"\"\"\n    print(\"Mapping embeddings to DataFrame...\")\n\n    # Map ID - Embedding\n    df['Embedding'] = df['ID'].map(embedding_map)\n\n    # Check nan value\n    missing_count = df['Embedding'].isna().sum()\n    if missing_count > 0:\n        print(f\"WARNING: {missing_count} proteins do NOT have embeddings!\")\n        # Drop NaN rows\n        df = df.dropna(subset=['Embedding'])\n        print(f\"Removed missing rows. New size: {len(df)}\")\n\n    return df","metadata":{"id":"XLY17cG3Tzgm","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:58:04.602132Z","iopub.execute_input":"2025-12-14T04:58:04.602853Z","iopub.status.idle":"2025-12-14T04:58:04.608303Z","shell.execute_reply.started":"2025-12-14T04:58:04.602826Z","shell.execute_reply":"2025-12-14T04:58:04.607736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load Embeddings\nemb_map = load_embedding_dict()\n\n# Merge vào DataFrame\ntrain_df_with_emb = add_embedding_to_df(train_df, emb_map)\n\ntrain_df_with_emb.head(3)","metadata":{"id":"zi-K3VayhS3Z","executionInfo":{"status":"ok","timestamp":1764302454990,"user_tz":-420,"elapsed":2173,"user":{"displayName":"minh Nguyen","userId":"14294519645000511864"}},"outputId":"040ef203-ceea-49b1-ffb6-04ca932f3e67","trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:58:06.505326Z","iopub.execute_input":"2025-12-14T04:58:06.506041Z","iopub.status.idle":"2025-12-14T04:58:13.546359Z","shell.execute_reply.started":"2025-12-14T04:58:06.506013Z","shell.execute_reply":"2025-12-14T04:58:13.545619Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Prepare training","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import MultiLabelBinarizer\nimport pickle\n\n# Label\nvalid_label = set()\nfor subl in train_df.term:\n  valid_label.update([label for label in subl])\nvalid_label = sorted(list(valid_label))\n\nprint(\"Number of valid class:\", len(valid_label))\n\ndef create_label(valid_label: list, train_df: pd.DataFrame):\n  mlb = MultiLabelBinarizer()\n  label = mlb.fit_transform(train_df[\"term\"])\n\n  with open(\"mlb.pkl\", 'wb') as f:\n        pickle.dump(mlb, f)\n  print(f\"Saved Label Binarizer to mlb.pkl\")\n  return label\n\ny_train = create_label(valid_label, train_df_with_emb)\nprint(\"Label shape:\", y_train.shape)\ny_train[:3]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:51:54.948255Z","iopub.execute_input":"2025-12-14T04:51:54.948498Z","iopub.status.idle":"2025-12-14T04:51:55.811379Z","shell.execute_reply.started":"2025-12-14T04:51:54.948481Z","shell.execute_reply":"2025-12-14T04:51:55.810674Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train = train_df_with_emb[\"Embedding\"]\nX_train = np.stack(x_train)\n\nprint(\"Input shape:\", X_train.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:47:27.711775Z","iopub.execute_input":"2025-12-14T04:47:27.712298Z","iopub.status.idle":"2025-12-14T04:47:27.882629Z","shell.execute_reply.started":"2025-12-14T04:47:27.712276Z","shell.execute_reply":"2025-12-14T04:47:27.881861Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\n\nclass ProteinClassifier(nn.Module):\n    def __init__(self, input_dim=1024, num_classes=7256, dropout_rate=0.3):\n        super(ProteinClassifier, self).__init__()\n\n        self.network = nn.Sequential(\n            # Layer 1: Nén nhẹ thông tin\n            nn.Linear(input_dim, 512),\n            nn.BatchNorm1d(512),      # Giúp hội tụ nhanh hơn\n            nn.ReLU(),\n            nn.Dropout(dropout_rate), # Chống học vẹt (Overfitting)\n\n            # Layer 2: Trích xuất đặc trưng cấp cao\n            nn.Linear(512, 256),\n            nn.BatchNorm1d(256),\n            nn.ReLU(),\n            nn.Dropout(dropout_rate),\n\n            # Output Layer: Trả về Logits (chưa qua Sigmoid)\n            nn.Linear(256, num_classes)\n        )\n\n    def forward(self, x):\n        return self.network(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:48:06.112319Z","iopub.execute_input":"2025-12-14T04:48:06.113031Z","iopub.status.idle":"2025-12-14T04:48:08.887892Z","shell.execute_reply.started":"2025-12-14T04:48:06.113006Z","shell.execute_reply":"2025-12-14T04:48:08.887324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class GO_Dataset(Dataset):\n    def __init__(self, embeddings, labels):\n        # embeddings: numpy array (N, 1024)\n        # labels: binary matrix (N, num_classes)\n        self.X = torch.tensor(embeddings, dtype=torch.float32)\n        self.y = torch.tensor(labels, dtype=torch.float32)\n\n    def __len__(self):\n        return len(self.X)\n\n    def __getitem__(self, idx):\n        return self.X[idx], self.y[idx]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:48:13.589785Z","iopub.execute_input":"2025-12-14T04:48:13.590326Z","iopub.status.idle":"2025-12-14T04:48:13.594694Z","shell.execute_reply.started":"2025-12-14T04:48:13.590301Z","shell.execute_reply":"2025-12-14T04:48:13.59398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_classes = y_train.shape[1]\ndevice = torch.device(\"cuda\")\n\n# Hyperparam and loss func\nmodel = ProteinClassifier(input_dim=1024, num_classes=num_classes).to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-3)\ncriterion = nn.BCEWithLogitsLoss()\n\n# Dataloader\ntrain_dataset = GO_Dataset(X_train, y_train)\ntrain_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)\n\n# Training\nnum_epochs = 20\nprint(\"Start Training...\")\n\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n\n    for inputs, labels in train_loader:\n        inputs, labels = inputs.to(device), labels.to(device)\n\n        # Zero gradients\n        optimizer.zero_grad()\n\n        # Forward\n        outputs = model(inputs) # Outputs là logits\n\n        # Calculate Loss\n        loss = criterion(outputs, labels)\n\n        # Backward\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n\n    print(f\"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:48:40.324015Z","iopub.execute_input":"2025-12-14T04:48:40.324595Z","iopub.status.idle":"2025-12-14T04:50:20.474652Z","shell.execute_reply.started":"2025-12-14T04:48:40.324567Z","shell.execute_reply":"2025-12-14T04:50:20.473399Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def save_artifacts(model, model_path=\"cafa_model.pth\"):\n    torch.save(model.state_dict(), model_path)\n    print(f\"Saved model weights to {model_path}\")\n\nsave_artifacts(model)\n\nimport gc\n\n# RAM free\ndel x_train, y_train, train_df, data\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:50:20.476146Z","iopub.execute_input":"2025-12-14T04:50:20.476693Z","iopub.status.idle":"2025-12-14T04:50:21.479548Z","shell.execute_reply.started":"2025-12-14T04:50:20.476674Z","shell.execute_reply":"2025-12-14T04:50:21.47895Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"# Load Embeddings (if need)\nemb_map = load_embedding_dict()\n\n# Merge vào DataFrame\ntest_df_with_emb = add_embedding_to_df(test_df, emb_map)\n\ntest_df_with_emb.head(3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:50:21.48024Z","iopub.execute_input":"2025-12-14T04:50:21.480491Z","iopub.status.idle":"2025-12-14T04:50:22.00201Z","shell.execute_reply.started":"2025-12-14T04:50:21.480474Z","shell.execute_reply":"2025-12-14T04:50:22.001237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import TensorDataset\n\nwith open(\"mlb.pkl\", 'rb') as f:\n    mlb = pickle.load(f)\ntarget_terms = mlb.classes_\n\ntest_ids = test_df_with_emb[\"ID\"].values\nX_test = np.stack(test_df_with_emb[\"Embedding\"])\n\ntest_tensor = torch.tensor(X_test, dtype=torch.float32)\ntest_dataset = TensorDataset(test_tensor)\ntest_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:52:11.157872Z","iopub.execute_input":"2025-12-14T04:52:11.158394Z","iopub.status.idle":"2025-12-14T04:52:12.05396Z","shell.execute_reply.started":"2025-12-14T04:52:11.158369Z","shell.execute_reply":"2025-12-14T04:52:12.053035Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import csv\nfrom tqdm import tqdm\n\n\nTHRESHOLD = 0.01\noutput_file = 'submission.tsv'\n\ndevice = torch.device(\"cuda\")\nnum_classes = len(target_terms)\nmodel = ProteinClassifier(input_dim=1024, num_classes=num_classes).to(device)\nmodel.state_dict(torch.load(\"cafa_model.pth\"))\nmodel.to(device)\nmodel.eval()\n\n\nprint(f\"Writing to {output_file}...\")\n\nwith open(output_file, 'w', newline='') as f:\n    writer = csv.writer(f, delimiter='\\t')\n\n    current_idx = 0\n\n    with torch.no_grad():\n        for inputs in tqdm(test_loader):\n            # 1. Đưa lên GPU & Dự đoán\n            # inputs từ TensorDataset là 1 tuple (data,), nên cần inputs[0]\n            if isinstance(inputs, list) or isinstance(inputs, tuple):\n                inputs = inputs[0]\n\n            inputs = inputs.to(device)\n            logits = model(inputs)\n            probs = torch.sigmoid(logits) # (Batch_size, 7256)\n\n            # 2. Lọc ngay trên GPU (Đây là bước tiết kiệm RAM nhất)\n            # Tìm các vị trí có xác suất > threshold\n            # rows: chỉ số dòng (tương ứng protein nào trong batch)\n            # cols: chỉ số cột (tương ứng GO term nào)\n            rows, cols = torch.where(probs > THRESHOLD)\n\n            # Lấy giá trị score tương ứng\n            scores = probs[rows, cols]\n\n            # 3. Chuyển dữ liệu đã lọc (Rất nhẹ) về CPU\n            rows = rows.cpu().numpy()\n            cols = cols.cpu().numpy()\n            scores = scores.cpu().numpy()\n\n            # 4. Ánh xạ về ID thực và Term thực\n            # Lấy ID thực tế từ mảng test_ids gốc\n            # rows đang là index tương đối trong batch (0->63), cần cộng current_idx\n            batch_real_ids = test_ids[current_idx + rows]\n            batch_real_terms = target_terms[cols]\n\n            # 5. Ghi vào file\n            # Zip lại thành từng dòng: (ID, Term, Score)\n            rows_to_write = zip(batch_real_ids, batch_real_terms, scores)\n            writer.writerows(rows_to_write)\n\n            # Cập nhật vị trí index cho batch sau\n            current_idx += inputs.size(0)\n\nprint(\"File submission created!.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-14T04:52:44.781274Z","iopub.execute_input":"2025-12-14T04:52:44.781577Z","iopub.status.idle":"2025-12-14T04:54:53.397849Z","shell.execute_reply.started":"2025-12-14T04:52:44.781555Z","shell.execute_reply":"2025-12-14T04:54:53.39691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}