{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":30627,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2025-02-10T14:00:52.734975Z","iopub.execute_input":"2025-02-10T14:00:52.735267Z","iopub.status.idle":"2025-02-10T14:00:53.040441Z","shell.execute_reply.started":"2025-02-10T14:00:52.735236Z","shell.execute_reply":"2025-02-10T14:00:53.039738Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(os.listdir(\"../input\"))\n\nimport zipfile\n\nwith zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats/test1.zip\",\"r\") as z:\n    z.extractall(\".\")\n    \nwith zipfile.ZipFile(\"/kaggle/input/dogs-vs-cats/train.zip\",\"r\") as z:\n    z.extractall(\".\")","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:00:53.043608Z","iopub.execute_input":"2025-02-10T14:00:53.043844Z","iopub.status.idle":"2025-02-10T14:01:02.250218Z","shell.execute_reply.started":"2025-02-10T14:00:53.043822Z","shell.execute_reply":"2025-02-10T14:01:02.249473Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"!ls train","metadata":{"execution":{"iopub.status.busy":"2024-01-08T06:57:18.293035Z","iopub.execute_input":"2024-01-08T06:57:18.293457Z","iopub.status.idle":"2024-01-08T06:57:19.311078Z","shell.execute_reply.started":"2024-01-08T06:57:18.293422Z","shell.execute_reply":"2024-01-08T06:57:19.309969Z"}}},{"cell_type":"code","source":"# plot dog photos from the dogs vs cats dataset\nfrom matplotlib import pyplot\nfrom matplotlib.image import imread\n# define location of dataset\nfolder = 'train/'\n# plot first few images\nfor i in range(9):\n\t# define subplot\n\tpyplot.subplot(330 + 1 + i)\n\t# define filename\n\tfilename = folder + 'dog.' + str(i) + '.jpg'\n\t# load image pixels\n\timage = imread(filename)\n\t# plot raw pixel data\n\tpyplot.imshow(image)\n# show the figure\npyplot.show()","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:02.252134Z","iopub.execute_input":"2025-02-10T14:01:02.252388Z","iopub.status.idle":"2025-02-10T14:01:03.294582Z","shell.execute_reply.started":"2025-02-10T14:01:02.252365Z","shell.execute_reply":"2025-02-10T14:01:03.293749Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# plot cat photos from the dogs vs cats dataset\nfrom matplotlib import pyplot\nfrom matplotlib.image import imread\n# define location of dataset\nfolder = 'train/'\n# plot first few images\nfor i in range(9):\n\t# define subplot\n\tpyplot.subplot(330 + 1 + i)\n\t# define filename\n\tfilename = folder + 'cat.' + str(i) + '.jpg'\n\t# load image pixels\n\timage = imread(filename)\n\t# plot raw pixel data\n\tpyplot.imshow(image)\n# show the figure\npyplot.show()","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:03.295797Z","iopub.execute_input":"2025-02-10T14:01:03.296076Z","iopub.status.idle":"2025-02-10T14:01:04.515363Z","shell.execute_reply.started":"2025-02-10T14:01:03.296051Z","shell.execute_reply":"2025-02-10T14:01:04.514400Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# load dogs vs cats dataset, reshape and save to a new file\nfrom os import listdir\nfrom numpy import asarray\nfrom numpy import save\nfrom keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import img_to_array","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:04.516506Z","iopub.execute_input":"2025-02-10T14:01:04.516824Z","iopub.status.idle":"2025-02-10T14:01:07.291441Z","shell.execute_reply.started":"2025-02-10T14:01:04.516797Z","shell.execute_reply":"2025-02-10T14:01:07.290208Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# organize dataset into a useful structure\nfrom os import makedirs\nfrom os import listdir\nfrom shutil import copyfile\nfrom random import seed\nfrom random import random","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:07.292547Z","iopub.execute_input":"2025-02-10T14:01:07.293372Z","iopub.status.idle":"2025-02-10T14:01:07.299210Z","shell.execute_reply.started":"2025-02-10T14:01:07.293327Z","shell.execute_reply":"2025-02-10T14:01:07.298435Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# create directories\ndataset_home = 'dataset_dogs_vs_cats/'\nsubdirs = ['train/', 'test/']\nfor subdir in subdirs:\n\t# create label subdirectories\n\tlabeldirs = ['dogs/', 'cats/']\n\tfor labldir in labeldirs:\n\t\tnewdir = dataset_home + subdir + labldir\n\t\tmakedirs(newdir, exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:07.300846Z","iopub.execute_input":"2025-02-10T14:01:07.301366Z","iopub.status.idle":"2025-02-10T14:01:07.320172Z","shell.execute_reply.started":"2025-02-10T14:01:07.301328Z","shell.execute_reply":"2025-02-10T14:01:07.318834Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# seed random number generator\nseed(1)\n# define ratio of pictures to use for validation\nval_ratio = 0.25\n# copy training dataset images into subdirectories\nsrc_directory = 'train/'\nfor file in listdir(src_directory):\n\tsrc = src_directory + '/' + file\n\tdst_dir = 'train/'\n\tif random() < val_ratio:\n\t\tdst_dir = 'test/'\n\tif file.startswith('cat'):\n\t\tdst = dataset_home + dst_dir + 'cats/'  + file\n\t\tcopyfile(src, dst)\n\telif file.startswith('dog'):\n\t\tdst = dataset_home + dst_dir + 'dogs/'  + file\n\t\tcopyfile(src, dst)","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:07.321570Z","iopub.execute_input":"2025-02-10T14:01:07.321899Z","iopub.status.idle":"2025-02-10T14:01:10.402853Z","shell.execute_reply.started":"2025-02-10T14:01:07.321870Z","shell.execute_reply":"2025-02-10T14:01:10.402120Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!ls -l dataset_dogs_vs_cats/train/dogs | wc -l","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:10.403942Z","iopub.execute_input":"2025-02-10T14:01:10.404198Z","iopub.status.idle":"2025-02-10T14:01:11.508919Z","shell.execute_reply.started":"2025-02-10T14:01:10.404177Z","shell.execute_reply":"2025-02-10T14:01:11.507984Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!ls -l dataset_dogs_vs_cats/train/cats | wc -l","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:11.510522Z","iopub.execute_input":"2025-02-10T14:01:11.511356Z","iopub.status.idle":"2025-02-10T14:01:12.583832Z","shell.execute_reply.started":"2025-02-10T14:01:11.511315Z","shell.execute_reply":"2025-02-10T14:01:12.582888Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip -q install livelossplot==0.5.5","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:12.585151Z","iopub.execute_input":"2025-02-10T14:01:12.585439Z","iopub.status.idle":"2025-02-10T14:01:21.012362Z","shell.execute_reply.started":"2025-02-10T14:01:12.585414Z","shell.execute_reply":"2025-02-10T14:01:21.011064Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from livelossplot import PlotLossesKeras","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:21.016702Z","iopub.execute_input":"2025-02-10T14:01:21.016971Z","iopub.status.idle":"2025-02-10T14:01:21.027353Z","shell.execute_reply.started":"2025-02-10T14:01:21.016948Z","shell.execute_reply":"2025-02-10T14:01:21.026750Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Prepare Final Dataset","metadata":{}},{"cell_type":"code","source":"# save the final model to file\nfrom keras.applications.vgg16 import VGG16\nfrom keras.applications.xception import Xception\nfrom keras.models import Model\nfrom keras.layers import Dense\nfrom keras.layers import Flatten\nfrom keras.optimizers import SGD\nfrom keras.preprocessing.image import ImageDataGenerator","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:21.028416Z","iopub.execute_input":"2025-02-10T14:01:21.028675Z","iopub.status.idle":"2025-02-10T14:01:21.033418Z","shell.execute_reply.started":"2025-02-10T14:01:21.028653Z","shell.execute_reply":"2025-02-10T14:01:21.032653Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"xcep_model = Xception(include_top=False, input_shape=(299, 299, 3))\nxcep_model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-01-27T04:11:23.494572Z","iopub.execute_input":"2024-01-27T04:11:23.495217Z","iopub.status.idle":"2024-01-27T04:11:26.579883Z","shell.execute_reply.started":"2024-01-27T04:11:23.495182Z","shell.execute_reply":"2024-01-27T04:11:26.578335Z"}}},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# ตั้งค่า ImageDataGenerator\ndatagen = ImageDataGenerator(rescale=1.0/255.0, validation_split=0.2)\n\n# โหลดข้อมูล Train และ Validation\ntrain_it = datagen.flow_from_directory(\n    dataset_home + \"train/\",\n    class_mode=\"binary\",\n    batch_size=32,  # สามารถลดเหลือ 16 ถ้า RAM เต็ม\n    target_size=(200, 200),\n    subset=\"training\"\n)\n\ntest_it = datagen.flow_from_directory(\n    dataset_home + \"train/\",\n    class_mode=\"binary\",\n    batch_size=32,\n    target_size=(200, 200),\n    subset=\"validation\"\n)","metadata":{"execution":{"iopub.status.busy":"2025-02-10T14:01:21.034409Z","iopub.execute_input":"2025-02-10T14:01:21.034739Z","iopub.status.idle":"2025-02-10T14:01:21.637198Z","shell.execute_reply.started":"2025-02-10T14:01:21.034709Z","shell.execute_reply":"2025-02-10T14:01:21.636515Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:01:21.638164Z","iopub.execute_input":"2025-02-10T14:01:21.638420Z","iopub.status.idle":"2025-02-10T14:01:21.643920Z","shell.execute_reply.started":"2025-02-10T14:01:21.638393Z","shell.execute_reply":"2025-02-10T14:01:21.642968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# define cnn model\ndef define_model():\n\tmodel = Sequential()\n\tmodel.add(Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same', input_shape=(200, 200, 3)))\n\tmodel.add(MaxPooling2D((2, 2)))\n\tmodel.add(Flatten())\n\tmodel.add(Dense(128, activation='relu', kernel_initializer='he_uniform'))\n\tmodel.add(Dense(1, activation='sigmoid'))\n\t# compile model\n\topt = SGD(lr=0.001, momentum=0.9)\n\tmodel.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy'])\n\treturn model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:01:21.645033Z","iopub.execute_input":"2025-02-10T14:01:21.645296Z","iopub.status.idle":"2025-02-10T14:01:21.652477Z","shell.execute_reply.started":"2025-02-10T14:01:21.645274Z","shell.execute_reply":"2025-02-10T14:01:21.651649Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# define model\nmodel = define_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:01:21.653441Z","iopub.execute_input":"2025-02-10T14:01:21.653725Z","iopub.status.idle":"2025-02-10T14:01:22.400833Z","shell.execute_reply.started":"2025-02-10T14:01:21.653673Z","shell.execute_reply":"2025-02-10T14:01:22.400150Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:01:22.401675Z","iopub.execute_input":"2025-02-10T14:01:22.401916Z","iopub.status.idle":"2025-02-10T14:01:22.421057Z","shell.execute_reply.started":"2025-02-10T14:01:22.401895Z","shell.execute_reply":"2025-02-10T14:01:22.420339Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# fit model\nhistory = model.fit(train_it, steps_per_epoch=len(train_it),\n\tvalidation_data=test_it, validation_steps=len(test_it), epochs=1, verbose=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:01:22.422373Z","iopub.execute_input":"2025-02-10T14:01:22.422678Z","iopub.status.idle":"2025-02-10T14:01:54.632755Z","shell.execute_reply.started":"2025-02-10T14:01:22.422648Z","shell.execute_reply":"2025-02-10T14:01:54.632032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# evaluate model\n_, acc = model.evaluate_generator(test_it, steps=len(test_it), verbose=1)\nprint('> %.3f' % (acc * 100.0))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:01:54.634061Z","iopub.execute_input":"2025-02-10T14:01:54.634420Z","iopub.status.idle":"2025-02-10T14:02:00.659582Z","shell.execute_reply.started":"2025-02-10T14:01:54.634386Z","shell.execute_reply":"2025-02-10T14:02:00.658750Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# plot diagnostic learning curves\ndef summarize_diagnostics(history):\n\t# plot loss\n\tpyplot.subplot(211)\n\tpyplot.title('Cross Entropy Loss')\n\tpyplot.plot(history.history['loss'], color='blue', label='train')\n\tpyplot.plot(history.history['val_loss'], color='orange', label='test')\n\t# plot accuracy\n\tpyplot.subplot(212)\n\tpyplot.title('Classification Accuracy')\n\tpyplot.plot(history.history['accuracy'], color='blue', label='train')\n\tpyplot.plot(history.history['val_accuracy'], color='orange', label='test')\n\t# save plot to file\n\tfilename = sys.argv[0].split('/')[-1]\n\tpyplot.savefig(filename + '_plot.png')\n\tpyplot.close()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:02:00.660800Z","iopub.execute_input":"2025-02-10T14:02:00.661436Z","iopub.status.idle":"2025-02-10T14:02:00.666643Z","shell.execute_reply.started":"2025-02-10T14:02:00.661407Z","shell.execute_reply":"2025-02-10T14:02:00.665809Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 5 pretrained","metadata":{}},{"cell_type":"markdown","source":"# datagen","metadata":{}},{"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\n# ✅ ใช้ Data Augmentation เดียวกัน\ndatagen = ImageDataGenerator(\n    featurewise_center=True,\n    rotation_range=30,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    fill_mode='nearest'\n)\n\n# ✅ ตั้งค่า mean ให้ตรงกับ ImageNet\ndatagen.mean = [123.68, 116.779, 103.939]\n\n# ✅ ฟังก์ชันโหลด dataset (ใช้ `target_size` ตามโมเดลที่เรียก)\ndef load_data(target_size):\n    train_it = datagen.flow_from_directory(\n        'dataset_dogs_vs_cats/train/',\n        class_mode='binary', batch_size=64, target_size=target_size\n    )\n    test_it = datagen.flow_from_directory(\n        'dataset_dogs_vs_cats/test/',\n        class_mode='binary', batch_size=64, target_size=target_size\n    )\n    return train_it, test_it\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:02:00.667759Z","iopub.execute_input":"2025-02-10T14:02:00.668011Z","iopub.status.idle":"2025-02-10T14:02:00.685609Z","shell.execute_reply.started":"2025-02-10T14:02:00.667984Z","shell.execute_reply":"2025-02-10T14:02:00.684579Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# vgg16","metadata":{}},{"cell_type":"code","source":"from keras.applications.vgg16 import VGG16\nfrom keras.models import Model\nfrom keras.layers import Dense, Flatten\nfrom keras.optimizers import Adam\nfrom keras.callbacks import EarlyStopping\nimport matplotlib.pyplot as plt\n\n# ✅ สร้างโมเดล VGG16\ndef define_vgg16():\n    model = VGG16(include_top=False, input_shape=(224, 224, 3), weights='imagenet')\n\n    # Fine-Tune เฉพาะ 4 เลเยอร์สุดท้าย\n    for layer in model.layers[:-4]:\n        layer.trainable = False\n    for layer in model.layers[-4:]:\n        layer.trainable = True\n\n    # Fully Connected Layers\n    flat1 = Flatten()(model.output)\n    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n    output = Dense(1, activation='sigmoid')(class1)\n\n    model = Model(inputs=model.input, outputs=output)\n    model.compile(optimizer=Adam(learning_rate=0.0001), loss='binary_crossentropy', metrics=['accuracy'])\n    return model\n\n# ✅ โหลดข้อมูล\ntrain_it_vgg, test_it_vgg = load_data((224, 224))\n\n# ✅ สร้างโมเดล VGG16\nmodel_vgg = define_vgg16()\n\n# ✅ Train VGG16\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)\nhistory_vgg = model_vgg.fit(\n    train_it_vgg, steps_per_epoch=len(train_it_vgg),\n    validation_data=test_it_vgg, validation_steps=len(test_it_vgg),\n    epochs=3, verbose=1, callbacks=[early_stopping]\n)\n\n# ✅ Evaluate VGG16\n_, acc_vgg = model_vgg.evaluate(test_it_vgg, steps=len(test_it_vgg), verbose=1)\nprint(f'\\n✅ VGG16 Accuracy: {acc_vgg * 100:.2f}%')\n\n# ✅ Plot ผลลัพธ์\nplt.figure(figsize=(10, 4))\n\n# Plot Accuracy\nplt.subplot(1, 2, 1)\nplt.plot(history_vgg.history['accuracy'], label='train')\nplt.plot(history_vgg.history['val_accuracy'], label='val')\nplt.title('VGG16 Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\n\n# Plot Loss\nplt.subplot(1, 2, 2)\nplt.plot(history_vgg.history['loss'], label='train')\nplt.plot(history_vgg.history['val_loss'], label='val')\nplt.title('VGG16 Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:47:51.883072Z","iopub.execute_input":"2025-02-10T14:47:51.883493Z","iopub.status.idle":"2025-02-10T14:59:12.330832Z","shell.execute_reply.started":"2025-02-10T14:47:51.883457Z","shell.execute_reply":"2025-02-10T14:59:12.329873Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Xception","metadata":{"execution":{"iopub.status.busy":"2025-02-10T12:56:13.501215Z","iopub.status.idle":"2025-02-10T12:56:13.501514Z","shell.execute_reply.started":"2025-02-10T12:56:13.501377Z","shell.execute_reply":"2025-02-10T12:56:13.501390Z"}}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom keras.applications.xception import Xception\nfrom keras.models import Model\nfrom keras.layers import Dense, GlobalAveragePooling2D, BatchNormalization\nfrom keras.optimizers import Adam\nfrom keras.callbacks import EarlyStopping\n\n# ✅ สร้างโมเดล Xception\ndef define_xception():\n    model = Xception(include_top=False, input_shape=(299, 299, 3), weights='imagenet')\n\n    # ✅ Fine-Tune 8 เลเยอร์สุดท้าย (แทน 4)\n    for layer in model.layers[:-8]:\n        layer.trainable = False\n    for layer in model.layers[-8:]:\n        layer.trainable = True\n\n    # ✅ Fully Connected Layers (เพิ่ม Batch Normalization)\n    gap = GlobalAveragePooling2D()(model.output)\n    gap = BatchNormalization()(gap)  # เพิ่ม Batch Normalization ลด NaN\n    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(gap)\n    output = Dense(1, activation='sigmoid')(class1)\n\n    model = Model(inputs=model.input, outputs=output)\n\n    # ✅ ลด Learning Rate และใช้ clipvalue เพื่อลด NaN\n    opt = Adam(learning_rate=0.00005, clipvalue=1.0)  # ลด LR จาก 0.0001 → 0.00005\n    model.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy'])\n    return model\n\n# ✅ โหลดข้อมูล (ลด Batch Size เป็น 32 เพื่อลดภาระ GPU)\ntrain_it_xc, test_it_xc = load_data((299, 299))\n\n# ✅ สร้างโมเดล Xception\nmodel_xc = define_xception()\n\n# ✅ Train Xception\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)\nhistory_xc = model_xc.fit(\n    train_it_xc, steps_per_epoch=len(train_it_xc),\n    validation_data=test_it_xc, validation_steps=len(test_it_xc),\n    epochs=3, verbose=1, callbacks=[early_stopping]\n)\n\n# ✅ Evaluate Xception\n_, acc_xc = model_xc.evaluate(test_it_xc, steps=len(test_it_xc), verbose=1)\nprint(f'\\n✅ Xception Accuracy: {acc_xc * 100:.2f}%')\n\n# ✅ Plot ผลลัพธ์\nplt.figure(figsize=(10, 4))\n\n# Plot Accuracy\nplt.subplot(1, 2, 1)\nplt.plot(history_xc.history['accuracy'], label='Train')\nplt.plot(history_xc.history['val_accuracy'], label='Validation')\nplt.title('Xception Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\n\n# Plot Loss\nplt.subplot(1, 2, 2)\nplt.plot(history_xc.history['loss'], label='Train')\nplt.plot(history_xc.history['val_loss'], label='Validation')\nplt.title('Xception Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T14:59:12.332733Z","iopub.execute_input":"2025-02-10T14:59:12.333385Z","iopub.status.idle":"2025-02-10T15:18:20.746197Z","shell.execute_reply.started":"2025-02-10T14:59:12.333358Z","shell.execute_reply":"2025-02-10T15:18:20.745326Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# VGG19","metadata":{}},{"cell_type":"code","source":"from keras.applications.vgg19 import VGG19\n\n# ✅ สร้างโมเดล VGG19\ndef define_vgg19():\n    model = VGG19(include_top=False, input_shape=(224, 224, 3), weights='imagenet')\n\n    # Fine-Tune เฉพาะ 4 เลเยอร์สุดท้าย\n    for layer in model.layers[:-4]:\n        layer.trainable = False\n    for layer in model.layers[-4:]:\n        layer.trainable = True\n\n    # Fully Connected Layers\n    flat1 = Flatten()(model.output)\n    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n    output = Dense(1, activation='sigmoid')(class1)\n\n    model = Model(inputs=model.input, outputs=output)\n    model.compile(optimizer=Adam(learning_rate=0.0001), loss='binary_crossentropy', metrics=['accuracy'])\n    return model\n\n# ✅ โหลดข้อมูล\ntrain_it_vgg19, test_it_vgg19 = load_data((224, 224))\n\n# ✅ สร้างโมเดล VGG19\nmodel_vgg19 = define_vgg19()\n\n# ✅ Train VGG19\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)\nhistory_vgg19 = model_vgg19.fit(\n    train_it_vgg19, steps_per_epoch=len(train_it_vgg19),\n    validation_data=test_it_vgg19, validation_steps=len(test_it_vgg19),\n    epochs=3, verbose=1, callbacks=[early_stopping]\n)\n\n# ✅ Evaluate VGG19\n_, acc_vgg19 = model_vgg19.evaluate(test_it_vgg19, steps=len(test_it_vgg19), verbose=1)\nprint(f'\\n✅ VGG19 Accuracy: {acc_vgg19 * 100:.2f}%')\n\n# ✅ Plot ผลลัพธ์\nplt.figure(figsize=(10, 4))\n\n# Plot Accuracy\nplt.subplot(1, 2, 1)\nplt.plot(history_vgg19.history['accuracy'], label='train')\nplt.plot(history_vgg19.history['val_accuracy'], label='val')\nplt.title('VGG19 Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\n\n# Plot Loss\nplt.subplot(1, 2, 2)\nplt.plot(history_vgg19.history['loss'], label='train')\nplt.plot(history_vgg19.history['val_loss'], label='val')\nplt.title('VGG19 Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T15:18:20.747460Z","iopub.execute_input":"2025-02-10T15:18:20.747819Z","iopub.status.idle":"2025-02-10T15:29:37.610865Z","shell.execute_reply.started":"2025-02-10T15:18:20.747787Z","shell.execute_reply":"2025-02-10T15:29:37.610031Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# InceptionV3","metadata":{}},{"cell_type":"code","source":"from keras.applications.inception_v3 import InceptionV3\nfrom keras.models import Model\nfrom keras.layers import Dense, GlobalAveragePooling2D\nfrom keras.optimizers import Adam\nfrom keras.callbacks import EarlyStopping\nimport matplotlib.pyplot as plt\n\n# ✅ สร้างโมเดล InceptionV3\ndef define_inceptionv3():\n    model = InceptionV3(include_top=False, input_shape=(299, 299, 3), weights='imagenet')\n\n    # Fine-Tune เฉพาะ 4 เลเยอร์สุดท้าย\n    for layer in model.layers[:-4]:\n        layer.trainable = False\n    for layer in model.layers[-4:]:\n        layer.trainable = True\n\n    # Fully Connected Layers\n    gap = GlobalAveragePooling2D()(model.output)\n    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(gap)\n    output = Dense(1, activation='sigmoid')(class1)\n\n    model = Model(inputs=model.input, outputs=output)\n    model.compile(optimizer=Adam(learning_rate=0.0001), loss='binary_crossentropy', metrics=['accuracy'])\n    return model\n\n# ✅ โหลดข้อมูล\ntrain_it_inc, test_it_inc = load_data((299, 299))\n\n# ✅ สร้างโมเดล InceptionV3\nmodel_inc = define_inceptionv3()\n\n# ✅ Train InceptionV3\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)\nhistory_inc = model_inc.fit(\n    train_it_inc, steps_per_epoch=len(train_it_inc),\n    validation_data=test_it_inc, validation_steps=len(test_it_inc),\n    epochs=3, verbose=1, callbacks=[early_stopping]\n)\n\n# ✅ Evaluate InceptionV3\n_, acc_inc = model_inc.evaluate(test_it_inc, steps=len(test_it_inc), verbose=1)\nprint(f'\\n✅ InceptionV3 Accuracy: {acc_inc * 100:.2f}%')\n\n# ✅ Plot ผลลัพธ์\nplt.figure(figsize=(10, 4))\n\n# Plot Accuracy\nplt.subplot(1, 2, 1)\nplt.plot(history_inc.history['accuracy'], label='train')\nplt.plot(history_inc.history['val_accuracy'], label='val')\nplt.title('InceptionV3 Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\n\n# Plot Loss\nplt.subplot(1, 2, 2)\nplt.plot(history_inc.history['loss'], label='train')\nplt.plot(history_inc.history['val_loss'], label='val')\nplt.title('InceptionV3 Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T15:29:37.613151Z","iopub.execute_input":"2025-02-10T15:29:37.613478Z","iopub.status.idle":"2025-02-10T15:48:19.514582Z","shell.execute_reply.started":"2025-02-10T15:29:37.613456Z","shell.execute_reply":"2025-02-10T15:48:19.513835Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# MobileNetV2","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom keras.applications.mobilenet_v2 import MobileNetV2\nfrom keras.models import Model\nfrom keras.layers import Dense, GlobalAveragePooling2D, BatchNormalization\nfrom keras.optimizers import Adam\nfrom keras.callbacks import EarlyStopping\n\n# ✅ สร้างโมเดล MobileNetV2\ndef define_mobilenetv2():\n    model = MobileNetV2(include_top=False, input_shape=(224, 224, 3), weights='imagenet')\n\n    # ✅ Fine-Tune 12 เลเยอร์สุดท้าย\n    for layer in model.layers[:-12]:\n        layer.trainable = False\n    for layer in model.layers[-12:]:\n        layer.trainable = True\n\n    # ✅ Fully Connected Layers\n    gap = GlobalAveragePooling2D()(model.output)\n    gap = BatchNormalization()(gap)  # ✅ ป้องกัน Numerical Instability\n    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(gap)\n    output = Dense(1, activation='sigmoid')(class1)\n\n    model = Model(inputs=model.input, outputs=output)\n\n    # ✅ ใช้ Adam Optimizer พร้อม Gradient Clipping\n    opt = Adam(learning_rate=0.00005, clipnorm=1.0)\n    model.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy'])\n    return model\n\n# ✅ โหลดข้อมูล (ใช้ขนาด 224x224)\ntrain_it_mob, test_it_mob = load_data((224, 224))\n\n# ✅ สร้างโมเดล MobileNetV2\nmodel_mob = define_mobilenetv2()\n\n# ✅ Train MobileNetV2\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)\nhistory_mob = model_mob.fit(\n    train_it_mob, steps_per_epoch=len(train_it_mob),\n    validation_data=test_it_mob, validation_steps=len(test_it_mob),\n    epochs=3, verbose=1, callbacks=[early_stopping]\n)\n\n# ✅ Evaluate MobileNetV2\n_, acc_mob = model_mob.evaluate(test_it_mob, steps=len(test_it_mob), verbose=1)\nprint(f'\\n✅ MobileNetV2 Accuracy: {acc_mob * 100:.2f}%')\n\n# ✅ Plot ผลลัพธ์\nplt.figure(figsize=(10, 4))\n\n# Plot Accuracy\nplt.subplot(1, 2, 1)\nplt.plot(history_mob.history['accuracy'], label='Train')\nplt.plot(history_mob.history['val_accuracy'], label='Validation')\nplt.title('MobileNetV2 Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\n\n# Plot Loss\nplt.subplot(1, 2, 2)\nplt.plot(history_mob.history['loss'], label='Train')\nplt.plot(history_mob.history['val_loss'], label='Validation')\nplt.title('MobileNetV2 Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T15:48:19.515813Z","iopub.execute_input":"2025-02-10T15:48:19.516085Z","iopub.status.idle":"2025-02-10T15:59:06.191574Z","shell.execute_reply.started":"2025-02-10T15:48:19.516062Z","shell.execute_reply":"2025-02-10T15:59:06.190725Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Random 10 to predict","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport random\nimport matplotlib.pyplot as plt\nfrom keras.preprocessing.image import load_img, img_to_array\nfrom keras.applications.vgg16 import preprocess_input as preprocess_vgg\nfrom keras.applications.xception import preprocess_input as preprocess_xc\n\n# ✅ โหลดโมเดลทั้งหมด\nmodels = {\n    \"VGG16\": model_vgg,\n    \"VGG19\": model_vgg19,\n    \"Xception\": model_xc,\n    \"InceptionV3\": model_inc,\n    \"MobileNetV2\": model_mob\n}\n\n# ✅ กำหนดขนาด Input ของแต่ละโมเดล\nmodel_input_sizes = {\n    \"VGG16\": (224, 224),\n    \"VGG19\": (224, 224),\n    \"Xception\": (299, 299),\n    \"InceptionV3\": (299, 299),\n    \"MobileNetV2\": (224, 224)\n}\n\n# ✅ เลือกฟังก์ชัน preprocess_input ให้ตรงกับโมเดล\npreprocess_functions = {\n    \"VGG16\": preprocess_vgg,\n    \"VGG19\": preprocess_vgg,\n    \"Xception\": preprocess_xc,\n    \"InceptionV3\": preprocess_xc,\n    \"MobileNetV2\": preprocess_vgg\n}\n\n# ✅ ตั้งค่าพาธของชุดทดสอบ\ntest_dir = \"dataset_dogs_vs_cats/test/\"\ncategories = [\"cats\", \"dogs\"]\n\n# ✅ สุ่มเลือก 5 รูปจากแต่ละคลาส\nnum_samples = 5\nselected_images = {category: random.sample(os.listdir(os.path.join(test_dir, category)), num_samples) for category in categories}\n\n# ✅ บันทึกพาธของภาพที่สุ่มได้ (ใช้เป็น Image 1 - 10)\nimage_paths = []\nfor category in categories:\n    for img_name in selected_images[category]:\n        img_path = os.path.join(test_dir, category, img_name)\n        image_paths.append(img_path)\n\n# ✅ สร้าง DataFrame สำหรับแสดงผล\nresults = []\n\n# ✅ วนลูปพยากรณ์จากทุกโมเดล (ใช้ Image 1 - 10 เหมือนกัน)\nfor model_name, model in models.items():\n    target_size = model_input_sizes[model_name]\n    preprocess_fn = preprocess_functions[model_name]\n\n    for img_index, img_path in enumerate(image_paths, start=1):\n        img = load_img(img_path, target_size=target_size)\n        img_array = img_to_array(img)\n        img_array = preprocess_fn(np.expand_dims(img_array, axis=0))\n\n        # ✅ ทำการพยากรณ์\n        prediction = model.predict(img_array)[0][0]\n        predicted_label = \"Cat 🐱\" if prediction > 0.5 else \"Dog 🐶\"\n        confidence = max(prediction, 1 - prediction)\n\n        # ✅ ตรวจสอบว่าทายถูกหรือผิด\n        true_label = \"Cats\" if \"cat\" in img_path else \"Dogs\"\n        correct_label = \"Cat 🐱\" if true_label == \"Cats\" else \"Dog 🐶\"\n        is_correct = \"T ✅\" if predicted_label == correct_label else f\"F ❌\"\n\n        # ✅ เก็บผลลัพธ์ลง DataFrame\n        results.append([model_name, true_label, f\"Image {img_index}\", predicted_label, f\"{confidence:.2f}\", is_correct])\n\n# ✅ STEP 1: แสดงภาพที่สุ่มมา (จัดเรียง 2 แถว พร้อมหมายเลขรูป 1 - 10)\nfig, axes = plt.subplots(2, num_samples, figsize=(10, 6))  # ✅ 2 แถว: บน = แมว, ล่าง = หมา\n\n# 🔹 **แถวบน = แมว**\nfor i, img_path in enumerate(image_paths[:num_samples]):\n    img = load_img(img_path)\n    axes[0, i].imshow(img)\n    axes[0, i].axis(\"off\")\n    axes[0, i].set_title(f\"Cat 🐱 (Image {i+1})\", fontsize=10)\n\n# 🔹 **แถวล่าง = หมา**\nfor i, img_path in enumerate(image_paths[num_samples:]):\n    img = load_img(img_path)\n    axes[1, i].imshow(img)\n    axes[1, i].axis(\"off\")\n    axes[1, i].set_title(f\"Dog 🐶 (Image {i+num_samples+1})\", fontsize=10)\n\nplt.tight_layout()\nplt.show()\n\n# ✅ STEP 2: แสดงผลพยากรณ์แบบ DataFrame (ตาราง)\ndf_results = pd.DataFrame(results, columns=[\"Model\", \"True Label\", \"Image\", \"Predicted Label\", \"Confidence\", \"Correct\"])\nfrom IPython.display import display\ndisplay(df_results)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-10T16:43:36.380577Z","iopub.execute_input":"2025-02-10T16:43:36.380933Z","iopub.status.idle":"2025-02-10T16:43:40.373162Z","shell.execute_reply.started":"2025-02-10T16:43:36.380903Z","shell.execute_reply":"2025-02-10T16:43:40.372405Z"}},"outputs":[],"execution_count":null}]}