{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.12"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"databundleVersionId":46665,"sourceId":4117,"sourceType":"competition"},{"databundleVersionId":16542367,"datasetId":9984766,"sourceId":15608790,"sourceType":"datasetVersion"}],"dockerImageVersionId":31329,"isGpuEnabled":true,"isInternetEnabled":true,"language":"python","sourceType":"notebook"},"papermill":{"default_parameters":{},"duration":10185.510896,"end_time":"2026-04-11T14:16:16.210742+00:00","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2026-04-11T11:26:30.699846+00:00","version":"2.7.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"1ce4e861e70a4c27a5428427ac0b596e":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_570d4d0a5b7c470db6791fb03e818f15","IPY_MODEL_a7ee64605e1745f29c0a1af682dff1ef","IPY_MODEL_432690f801f04aa2be23ff60325446c1"],"layout":"IPY_MODEL_a72db273c8894a8e9f6be434db9eaf1b","tabbable":null,"tooltip":null}},"3fc5a242a70844abbc271c0da57e6892":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"432690f801f04aa2be23ff60325446c1":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_3fc5a242a70844abbc271c0da57e6892","placeholder":"​","style":"IPY_MODEL_bc389604122d4318a1639bb9582a9aca","tabbable":null,"tooltip":null,"value":" 46.8M/46.8M [00:00&lt;00:00, 35.9MB/s]"}},"4d8e0b35bb444a65b679bad332b28d19":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"4f5d12a0844d4a479f0481a2af5fc86a":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"570d4d0a5b7c470db6791fb03e818f15":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_beaedea873df42cbbb45b96d7f6a38c1","placeholder":"​","style":"IPY_MODEL_7d9b997b5721455b9eedad1e72d0165d","tabbable":null,"tooltip":null,"value":"model.safetensors: 100%"}},"644816c789294860875e3b958e562d66":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_d9513c79043e4a99bb8cfa1c40e1d71a","placeholder":"​","style":"IPY_MODEL_8dc4ee3abc8f45ecaa8883d3d91af92d","tabbable":null,"tooltip":null,"value":"model.safetensors: 100%"}},"696e22f2a21c4e1389545dbbb5fde5e6":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"6a4c72c706da4c7488af4aae5a6369a7":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_c2432d29a575454c959320ee00a0f2ba","max":114918618,"min":0,"orientation":"horizontal","style":"IPY_MODEL_c485f66f6c4148dd9ed9b1d1dd8063be","tabbable":null,"tooltip":null,"value":114918618}},"7d9b997b5721455b9eedad1e72d0165d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"7ee932a38be4400eb48a1e7aa07f8d53":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_644816c789294860875e3b958e562d66","IPY_MODEL_6a4c72c706da4c7488af4aae5a6369a7","IPY_MODEL_94b3ac7465264391aa0cc6c0a891fae9"],"layout":"IPY_MODEL_952e29fb6c614dd180ba8481f5693405","tabbable":null,"tooltip":null}},"8dc4ee3abc8f45ecaa8883d3d91af92d":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"94b3ac7465264391aa0cc6c0a891fae9":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"HTMLView","description":"","description_allow_html":false,"layout":"IPY_MODEL_4f5d12a0844d4a479f0481a2af5fc86a","placeholder":"​","style":"IPY_MODEL_696e22f2a21c4e1389545dbbb5fde5e6","tabbable":null,"tooltip":null,"value":" 115M/115M [00:02&lt;00:00, 84.5MB/s]"}},"952e29fb6c614dd180ba8481f5693405":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"a72db273c8894a8e9f6be434db9eaf1b":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"a7ee64605e1745f29c0a1af682dff1ef":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"FloatProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"FloatProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"2.0.0","_view_name":"ProgressView","bar_style":"success","description":"","description_allow_html":false,"layout":"IPY_MODEL_f9fb037e150d46f0b6e684c593254fa4","max":46807446,"min":0,"orientation":"horizontal","style":"IPY_MODEL_4d8e0b35bb444a65b679bad332b28d19","tabbable":null,"tooltip":null,"value":46807446}},"bc389604122d4318a1639bb9582a9aca":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"HTMLStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"HTMLStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","background":null,"description_width":"","font_size":null,"text_color":null}},"beaedea873df42cbbb45b96d7f6a38c1":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"c2432d29a575454c959320ee00a0f2ba":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"c485f66f6c4148dd9ed9b1d1dd8063be":{"model_module":"@jupyter-widgets/controls","model_module_version":"2.0.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"2.0.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"StyleView","bar_color":null,"description_width":""}},"d9513c79043e4a99bb8cfa1c40e1d71a":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"f9fb037e150d46f0b6e684c593254fa4":{"model_module":"@jupyter-widgets/base","model_module_version":"2.0.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"2.0.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"2.0.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border_bottom":null,"border_left":null,"border_right":null,"border_top":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,"padding":null,"right":null,"top":null,"visibility":null,"width":null}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"c624d3d3","cell_type":"code","source":"from huggingface_hub import login\n\n# Đăng nhập trực tiếp bằng API\nlogin(token=\"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\")\nprint(\"Đã nạp Token Hugging Face thành công!\")","metadata":{"execution":{"iopub.execute_input":"2026-04-11T11:26:32.987897Z","iopub.status.busy":"2026-04-11T11:26:32.987641Z","iopub.status.idle":"2026-04-11T11:26:33.961587Z","shell.execute_reply":"2026-04-11T11:26:33.960779Z"},"papermill":{"duration":0.978531,"end_time":"2026-04-11T11:26:33.963127+00:00","exception":false,"start_time":"2026-04-11T11:26:32.984596+00:00","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"f878d779","cell_type":"code","source":"import gc\nimport numpy as np\nimport pandas as pd\nimport copy\nimport torch\nimport torch.nn as nn\nimport timm\nimport os\nfrom PIL import Image\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import StratifiedKFold\nfrom tqdm.notebook import tqdm","metadata":{"execution":{"iopub.execute_input":"2026-04-11T11:26:33.967493Z","iopub.status.busy":"2026-04-11T11:26:33.967218Z","iopub.status.idle":"2026-04-11T11:26:48.15284Z","shell.execute_reply":"2026-04-11T11:26:48.152178Z"},"papermill":{"duration":14.189778,"end_time":"2026-04-11T11:26:48.15464+00:00","exception":false,"start_time":"2026-04-11T11:26:33.964862+00:00","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"bbf7d09d","cell_type":"code","source":"# ==========================================\n# 1. CẤU HÌNH & HYPERPARAMETERS\n# ==========================================\nDATA_DIR = '/kaggle/input/competitions/malware-classification'\nLABELS_CSV = os.path.join(DATA_DIR, 'trainLabels.csv')\nSAMPLE_SUB_CSV = os.path.join(DATA_DIR, 'sampleSubmission.csv')\n\n# THAY BẰNG ĐƯỜNG DẪN DATASET ẢNH CỦA BẠN\nTRAIN_BYTES_DIR = '/kaggle/input/datasets/trankimhuu/images-2-datasets-of-big2015/train/train/train_images_bytes' \nTRAIN_ASM_DIR = '/kaggle/input/datasets/trankimhuu/images-2-datasets-of-big2015/train/train/train_images_asm'\nTEST_BYTES_DIR = '/kaggle/input/datasets/trankimhuu/images-2-datasets-of-big2015/test/test/test_images_bytes'\nTEST_ASM_DIR = '/kaggle/input/datasets/trankimhuu/images-2-datasets-of-big2015/test/test/test_images_asm'\n\nOUT_DIR = '/kaggle/working/processed_dl_features/'\nos.makedirs(OUT_DIR, exist_ok=True)\n\nBATCH_SIZE = 32\nEPOCHS_PHASE_1 = 3   # 3 Epochs đầu chỉ train Feature Extractor và Head\nEPOCHS_PHASE_2 = 7  # 12 Epochs sau Fine-tune toàn mạng\nTOTAL_EPOCHS = EPOCHS_PHASE_1 + EPOCHS_PHASE_2\nNFOLDS = 5\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.execute_input":"2026-04-11T11:26:48.159345Z","iopub.status.busy":"2026-04-11T11:26:48.158925Z","iopub.status.idle":"2026-04-11T11:26:48.408697Z","shell.execute_reply":"2026-04-11T11:26:48.407939Z"},"papermill":{"duration":0.253786,"end_time":"2026-04-11T11:26:48.4102+00:00","exception":false,"start_time":"2026-04-11T11:26:48.156414+00:00","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"41ef69b5","cell_type":"code","source":"# ==========================================\n# 2. DATASET & TRANSFORM\n# ==========================================\ntransform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nclass DualBranchDataset(Dataset):\n    def __init__(self, df, bytes_dir, asm_dir, transform=None, is_test=False):\n        self.df = df\n        self.bytes_dir, self.asm_dir = bytes_dir, asm_dir\n        self.transform = transform\n        self.is_test = is_test\n\n    def __len__(self): return len(self.df)\n\n    def __getitem__(self, idx):\n        img_id = str(self.df.iloc[idx]['Id'])\n        try: img_bytes = Image.open(os.path.join(self.bytes_dir, f\"{img_id}.png\")).convert('RGB')\n        except: img_bytes = Image.new('RGB', (256, 256), color='black')\n            \n        try: img_asm = Image.open(os.path.join(self.asm_dir, f\"{img_id}.png\")).convert('RGB')\n        except: img_asm = Image.new('RGB', (256, 256), color='black')\n            \n        if self.transform:\n            img_bytes, img_asm = self.transform(img_bytes), self.transform(img_asm)\n            \n        if self.is_test: return img_bytes, img_asm\n        return img_bytes, img_asm, int(self.df.iloc[idx]['Class']) - 1","metadata":{"execution":{"iopub.execute_input":"2026-04-11T11:26:48.414962Z","iopub.status.busy":"2026-04-11T11:26:48.414458Z","iopub.status.idle":"2026-04-11T11:26:48.421726Z","shell.execute_reply":"2026-04-11T11:26:48.421049Z"},"papermill":{"duration":0.011149,"end_time":"2026-04-11T11:26:48.423145+00:00","exception":false,"start_time":"2026-04-11T11:26:48.411996+00:00","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"2564e054","cell_type":"code","source":"# ==========================================\n# 3. KIẾN TRÚC MODEL (HỖ TRỢ FEATURE EXTRACTION)\n# ==========================================\nclass DualBranchMalwareNet(nn.Module):\n    def __init__(self, num_classes=9):\n        super().__init__()\n        self.branch_bytes = timm.create_model('swinv2_tiny_window8_256', pretrained=True, num_classes=0)\n        self.branch_asm = timm.create_model('resnet18', pretrained=True, num_classes=0)\n        \n        self.feature_extractor = nn.Sequential(\n            nn.Dropout(p=0.4),\n            nn.Linear(self.branch_bytes.num_features + self.branch_asm.num_features, 512),\n            nn.BatchNorm1d(512),\n            nn.ReLU(),\n            nn.Dropout(p=0.4)\n        )\n        self.final_head = nn.Linear(512, num_classes)\n\n    def forward(self, img_bytes, img_asm, return_features=False):\n        combined = torch.cat((self.branch_bytes(img_bytes), self.branch_asm(img_asm)), dim=1)\n        deep_features = self.feature_extractor(combined)\n        out = self.final_head(deep_features)\n        return deep_features if return_features else out","metadata":{"execution":{"iopub.execute_input":"2026-04-11T11:26:48.427256Z","iopub.status.busy":"2026-04-11T11:26:48.427006Z","iopub.status.idle":"2026-04-11T11:26:48.432462Z","shell.execute_reply":"2026-04-11T11:26:48.431782Z"},"papermill":{"duration":0.009193,"end_time":"2026-04-11T11:26:48.433914+00:00","exception":false,"start_time":"2026-04-11T11:26:48.424721+00:00","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"f9a0dd70","cell_type":"code","source":"# ==========================================\n# 4. K-FOLD HUẤN LUYỆN & TRÍCH XUẤT OOF\n# ==========================================\nimport copy\n\ndf_train = pd.read_csv(LABELS_CSV)\ndf_test = pd.read_csv(SAMPLE_SUB_CSV)\n\nX_train_deep_oof = np.zeros((len(df_train), 512))\nX_test_deep_folds = np.zeros((NFOLDS, len(df_test), 512))\n\nskf = StratifiedKFold(n_splits=NFOLDS, shuffle=True, random_state=42)\ntest_loader = DataLoader(DualBranchDataset(df_test, TEST_BYTES_DIR, TEST_ASM_DIR, transform, is_test=True), batch_size=BATCH_SIZE, shuffle=False, num_workers=2)\n\ndef extract_features(model, loader):\n    model.eval()\n    feats = []\n    with torch.no_grad():\n        for batch in loader:\n            img_b, img_a = batch[0].to(DEVICE), batch[1].to(DEVICE)\n            feats.append(model(img_b, img_a, return_features=True).cpu().numpy())\n    return np.vstack(feats)\n\nprint(\"BẮT ĐẦU CHẠY K-FOLD DEEP LEARNING (OOF EXTRACTION)\")\nprint(\"➔ Đang tải Pre-trained weights 1 lần duy nhất...\")\nbase_model = DualBranchMalwareNet().to(DEVICE)\ninitial_weights = copy.deepcopy(base_model.state_dict())\nprint(\"➔ Tải Model thành công! Bắt đầu vào Folds.\\n\")\n\nfor fold, (train_idx, val_idx) in enumerate(skf.split(df_train, df_train['Class'])):\n    print(f\"\\n{'='*30} FOLD {fold + 1}/{NFOLDS} {'='*30}\")\n    \n    train_loader = DataLoader(DualBranchDataset(df_train.iloc[train_idx], TRAIN_BYTES_DIR, TRAIN_ASM_DIR, transform), batch_size=BATCH_SIZE, shuffle=True, num_workers=2)\n    # Shuffle BẮT BUỘC = False cho Validation để trích xuất đúng Index\n    val_loader = DataLoader(DualBranchDataset(df_train.iloc[val_idx], TRAIN_BYTES_DIR, TRAIN_ASM_DIR, transform), batch_size=BATCH_SIZE, shuffle=False, num_workers=2)\n    \n    # Khởi tạo model và nạp lại trọng số gốc từ RAM\n    model = DualBranchMalwareNet().to(DEVICE)\n    model.load_state_dict(copy.deepcopy(initial_weights))\n    optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=1e-2)\n    criterion = nn.CrossEntropyLoss()\n    \n    for epoch in range(TOTAL_EPOCHS):\n        \n        # [PHASE 1] ĐÓNG BĂNG BACKBONE\n        if epoch == 0:\n            print(f\"\\n[PHASE 1] FREEZE BACKBONE (Epoch 1 - {EPOCHS_PHASE_1})\")\n            for param in model.branch_bytes.parameters(): param.requires_grad = False\n            for param in model.branch_asm.parameters(): param.requires_grad = False\n            \n            optimizer = torch.optim.AdamW([\n                {'params': model.feature_extractor.parameters()},\n                {'params': model.final_head.parameters()}\n            ], lr=1e-3, weight_decay=1e-2)\n            \n        # [PHASE 2] MỞ BĂNG VÀ DIFFERENTIAL LR\n        elif epoch == EPOCHS_PHASE_1:\n            print(f\"\\n[PHASE 2] UNFREEZE TOÀN MẠNG (Epoch {EPOCHS_PHASE_1 + 1} - {TOTAL_EPOCHS})\")\n            for param in model.branch_bytes.parameters(): param.requires_grad = True\n            for param in model.branch_asm.parameters(): param.requires_grad = True\n            \n            optimizer = torch.optim.AdamW([\n                {'params': model.branch_bytes.parameters(), 'lr': 1e-5},\n                {'params': model.branch_asm.parameters(), 'lr': 1e-5},\n                {'params': model.feature_extractor.parameters(), 'lr': 1e-4},\n                {'params': model.final_head.parameters(), 'lr': 1e-4}\n            ], weight_decay=1e-2)\n\n        # ==========================================\n        # BẮT ĐẦU VÒNG LẶP TRAIN TRONG 1 EPOCH\n        # ==========================================\n        model.train()\n        train_loss = 0.0\n        correct_preds = 0\n        total_samples = 0\n        \n        # BỎ TQDM ĐỂ TRÁNH LỖI PHÌNH LOG KHI CHẠY NGẦM\n        for img_b, img_a, labels in train_loader:\n            img_b, img_a, labels = img_b.to(DEVICE), img_a.to(DEVICE), labels.to(DEVICE)\n            \n            optimizer.zero_grad()\n            \n            outputs = model(img_b, img_a, return_features=False) \n            loss = criterion(outputs, labels)\n            \n            loss.backward()\n            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n            optimizer.step()\n            \n            # Tích lũy Loss\n            train_loss += loss.item()\n            \n            # Tích lũy Accuracy\n            _, preds = torch.max(outputs, 1)\n            correct_preds += torch.sum(preds == labels).item()\n            total_samples += labels.size(0)\n            \n        # ==========================================\n        # TỔNG HỢP VÀ IN KẾT QUẢ EPOCH\n        # ==========================================\n        epoch_loss = train_loss / len(train_loader)\n        epoch_acc = correct_preds / total_samples\n        \n        print(f\"Fold {fold+1} - Epoch [{epoch+1:02d}/{TOTAL_EPOCHS}] | Train Loss: {epoch_loss:.4f} | Train Acc: {epoch_acc:.4f}\")\n            \n    # Trích xuất đặc trưng OOF và lưu vào đúng vị trí Index gốc\n    print(\"➔ Đang trích xuất đặc trưng...\")\n    X_train_deep_oof[val_idx] = extract_features(model, val_loader)\n    X_test_deep_folds[fold, :, :] = extract_features(model, test_loader)\n    \n    del model, optimizer, train_loader, val_loader\n    torch.cuda.empty_cache()\n    gc.collect()\n\nX_test_deep_final = np.mean(X_test_deep_folds, axis=0)\n\nnp.save(os.path.join(OUT_DIR, 'X_train_deep_oof.npy'), X_train_deep_oof)\nnp.save(os.path.join(OUT_DIR, 'X_test_deep_final.npy'), X_test_deep_final)\nprint(f\"\\nHOÀN TẤT! Dữ liệu đã lưu tại {OUT_DIR}\")","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2026-04-11T11:26:48.438072Z","iopub.status.busy":"2026-04-11T11:26:48.437829Z","iopub.status.idle":"2026-04-11T14:16:13.372765Z","shell.execute_reply":"2026-04-11T14:16:13.371933Z"},"papermill":{"duration":10164.942479,"end_time":"2026-04-11T14:16:13.377876+00:00","exception":false,"start_time":"2026-04-11T11:26:48.435397+00:00","status":"completed"},"tags":[]},"outputs":[],"execution_count":null}]}