{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":4117,"databundleVersionId":46665},{"sourceType":"datasetVersion","sourceId":15694232,"datasetId":10052595,"databundleVersionId":16632937},{"sourceType":"datasetVersion","sourceId":15608790,"datasetId":9984766,"databundleVersionId":16542367}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport scipy.sparse as sp\nfrom sklearn.feature_selection import SelectKBest, f_classif\n\nDATA_IN_DIR = '/kaggle/input/datasets/huylhn1810/weight' # Đổi tên thư mục Data bạn đã upload\nOUT_DIR = '/kaggle/working/processed_data/'\nos.makedirs(OUT_DIR, exist_ok=True)\n\nTOTAL_TRAIN_PARTS = 2\nTOTAL_TEST_PARTS = 8\n\nprint(\"1. Đang tải và gộp dữ liệu TRAIN...\")\ntrain_tab_list, train_ng_list, y_train_list = [], [], []\nfor i in range(1, TOTAL_TRAIN_PARTS + 1):\n    train_tab_list.append(np.load(os.path.join(DATA_IN_DIR, f'X_train_tab_part{i}.npy')))\n    train_ng_list.append(sp.load_npz(os.path.join(DATA_IN_DIR, f'X_train_ng_part{i}.npz')))\n    y_train_list.append(np.load(os.path.join(DATA_IN_DIR, f'y_train_part{i}.npy')))\n\nX_train_tab = np.vstack(train_tab_list)\nX_train_ng_sparse = sp.vstack(train_ng_list)\ny_train = np.concatenate(y_train_list)\n\nprint(\"2. Đang tải và gộp dữ liệu TEST...\")\ntest_tab_list, test_ng_list = [], []\nfor i in range(1, TOTAL_TEST_PARTS + 1):\n    test_tab_list.append(np.load(os.path.join(DATA_IN_DIR, f'X_test_tab_part{i}.npy')))\n    test_ng_list.append(sp.load_npz(os.path.join(DATA_IN_DIR, f'X_test_ng_part{i}.npz')))\n\nX_test_tab = np.vstack(test_tab_list)\nX_test_ng_sparse = sp.vstack(test_ng_list)\n\nprint(f\"-> Tổng số mẫu Train: {X_train_tab.shape[0]}\")\nprint(f\"-> Tổng số mẫu Test: {X_test_tab.shape[0]}\")\n\nprint(\"3. Đang chạy SelectKBest lọc 2000 N-grams tốt nhất...\")\nselector = SelectKBest(f_classif, k=2000)\nX_train_ngrams = selector.fit_transform(X_train_ng_sparse, y_train).toarray()\nX_test_ngrams = selector.transform(X_test_ng_sparse).toarray()\n\nprint(\"4. Lưu ra mảng hoàn chỉnh chuẩn bị Train...\")\nnp.save(os.path.join(OUT_DIR, 'X_train_tab.npy'), X_train_tab)\nnp.save(os.path.join(OUT_DIR, 'X_test_tab.npy'), X_test_tab)\nnp.save(os.path.join(OUT_DIR, 'X_train_ngrams.npy'), X_train_ngrams)\nnp.save(os.path.join(OUT_DIR, 'X_test_ngrams.npy'), X_test_ngrams)\nnp.save(os.path.join(OUT_DIR, 'y_train.npy'), y_train)\n\nprint(\"✅ Đã nối xong toàn bộ dữ liệu!\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport time\nimport joblib\nimport numpy as np\nimport lightgbm as lgb\nimport xgboost as xgb\nfrom sklearn.ensemble import ExtraTreesClassifier\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.utils.class_weight import compute_class_weight\n\nOUT_DIR = 'processed_data/'\nMODEL_DIR = 'models/'\nos.makedirs(MODEL_DIR, exist_ok=True)\n\n# Load dữ liệu\nX_train_tab = np.load(os.path.join(OUT_DIR, 'X_train_tab.npy'))\nX_test_tab = np.load(os.path.join(OUT_DIR, 'X_test_tab.npy'))\nX_train_ngrams = np.load(os.path.join(OUT_DIR, 'X_train_ngrams.npy'))\nX_test_ngrams = np.load(os.path.join(OUT_DIR, 'X_test_ngrams.npy'))\ny_train = np.load(os.path.join(OUT_DIR, 'y_train.npy'))\n\n# Ghép (Concat) đặc trưng bảng và N-grams\nX_train_final = np.hstack([X_train_tab, X_train_ngrams])\nX_test_final = np.hstack([X_test_tab, X_test_ngrams])\nprint(f\"Kích thước X_train: {X_train_final.shape}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_classes = 9\nnfolds = 5\nclasses = np.unique(y_train)\nweights = compute_class_weight('balanced', classes=classes, y=y_train)\nclass_weights_dict = dict(zip(classes, weights))\n\nbase_models = {\n    'xgb': xgb.XGBClassifier(\n        objective='multi:softprob', \n        num_class=num_classes, \n        max_depth=6, \n        # Cập nhật thông số để chạy trên GPU T4\n        tree_method='hist',   \n        device='cuda',        # Bật tăng tốc GPU phần cứng\n        random_state=42\n    ),\n    'lgb': lgb.LGBMClassifier(\n        objective='multiclass', \n        num_class=num_classes, \n        class_weight=class_weights_dict, \n        # Cập nhật thông số để chạy trên GPU\n        device='gpu',         \n        random_state=42, \n        verbose=-1\n    ),\n    'extra_trees': ExtraTreesClassifier(\n        n_estimators=500, \n        max_depth=15, \n        class_weight='balanced', \n        n_jobs=-1,            # ExtraTrees chỉ dùng được CPU, n_jobs=-1 để dùng full 4 lõi CPU\n        random_state=42\n    )\n}\n\nmeta_X_train_list, meta_X_test_list = [], []\nskf = StratifiedKFold(n_splits=nfolds, shuffle=True, random_state=2026)\n\nprint(\"=\"*50)\nprint(\"BẮT ĐẦU HUẤN LUYỆN LEVEL-0 (META-FEATURES EXTRATION)\")\nprint(\"=\"*50)\n\nfor model_name, model in base_models.items():\n    print(f\"\\n🚀 [Level-0] Đang xử lý mô hình: {model_name.upper()}\")\n    oof_train = np.zeros((X_train_final.shape[0], num_classes))\n    oof_test_skf = np.zeros((nfolds, X_test_final.shape[0], num_classes))\n    \n    # --- 1. Train toàn bộ trên tập Train ---\n    print(f\" ➔ Đang huấn luyện trên toàn bộ tập Train (Full Model)...\", end=\"\", flush=True)\n    start_time = time.time()\n    \n    model_full = model.fit(X_train_final, y_train)\n    joblib.dump(model_full, os.path.join(MODEL_DIR, f'{model_name}_full.pkl'))\n    \n    print(f\" Xong! ({time.time() - start_time:.1f}s)\")\n    \n    # --- 2. Cross Validation (Tạo OOF) ---\n    print(f\" ➔ Bắt đầu Cross-Validation ({nfolds} Folds):\")\n    for i, (train_idx, valid_idx) in enumerate(skf.split(X_train_final, y_train)):\n        print(f\"    + Đang chạy Fold {i+1}/{nfolds}...\", end=\"\", flush=True)\n        fold_start_time = time.time()\n        \n        x_tr, y_tr = X_train_final[train_idx], y_train[train_idx]\n        x_val = X_train_final[valid_idx]\n        \n        # Huấn luyện trên Fold hiện tại\n        model.fit(x_tr, y_tr)\n        \n        # Dự đoán\n        oof_train[valid_idx] = model.predict_proba(x_val)\n        oof_test_skf[i, :, :] = model.predict_proba(X_test_final)\n        \n        print(f\" Xong! ({time.time() - fold_start_time:.1f}s)\")\n        \n    meta_X_train_list.append(oof_train)\n    meta_X_test_list.append(oof_test_skf.mean(axis=0))\n    print(f\" ✅ Đã hoàn thành mô hình {model_name.upper()}!\")\n\n# Nối các OOF predictions lại thành Input cho Meta-Learner\nX_train_level1 = np.hstack(meta_X_train_list)\nX_test_level1 = np.hstack(meta_X_test_list)\n\nprint(\"\\nĐang lưu Meta-features của tập Test (X_test_level1.npy)...\")\nnp.save(os.path.join(OUT_DIR, 'X_test_level1.npy'), X_test_level1) \nprint(\"Hoàn tất Level-0! Đã sẵn sàng cho tầng Meta-Learner.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import time\nimport os\nimport joblib\nimport numpy as np\nimport xgboost as xgb\n\n# (Giả định X_train_level1, X_test_level1, y_train, OUT_DIR, MODEL_DIR, num_classes đã có sẵn)\n\nprint(\"\\n\" + \"=\"*50)\nprint(\"BẮT ĐẦU HUẤN LUYỆN LEVEL-1 (META-LEARNER & FUSION)\")\nprint(\"=\"*50)\n    \n# --- 1. TẢI META-FEATURES TỪ DEEP LEARNING ---\nprint(\"Đang tải dự đoán từ mô hình Dual-Band Deep Learning (Swin + ResNet)...\")\nDL_train_probs = np.load(os.path.join(\"/kaggle/input/datasets/huylhn1810/linear-stacking-dataset\", 'DL_train_probs.npy'))\nDL_test_probs = np.load(os.path.join(\"/kaggle/input/datasets/huylhn1810/linear-stacking-dataset\", 'DL_test_probs.npy'))\n\n# --- 2. DUNG HỢP (FUSION) ---\nprint(\"Đang ghép nối đặc trưng Tree-based và Deep Learning...\")\nX_train_fusion = np.hstack([X_train_level1, DL_train_probs])\nX_test_fusion = np.hstack([X_test_level1, DL_test_probs])\n\nprint(f\"-> Kích thước Train Fusion: {X_train_fusion.shape}\")\nprint(f\"-> Kích thước Test Fusion: {X_test_fusion.shape}\")\n\n\n# --- 3. PSEUDO-LABELING TRÊN DỮ LIỆU FUSION ---\nprint(\"\\n[Trick] Đang tạo nhãn giả (Pseudo-labeling) trên tập Test...\", end=\"\", flush=True)\nstart_trick_time = time.time()\n\n# Dùng một mô hình nháp để lấy dự đoán trên tập Test Fusion\ntemp_meta = xgb.XGBClassifier(objective='multi:softprob', max_depth=3, random_state=99)\ntemp_meta.fit(X_train_fusion, y_train)\ntest_probs = temp_meta.predict_proba(X_test_fusion)\n\n# Lọc các dự đoán cực kỳ tự tin (> 0.99)\nconfident_indices = np.where(test_probs.max(axis=1) > 0.99)[0]\npseudo_labels = test_probs.argmax(axis=1)[confident_indices]\nX_test_confident = X_test_fusion[confident_indices]\n\n# Ghép dữ liệu tự tin của Test vào tập Train\nX_train_fusion_extended = np.vstack([X_train_fusion, X_test_confident])\ny_train_extended = np.concatenate([y_train, pseudo_labels])\n\nprint(f\" Xong! ({time.time() - start_trick_time:.1f}s)\")\nprint(f\" ➔ Đã đóng băng và thêm {len(confident_indices)} mẫu siêu tự tin (>99%) từ tập Test vào huấn luyện.\")\n\n\n# --- 4. HUẤN LUYỆN META-LEARNER CHÍNH THỨC ---\nprint(\"\\n[Level-1] Đang huấn luyện Meta-Learner (XGBoost) trên toàn bộ dữ liệu Fusion + Nhãn giả...\", end=\"\", flush=True)\nstart_meta_time = time.time()\n\nmeta_learner = xgb.XGBClassifier(\n    objective='multi:softprob', \n    num_class=num_classes, \n    learning_rate=0.01, \n    max_depth=4, # Tăng lên 4 vì giờ features nhiều hơn do có thêm DL\n    n_estimators=600, # Tăng số lượng cây lên một chút\n    tree_method='hist',\n    device='cuda', # Bật GPU\n    random_state=99\n)\nmeta_learner.fit(X_train_fusion_extended, y_train_extended)\n\nprint(f\" Xong! ({time.time() - start_meta_time:.1f}s)\")\n\n# --- 5. LƯU MÔ HÌNH VÀ META-FEATURES ---\nprint(\"\\nĐang lưu mô hình và các file phục vụ Inference...\")\njoblib.dump(meta_learner, os.path.join(MODEL_DIR, 'meta_learner_fusion.pkl'))\nnp.save(os.path.join(OUT_DIR, 'X_test_fusion.npy'), X_test_fusion) # Lưu mảng Fusion của Test để dùng ở Phần 3\n\nprint(\"✅ HOÀN TẤT PHẦN 2! Cỗ máy Meta-Stacking của bạn giờ đã mang sức mạnh của cả Tree-based và Deep Learning.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport joblib\nimport numpy as np\nimport pandas as pd\n\n# ==========================================\n# CẤU HÌNH ĐƯỜNG DẪN\n# ==========================================\nOUT_DIR = '/kaggle/working/processed_data/'\nMODEL_DIR = '/kaggle/working/models/'\n\n# Tự động dò đường dẫn file submission mẫu\npath_1 = '/kaggle/input/competitions/malware-classification/sampleSubmission.csv'\npath_2 = '/kaggle/input/malware-classification/sampleSubmission.csv'\nSUBMISSION_CSV = path_1 if os.path.exists(path_1) else path_2\n\nprint(\"=\"*50)\nprint(\"BẮT ĐẦU TẠO FILE SUBMIT KAGGLE\")\nprint(\"=\"*50)\n\n# 1. Đọc danh sách ID chuẩn của tập Test\nprint(\"1. Đọc danh sách ID từ file mẫu...\")\nsub_df = pd.read_csv(SUBMISSION_CSV)\ntest_ids = sub_df['Id'].tolist()\n\n# 2. Load Model và Dữ liệu Test Fusion\nprint(\"2. Tải mô hình Meta-Learner Fusion và Dữ liệu Test...\")\nmeta_learner = joblib.load(os.path.join(MODEL_DIR, 'meta_learner_fusion.pkl'))\nX_test_fusion = np.load(os.path.join(OUT_DIR, 'X_test_fusion.npy'))\n\n# Kiểm tra an toàn: Đảm bảo số lượng mẫu Test khớp với số lượng ID\nif X_test_fusion.shape[0] != len(test_ids):\n    raise ValueError(f\"Lỗi: Số lượng mẫu dự đoán ({X_test_fusion.shape[0]}) không khớp với số lượng ID trong file mẫu ({len(test_ids)})!\")\n\n# 3. Chạy dự đoán\nprint(\"3. Đang tiến hành tính toán xác suất (Predict Proba)...\")\nfinal_probabilities = meta_learner.predict_proba(X_test_fusion)\n\n# 4. Định dạng DataFrame\nprint(\"4. Định dạng file theo đúng chuẩn Microsoft BIG 2015...\")\ncol_names = [f'Prediction{i}' for i in range(1, 10)]\nsubmission = pd.DataFrame(final_probabilities, columns=col_names)\n\n# Chèn cột ID vào vị trí đầu tiên\nsubmission.insert(0, 'Id', test_ids)\n\n# 5. Lưu ra CSV\nsub_filename = '/kaggle/working/final_fusion_submission.csv'\nsubmission.to_csv(sub_filename, index=False)\n\nprint(f\"\\n✅ THÀNH CÔNG MỸ MÃN! File submit đã được lưu tại: {sub_filename}\")\nprint(f\"Kích thước file: {submission.shape[0]} dòng, {submission.shape[1]} cột.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}