{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"},{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"},{"sourceId":12110381,"sourceType":"datasetVersion","datasetId":7624743},{"sourceId":12110410,"sourceType":"datasetVersion","datasetId":7624766},{"sourceId":12110443,"sourceType":"datasetVersion","datasetId":7624788},{"sourceId":12110455,"sourceType":"datasetVersion","datasetId":7624798},{"sourceId":12111528,"sourceType":"datasetVersion","datasetId":7625539},{"sourceId":12111533,"sourceType":"datasetVersion","datasetId":7625544},{"sourceId":122519208,"sourceType":"kernelVersion"},{"sourceId":184238399,"sourceType":"kernelVersion"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # Hilangkan info & warning dari TensorFlow\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:27:45.416698Z","iopub.execute_input":"2025-06-09T15:27:45.417275Z","iopub.status.idle":"2025-06-09T15:27:45.421758Z","shell.execute_reply.started":"2025-06-09T15:27:45.41725Z","shell.execute_reply":"2025-06-09T15:27:45.420874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport zipfile\nimport random\nimport shutil\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras import layers, models, Input\n\n# Supress warning log dari TensorFlow\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'\n\n# Path dataset zip (sesuaikan jika path berbeda)\nzip_path = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip'\nextract_path = '/tmp/dogs-vs-cats'\n\n# Jika folder ekstraksi sudah ada, hapus dulu agar tidak ada file duplikat error\nif os.path.exists(extract_path):\n    shutil.rmtree(extract_path)\n\n# Ekstrak dataset ZIP\nwith zipfile.ZipFile(zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n\nbase_dir = os.path.join(extract_path, 'train')\n\n# Folder untuk training dan validation\ntrain_dir = os.path.join(extract_path, 'training')\nval_dir = os.path.join(extract_path, 'validation')\n\n# Bersihkan dulu folder training & validation agar bisa run ulang\nfor folder in [train_dir, val_dir]:\n    if os.path.exists(folder):\n        shutil.rmtree(folder)\n\nos.makedirs(os.path.join(train_dir, 'cats'), exist_ok=True)\nos.makedirs(os.path.join(train_dir, 'dogs'), exist_ok=True)\nos.makedirs(os.path.join(val_dir, 'cats'), exist_ok=True)\nos.makedirs(os.path.join(val_dir, 'dogs'), exist_ok=True)\n\ndef split_data(source_files, train_subdir, val_subdir, split_size):\n    random.shuffle(source_files)\n    split_index = int(len(source_files) * split_size)\n    train_files = source_files[:split_index]\n    val_files = source_files[split_index:]\n    \n    for f in train_files:\n        shutil.copy(f, os.path.join(train_subdir, os.path.basename(f)))\n    for f in val_files:\n        shutil.copy(f, os.path.join(val_subdir, os.path.basename(f)))\n\ncat_files = [os.path.join(base_dir, f) for f in os.listdir(base_dir) if f.startswith('cat')][:2500]\ndog_files = [os.path.join(base_dir, f) for f in os.listdir(base_dir) if f.startswith('dog')][:2500]\n\nsplit_data(cat_files, os.path.join(train_dir, 'cats'), os.path.join(val_dir, 'cats'), 0.9)\nsplit_data(dog_files, os.path.join(train_dir, 'dogs'), os.path.join(val_dir, 'dogs'), 0.9)\n\n# Data augmentation dan preprocessing\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    rotation_range=40,\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)\n\nval_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_directory(\n    train_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary'\n)\n\nval_generator = val_datagen.flow_from_directory(\n    val_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary'\n)\n\n# Model CNN dengan Input layer\nmodel = models.Sequential([\n    Input(shape=(150, 150, 3)),\n    layers.Conv2D(32, (3, 3), activation='relu'),\n    layers.MaxPooling2D(2, 2),\n\n    layers.Conv2D(64, (3, 3), activation='relu'),\n    layers.MaxPooling2D(2, 2),\n\n    layers.Conv2D(128, (3, 3), activation='relu'),\n    layers.MaxPooling2D(2, 2),\n\n    layers.Flatten(),\n    layers.Dropout(0.5),\n    layers.Dense(512, activation='relu'),\n    layers.Dense(1, activation='sigmoid')\n])\n\nmodel.compile(optimizer='adam',\n              loss='binary_crossentropy',\n              metrics=['accuracy'])\n\nmodel.summary()\n\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=10\n)\n\n# Visualisasi hasil training\nacc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nplt.figure(figsize=(12, 5))\nplt.subplot(1, 2, 1)\nplt.plot(acc, label='Training Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.legend()\nplt.title('Training vs Validation Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(loss, label='Training Loss')\nplt.plot(val_loss, label='Validation Loss')\nplt.legend()\nplt.title('Training vs Validation Loss')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:38:18.792238Z","iopub.execute_input":"2025-06-09T15:38:18.792577Z","iopub.status.idle":"2025-06-09T16:00:56.026092Z","shell.execute_reply.started":"2025-06-09T15:38:18.792557Z","shell.execute_reply":"2025-06-09T16:00:56.024958Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(os.listdir('/kaggle/input/dogs-vs-cats-redux-kernels-edition'))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T15:33:51.204971Z","iopub.execute_input":"2025-06-09T15:33:51.205309Z","iopub.status.idle":"2025-06-09T15:33:51.225911Z","shell.execute_reply.started":"2025-06-09T15:33:51.205271Z","shell.execute_reply":"2025-06-09T15:33:51.224836Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save('cats_vs_dogs_model.h5')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:05:06.225035Z","iopub.execute_input":"2025-06-09T16:05:06.225386Z","iopub.status.idle":"2025-06-09T16:05:06.690506Z","shell.execute_reply.started":"2025-06-09T16:05:06.225363Z","shell.execute_reply":"2025-06-09T16:05:06.689719Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Simpan model setelah training\nmodel_path = '/tmp/cat_dog_classifier.h5'\nmodel.save(model_path)\nprint(f\"Model saved to: {model_path}\")\n\n# Fungsi untuk memuat dan memprediksi gambar baru\nimport numpy as np\nfrom tensorflow.keras.preprocessing import image\n\ndef predict_image(img_path, model_path=model_path):\n    if not os.path.exists(model_path):\n        raise FileNotFoundError(\"Model belum dilatih atau file model tidak ditemukan.\")\n    \n    # Load model\n    loaded_model = tf.keras.models.load_model(model_path)\n    \n    # Preprocess gambar\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n    \n    # Prediksi\n    prediction = loaded_model.predict(img_array)[0][0]\n    label = \"Dog\" if prediction > 0.5 else \"Cat\"\n    \n    # Visualisasi hasil prediksi\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label} ({prediction:.2f})\")\n    plt.axis('off')\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:10:06.334422Z","iopub.execute_input":"2025-06-09T16:10:06.334739Z","iopub.status.idle":"2025-06-09T16:10:06.752892Z","shell.execute_reply.started":"2025-06-09T16:10:06.334715Z","shell.execute_reply":"2025-06-09T16:10:06.75204Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\n\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_tensor = image.img_to_array(img) / 255.0\n    img_tensor = np.expand_dims(img_tensor, axis=0)\n    \n    prediction = model.predict(img_tensor)[0][0]\n    if prediction > 0.5:\n        print(\"Prediction: Dog 🐶\")\n    else:\n        print(\"Prediction: Cat 🐱\")\n\n# Contoh: file lokal di /tmp atau upload\npredict_image('/tmp/dogs-vs-cats/train/dog.5001.jpg')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:11:03.429142Z","iopub.execute_input":"2025-06-09T16:11:03.42988Z","iopub.status.idle":"2025-06-09T16:11:03.69035Z","shell.execute_reply.started":"2025-06-09T16:11:03.429851Z","shell.execute_reply":"2025-06-09T16:11:03.689378Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Fungsi untuk memuat model dan memprediksi gambar baru\nimport numpy as np\nfrom tensorflow.keras.preprocessing import image\n\ndef predict_image(img_path, model_path='/tmp/cat_dog_classifier.h5'):\n    if not os.path.exists(model_path):\n        raise FileNotFoundError(\"Model belum dilatih atau file model tidak ditemukan.\")\n    \n    # Load model\n    loaded_model = tf.keras.models.load_model(model_path)\n\n    # Preprocess gambar\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n    \n    # Prediksi\n    prediction = loaded_model.predict(img_array)[0][0]\n    label = \"Dog\" if prediction > 0.5 else \"Cat\"\n    \n    # Visualisasi hasil prediksi\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label} ({prediction:.2f})\")\n    plt.axis('off')\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:12:40.699436Z","iopub.execute_input":"2025-06-09T16:12:40.700346Z","iopub.status.idle":"2025-06-09T16:12:40.708408Z","shell.execute_reply.started":"2025-06-09T16:12:40.700312Z","shell.execute_reply":"2025-06-09T16:12:40.707383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict_image('/tmp/dogs-vs-cats/train/dog.5001.jpg')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:13:28.677235Z","iopub.execute_input":"2025-06-09T16:13:28.67759Z","iopub.status.idle":"2025-06-09T16:13:29.510821Z","shell.execute_reply.started":"2025-06-09T16:13:28.677566Z","shell.execute_reply":"2025-06-09T16:13:29.509832Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loss, acc = model.evaluate(val_generator)\nprint(f\"Validation Accuracy: {acc:.2f}, Loss: {loss:.2f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:13:47.893715Z","iopub.execute_input":"2025-06-09T16:13:47.894506Z","iopub.status.idle":"2025-06-09T16:13:51.530835Z","shell.execute_reply.started":"2025-06-09T16:13:47.894477Z","shell.execute_reply":"2025-06-09T16:13:51.529972Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report\nimport seaborn as sns\n\n# Ambil data dan label\nval_generator.reset()\nY_pred = model.predict(val_generator)\ny_pred = (Y_pred > 0.5).astype(int).flatten()\n\ny_true = val_generator.classes\n\n# Plot Confusion Matrix\ncm = confusion_matrix(y_true, y_pred)\nplt.figure(figsize=(6,4))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues')\nplt.xlabel('Predicted')\nplt.ylabel('Actual')\nplt.title('Confusion Matrix')\nplt.show()\n\n# Classification report\nprint(classification_report(y_true, y_pred, target_names=['Cat', 'Dog']))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:13:57.242124Z","iopub.execute_input":"2025-06-09T16:13:57.242451Z","iopub.status.idle":"2025-06-09T16:14:02.170585Z","shell.execute_reply.started":"2025-06-09T16:13:57.242425Z","shell.execute_reply":"2025-06-09T16:14:02.169474Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_predictions(generator, model, n=10):\n    class_names = list(generator.class_indices.keys())\n    x_batch, y_batch = next(generator)\n    y_pred = model.predict(x_batch) > 0.5\n\n    plt.figure(figsize=(15, 5))\n    for i in range(n):\n        plt.subplot(2, n//2, i+1)\n        plt.imshow(x_batch[i])\n        true_label = class_names[int(y_batch[i])]\n        pred_label = class_names[int(y_pred[i][0])]\n        plt.title(f'True: {true_label}\\nPred: {pred_label}')\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Tampilkan 10 prediksi dari validation\nshow_predictions(val_generator, model)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:14:18.617686Z","iopub.execute_input":"2025-06-09T16:14:18.618252Z","iopub.status.idle":"2025-06-09T16:14:19.933195Z","shell.execute_reply.started":"2025-06-09T16:14:18.618226Z","shell.execute_reply":"2025-06-09T16:14:19.932169Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/kucing-1/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:16:39.993013Z","iopub.execute_input":"2025-06-09T16:16:39.995544Z","iopub.status.idle":"2025-06-09T16:16:40.395002Z","shell.execute_reply.started":"2025-06-09T16:16:39.995483Z","shell.execute_reply":"2025-06-09T16:16:40.393792Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang ingin diprediksi\nimg_path = '/kaggle/input/kucing-2/images.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path, model=model):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog\" if prediction > 0.5 else \"Cat\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label} ({prediction:.2f})\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:19:42.565358Z","iopub.execute_input":"2025-06-09T16:19:42.566133Z","iopub.status.idle":"2025-06-09T16:19:42.868532Z","shell.execute_reply.started":"2025-06-09T16:19:42.566097Z","shell.execute_reply":"2025-06-09T16:19:42.867329Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang ingin diprediksi\nimg_path = '/kaggle/input/kucing-3/images.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path, model=model):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog\" if prediction > 0.5 else \"Cat\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label} ({prediction:.2f})\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:21:05.159498Z","iopub.execute_input":"2025-06-09T16:21:05.159904Z","iopub.status.idle":"2025-06-09T16:21:05.457992Z","shell.execute_reply.started":"2025-06-09T16:21:05.159877Z","shell.execute_reply":"2025-06-09T16:21:05.456869Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang ingin diprediksi\nimg_path = '/kaggle/input/anjing-1/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path, model=model):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog\" if prediction > 0.5 else \"Cat\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label} ({prediction:.2f})\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:22:02.174105Z","iopub.execute_input":"2025-06-09T16:22:02.174844Z","iopub.status.idle":"2025-06-09T16:22:02.460926Z","shell.execute_reply.started":"2025-06-09T16:22:02.174811Z","shell.execute_reply":"2025-06-09T16:22:02.459736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict_image('/tmp/dogs-vs-cats/train/dog.5002.jpg')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:22:16.031116Z","iopub.execute_input":"2025-06-09T16:22:16.031462Z","iopub.status.idle":"2025-06-09T16:22:16.31448Z","shell.execute_reply.started":"2025-06-09T16:22:16.031439Z","shell.execute_reply":"2025-06-09T16:22:16.313413Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/anjing-1/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:22:45.642377Z","iopub.execute_input":"2025-06-09T16:22:45.642742Z","iopub.status.idle":"2025-06-09T16:22:45.927258Z","shell.execute_reply.started":"2025-06-09T16:22:45.642715Z","shell.execute_reply":"2025-06-09T16:22:45.926379Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict_image('/tmp/dogs-vs-cats/train/cat.5020.jpg')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:22:57.505933Z","iopub.execute_input":"2025-06-09T16:22:57.506266Z","iopub.status.idle":"2025-06-09T16:22:57.780513Z","shell.execute_reply.started":"2025-06-09T16:22:57.506244Z","shell.execute_reply":"2025-06-09T16:22:57.779639Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_predictions(generator, model, n=10):\n    class_names = list(generator.class_indices.keys())\n    x_batch, y_batch = next(generator)\n    y_pred = model.predict(x_batch) > 0.5\n\n    plt.figure(figsize=(15, 5))\n    for i in range(n):\n        plt.subplot(2, n//2, i+1)\n        plt.imshow(x_batch[i])\n        true_label = class_names[int(y_batch[i])]\n        pred_label = class_names[int(y_pred[i][0])]\n        plt.title(f'True: {true_label}\\nPred: {pred_label}')\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Tampilkan 10 prediksi dari validation\nshow_predictions(val_generator, model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:23:06.412488Z","iopub.execute_input":"2025-06-09T16:23:06.413125Z","iopub.status.idle":"2025-06-09T16:23:07.68382Z","shell.execute_reply.started":"2025-06-09T16:23:06.413098Z","shell.execute_reply":"2025-06-09T16:23:07.682558Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Simpan model setelah training\nmodel_path = '/tmp/cat_dog_classifier.h5'\nmodel.save(model_path)\nprint(f\"Model saved to: {model_path}\")\n\n# Fungsi untuk memuat dan memprediksi gambar baru\nimport numpy as np\nfrom tensorflow.keras.preprocessing import image\n\ndef predict_image(img_path, model_path=model_path):\n    if not os.path.exists(model_path):\n        raise FileNotFoundError(\"Model belum dilatih atau file model tidak ditemukan.\")\n\n    # Load model\n    loaded_model = tf.keras.models.load_model(model_path)\n\n    # Preprocess gambar\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    # Prediksi\n    prediction = loaded_model.predict(img_array)[0][0]\n    label = \"Dog\" if prediction > 0.5 else \"Cat\"\n\n    # Visualisasi hasil prediksi\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label} ({prediction:.2f})\")\n    plt.axis('off')\n    plt.show()\n\n# Contoh penggunaan fungsi prediksi (ubah path sesuai gambar):\n# predict_image('/path/to/your/image.jpg')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:30:56.906247Z","iopub.execute_input":"2025-06-09T16:30:56.906671Z","iopub.status.idle":"2025-06-09T16:30:57.787469Z","shell.execute_reply.started":"2025-06-09T16:30:56.906644Z","shell.execute_reply":"2025-06-09T16:30:57.786534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nfrom tensorflow.keras.models import Model\nimport tensorflow as tf\nimport warnings\n\ndef plot_feature_maps(model, img_array, layer_name):\n    warnings.filterwarnings(\"ignore\", category=UserWarning)\n\n    # Buat feature extractor\n    feature_extractor = Model(inputs=model.inputs, outputs=model.get_layer(layer_name).output)\n    feature_maps = feature_extractor.predict(img_array)\n\n    square = int(np.ceil(np.sqrt(feature_maps.shape[-1])))\n    fig, axes = plt.subplots(square, square, figsize=(12, 12))\n    for i in range(square * square):\n        if i < feature_maps.shape[-1]:\n            feature = feature_maps[0, :, :, i]\n            # Min-Max Normalization agar lebih terlihat\n            feature -= feature.min()\n            feature /= (feature.max() + 1e-8)  # tambahkan epsilon agar tidak dibagi nol\n            ax = axes[i // square, i % square]\n            ax.imshow(feature, cmap='inferno')\n            ax.axis('off')\n        else:\n            axes[i // square, i % square].axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Load gambar dengan ukuran yang sesuai\nimg = tf.keras.preprocessing.image.load_img(\n    \"/kaggle/input/anjing-1/download.jpg\", target_size=(150, 150)\n)\nimg_array = tf.keras.preprocessing.image.img_to_array(img)\nimg_array = np.expand_dims(img_array, axis=0) / 255.0\n\n# Panggil fungsi\nplot_feature_maps(model, img_array, 'conv2d_5')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:38:56.313148Z","iopub.execute_input":"2025-06-09T16:38:56.31353Z","iopub.status.idle":"2025-06-09T16:39:00.170537Z","shell.execute_reply.started":"2025-06-09T16:38:56.313507Z","shell.execute_reply":"2025-06-09T16:39:00.169557Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\nimport numpy as np\n\ndef plot_confusion_matrix(y_true, y_pred, class_names):\n    print(\"y_true:\", y_true)\n    print(\"y_pred:\", y_pred)\n    cm = confusion_matrix(y_true, y_pred)\n    print(\"Confusion Matrix:\\n\", cm)\n    \n    disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)\n    disp.plot(cmap=plt.cm.Blues)\n    plt.title(\"Confusion Matrix\")\n    plt.xlabel(\"Predicted Label\")\n    plt.ylabel(\"True Label\")\n    plt.show()\n\n# Dummy data untuk contoh:\ny_true = np.array([0, 1, 1, 0, 1, 0, 1])\ny_pred = np.array([0, 1, 0, 0, 1, 0, 1])\n\n# Class names:\nclass_names = ['Cat', 'Dog']\n\n# Panggil fungsi\nplot_confusion_matrix(y_true, y_pred, class_names)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T16:55:35.653331Z","iopub.execute_input":"2025-06-09T16:55:35.653959Z","iopub.status.idle":"2025-06-09T16:55:35.847796Z","shell.execute_reply.started":"2025-06-09T16:55:35.65393Z","shell.execute_reply":"2025-06-09T16:55:35.846742Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import zipfile\nimport shutil\n\ndataset_2_zip = '/kaggle/input/dogs-vs-cats/train.zip'\ndataset_2_extract = '/tmp/dogs-vs-cats-2/train'\n\n# Pastikan folder kosong dulu agar tidak ada error\nif os.path.exists(dataset_2_extract):\n    shutil.rmtree(dataset_2_extract)\n\nwith zipfile.ZipFile(dataset_2_zip, 'r') as zip_ref:\n    zip_ref.extractall('/tmp/dogs-vs-cats-2')\n\nprint(\"Dataset 2 sudah diekstrak.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:04:35.092438Z","iopub.execute_input":"2025-06-09T17:04:35.093316Z","iopub.status.idle":"2025-06-09T17:04:41.568768Z","shell.execute_reply.started":"2025-06-09T17:04:35.093257Z","shell.execute_reply":"2025-06-09T17:04:41.567762Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport zipfile\nimport shutil\nimport random\n\n# Path dataset zip (dataset 1)\nzip_path = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip'\nextract_path = '/tmp/dogs-vs-cats'\n\n# Jika folder ekstraksi sudah ada, hapus dulu agar tidak error\nif os.path.exists(extract_path):\n    shutil.rmtree(extract_path)\n\n# Ekstrak dataset ZIP\nwith zipfile.ZipFile(zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n\n# Path gambar hasil ekstraksi\nbase_dir = os.path.join(extract_path, 'train')\n\n# Buat folder dataset 1 (training dan validation)\ndataset_1_train_dir = os.path.join(extract_path, 'dataset1', 'train')\ndataset_1_val_dir = os.path.join(extract_path, 'dataset1', 'validation')\n\n# Buat folder kelas\nfor category in ['cat', 'dog']:\n    os.makedirs(os.path.join(dataset_1_train_dir, category), exist_ok=True)\n    os.makedirs(os.path.join(dataset_1_val_dir, category), exist_ok=True)\n\n# Split gambar ke train dan validation\nall_files = os.listdir(base_dir)\ncats = [f for f in all_files if f.startswith('cat')]\ndogs = [f for f in all_files if f.startswith('dog')]\n\nrandom.shuffle(cats)\nrandom.shuffle(dogs)\n\nsplit_ratio = 0.8  # 80% train, 20% validation\nsplit_cats = int(len(cats) * split_ratio)\nsplit_dogs = int(len(dogs) * split_ratio)\n\n# Salin ke folder training\nfor fname in cats[:split_cats]:\n    src = os\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:07:12.744207Z","iopub.execute_input":"2025-06-09T19:07:12.74519Z","iopub.status.idle":"2025-06-09T19:07:24.492618Z","shell.execute_reply.started":"2025-06-09T19:07:12.74516Z","shell.execute_reply":"2025-06-09T19:07:24.49171Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport zipfile\nimport shutil\nimport random\n\ndataset_2_zip = '/kaggle/input/dogs-vs-cats/train.zip'\ndataset_2_extract = '/tmp/dogs-vs-cats-2'\n\n# Hapus folder jika sudah ada agar tidak error\nif os.path.exists(dataset_2_extract):\n    shutil.rmtree(dataset_2_extract)\n\n# Ekstrak dataset ZIP\nwith zipfile.ZipFile(dataset_2_zip, 'r') as zip_ref:\n    zip_ref.extractall(dataset_2_extract)\n\nprint(\"✅ Dataset 2 berhasil diekstrak.\")\n\n# Cari folder train di dataset_2_extract\n# (karena bisa saja ada subfolder lain)\nfor root, dirs, files in os.walk(dataset_2_extract):\n    if os.path.basename(root).lower() == 'train':\n        base_dir_2 = root\n        break\nelse:\n    raise FileNotFoundError(\"❌ Folder 'train' tidak ditemukan di dataset_2_extract\")\n\nprint(f\"📂 Dataset 2 train folder ditemukan di: {base_dir_2}\")\n\n# Buat folder dataset 2 (training dan validation)\ndataset_2_train_dir = os.path.join(dataset_2_extract, 'dataset2', 'train')\ndataset_2_val_dir = os.path.join(dataset_2_extract, 'dataset2', 'validation')\n\nfor category in ['cat', 'dog']:\n    os.makedirs(os.path.join(dataset_2_train_dir, category), exist_ok=True)\n    os.makedirs(os.path.join(dataset_2_val_dir, category), exist_ok=True)\n\n# Split gambar ke train dan validation\nall_files_2 = os.listdir(base_dir_2)\ncats_2 = [f for f in all_files_2 if f.startswith('cat')]\ndogs_2 = [f for f in all_files_2 if f.startswith('dog')]\n\nrandom.shuffle(cats_2)\nrandom.shuffle(dogs_2)\n\nsplit_ratio = 0.8  # 80% train, 20% validation\nsplit_cats_2 = int(len(cats_2) * split_ratio)\nsplit_dogs_2 = int(len(dogs_2) * split_ratio)\n\n# Salin ke folder training\nfor fname in cats_2[:split_cats_2]:\n    src = os.path.join(base_dir_2, fname)\n    dst = os.path.join(dataset_2_train_dir, 'cat', fname)\n    shutil.copy(src, dst)\n\nfor fname in dogs_2[:split_dogs_2]:\n    src = os.path.join(base_dir_2, fname)\n    dst = os.path.join(dataset_2_train_dir, 'dog', fname)\n    shutil.copy(src, dst)\n\n# Salin ke folder validation\nfor fname in cats_2[split_cats_2:]:\n    src = os.path.join(base_dir_2, fname)\n    dst = os.path.join(dataset_2_val_dir, 'cat', fname)\n    shutil.copy(src, dst)\n\nfor fname in dogs_2[split_dogs_2:]:\n    src = os.path.join(base_dir_2, fname)\n    dst = os.path.join(dataset_2_val_dir, 'dog', fname)\n    shutil.copy(src, dst)\n\nprint(\"✅ Dataset 2 sudah dipisah train/validation.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:07:35.686633Z","iopub.execute_input":"2025-06-09T17:07:35.686988Z","iopub.status.idle":"2025-06-09T17:07:49.752015Z","shell.execute_reply.started":"2025-06-09T17:07:35.68696Z","shell.execute_reply":"2025-06-09T17:07:49.751116Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dir = '/tmp/dogs-vs-cats/dataset1/train'\nval_dir = '/tmp/dogs-vs-cats/dataset1/validation'\n\nprint(\"Train directory:\", train_dir)\nprint(\"Validation directory:\", val_dir)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:09:16.35481Z","iopub.execute_input":"2025-06-09T17:09:16.355238Z","iopub.status.idle":"2025-06-09T17:09:16.360965Z","shell.execute_reply.started":"2025-06-09T17:09:16.355212Z","shell.execute_reply":"2025-06-09T17:09:16.359948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nif os.path.exists(train_dir):\n    print(\"✅ Train directory exists.\")\nelse:\n    print(\"❌ Train directory not found.\")\n\nif os.path.exists(val_dir):\n    print(\"✅ Validation directory exists.\")\nelse:\n    print(\"❌ Validation directory not found.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:09:22.099261Z","iopub.execute_input":"2025-06-09T17:09:22.099971Z","iopub.status.idle":"2025-06-09T17:09:22.105962Z","shell.execute_reply.started":"2025-06-09T17:09:22.099943Z","shell.execute_reply":"2025-06-09T17:09:22.104928Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ntrain_datagen = ImageDataGenerator(rescale=1./255)\nval_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_directory(\n    '/tmp/dogs-vs-cats/dataset1/train',\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary'  # binary classification (cat vs dog)\n)\n\nvalidation_generator = val_datagen.flow_from_directory(\n    '/tmp/dogs-vs-cats/dataset1/validation',\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary'\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:09:52.457431Z","iopub.execute_input":"2025-06-09T17:09:52.457784Z","iopub.status.idle":"2025-06-09T17:09:52.47618Z","shell.execute_reply.started":"2025-06-09T17:09:52.457756Z","shell.execute_reply":"2025-06-09T17:09:52.475356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras import layers, models\n\nmodel = models.Sequential([\n    layers.Conv2D(32, (3,3), activation='relu', input_shape=(150,150,3)),\n    layers.MaxPooling2D(2,2),\n    layers.Conv2D(64, (3,3), activation='relu'),\n    layers.MaxPooling2D(2,2),\n    layers.Conv2D(128, (3,3), activation='relu'),\n    layers.MaxPooling2D(2,2),\n    layers.Flatten(),\n    layers.Dense(512, activation='relu'),\n    layers.Dense(1, activation='sigmoid')  # binary output\n])\n\nmodel.compile(loss='binary_crossentropy',\n              optimizer='adam',\n              metrics=['accuracy'])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:10:00.215528Z","iopub.execute_input":"2025-06-09T17:10:00.216211Z","iopub.status.idle":"2025-06-09T17:10:00.49111Z","shell.execute_reply.started":"2025-06-09T17:10:00.216181Z","shell.execute_reply":"2025-06-09T17:10:00.490176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport shutil\nimport random\n\n# Path asli hasil ekstraksi zip\noriginal_train_dir = '/tmp/dogs-vs-cats/train'  # berisi file-file jpg\n\n# Target folder\ndataset_dir = '/tmp/dogs-vs-cats/dataset1'\ntrain_dir = os.path.join(dataset_dir, 'train')\nvalidation_dir = os.path.join(dataset_dir, 'validation')\n\n# Buat folder train/validation jika belum ada\nfor category in ['cat', 'dog']:\n    os.makedirs(os.path.join(train_dir, category), exist_ok=True)\n    os.makedirs(os.path.join(validation_dir, category), exist_ok=True)\n\n# List semua file\nall_files = os.listdir(original_train_dir)\ncats = [f for f in all_files if f.startswith('cat')]\ndogs = [f for f in all_files if f.startswith('dog')]\n\n# Random shuffle\nrandom.shuffle(cats)\nrandom.shuffle(dogs)\n\n# Split (80% train, 20% validation)\nsplit_idx_cat = int(0.8 * len(cats))\nsplit_idx_dog = int(0.8 * len(dogs))\n\ntrain_cats = cats[:split_idx_cat]\nval_cats = cats[split_idx_cat:]\ntrain_dogs = dogs[:split_idx_dog]\nval_dogs = dogs[split_idx_dog:]\n\n# Copy ke folder train\nfor filename in train_cats:\n    src = os.path.join(original_train_dir, filename)\n    dst = os.path.join(train_dir, 'cat', filename)\n    shutil.copyfile(src, dst)\n\nfor filename in train_dogs:\n    src = os.path.join(original_train_dir, filename)\n    dst = os.path.join(train_dir, 'dog', filename)\n    shutil.copyfile(src, dst)\n\n# Copy ke folder validation\nfor filename in val_cats:\n    src = os.path.join(original_train_dir, filename)\n    dst = os.path.join(validation_dir, 'cat', filename)\n    shutil.copyfile(src, dst)\n\nfor filename in val_dogs:\n    src = os.path.join(original_train_dir, filename)\n    dst = os.path.join(validation_dir, 'dog', filename)\n    shutil.copyfile(src, dst)\n\nprint(\"Dataset sudah dipisahkan ke train/validation.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:13:49.919832Z","iopub.execute_input":"2025-06-09T17:13:49.920233Z","iopub.status.idle":"2025-06-09T17:13:54.10529Z","shell.execute_reply.started":"2025-06-09T17:13:49.92021Z","shell.execute_reply":"2025-06-09T17:13:54.104316Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Jumlah file train/cat:\", len(os.listdir(os.path.join(train_dir, 'cat'))))\nprint(\"Jumlah file validation/cat:\", len(os.listdir(os.path.join(validation_dir, 'cat'))))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:14:00.639078Z","iopub.execute_input":"2025-06-09T17:14:00.639437Z","iopub.status.idle":"2025-06-09T17:14:00.664668Z","shell.execute_reply.started":"2025-06-09T17:14:00.639409Z","shell.execute_reply":"2025-06-09T17:14:00.663642Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras import layers, models, optimizers\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:14:50.825547Z","iopub.execute_input":"2025-06-09T17:14:50.825893Z","iopub.status.idle":"2025-06-09T17:14:50.830338Z","shell.execute_reply.started":"2025-06-09T17:14:50.825866Z","shell.execute_reply":"2025-06-09T17:14:50.829381Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Path dataset\ntrain_dir = '/tmp/dogs-vs-cats/dataset1/train'\nvalidation_dir = '/tmp/dogs-vs-cats/dataset1/validation'\n\n# ImageDataGenerator\ntrain_datagen = ImageDataGenerator(rescale=1./255)\nval_datagen = ImageDataGenerator(rescale=1./255)\n\n# Generator train\ntrain_generator = train_datagen.flow_from_directory(\n    train_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary'\n)\n\n# Generator validation\nvalidation_generator = val_datagen.flow_from_directory(\n    validation_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary'\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:14:56.17386Z","iopub.execute_input":"2025-06-09T17:14:56.17419Z","iopub.status.idle":"2025-06-09T17:14:56.42231Z","shell.execute_reply.started":"2025-06-09T17:14:56.174168Z","shell.execute_reply":"2025-06-09T17:14:56.42142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = models.Sequential([\n    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),\n    layers.MaxPooling2D((2, 2)),\n\n    layers.Conv2D(64, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n\n    layers.Conv2D(128, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n\n    layers.Flatten(),\n    layers.Dense(512, activation='relu'),\n    layers.Dense(1, activation='sigmoid')  # binary classification\n])\n\nmodel.compile(\n    loss='binary_crossentropy',\n    optimizer=optimizers.Adam(learning_rate=0.001),\n    metrics=['accuracy']\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:15:31.736028Z","iopub.execute_input":"2025-06-09T17:15:31.736992Z","iopub.status.idle":"2025-06-09T17:15:31.962393Z","shell.execute_reply.started":"2025-06-09T17:15:31.736941Z","shell.execute_reply":"2025-06-09T17:15:31.961598Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_generator,\n    steps_per_epoch=len(train_generator) // 2,  # Gunakan setengah langkah\n    epochs=10,\n    validation_data=validation_generator,\n    validation_steps=len(validation_generator)  # Validation tetap pakai semua\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T17:21:10.144503Z","iopub.execute_input":"2025-06-09T17:21:10.14488Z","iopub.status.idle":"2025-06-09T18:00:47.397788Z","shell.execute_reply.started":"2025-06-09T17:21:10.144849Z","shell.execute_reply":"2025-06-09T18:00:47.395733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Plot training & validation accuracy\nacc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs_range = range(10)\n\nplt.figure(figsize=(12, 4))\n\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label='Training Accuracy')\nplt.plot(epochs_range, val_acc, label='Validation Accuracy')\nplt.legend(loc='lower right')\nplt.title('Training and Validation Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(epochs_range, loss, label='Training Loss')\nplt.plot(epochs_range, val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.title('Training and Validation Loss')\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:06:10.730289Z","iopub.execute_input":"2025-06-09T18:06:10.730754Z","iopub.status.idle":"2025-06-09T18:06:11.189577Z","shell.execute_reply.started":"2025-06-09T18:06:10.730684Z","shell.execute_reply":"2025-06-09T18:06:11.188579Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Val Accuracy')\nplt.plot(history.history['loss'], label='Train Loss')\nplt.plot(history.history['val_loss'], label='Val Loss')\nplt.legend()\nplt.title('Training History')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:11:18.451802Z","iopub.execute_input":"2025-06-09T18:11:18.452137Z","iopub.status.idle":"2025-06-09T18:11:18.673643Z","shell.execute_reply.started":"2025-06-09T18:11:18.452112Z","shell.execute_reply":"2025-06-09T18:11:18.672707Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Cek direktori saat ini\nprint(\"Isi direktori saat ini:\")\nprint(os.listdir())\n\n# Coba masuk ke dalam folder satu per satu\npath = '/content'\nif os.path.exists(path):\n    print(f\"\\nIsi dari {path}:\")\n    print(os.listdir(path))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:14:42.537267Z","iopub.execute_input":"2025-06-09T18:14:42.538219Z","iopub.status.idle":"2025-06-09T18:14:42.544459Z","shell.execute_reply.started":"2025-06-09T18:14:42.538189Z","shell.execute_reply":"2025-06-09T18:14:42.543417Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nprint(\"Isi dari combined_dataset:\")\nprint(os.listdir('combined_dataset'))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:15:00.004513Z","iopub.execute_input":"2025-06-09T18:15:00.004846Z","iopub.status.idle":"2025-06-09T18:15:00.010464Z","shell.execute_reply.started":"2025-06-09T18:15:00.004823Z","shell.execute_reply":"2025-06-09T18:15:00.009442Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Isi dari combined_dataset/train:\")\nprint(os.listdir('combined_dataset/train'))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:15:31.946103Z","iopub.execute_input":"2025-06-09T18:15:31.946466Z","iopub.status.idle":"2025-06-09T18:15:31.95221Z","shell.execute_reply.started":"2025-06-09T18:15:31.946439Z","shell.execute_reply":"2025-06-09T18:15:31.950871Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_path = 'combined_dataset/train'\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:15:44.570325Z","iopub.execute_input":"2025-06-09T18:15:44.570705Z","iopub.status.idle":"2025-06-09T18:15:44.57513Z","shell.execute_reply.started":"2025-06-09T18:15:44.570676Z","shell.execute_reply":"2025-06-09T18:15:44.574081Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_gen = datagen.flow_from_directory(\n    dataset_path,\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='binary',\n    subset='training'\n)\n\nval_gen = datagen.flow_from_directory(\n    dataset_path,\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='binary',\n    subset='validation'\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:15:48.75265Z","iopub.execute_input":"2025-06-09T18:15:48.752994Z","iopub.status.idle":"2025-06-09T18:15:49.641462Z","shell.execute_reply.started":"2025-06-09T18:15:48.752963Z","shell.execute_reply":"2025-06-09T18:15:49.64069Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(\n    rescale=1./255,\n    rotation_range=20,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    shear_range=0.1,\n    brightness_range=[0.8, 1.2],\n    validation_split=0.2\n)\n\ndataset_path = 'combined_dataset/train'\n\nval_gen = datagen.flow_from_directory(\n    dataset_path,\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='binary',\n    subset='validation',\n    shuffle=False\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:17:25.183369Z","iopub.execute_input":"2025-06-09T18:17:25.183706Z","iopub.status.idle":"2025-06-09T18:17:25.428904Z","shell.execute_reply.started":"2025-06-09T18:17:25.183683Z","shell.execute_reply":"2025-06-09T18:17:25.427896Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.input_shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:18:06.174323Z","iopub.execute_input":"2025-06-09T18:18:06.174744Z","iopub.status.idle":"2025-06-09T18:18:06.18237Z","shell.execute_reply.started":"2025-06-09T18:18:06.174717Z","shell.execute_reply":"2025-06-09T18:18:06.181156Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_gen = datagen.flow_from_directory(\n    dataset_path,\n    target_size=(160, 160),  # Sesuaikan dengan input model\n    batch_size=32,\n    class_mode='binary',\n    subset='validation',\n    shuffle=False\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:18:22.746414Z","iopub.execute_input":"2025-06-09T18:18:22.746724Z","iopub.status.idle":"2025-06-09T18:18:22.960149Z","shell.execute_reply.started":"2025-06-09T18:18:22.746702Z","shell.execute_reply":"2025-06-09T18:18:22.959137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:18:30.348201Z","iopub.execute_input":"2025-06-09T18:18:30.348581Z","iopub.status.idle":"2025-06-09T18:18:30.376063Z","shell.execute_reply.started":"2025-06-09T18:18:30.348555Z","shell.execute_reply":"2025-06-09T18:18:30.375165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.models import load_model\n\nmodel = load_model('cats_vs_dogs_model.h5')\nprint(\"Input shape model:\", model.input_shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:19:31.568395Z","iopub.execute_input":"2025-06-09T18:19:31.56902Z","iopub.status.idle":"2025-06-09T18:19:32.035277Z","shell.execute_reply.started":"2025-06-09T18:19:31.56897Z","shell.execute_reply":"2025-06-09T18:19:32.034427Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224,224,3))\nbase_model.trainable = False\n\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(128, activation='relu')(x)\noutput = Dense(1, activation='sigmoid')(x)\n\nmodel = Model(inputs=base_model.input, outputs=output)\nmodel.compile(optimizer=Adam(learning_rate=1e-4), loss='binary_crossentropy', metrics=['accuracy'])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:19:47.98818Z","iopub.execute_input":"2025-06-09T18:19:47.988552Z","iopub.status.idle":"2025-06-09T18:19:49.635417Z","shell.execute_reply.started":"2025-06-09T18:19:47.988528Z","shell.execute_reply":"2025-06-09T18:19:49.634505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.preprocessing import image\n\nimg = image.load_img('/kaggle/input/anjing-1/download.jpg', target_size=(224, 224))\nimg_array = image.img_to_array(img) / 255.0\nimg_array = np.expand_dims(img_array, axis=0)\n\nprediction = model.predict(img_array)[0][0]\nprint(\"Predicted:\", \"Dog\" if prediction > 0.5 else \"Cat\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:20:42.820962Z","iopub.execute_input":"2025-06-09T18:20:42.821654Z","iopub.status.idle":"2025-06-09T18:20:44.669347Z","shell.execute_reply.started":"2025-06-09T18:20:42.821627Z","shell.execute_reply":"2025-06-09T18:20:44.668066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.applications.mobilenet import preprocess_input\n\nimg = image.load_img('/kaggle/input/kucing-2/images.jpg', target_size=(224, 224))\nimg_array = image.img_to_array(img)\nimg_array = np.expand_dims(img_array, axis=0)\nimg_array = preprocess_input(img_array)\n\nprediction = model.predict(img_array)[0][0]\nprint(\"Predicted:\", \"Dog\" if prediction > 0.5 else \"Cat\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:22:40.796007Z","iopub.execute_input":"2025-06-09T18:22:40.79635Z","iopub.status.idle":"2025-06-09T18:22:40.936381Z","shell.execute_reply.started":"2025-06-09T18:22:40.796324Z","shell.execute_reply":"2025-06-09T18:22:40.935286Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.applications.mobilenet import preprocess_input\n\nimg = image.load_img('/kaggle/input/kucing-3/images.jpg', target_size=(224, 224))\nimg_array = image.img_to_array(img)\nimg_array = np.expand_dims(img_array, axis=0)\nimg_array = preprocess_input(img_array)\n\nprediction = model.predict(img_array)[0][0]\nprint(\"Predicted:\", \"Dog\" if prediction > 0.5 else \"Cat\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:23:09.671224Z","iopub.execute_input":"2025-06-09T18:23:09.671574Z","iopub.status.idle":"2025-06-09T18:23:09.810575Z","shell.execute_reply.started":"2025-06-09T18:23:09.671552Z","shell.execute_reply":"2025-06-09T18:23:09.809694Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.applications.mobilenet import preprocess_input\n\nimg = image.load_img('/kaggle/input/anjing-3/download.jpg', target_size=(224, 224))\nimg_array = image.img_to_array(img)\nimg_array = np.expand_dims(img_array, axis=0)\nimg_array = preprocess_input(img_array)\n\nprediction = model.predict(img_array)[0][0]\nprint(\"Predicted:\", \"Dog\" if prediction > 0.5 else \"Cat\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:24:42.274976Z","iopub.execute_input":"2025-06-09T18:24:42.275351Z","iopub.status.idle":"2025-06-09T18:24:42.414152Z","shell.execute_reply.started":"2025-06-09T18:24:42.275321Z","shell.execute_reply":"2025-06-09T18:24:42.413235Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_predictions(generator, model, n=10):\n    class_names = list(generator.class_indices.keys())\n    x_batch, y_batch = next(generator)\n    y_pred = model.predict(x_batch) > 0.5\n\n    plt.figure(figsize=(15, 5))\n    for i in range(n):\n        plt.subplot(2, n//2, i+1)\n        plt.imshow(x_batch[i])\n        true_label = class_names[int(y_batch[i])]\n        pred_label = class_names[int(y_pred[i][0])]\n        plt.title(f'True: {true_label}\\nPred: {pred_label}')\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Tampilkan 10 prediksi dari validation\nshow_predictions(val_gen, model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:44:44.403555Z","iopub.execute_input":"2025-06-09T18:44:44.403996Z","iopub.status.idle":"2025-06-09T18:44:47.413374Z","shell.execute_reply.started":"2025-06-09T18:44:44.403967Z","shell.execute_reply":"2025-06-09T18:44:47.412194Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict_image('/tmp/dogs-vs-cats/train/cat.5020.jpg')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:51:17.652483Z","iopub.execute_input":"2025-06-09T18:51:17.652813Z","iopub.status.idle":"2025-06-09T18:51:19.003351Z","shell.execute_reply.started":"2025-06-09T18:51:17.652779Z","shell.execute_reply":"2025-06-09T18:51:19.002468Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\nimport numpy as np\n\ndef plot_confusion_matrix(y_true, y_pred, class_names):\n    print(\"y_true:\", y_true)\n    print(\"y_pred:\", y_pred)\n    cm = confusion_matrix(y_true, y_pred)\n    print(\"Confusion Matrix:\\n\", cm)\n    \n    disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)\n    disp.plot(cmap=plt.cm.Blues)\n    plt.title(\"Confusion Matrix\")\n    plt.xlabel(\"Predicted Label\")\n    plt.ylabel(\"True Label\")\n    plt.show()\n\n# Dummy data untuk contoh:\ny_true = np.array([0, 1, 1, 0, 1, 0, 1])\ny_pred = np.array([0, 1, 0, 0, 1, 0, 1])\n\n# Class names:\nclass_names = ['Cat', 'Dog']\n\n# Panggil fungsi\nplot_confusion_matrix(y_true, y_pred, class_names)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T18:55:59.374026Z","iopub.execute_input":"2025-06-09T18:55:59.374412Z","iopub.status.idle":"2025-06-09T18:55:59.568172Z","shell.execute_reply.started":"2025-06-09T18:55:59.374387Z","shell.execute_reply":"2025-06-09T18:55:59.567265Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/kucing-1/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:06:01.367848Z","iopub.execute_input":"2025-06-09T19:06:01.368249Z","iopub.status.idle":"2025-06-09T19:06:01.679356Z","shell.execute_reply.started":"2025-06-09T19:06:01.368218Z","shell.execute_reply":"2025-06-09T19:06:01.678383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/anjing-3/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:06:20.273876Z","iopub.execute_input":"2025-06-09T19:06:20.274801Z","iopub.status.idle":"2025-06-09T19:06:20.57789Z","shell.execute_reply.started":"2025-06-09T19:06:20.27477Z","shell.execute_reply":"2025-06-09T19:06:20.577021Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_path = '/kaggle/working/combined_dataset/train'\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:13:19.272463Z","iopub.execute_input":"2025-06-09T19:13:19.273349Z","iopub.status.idle":"2025-06-09T19:13:19.277667Z","shell.execute_reply.started":"2025-06-09T19:13:19.273315Z","shell.execute_reply":"2025-06-09T19:13:19.276602Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Model input shape:\", model.input_shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:12:33.859828Z","iopub.execute_input":"2025-06-09T19:12:33.86083Z","iopub.status.idle":"2025-06-09T19:12:33.865996Z","shell.execute_reply.started":"2025-06-09T19:12:33.860796Z","shell.execute_reply":"2025-06-09T19:12:33.864956Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_gen = datagen.flow_from_directory(\n    dataset_path,\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='binary',\n    subset='validation',\n    shuffle=False\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:13:48.344444Z","iopub.execute_input":"2025-06-09T19:13:48.345608Z","iopub.status.idle":"2025-06-09T19:13:48.44516Z","shell.execute_reply.started":"2025-06-09T19:13:48.345567Z","shell.execute_reply":"2025-06-09T19:13:48.444141Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(6,4))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.title('Confusion Matrix')  # <- pastikan ada tanda ()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:17:18.961Z","iopub.execute_input":"2025-06-09T19:17:18.961725Z","iopub.status.idle":"2025-06-09T19:17:19.142432Z","shell.execute_reply.started":"2025-06-09T19:17:18.961695Z","shell.execute_reply":"2025-06-09T19:17:19.141359Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_predictions(generator, model, n=10):\n    class_names = list(generator.class_indices.keys())\n    x_batch, y_batch = next(generator)\n    y_pred = model.predict(x_batch) > 0.5\n\n    plt.figure(figsize=(15, 5))\n    for i in range(n):\n        plt.subplot(2, n//2, i+1)\n        plt.imshow(x_batch[i])\n        true_label = class_names[int(y_batch[i])]\n        pred_label = class_names[int(y_pred[i][0])]\n        plt.title(f'True: {true_label}\\nPred: {pred_label}')\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Tampilkan 10 prediksi dari validation\nshow_predictions(val_gen, model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:18:50.516028Z","iopub.execute_input":"2025-06-09T19:18:50.516481Z","iopub.status.idle":"2025-06-09T19:18:52.652102Z","shell.execute_reply.started":"2025-06-09T19:18:50.516453Z","shell.execute_reply":"2025-06-09T19:18:52.651146Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_predictions(generator, model, n=10):\n    class_names = list(generator.class_indices.keys())\n    x_batch, y_batch = next(generator)\n    y_pred = model.predict(x_batch) > 0.5\n\n    plt.figure(figsize=(15, 5))\n    for i in range(n):\n        plt.subplot(2, n//2, i+1)\n        plt.imshow(x_batch[i])\n        true_label = class_names[int(y_batch[i])]\n        pred_label = class_names[int(y_pred[i][0])]\n        plt.title(f'True: {true_label}\\nPred: {pred_label}')\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Tampilkan 10 prediksi dari validation\nshow_predictions(val_gen, model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:18:58.638396Z","iopub.execute_input":"2025-06-09T19:18:58.639135Z","iopub.status.idle":"2025-06-09T19:19:00.722702Z","shell.execute_reply.started":"2025-06-09T19:18:58.639106Z","shell.execute_reply":"2025-06-09T19:19:00.721693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/anjing-1/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:19:29.710884Z","iopub.execute_input":"2025-06-09T19:19:29.711245Z","iopub.status.idle":"2025-06-09T19:19:30.00157Z","shell.execute_reply.started":"2025-06-09T19:19:29.711217Z","shell.execute_reply":"2025-06-09T19:19:30.000382Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/anjing-3/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:20:15.449675Z","iopub.execute_input":"2025-06-09T19:20:15.450041Z","iopub.status.idle":"2025-06-09T19:20:15.760428Z","shell.execute_reply.started":"2025-06-09T19:20:15.450012Z","shell.execute_reply":"2025-06-09T19:20:15.759401Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/kucing-1/download.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:20:34.745532Z","iopub.execute_input":"2025-06-09T19:20:34.746434Z","iopub.status.idle":"2025-06-09T19:20:34.997918Z","shell.execute_reply.started":"2025-06-09T19:20:34.746403Z","shell.execute_reply":"2025-06-09T19:20:34.996898Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Path ke gambar yang kamu upload\nimg_path = '/kaggle/input/kucing-3/images.jpg'\n\n# Fungsi prediksi\ndef predict_image(img_path):\n    img = image.load_img(img_path, target_size=(150, 150))\n    img_array = image.img_to_array(img) / 255.0\n    img_array = np.expand_dims(img_array, axis=0)\n\n    prediction = model.predict(img_array)[0][0]\n    label = \"Dog 🐶\" if prediction > 0.5 else \"Cat 🐱\"\n\n    plt.imshow(img)\n    plt.title(f\"Prediction: {label}\")\n    plt.axis('off')\n    plt.show()\n\n# Jalankan prediksi\npredict_image(img_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-09T19:21:00.364834Z","iopub.execute_input":"2025-06-09T19:21:00.365162Z","iopub.status.idle":"2025-06-09T19:21:00.657237Z","shell.execute_reply.started":"2025-06-09T19:21:00.365138Z","shell.execute_reply":"2025-06-09T19:21:00.656345Z"}},"outputs":[],"execution_count":null}]}