{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":4117,"databundleVersionId":46665,"sourceType":"competition"},{"sourceId":290047328,"sourceType":"kernelVersion"},{"sourceId":290128330,"sourceType":"kernelVersion"},{"sourceId":290326357,"sourceType":"kernelVersion"}],"dockerImageVersionId":31234,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# 1. Cài đặt lại thư viện cần thiết\n!pip install \"protobuf<4.21\"\n!pip install \"tensorflow-io-gcs-filesystem>=0.23.1\"\n\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport os\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models, callbacks, optimizers, regularizers\nfrom tensorflow.keras.layers import LeakyReLU # [MỚI] Hàm kích hoạt tốt hơn\nfrom sklearn.model_selection import train_test_split\n# Bỏ import class_weight vì nó gây nhiễu model lúc này\n\n# --- 1. CẤU HÌNH HỆ THỐNG & GPU ---\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.TPUStrategy(tpu)\n    print(\"Running on TPU!\")\nexcept ValueError:\n    strategy = tf.distribute.get_strategy()\n    print(f\"Running on {strategy.num_replicas_in_sync} device(s) (GPU/CPU)\")\n\n# Cấu hình đường dẫn\nIMG_DIR = '/kaggle/input/microsoft-malware/processed_images'\nLABEL_FILE = '../input/malware-classification/trainLabels.csv'\nIMG_SIZE = (226, 226)\nBATCH_SIZE = 32 * strategy.num_replicas_in_sync\nEPOCHS = 40 # Tăng epoch vì kiến trúc mới (GAP) học chậm mà chắc\n\n# --- 2. LOAD DỮ LIỆU ---\nprint(\"Loading data...\")\nlabels_df = pd.read_csv(LABEL_FILE)\nlabels_df['Class'] = labels_df['Class'] - 1 \n\n# [QUAN TRỌNG] Sắp xếp ID để khớp với XGBoost\nlabels_df = labels_df.sort_values('Id').reset_index(drop=True)\n\nX = []\ny = []\n\nif os.path.exists(IMG_DIR):\n    valid_files = set(os.listdir(IMG_DIR))\n    print(f\"Found {len(valid_files)} images.\")\n    \n    for index, row in labels_df.iterrows():\n        file_name = row['Id'] + '.png'\n        if file_name in valid_files:\n            try:\n                path = os.path.join(IMG_DIR, file_name)\n                img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n                if img is not None:\n                    img = cv2.resize(img, IMG_SIZE)\n                    X.append(img)\n                    y.append(row['Class'])\n            except:\n                pass\n    print(f\"Successfully loaded: {len(X)} images.\")\nelse:\n    print(\"ERROR: Image directory not found!\")\n\n# Chuẩn hóa\nX = np.array(X).reshape(-1, IMG_SIZE[0], IMG_SIZE[1], 1) / 255.0\ny = np.array(y)\n\n# Chia tập dữ liệu (Random State 20251226 khớp XGBoost)\nprint(\"Splitting data...\")\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=20251226, stratify=y)\nprint(f\"Train shape: {X_train.shape}\")\n\n# --- 3. XÂY DỰNG MODEL (KIẾN TRÚC NÂNG CẤP) ---\nwith strategy.scope():\n    model = models.Sequential()\n    \n    model.add(layers.Input(shape=(226, 226, 1)))\n    \n    # Block 1\n    model.add(layers.Conv2D(64, (3, 3), padding='same'))\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU(alpha=0.1)) # [MỚI] Thay ReLU\n    model.add(layers.MaxPooling2D((2, 2)))\n    \n    # Block 2\n    model.add(layers.Conv2D(128, (3, 3), padding='same'))\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU(alpha=0.1))\n    model.add(layers.MaxPooling2D((2, 2)))\n    model.add(layers.Dropout(0.3))\n    \n    # Block 3\n    model.add(layers.Conv2D(256, (3, 3), padding='same'))\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU(alpha=0.1))\n    model.add(layers.MaxPooling2D((2, 2)))\n    model.add(layers.Dropout(0.4)) \n    \n    # Block 4\n    model.add(layers.Conv2D(512, (3, 3), padding='same'))\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU(alpha=0.1))\n    model.add(layers.MaxPooling2D((2, 2)))\n    model.add(layers.Dropout(0.4)) \n    \n    # [NÂNG CẤP QUAN TRỌNG NHẤT] Thay Flatten bằng GlobalAveragePooling2D\n    # Giúp model khái quát hóa tốt hơn, tăng Val Acc\n    model.add(layers.GlobalAveragePooling2D())\n    \n    # Head\n    model.add(layers.Dense(1024))\n    model.add(layers.BatchNormalization())\n    model.add(layers.LeakyReLU(alpha=0.1))\n    model.add(layers.Dropout(0.5))\n    model.add(layers.Dense(9, activation='softmax'))\n\n    # Dùng learning rate nhỏ hơn chút để hội tụ mượt\n    model.compile(optimizer=optimizers.Adam(learning_rate=0.0005),\n                  loss='sparse_categorical_crossentropy',\n                  metrics=['accuracy'])\n\n# --- 4. TRAIN ---\ncheckpoint = callbacks.ModelCheckpoint('best_cnn_sync.keras', \n                                       monitor='val_accuracy', \n                                       save_best_only=True, \n                                       mode='max', verbose=1)\n\nreduce_lr = callbacks.ReduceLROnPlateau(monitor='val_loss', \n                                        factor=0.5, \n                                        patience=4, \n                                        min_lr=1e-6, verbose=1)\n\nearly_stop = callbacks.EarlyStopping(monitor='val_loss', \n                                     patience=10, \n                                     restore_best_weights=True, verbose=1)\n\nprint(\"Starting training (Optimized Architecture - No Class Weight)...\")\nhistory = model.fit(X_train, y_train,\n                    epochs=EPOCHS,\n                    batch_size=BATCH_SIZE,\n                    validation_data=(X_test, y_test),\n                    callbacks=[checkpoint, reduce_lr, early_stop])\n                    # Đã bỏ class_weight để tránh lỗi tụt accuracy\n\n# --- 5. LƯU KẾT QUẢ ---\nprint(\"Saving results...\")\nmodel.load_weights('best_cnn_sync.keras')\n\ny_pred_probs = model.predict(X_test)\nnp.save('cnn_probs.npy', y_pred_probs)\nnp.save('y_test_labels.npy', y_test)\n\nprint(f\"Final Validation Accuracy: {max(history.history['val_accuracy'])*100:.2f}%\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-01-05T09:49:01.528664Z","iopub.execute_input":"2026-01-05T09:49:01.528883Z","iopub.status.idle":"2026-01-05T09:51:11.737611Z","shell.execute_reply.started":"2026-01-05T09:49:01.528863Z","shell.execute_reply":"2026-01-05T09:51:11.736903Z"}},"outputs":[],"execution_count":null}]}