{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":4104,"databundleVersionId":46661,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":418031,"sourceType":"datasetVersion","datasetId":131128}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras.applications.mobilenet_v2 import preprocess_input\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nfrom sklearn.model_selection import train_test_split\nimport os\nimport matplotlib.pyplot as plt\n\n# --- 1. SETUP PATH & DATA ---\nprint(\"🚀 Menyiapkan Data...\")\nBASE_PATH = \"../input/diabetic-retinopathy-resized\"\nIMG_DIR = os.path.join(BASE_PATH, \"resized_train_cropped\", \"resized_train_cropped\")\nCSV_PATH = os.path.join(BASE_PATH, \"trainLabels_cropped.csv\")\n\n# Baca CSV\ndf = pd.read_csv(CSV_PATH)\ndf = df[['image', 'level']]\ndf['image'] = df['image'].astype(str) + '.jpeg'\ndf['level'] = df['level'].astype(str)\n\n# ⚠️ UPGRADE: Kita pakai 3000 data (lebih banyak dari sebelumnya) biar makin akurat\ndf = df.sample(3000, random_state=42)\nprint(f\"✅ Menggunakan {len(df)} gambar untuk training.\")\n\n# Split Data (80% Train, 20% Val)\ntrain_df, val_df = train_test_split(df, test_size=0.2, stratify=df['level'], random_state=42)\n\n# --- 2. PREPROCESSING CANGGIH (Transfer Learning) ---\n# Kita pakai preprocessing bawaan MobileNetV2 (bukan cuma bagi 255)\ntrain_datagen = ImageDataGenerator(\n    preprocessing_function=preprocess_input, # Kunci rahasia MobileNet\n    rotation_range=20,\n    zoom_range=0.15,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    horizontal_flip=True,\n    fill_mode='nearest'\n)\n\nval_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_df,\n    directory=IMG_DIR,\n    x_col='image',\n    y_col='level',\n    target_size=(224, 224), # Ukuran standar MobileNet\n    batch_size=32,\n    class_mode='categorical'\n)\n\nval_generator = val_datagen.flow_from_dataframe(\n    dataframe=val_df,\n    directory=IMG_DIR,\n    x_col='image',\n    y_col='level',\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='categorical'\n)\n\n# --- 3. MEMBANGUN MODEL SULTAN (MobileNetV2) ---\nprint(\"\\n🧠 Mendownload Otak Pre-Trained (MobileNetV2)...\")\n\n# Download base model (tanpa bagian kepala/top)\nbase_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))\n\n# Bekukan base model (biar ilmu lamanya gak hilang)\nbase_model.trainable = False \n\n# Tambahkan kepala baru khusus Retina\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(256, activation='relu')(x)\nx = Dropout(0.5)(x) # Dropout tinggi biar gak overfitting\npredictions = Dense(5, activation='softmax')(x)\n\nmodel = Model(inputs=base_model.input, outputs=predictions)\n\n# Compile dengan Learning Rate KECIL (Penting buat fine-tuning)\nmodel.compile(optimizer=Adam(learning_rate=0.0001), \n              loss='categorical_crossentropy', \n              metrics=['accuracy'])\n\n# --- 4. TRAINING ---\nprint(\"\\n🔥 MULAI TRAINING (20 Epochs)...\")\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=20 # Kita gas 20 putaran\n)\n\n# --- 5. HASIL ---\nmodel.save(\"model_mobilenet_retinopathy.h5\")\nprint(\"\\n✅ Selesai! Model tersimpan.\")\n\n# Plot Grafik\nacc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs_range = range(len(acc))\n\nplt.figure(figsize=(14, 5))\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')\nplt.show()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-08T08:47:18.060447Z","iopub.execute_input":"2025-12-08T08:47:18.0612Z","iopub.status.idle":"2025-12-08T09:00:56.341998Z","shell.execute_reply.started":"2025-12-08T08:47:18.061176Z","shell.execute_reply":"2025-12-08T09:00:56.341409Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\n\n# --- 1. SETUP DATA ---\nBASE_PATH = \"../input/diabetic-retinopathy-resized\"\nCSV_PATH = os.path.join(BASE_PATH, \"trainLabels_cropped.csv\")\n\n# Baca Data Label\ndf = pd.read_csv(CSV_PATH)\n\n# Ubah angka 0-4 jadi nama penyakit biar persis kayak contoh dosen\nclass_names = {\n    0: 'No DR (Normal)',\n    1: 'Mild',\n    2: 'Moderate',\n    3: 'Severe',\n    4: 'Proliferative DR'\n}\ndf['Kondisi'] = df['level'].map(class_names)\n\n# Hitung jumlah data\ncounts = df['Kondisi'].value_counts()\n\n# --- 2. BUAT GRAFIK ---\nplt.figure(figsize=(16, 6)) # Ukuran gambar lebar\n\n# GRAFIK KIRI: PIE CHART (Persentase - Sesuai kolom % di contoh dosen)\nplt.subplot(1, 2, 1)\ncolors = sns.color_palette('pastel')[0:5]\nplt.pie(counts, labels=counts.index, autopct='%1.1f%%', startangle=140, colors=colors, explode=(0.05, 0, 0, 0, 0))\nplt.title('Persentase Keparahan Penyakit (Pie Chart)', fontsize=14, fontweight='bold')\n\n# GRAFIK KANAN: BAR CHART (Jumlah Sample - Sesuai kolom Qty di contoh dosen)\nplt.subplot(1, 2, 2)\nax = sns.barplot(x=counts.index, y=counts.values, palette='viridis')\nplt.title('Jumlah Gambar per Kategori (Bar Chart)', fontsize=14, fontweight='bold')\nplt.xlabel('Tingkat Keparahan', fontsize=12)\nplt.ylabel('Jumlah Sampel', fontsize=12)\nplt.xticks(rotation=45)\n\n# Tambahkan angka di atas batang (biar detail)\nfor i in ax.containers:\n    ax.bar_label(i,)\n\n# Tampilkan\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T09:09:24.246088Z","iopub.execute_input":"2025-12-08T09:09:24.246372Z","iopub.status.idle":"2025-12-08T09:09:24.953726Z","shell.execute_reply.started":"2025-12-08T09:09:24.246353Z","shell.execute_reply":"2025-12-08T09:09:24.953082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix, classification_report\n\n# --- 1. SIAPKAN DATA UJIAN (Validation) ---\n# Kita bikin generator khusus buat ujian.\n# PENTING: shuffle=False supaya urutan kunci jawaban gak diacak-acak\nprint(\"🔄 Menyiapkan data ujian...\")\nval_gen_eval = val_datagen.flow_from_dataframe(\n    dataframe=val_df,\n    directory=IMG_DIR,\n    x_col='image',\n    y_col='level',\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='categorical',\n    shuffle=False \n)\n\n# --- 2. SURUH AI MENEBAK ---\nprint(\"🤔 AI sedang mengerjakan soal ujian... (Tunggu sebentar)\")\nY_pred = model.predict(val_gen_eval)\ny_pred = np.argmax(Y_pred, axis=1) # Ambil tebakan AI\n\n# Kunci jawaban asli\ny_true = val_gen_eval.classes \n\n# --- 3. GAMBAR CONFUSION MATRIX (Tabel Dosen) ---\ncm = confusion_matrix(y_true, y_pred)\n\nplt.figure(figsize=(10, 8))\n# Gambar kotak-kotak biru\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues', \n            xticklabels=['Normal', 'Mild', 'Moderate', 'Severe', 'Proliferative'],\n            yticklabels=['Normal', 'Mild', 'Moderate', 'Severe', 'Proliferative'])\n\nplt.title('Confusion Matrix (Evaluasi Model)', fontsize=16, fontweight='bold')\nplt.ylabel('Kondisi Asli Pasien', fontsize=12)\nplt.xlabel('Tebakan AI', fontsize=12)\nplt.show()\n\n# --- 4. TAMPILKAN NILAI DETAIL ---\nprint(\"\\n=== RAPOR NILAI AI (Classification Report) ===\")\nprint(classification_report(y_true, y_pred, target_names=['Normal', 'Mild', 'Moderate', 'Severe', 'Proliferative']))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T09:18:41.725675Z","iopub.execute_input":"2025-12-08T09:18:41.726316Z","iopub.status.idle":"2025-12-08T09:18:53.295575Z","shell.execute_reply.started":"2025-12-08T09:18:41.726293Z","shell.execute_reply":"2025-12-08T09:18:53.294891Z"}},"outputs":[],"execution_count":null}]}