{"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"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n# import seaborn as sns\nimport cv2\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau, TensorBoard, ModelCheckpoint\n\nfrom glob import glob \nimport os","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:16:47.929278Z","iopub.execute_input":"2023-04-12T14:16:47.929648Z","iopub.status.idle":"2023-04-12T14:16:47.938515Z","shell.execute_reply.started":"2023-04-12T14:16:47.929616Z","shell.execute_reply":"2023-04-12T14:16:47.937429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:09:11.110685Z","iopub.execute_input":"2023-04-12T14:09:11.111410Z","iopub.status.idle":"2023-04-12T14:09:11.120400Z","shell.execute_reply.started":"2023-04-12T14:09:11.111369Z","shell.execute_reply":"2023-04-12T14:09:11.118991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!unzip -q \"/kaggle/input/dogs-vs-cats/test1.zip\"\n!unzip -q \"/kaggle/input/dogs-vs-cats/train.zip\"","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:05:13.043515Z","iopub.execute_input":"2023-04-12T14:05:13.043972Z","iopub.status.idle":"2023-04-12T14:05:32.575066Z","shell.execute_reply.started":"2023-04-12T14:05:13.043934Z","shell.execute_reply":"2023-04-12T14:05:32.573752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = '/kaggle/working/train'","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for dirname, _, filenames in os.walk('/kaggle/working'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:09:33.189527Z","iopub.execute_input":"2023-04-12T14:09:33.189916Z","iopub.status.idle":"2023-04-12T14:09:33.556730Z","shell.execute_reply.started":"2023-04-12T14:09:33.189880Z","shell.execute_reply":"2023-04-12T14:09:33.555530Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load data\nfilenames = glob('/kaggle/working/train/*.jpg')\nlabels = [1 if 'dog' in pic else 0 for pic in os.listdir('/kaggle/working/train')]\n# os.listdir trả về một list các file trong thư mục (trả về theo tên file)\n# glob trả về một list các file trong thư mục theo định dạng\nprint(filenames[:5])\nprint(labels[:5])","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:10:14.411219Z","iopub.execute_input":"2023-04-12T14:10:14.411622Z","iopub.status.idle":"2023-04-12T14:10:14.504898Z","shell.execute_reply.started":"2023-04-12T14:10:14.411587Z","shell.execute_reply":"2023-04-12T14:10:14.503922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.DataFrame({'filename': filenames, 'label': labels})\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:10:18.182307Z","iopub.execute_input":"2023-04-12T14:10:18.182764Z","iopub.status.idle":"2023-04-12T14:10:18.229533Z","shell.execute_reply.started":"2023-04-12T14:10:18.182721Z","shell.execute_reply":"2023-04-12T14:10:18.228180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['label'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:10:24.088358Z","iopub.execute_input":"2023-04-12T14:10:24.088948Z","iopub.status.idle":"2023-04-12T14:10:24.399092Z","shell.execute_reply.started":"2023-04-12T14:10:24.088864Z","shell.execute_reply":"2023-04-12T14:10:24.398061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['label'] = df['label'].replace({0: 'cat', 1: 'dog'})\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:10:27.649259Z","iopub.execute_input":"2023-04-12T14:10:27.649743Z","iopub.status.idle":"2023-04-12T14:10:27.664179Z","shell.execute_reply.started":"2023-04-12T14:10:27.649707Z","shell.execute_reply":"2023-04-12T14:10:27.663070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train test split\nfrom sklearn.model_selection import train_test_split\n\ntrain_df, validate_df = train_test_split(df, test_size=0.20, random_state=42)\ntrain_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)\n# reset_index để reset lại index của dataframe\n\nprint(train_df.shape)\nprint(validate_df.shape)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:11.845152Z","iopub.execute_input":"2023-04-12T14:11:11.845947Z","iopub.status.idle":"2023-04-12T14:11:12.383397Z","shell.execute_reply.started":"2023-04-12T14:11:11.845903Z","shell.execute_reply":"2023-04-12T14:11:12.382295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read images test \nfilenames_test = os.listdir('/kaggle/working/test1')\n\ntest_df = pd.DataFrame({'filename': filenames_test})\nprint(test_df.shape)\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:15.725558Z","iopub.execute_input":"2023-04-12T14:11:15.725956Z","iopub.status.idle":"2023-04-12T14:11:15.746527Z","shell.execute_reply.started":"2023-04-12T14:11:15.725921Z","shell.execute_reply":"2023-04-12T14:11:15.745468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# img processing\nfrom keras.preprocessing.image import ImageDataGenerator\n\nIMG_SIZE = (150, 150)\nBATCH_SIZE = 32\n\ndatagen = ImageDataGenerator(rescale=1./255)\n# rescale = 1./255: chuyển đổi các giá trị pixel từ 0-255 thành 0-1\n\ntrain_generator = datagen.flow_from_dataframe(\n    dataframe=train_df,\n    # directory='../dataset/train', # thư mục chứa ảnh\n    x_col='filename',\n    y_col='label',\n    class_mode='binary', # binary: 2 lớp, categorical: nhiều lớp\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE\n)\n# flow_from_dataframe: tạo ra một generator từ dataframe\n\nvalidation_generator = datagen.flow_from_dataframe(\n    dataframe=validate_df,\n    # directory='../dataset/train',\n    x_col='filename',\n    y_col='label',\n    class_mode='binary',\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE\n)\n\ntest_generator = datagen.flow_from_dataframe(\n    dataframe=test_df,\n    directory='/kaggle/working/test1',\n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    shuffle=False\n)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:19.323816Z","iopub.execute_input":"2023-04-12T14:11:19.324918Z","iopub.status.idle":"2023-04-12T14:11:19.647447Z","shell.execute_reply.started":"2023-04-12T14:11:19.324843Z","shell.execute_reply":"2023-04-12T14:11:19.646473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_generator.class_indices) \n# trả về một dict chứa các class và index của class đó","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:23.159687Z","iopub.execute_input":"2023-04-12T14:11:23.160173Z","iopub.status.idle":"2023-04-12T14:11:23.166731Z","shell.execute_reply.started":"2023-04-12T14:11:23.160129Z","shell.execute_reply":"2023-04-12T14:11:23.165701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = train_generator.next()[:10]\n\n# plot 9 original training images\nplt.figure(figsize=(10, 10))\nfor i in range(9):\n    plt.subplot(3, 3, i+1)\n    plt.imshow(images[0][i])\n    plt.axis('off')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:25.353373Z","iopub.execute_input":"2023-04-12T14:11:25.353762Z","iopub.status.idle":"2023-04-12T14:11:26.460337Z","shell.execute_reply.started":"2023-04-12T14:11:25.353724Z","shell.execute_reply":"2023-04-12T14:11:26.448949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.applications import VGG16\n\nconv_base = VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))\n# weights: 'imagenet' sử dụng các trọng số được học trên tập dữ liệu ImageNet\n# include_top: False: không sử dụng các lớp fully-connected ở cuối mạng\n# input_shape: kích thước ảnh đầu vào\n","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:37.922283Z","iopub.execute_input":"2023-04-12T14:11:37.923219Z","iopub.status.idle":"2023-04-12T14:11:43.157547Z","shell.execute_reply.started":"2023-04-12T14:11:37.923169Z","shell.execute_reply":"2023-04-12T14:11:43.156480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Build model\nmodel = Sequential()\n\nmodel.add(Conv2D(filters=32, kernel_size=(3, 3), input_shape=(150, 150, 3), activation='relu', padding='same'))\nmodel.add(MaxPool2D(pool_size=(2, 2)))\nmodel.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same'))\nmodel.add(MaxPool2D(pool_size=(2, 2)))\nmodel.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same'))\nmodel.add(MaxPool2D(pool_size=(2, 2)))\n# Flatten\nmodel.add(Flatten())\nmodel.add(Dense(32, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(1, activation='sigmoid'))\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:11:59.046620Z","iopub.execute_input":"2023-04-12T14:11:59.047111Z","iopub.status.idle":"2023-04-12T14:11:59.164843Z","shell.execute_reply.started":"2023-04-12T14:11:59.047074Z","shell.execute_reply":"2023-04-12T14:11:59.164063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fit model\nmodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])\n\ncallbacks = [\n    EarlyStopping(monitor='val_loss', patience=5, verbose=1, mode='min'), # mode in {'auto', 'min', 'max'}, patience: sau bao nhiêu epoch không có sự cải thiện thì dừng lại, mode='min': chỉ dừng lại khi loss giảm dần, mode='max': chỉ dừng lại khi loss tăng dần\n    ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, verbose=1, mode='min'), # factor: giảm learning rate bằng factor, patience: số lần không có sự cải thiện nào thì dừng lại, verbose: thông báo\n]\n\nhistory = model.fit(\n    train_generator,\n    epochs=100,\n    batch_size=BATCH_SIZE,\n    validation_data=validation_generator, # dùng để đánh giá mô hình\n    validation_steps=validate_df.shape[0]//BATCH_SIZE, # số lượng ảnh dùng để đánh giá mô hình\n    steps_per_epoch=train_df.shape[0]//BATCH_SIZE, # số lượng ảnh dùng để train \n    verbose=1, # 0: không hiển thị, 1: hiển thị tiến trình, 2: hiển thị tiến trình chi tiết\\\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:16:54.650732Z","iopub.execute_input":"2023-04-12T14:16:54.651420Z","iopub.status.idle":"2023-04-12T14:30:25.178919Z","shell.execute_reply.started":"2023-04-12T14:16:54.651381Z","shell.execute_reply":"2023-04-12T14:30:25.177737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot performance\npd.DataFrame(history.history).plot(figsize=(8, 5))","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:30:25.181194Z","iopub.execute_input":"2023-04-12T14:30:25.181653Z","iopub.status.idle":"2023-04-12T14:30:29.593999Z","shell.execute_reply.started":"2023-04-12T14:30:25.181616Z","shell.execute_reply":"2023-04-12T14:30:29.592817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# predict\ntest_generator.reset()\npred = model.predict(test_generator, verbose=1)\nprint(pred[:10])","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:30:29.595385Z","iopub.execute_input":"2023-04-12T14:30:29.595873Z","iopub.status.idle":"2023-04-12T14:31:03.516720Z","shell.execute_reply.started":"2023-04-12T14:30:29.595813Z","shell.execute_reply":"2023-04-12T14:31:03.515532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = pred > 0.5\npred_label = ['dog' if p==1 else 'cat' for p in pred]\nprint(pred_label[:10])\n# plot 9 images with their predicted and true labels\nplt.figure(figsize=(10, 10))\nfor i in range(9):\n    plt.subplot(3, 3, i+1)\n    plt.imshow(images[0][i])\n    plt.title('Predicted: ' + pred_label[i])\n    plt.axis('off')\nplt.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:31:03.519680Z","iopub.execute_input":"2023-04-12T14:31:03.520072Z","iopub.status.idle":"2023-04-12T14:31:04.552428Z","shell.execute_reply.started":"2023-04-12T14:31:03.520034Z","shell.execute_reply":"2023-04-12T14:31:04.551423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# evaluate\nmodel.evaluate(validation_generator)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:31:04.553756Z","iopub.execute_input":"2023-04-12T14:31:04.554303Z","iopub.status.idle":"2023-04-12T14:31:18.206866Z","shell.execute_reply.started":"2023-04-12T14:31:04.554268Z","shell.execute_reply":"2023-04-12T14:31:18.205695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('model_first.h5')","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:31:18.208691Z","iopub.execute_input":"2023-04-12T14:31:18.209238Z","iopub.status.idle":"2023-04-12T14:31:18.272695Z","shell.execute_reply.started":"2023-04-12T14:31:18.209199Z","shell.execute_reply":"2023-04-12T14:31:18.271638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# vgg16 + model\nfor layer in conv_base.layers:\n    layer.trainable = False\n\nmodel_vgg = Sequential()\nmodel_vgg.add(conv_base)\nmodel_vgg.add(Flatten())\nmodel_vgg.add(Dense(32, activation='relu'))\nmodel_vgg.add(Dropout(0.5))\nmodel_vgg.add(Dense(1, activation='sigmoid'))\n\nmodel_vgg.summary()\n\nmodel_vgg.compile(loss='binary_crossentropy', optimizer='adam', metrics='accuracy')","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:31:18.274058Z","iopub.execute_input":"2023-04-12T14:31:18.274420Z","iopub.status.idle":"2023-04-12T14:31:18.399889Z","shell.execute_reply.started":"2023-04-12T14:31:18.274382Z","shell.execute_reply":"2023-04-12T14:31:18.398814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [\n    EarlyStopping(monitor='val_loss', patience=5, verbose=1, mode='min'), # mode in {'auto', 'min', 'max'}, patience: sau bao nhiêu epoch không có sự cải thiện thì dừng lại, mode='min': chỉ dừng lại khi loss giảm dần, mode='max': chỉ dừng lại khi loss tăng dần\n    ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, verbose=1, mode='min'), # factor: giảm learning rate bằng factor, patience: số lần không có sự cải thiện nào thì dừng lại, verbose: thông báo\n]\n\nhistory_vgg = model_vgg.fit(\n    train_generator,\n    epochs=100, \n    batch_size=BATCH_SIZE,\n    validation_data=validation_generator, # dùng để đánh giá mô hình\n    validation_steps=validate_df.shape[0]//BATCH_SIZE, # số lượng ảnh dùng để đánh giá mô hình\n    steps_per_epoch=train_df.shape[0]//BATCH_SIZE, # số lượng ảnh dùng để train\n    verbose=1, # 0: không hiển thị, 1: hiển thị tiến trình, 2: hiển thị tiến trình chi tiết\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:31:18.401418Z","iopub.execute_input":"2023-04-12T14:31:18.402293Z","iopub.status.idle":"2023-04-12T14:42:52.377095Z","shell.execute_reply.started":"2023-04-12T14:31:18.402253Z","shell.execute_reply":"2023-04-12T14:42:52.376127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot performance\npd.DataFrame(history_vgg.history).plot(figsize=(8, 5))","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:42:52.378845Z","iopub.execute_input":"2023-04-12T14:42:52.379222Z","iopub.status.idle":"2023-04-12T14:42:52.639796Z","shell.execute_reply.started":"2023-04-12T14:42:52.379179Z","shell.execute_reply":"2023-04-12T14:42:52.638893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# predict\ntest_generator.reset()\npred = model_vgg.predict(test_generator, verbose=1)\nprint(pred[:10])","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:42:52.642953Z","iopub.execute_input":"2023-04-12T14:42:52.643728Z","iopub.status.idle":"2023-04-12T14:43:30.960027Z","shell.execute_reply.started":"2023-04-12T14:42:52.643701Z","shell.execute_reply":"2023-04-12T14:43:30.958988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = pred > 0.5\npred_label = ['dog' if p==1 else 'cat' for p in pred]\nprint(pred_label[:10])\n# plot 9 images with their predicted and true labels\nplt.figure(figsize=(10, 10))\nfor i in range(9):\n    plt.subplot(3, 3, i+1)\n    plt.imshow(images[0][i])\n    plt.title('Predicted: ' + pred_label[i])\n    plt.axis('off')\nplt.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:43:30.961562Z","iopub.execute_input":"2023-04-12T14:43:30.961946Z","iopub.status.idle":"2023-04-12T14:43:32.227053Z","shell.execute_reply.started":"2023-04-12T14:43:30.961907Z","shell.execute_reply":"2023-04-12T14:43:32.226039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_vgg.save('model_second_vgg.h5')","metadata":{"execution":{"iopub.status.busy":"2023-04-12T14:43:32.228509Z","iopub.execute_input":"2023-04-12T14:43:32.229523Z","iopub.status.idle":"2023-04-12T14:43:32.467047Z","shell.execute_reply.started":"2023-04-12T14:43:32.229485Z","shell.execute_reply":"2023-04-12T14:43:32.466031Z"},"trusted":true},"execution_count":null,"outputs":[]}]}