{"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":"none","dataSources":[{"sourceId":4117,"databundleVersionId":46665,"sourceType":"competition"},{"sourceId":288810334,"sourceType":"kernelVersion"}],"dockerImageVersionId":31234,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# --- BƯỚC 0: SỬA LỖI THƯ VIỆN (Chạy dòng này đầu tiên để tránh lỗi đỏ) ---\n!pip install \"protobuf<4\"\n# Sau khi pip install xong, hệ thống có thể yêu cầu Restart Session. \n# Nhưng code dưới đây vẫn chạy được, nếu lỗi import thì Restart nhé.\n\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport os\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models, callbacks\nfrom sklearn.model_selection import train_test_split\n\n# --- 1. CẤU HÌNH ---\n# Kiểm tra kỹ đường dẫn ảnh của bạn (Folder chứa 10k ảnh)\nIMG_DIR = '/kaggle/input/microsoft-malware/processed_images' \nLABEL_FILE = '../input/malware-classification/trainLabels.csv'\nIMG_SIZE = (226, 226) # Kích thước chuẩn\nBATCH_SIZE = 32\nEPOCHS = 25 # Chỉ cần 25 vòng là đủ, không cần 50\n\n# --- 2. LOAD DỮ LIỆU ---\nprint(\"⏳ Đang tải danh sách ảnh và nhãn...\")\nlabels_df = pd.read_csv(LABEL_FILE)\nlabels_df['Class'] = labels_df['Class'] - 1 # Chuyển về 0-8\n\nX = []\ny = []\n\n# Kiểm tra thư mục ảnh\nif os.path.exists(IMG_DIR):\n    # Lấy danh sách file thực tế trong folder để đối chiếu\n    valid_files = set(os.listdir(IMG_DIR))\n    print(f\"✅ Tìm thấy {len(valid_files)} file ảnh trong thư mục.\")\n\n    print(\"⏳ Đang đọc ảnh vào RAM (Mất khoảng 2-3 phút)...\")\n    count = 0\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                # Đọc ảnh xám (Grayscale) cho nhẹ\n                img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n                if img is not None:\n                    # Resize lại cho chắc chắn\n                    img = cv2.resize(img, IMG_SIZE)\n                    X.append(img)\n                    y.append(row['Class'])\n                    count += 1\n            except Exception as e:\n                pass\n            \n    print(f\"✅ Đã load thành công: {len(X)} ảnh.\")\nelse:\n    print(\"❌ LỖI: Không tìm thấy thư mục ảnh! Hãy kiểm tra lại đường dẫn Input.\")\n\n# Chuẩn hóa dữ liệu\nX = np.array(X).reshape(-1, IMG_SIZE[0], IMG_SIZE[1], 1) / 255.0\ny = np.array(y)\n\n# Chia tập Train/Test (80% Train, 20% Test)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n\n# --- 3. XÂY DỰNG MODEL \"NHẸ MÀ CHẤT\" ---\n# Kiến trúc 5 lớp (VGG-style thu nhỏ) - Đảm bảo chạy nhanh và Acc cao\nmodel = models.Sequential([\n    # Block 1\n    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(226, 226, 1)),\n    layers.MaxPooling2D((2, 2)),\n    \n    # Block 2\n    layers.Conv2D(64, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n    \n    # Block 3\n    layers.Conv2D(128, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n    \n    # Flatten & Classification\n    layers.Flatten(),\n    layers.Dense(256, activation='relu'),\n    layers.Dropout(0.5), # Quan trọng: Chống học vẹt\n    layers.Dense(9, activation='softmax')\n])\n\nmodel.compile(optimizer='adam',\n              loss='sparse_categorical_crossentropy',\n              metrics=['accuracy'])\n\nmodel.summary()\n\n# --- 4. TRAIN VỚI CHIẾN THUẬT THÔNG MINH ---\n# Tự động lưu model tốt nhất\ncheckpoint = callbacks.ModelCheckpoint('best_cnn_model.keras', \n                                       monitor='val_accuracy', \n                                       save_best_only=True, \n                                       mode='max',\n                                       verbose=1)\n\n# Tự động dừng nếu train mãi không khá lên (tránh tốn thời gian)\nearly_stop = callbacks.EarlyStopping(monitor='val_loss', \n                                     patience=5, # 5 vòng không giảm loss thì dừng\n                                     restore_best_weights=True)\n\nprint(\"\\n🚀 BẮT ĐẦU TRAIN (Dự kiến mất 20-40 phút)...\")\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, early_stop])\n\n# --- 5. LƯU KẾT QUẢ CUỐI CÙNG ---\nprint(\"\\n💾 Đang lưu kết quả để dùng cho Ensemble...\")\n# Lưu Model\nmodel.save('final_cnn_model.h5')\n\n# Dự đoán trên tập Test và lưu lại (cho bước Ensemble sau này)\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(\"🎉 HOÀN TẤT! Bạn đã có file 'cnn_probs.npy' và model.\")\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":"2025-12-28T09:17:22.888653Z","iopub.execute_input":"2025-12-28T09:17:22.889098Z","iopub.status.idle":"2025-12-28T11:32:33.568210Z","shell.execute_reply.started":"2025-12-28T09:17:22.889067Z","shell.execute_reply":"2025-12-28T11:32:33.567387Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install \"protobuf<4\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-28T09:15:04.149869Z","iopub.execute_input":"2025-12-28T09:15:04.150291Z","iopub.status.idle":"2025-12-28T09:15:09.862150Z","shell.execute_reply.started":"2025-12-28T09:15:04.150266Z","shell.execute_reply":"2025-12-28T09:15:09.860623Z"}},"outputs":[],"execution_count":null}]}