{"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":122519208,"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'  # Hanya tampilkan error, abaikan warning\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-06T19:08:30.553835Z","iopub.execute_input":"2025-06-06T19:08:30.554263Z","iopub.status.idle":"2025-06-06T19:08:30.560599Z","shell.execute_reply.started":"2025-06-06T19:08:30.554215Z","shell.execute_reply":"2025-06-06T19:08:30.558990Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Supress warning log dari TensorFlow\nimport os\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # Hanya tampilkan error, abaikan warning\n\nimport zipfile\nimport random\nimport shutil\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras import layers, models\n\n# Ekstrak dataset dari ZIP (gunakan dataset dari kompetisi Kaggle: Dogs vs Cats)\nwith zipfile.ZipFile('../input/dogs-vs-cats/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/tmp/dogs-vs-cats')\n\nbase_dir = '/tmp/dogs-vs-cats/train'\n\n# Buat folder training dan validation\ntrain_dir = '/tmp/cats-vs-dogs/training'\nval_dir = '/tmp/cats-vs-dogs/validation'\nos.makedirs(train_dir + '/cats', exist_ok=True)\nos.makedirs(train_dir + '/dogs', exist_ok=True)\nos.makedirs(val_dir + '/cats', exist_ok=True)\nos.makedirs(val_dir + '/dogs', exist_ok=True)\n\n# Fungsi membagi gambar ke folder training & validation\ndef split_data(source_dir, train_dir, val_dir, split_size):\n    files = [f for f in os.listdir(source_dir) if os.path.getsize(os.path.join(source_dir, f)) > 0]\n    random.shuffle(files)\n    split_index = int(len(files) * split_size)\n    train_files = files[:split_index]\n    val_files = files[split_index:]\n    \n    for f in train_files:\n        shutil.copy(os.path.join(source_dir, f), os.path.join(train_dir, f))\n    for f in val_files:\n        shutil.copy(os.path.join(source_dir, f), os.path.join(val_dir, f))\n\n# Pisahkan file berdasarkan nama\ncat_source = [f for f in os.listdir(base_dir) if f.startswith('cat')]\ndog_source = [f for f in os.listdir(base_dir) if f.startswith('dog')]\n\nos.makedirs('/tmp/cats_temp', exist_ok=True)\nos.makedirs('/tmp/dogs_temp', exist_ok=True)\n\nfor f in cat_source:\n    shutil.copy(os.path.join(base_dir, f), os.path.join('/tmp/cats_temp', f))\nfor f in dog_source:\n    shutil.copy(os.path.join(base_dir, f), os.path.join('/tmp/dogs_temp', f))\n\n# Split data: 90% train, 10% validation\nsplit_data('/tmp/cats_temp', train_dir + '/cats', val_dir + '/cats', 0.9)\nsplit_data('/tmp/dogs_temp', train_dir + '/dogs', val_dir + '/dogs', 0.9)\n\n# ImageDataGenerator\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\nmodel = 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.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\n# Training\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=10\n)\n\n# Visualisasi Akurasi & Loss\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-06T19:08:51.590910Z","iopub.execute_input":"2025-06-06T19:08:51.591268Z"}},"outputs":[],"execution_count":null}]}