{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nfrom os import makedirs\nfrom os import listdir\nimport numpy as np\nimport pandas as pd\nimport shutil\nimport matplotlib.pyplot as plt\nfrom matplotlib.image import imread\nimport matplotlib.gridspec as gridspec\nfrom pathlib import Path\nfrom shutil import copyfile\nfrom random import seed\nfrom random import random\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report,confusion_matrix,ConfusionMatrixDisplay\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import Dense,MaxPooling2D,Dropout,Flatten,BatchNormalization,Conv2D\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau,EarlyStopping\nimport seaborn as sns\nfrom tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nif tf.config.experimental.list_physical_devices('GPU'): # Kiểm tra GPU\n    print(\"GPU is available\")\nelse:\n    print(\"GPU is not available\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:28.127384Z","iopub.execute_input":"2024-12-18T17:15:28.127767Z","iopub.status.idle":"2024-12-18T17:15:44.755917Z","shell.execute_reply.started":"2024-12-18T17:15:28.127698Z","shell.execute_reply":"2024-12-18T17:15:44.754861Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Giải nén tệp zip","metadata":{}},{"cell_type":"code","source":"train_path = \"../input/dogs-vs-cats/test1.zip\"\ntest_path = \"../input/dogs-vs-cats/train.zip\"\nfiles = \"/kaggle/working/\"\n\n# Giải nén tệp train\nshutil.unpack_archive(train_path, files)\n\n# Giải nén tệp test\nshutil.unpack_archive(test_path, files)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:44.757322Z","iopub.execute_input":"2024-12-18T17:15:44.757864Z","iopub.status.idle":"2024-12-18T17:15:56.995950Z","shell.execute_reply.started":"2024-12-18T17:15:44.757832Z","shell.execute_reply":"2024-12-18T17:15:56.995024Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_dir = Path(\"../working/train/\")\nfilenames = list(image_dir.iterdir())  \ndata = pd.DataFrame({\n    \"filename\": [file.name for file in filenames],\n    \"label\": [file.stem.split(\".\")[0] for file in filenames]  \n})\n\ndata.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:56.997186Z","iopub.execute_input":"2024-12-18T17:15:56.997946Z","iopub.status.idle":"2024-12-18T17:15:57.076625Z","shell.execute_reply.started":"2024-12-18T17:15:56.997903Z","shell.execute_reply":"2024-12-18T17:15:57.075737Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Hiển thị 10 ảnh đầu từ dataset","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(20, 20))\ngs = gridspec.GridSpec(1, 10, wspace=0.4) \n\nfor i in range(10):\n    ax = plt.subplot(gs[i]) \n    filename = 'train/' + 'dog.' + str(i) + '.jpg'\n    image = imread(filename)\n    ax.imshow(image)\n    ax.set_title('Dog', fontsize=12)\n    ax.axis('off') \n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:57.078466Z","iopub.execute_input":"2024-12-18T17:15:57.078780Z","iopub.status.idle":"2024-12-18T17:15:58.090690Z","shell.execute_reply.started":"2024-12-18T17:15:57.078751Z","shell.execute_reply":"2024-12-18T17:15:58.089772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(20, 20))\ngs = gridspec.GridSpec(1, 10, wspace=0.4) \n\nfor i in range(10):\n    ax = plt.subplot(gs[i]) \n    filename = 'train/' + 'cat.' + str(i) + '.jpg'\n    image = imread(filename)\n    ax.imshow(image)\n    ax.set_title('Cat', fontsize=12)\n    ax.axis('off') \n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:58.091813Z","iopub.execute_input":"2024-12-18T17:15:58.092098Z","iopub.status.idle":"2024-12-18T17:15:58.766193Z","shell.execute_reply.started":"2024-12-18T17:15:58.092071Z","shell.execute_reply":"2024-12-18T17:15:58.765378Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Phân chia tập dữ liệu","metadata":{}},{"cell_type":"code","source":"labels = data['label']\n\nX_train, X_temp = train_test_split(data, test_size=0.2, stratify=labels, random_state = 42)\n\nlabel_test_val = X_temp['label']\n\nX_test, X_val = train_test_split(X_temp, test_size=0.5, stratify=label_test_val, random_state = 42)\n\nprint('The shape of train data',X_train.shape)\nprint('The shape of test data',X_test.shape)\nprint('The shape of validation data',X_val.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:58.767633Z","iopub.execute_input":"2024-12-18T17:15:58.768025Z","iopub.status.idle":"2024-12-18T17:15:58.811731Z","shell.execute_reply.started":"2024-12-18T17:15:58.767984Z","shell.execute_reply":"2024-12-18T17:15:58.810895Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_home = 'dataset_dogs_vs_cats/'\nsubdirs = ['train/', 'test/']\n\nfor subdir in subdirs:\n    labeldirs = ['dogs/', 'cats/']\n    for labldir in labeldirs:\n        newdir = dataset_home + subdir + labldir\n        makedirs(newdir, exist_ok=True)\nseed(1)\nval_ratio = 0.2 \nsrc_directory = 'train/'\nfor file in listdir(src_directory):\n        src = src_directory + '/' + file\n        dst_dir = 'train/'\n        if random() < val_ratio:\n            dst_dir = 'test/'\n        if file.startswith('cat'):\n            dst = dataset_home + dst_dir + 'cats/' + file\n            copyfile(src, dst)\n        elif file.startswith('dog'):\n            dst = dataset_home + dst_dir + 'dogs/' + file\n            copyfile(src, dst)\n\n            \npath1 = \"/kaggle/working/dataset_dogs_vs_cats/train/cats\"\npath2 = \"/kaggle/working/dataset_dogs_vs_cats/train/dogs\"\npath3 = \"/kaggle/working/dataset_dogs_vs_cats/test/cats\"\npath4 = \"/kaggle/working/dataset_dogs_vs_cats/test/dogs\"\n\n\nprint('Then number of cat images in training data is' ,len(os.listdir(path1)))\nprint('Then number of dog images in training data is' ,len(os.listdir(path2)))\nprint('Then number of cat images in validation data is' ,len(os.listdir(path3)))\nprint('Then number of dog images in validation data is' ,len(os.listdir(path4)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:15:58.812809Z","iopub.execute_input":"2024-12-18T17:15:58.813080Z","iopub.status.idle":"2024-12-18T17:16:01.227151Z","shell.execute_reply.started":"2024-12-18T17:15:58.813055Z","shell.execute_reply":"2024-12-18T17:16:01.226202Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Cấu hình dữ liệu đầu vào","metadata":{}},{"cell_type":"code","source":"image_size = 128\nimage_channel = 3\nbat_size = 32","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:01.228083Z","iopub.execute_input":"2024-12-18T17:16:01.228394Z","iopub.status.idle":"2024-12-18T17:16:01.232780Z","shell.execute_reply.started":"2024-12-18T17:16:01.228350Z","shell.execute_reply":"2024-12-18T17:16:01.231780Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Tạo ImageDataGenerator","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1./255,\n                                    rotation_range = 15,\n                                    horizontal_flip = True,\n                                    zoom_range = 0.2,\n                                    shear_range = 0.1,\n                                    fill_mode = 'reflect',\n                                    width_shift_range = 0.1,\n                                    height_shift_range = 0.1)\n\ntest_datagen = ImageDataGenerator(rescale=1./255)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:01.234009Z","iopub.execute_input":"2024-12-18T17:16:01.234392Z","iopub.status.idle":"2024-12-18T17:16:01.244655Z","shell.execute_reply.started":"2024-12-18T17:16:01.234352Z","shell.execute_reply":"2024-12-18T17:16:01.244016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator = train_datagen.flow_from_dataframe(X_train,\n                                                    directory = 'train/',\n                                                    x_col= 'filename',\n                                                    y_col= 'label',\n                                                    batch_size = bat_size,\n                                                    target_size = (image_size,image_size)\n                                                   )\nval_generator = test_datagen.flow_from_dataframe(X_val, \n                                                 directory = 'train/',\n                                                 x_col= 'filename',\n                                                 y_col= 'label',\n                                                 batch_size = bat_size,\n                                                 target_size = (image_size,image_size),\n                                                 shuffle=False\n                                                )\n\ntest_generator = test_datagen.flow_from_dataframe(X_test, \n                                                  directory = 'train/',\n                                                  x_col= 'filename',\n                                                  y_col= 'label',\n                                                  batch_size = bat_size,\n                                                  target_size = (image_size,image_size),\n                                                  shuffle=False\n                                                 )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:01.247830Z","iopub.execute_input":"2024-12-18T17:16:01.248093Z","iopub.status.idle":"2024-12-18T17:16:01.484908Z","shell.execute_reply.started":"2024-12-18T17:16:01.248068Z","shell.execute_reply":"2024-12-18T17:16:01.484180Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_gen = train_datagen.flow_from_directory('/kaggle/working/dataset_dogs_vs_cats/train/', \n                                              class_mode='binary',\n                                              target_size = (image_size,image_size),\n                                              batch_size = bat_size,\n                                             )\n\nval_gen = test_datagen.flow_from_directory('/kaggle/working/dataset_dogs_vs_cats/test/', \n                                          class_mode='binary',\n                                          batch_size = bat_size,\n                                          target_size = (image_size,image_size),\n                                          shuffle = False\n                                         )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:01.486051Z","iopub.execute_input":"2024-12-18T17:16:01.486445Z","iopub.status.idle":"2024-12-18T17:16:02.018171Z","shell.execute_reply.started":"2024-12-18T17:16:01.486384Z","shell.execute_reply":"2024-12-18T17:16:02.017182Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Sử dụng MirroredStrategy để phân phối mô hình lên nhiều GPU","metadata":{}},{"cell_type":"code","source":"strategy = tf.distribute.MirroredStrategy()\n\nprint(f\"Number of devices: {strategy.num_replicas_in_sync}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:02.019326Z","iopub.execute_input":"2024-12-18T17:16:02.019678Z","iopub.status.idle":"2024-12-18T17:16:03.037900Z","shell.execute_reply.started":"2024-12-18T17:16:02.019641Z","shell.execute_reply":"2024-12-18T17:16:03.036869Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Định nghĩa mô hình ","metadata":{}},{"cell_type":"code","source":"# Input Layer\ninputs = Input(shape=(image_size, image_size, image_channel))\n\n# Block 1\nx = Conv2D(32, (3, 3), activation='relu')(inputs)\nx = BatchNormalization()(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\nx = Dropout(0.2)(x)\n\n# Block 2\nx = Conv2D(64, (3, 3), activation='relu')(x)\nx = BatchNormalization()(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\nx = Dropout(0.2)(x)\n\n# Block 3\nx = Conv2D(128, (3, 3), activation='relu')(x)\nx = BatchNormalization()(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\nx = Dropout(0.2)(x)\n\n# Block 4\nx = Conv2D(256, (3, 3), activation='relu')(x)\nx = BatchNormalization()(x)\nx = MaxPooling2D(pool_size=(2, 2))(x)\nx = Dropout(0.2)(x)\n\n# Fully Connected Layers\nx = Flatten()(x)\nx = Dense(512, activation='relu')(x)\nx = BatchNormalization()(x)\nx = Dropout(0.2)(x)\n\n# Output Layer\noutputs = Dense(2, activation='softmax')(x)\n\n# Build mô hình\nmodel = Model(inputs=inputs, outputs=outputs)\n\n# Compile mô hình\nmodel.compile(optimizer=Adam(),\n              loss='binary_crossentropy',\n              metrics=['accuracy'])\n\n# In cấu trúc mô hình\nmodel.summary()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:03.038911Z","iopub.execute_input":"2024-12-18T17:16:03.039159Z","iopub.status.idle":"2024-12-18T17:16:03.229129Z","shell.execute_reply.started":"2024-12-18T17:16:03.039135Z","shell.execute_reply":"2024-12-18T17:16:03.228077Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo ReduceLROnPlateau với các tham số được truyền bằng từ điển\nlr_params = {\n    'monitor': 'val_accuracy',  \n    'patience': 2,             \n    'factor': 0.5,              \n    'min_lr': 1e-5,             \n    'verbose': 1                \n}\n\nlearning_rate_reduction = ReduceLROnPlateau(**lr_params)\n\n# Khởi tạo EarlyStopping với các tham số\nearly_stopping_params = {\n    'monitor': 'val_loss',             \n    'patience': 3,                     \n    'restore_best_weights': True,     \n    'verbose': 0                      \n}\n\nearly_stopping = EarlyStopping(**early_stopping_params)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:03.230117Z","iopub.execute_input":"2024-12-18T17:16:03.230349Z","iopub.status.idle":"2024-12-18T17:16:03.235271Z","shell.execute_reply.started":"2024-12-18T17:16:03.230326Z","shell.execute_reply":"2024-12-18T17:16:03.234332Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Huấn luyện mô hình","metadata":{}},{"cell_type":"code","source":"cat_dog = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=20,\n    callbacks=[learning_rate_reduction, early_stopping]\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:16:03.236467Z","iopub.execute_input":"2024-12-18T17:16:03.236762Z","iopub.status.idle":"2024-12-18T17:49:00.327027Z","shell.execute_reply.started":"2024-12-18T17:16:03.236722Z","shell.execute_reply":"2024-12-18T17:49:00.326055Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Biểu đồ Loss và Accuracy","metadata":{}},{"cell_type":"code","source":"error = pd.DataFrame(cat_dog.history)\n\nplt.figure(figsize=(18,5),dpi=200)\n\nplt.subplot(121)\nplt.title('Cross Entropy Loss', fontsize=15)\nplt.plot(error['loss'], label='Training Loss')\nplt.plot(error['val_loss'], label='Validation Loss')\nplt.xlabel('Epochs', fontsize=12)\nplt.ylabel('Loss', fontsize=12)\nplt.legend()\n\nplt.subplot(122)\nplt.title('Classification Accuracy', fontsize=15)\nplt.plot(error['accuracy'], label='Training Accuracy')\nplt.plot(error['val_accuracy'], label='Validation Accuracy')\nplt.xlabel('Epochs', fontsize=12)\nplt.ylabel('Accuracy', fontsize=12)\nplt.legend()\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:49:00.328077Z","iopub.execute_input":"2024-12-18T17:49:00.328354Z","iopub.status.idle":"2024-12-18T17:49:01.062275Z","shell.execute_reply.started":"2024-12-18T17:49:00.328318Z","shell.execute_reply":"2024-12-18T17:49:01.061413Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Đánh giá hiệu quả của mô hình","metadata":{}},{"cell_type":"code","source":"def evaluate_model(generator, generator_name):\n    loss, acc = model.evaluate(generator, batch_size=bat_size, verbose=0)\n    print(f'The accuracy of the model for {generator_name} data is: {acc * 100:.2f}%')\n    print(f'The Loss of the model for {generator_name} data is: {loss:.4f}')\n\n# Đánh giá trên tập train và validation\nevaluate_model(train_generator, \"training\")\nevaluate_model(val_generator, \"validation\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:49:01.063663Z","iopub.execute_input":"2024-12-18T17:49:01.064100Z","iopub.status.idle":"2024-12-18T17:50:36.725075Z","shell.execute_reply.started":"2024-12-18T17:49:01.064057Z","shell.execute_reply":"2024-12-18T17:50:36.724149Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dự đoán nhãn cho dữ liệu kiểm tra\npredictions = model.predict(test_generator, batch_size=bat_size, verbose=0)\n\n# Lấy nhãn dự đoán bằng cách chọn lớp có xác suất cao nhất\ny_pred = np.argmax(predictions, axis=1)\n\n# Lấy nhãn thực tế từ test generator\ny_true = np.array(test_generator.labels)\n\n#Đánh giá mô hình trên dữ liệu kiểm tra\ntest_loss, test_acc = model.evaluate(test_generator, batch_size=bat_size, verbose=0)\n\n\nprint(f\"Test Accuracy: {test_acc * 100:.2f}%\")\nprint(f\"Test Loss: {test_loss:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:50:36.726300Z","iopub.execute_input":"2024-12-18T17:50:36.726569Z","iopub.status.idle":"2024-12-18T17:50:43.945223Z","shell.execute_reply.started":"2024-12-18T17:50:36.726543Z","shell.execute_reply":"2024-12-18T17:50:43.944284Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Báo cáo hiệu suất mô hình","metadata":{}},{"cell_type":"code","source":"labels =['Cat','Dog']\nprint(classification_report(y_true, y_pred,target_names=labels))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:50:43.946373Z","iopub.execute_input":"2024-12-18T17:50:43.946656Z","iopub.status.idle":"2024-12-18T17:50:43.962910Z","shell.execute_reply.started":"2024-12-18T17:50:43.946630Z","shell.execute_reply":"2024-12-18T17:50:43.962107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Tính toán ma trận nhầm lẫn\nconfusion_mtx = confusion_matrix(y_true, y_pred)\n\n# Tạo hình vẽ\nplt.figure(figsize=(8, 6), dpi=200)\n\n# Vẽ heatmap với seaborn\nsns.heatmap(confusion_mtx, annot=True, fmt='d', cmap='Blues', \n            xticklabels=labels, yticklabels=labels, \n            linewidths=1, linecolor='black', cbar=True)\n\n# Thêm nhãn cho các trục và tiêu đề\nplt.xlabel('Predicted Label', fontsize=12)\nplt.ylabel('True Label', fontsize=12)\nplt.title('Confusion Matrix', fontsize=14)\n\n# Hiển thị đồ thị\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:50:43.963998Z","iopub.execute_input":"2024-12-18T17:50:43.964608Z","iopub.status.idle":"2024-12-18T17:50:44.298648Z","shell.execute_reply.started":"2024-12-18T17:50:43.964561Z","shell.execute_reply":"2024-12-18T17:50:44.297758Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Dự đoán nhãn và tạo file submission","metadata":{}},{"cell_type":"code","source":"# Cài đặt kích thước ảnh và batch_size\nsize = (128, 128)\nbat_size = 32\n\n# Đường dẫn tới thư mục kiểm thử\ntest_dir = \"../working/test1/\"\n\n# Tạo DataFrame cho dữ liệu kiểm thử\ntest_data = pd.DataFrame({\n    \"filename\": os.listdir(test_dir), \n    \"label\": 'unknown'                \n})\n\n# Tạo bộ sinh dữ liệu cho dữ liệu kiểm thử\ntest_datagen = ImageDataGenerator(rescale=1./255)  \ntest_generator = test_datagen.flow_from_dataframe(\n    test_data,\n    directory=test_dir,\n    x_col='filename',\n    y_col='label',\n    target_size=size,\n    batch_size=bat_size,\n    shuffle=False  \n)\n\n# Dự đoán nhãn cho dữ liệu kiểm thử\ntest_predictions = model.predict(test_generator, verbose=0)\n\n# Chuyển kết quả thành nhãn\npredicted_labels = np.argmax(test_predictions, axis=1)\n\n# Ánh xạ kết quả dự đoán thành 'cat' và 'dog'\nlabel_mapping = {0: 'cat', 1: 'dog'}\ntest_data['label'] = pd.Series(predicted_labels).map(label_mapping)\n\n# Kiểm tra các giá trị trong DataFrame sau khi ánh xạ\nprint(test_data.head())\n\n# Đọc file submission mẫu\nsub = pd.read_csv('/kaggle/input/dogs-vs-cats/sampleSubmission.csv', index_col='id')\n\n# Gán nhãn dự đoán vào cột 'label' của file submission\nsub['label'] = test_data['label']\n\n# Xuất kết quả ra file CSV\nsub.to_csv('submission.csv', index=True)\n\nprint(\"Submission file created successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:50:44.299800Z","iopub.execute_input":"2024-12-18T17:50:44.300077Z","iopub.status.idle":"2024-12-18T17:51:01.313188Z","shell.execute_reply.started":"2024-12-18T17:50:44.300050Z","shell.execute_reply":"2024-12-18T17:51:01.312325Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Hiển thị ảnh và nhãn tương ứng","metadata":{}},{"cell_type":"code","source":"# Tạo ImageDataGenerator để làm việc với test data\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\ntest_generator = test_datagen.flow_from_dataframe(\n    dataframe=test_data,\n    directory=test_dir,\n    x_col='filename',\n    y_col='label',\n    target_size=(128, 128),\n    batch_size=20,\n    class_mode=None,  \n    shuffle=False\n)\n\n# Hiển thị 20 ảnh kiểm thử\nplt.figure(figsize=(20, 4))\nfor idx, (image, label) in enumerate(zip(test_generator[0], test_data['label'])):\n    plt.subplot(2, 10, idx + 1)  \n    plt.imshow(image)\n    plt.title(label)\n    plt.axis('off')\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:51:01.314276Z","iopub.execute_input":"2024-12-18T17:51:01.314582Z","iopub.status.idle":"2024-12-18T17:51:02.989991Z","shell.execute_reply.started":"2024-12-18T17:51:01.314555Z","shell.execute_reply":"2024-12-18T17:51:02.988935Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Save model","metadata":{}},{"cell_type":"code","source":"model.save(\"model_classification_dogs_and_cats.h5\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:51:02.991034Z","iopub.execute_input":"2024-12-18T17:51:02.991320Z","iopub.status.idle":"2024-12-18T17:51:03.173405Z","shell.execute_reply.started":"2024-12-18T17:51:02.991293Z","shell.execute_reply":"2024-12-18T17:51:03.172611Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.models import load_model\n\n# Tải lại mô hình\nmodel = load_model(\"model_classification_dogs_and_cats.h5\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-18T17:51:03.174359Z","iopub.execute_input":"2024-12-18T17:51:03.174600Z","iopub.status.idle":"2024-12-18T17:51:03.323903Z","shell.execute_reply.started":"2024-12-18T17:51:03.174577Z","shell.execute_reply":"2024-12-18T17:51:03.323185Z"}},"outputs":[],"execution_count":null}]}