{"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":"none","dataSources":[{"sourceId":21154,"databundleVersionId":1243559,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ============================================================\n# 1. IMPORT LIBRARY UMUM\n# ============================================================\nimport numpy as np\nimport pandas as pd\nimport os\n\nfrom sklearn.linear_model import Perceptron\nfrom sklearn.metrics import classification_report, f1_score\n\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\n\nimport os\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"-1\"\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:57.658924Z","iopub.execute_input":"2025-12-03T10:13:57.659884Z","iopub.status.idle":"2025-12-03T10:13:57.664823Z","shell.execute_reply.started":"2025-12-03T10:13:57.659850Z","shell.execute_reply":"2025-12-03T10:13:57.663973Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 2. EXERCISE 1 – SIMPLE PERCEPTRON (FROM SCRATCH, AND GATE)\n# ============================================================\n\nprint(\"=== Exercise 1: Simple Perceptron (AND gate, from scratch) ===\")\n\n# Dataset AND gate\nand_data = pd.DataFrame({\n    \"x1\": [0, 0, 1, 1],\n    \"x2\": [0, 1, 0, 1],\n    \"t\":  [0, 0, 0, 1]\n})\n\nX_and = and_data[[\"x1\", \"x2\"]].values\nt_and = and_data[\"t\"].values\n\ndef step_function(net, theta=0.0):\n    \"\"\"Step function: jika net >= theta -> 1, else 0.\"\"\"\n    return np.where(net >= theta, 1, 0)\n\n# Inisialisasi parameter perceptron\nnp.random.seed(42)\nw = np.random.randn(2) * 0.1   # bobot awal kecil\nb = 0.0                        # bias awal\nalpha = 0.1                    # learning rate\ntheta = 0.0                    # threshold\nepochs = 20\n\nprint(f\"Bobot awal: {w}, bias awal: {b}\")\n\n# Training loop\nfor epoch in range(epochs):\n    total_error = 0\n    for i in range(len(X_and)):\n        x = X_and[i]\n        t = t_and[i]\n\n        net = np.dot(w, x) + b\n        y = step_function(net, theta)\n\n        error = t - y\n        total_error += abs(error)\n\n        # Update aturan perceptron\n        w = w + alpha * error * x\n        b = b + alpha * error\n\n    print(f\"Epoch {epoch+1:02d} - total error: {total_error}\")\n\nprint(\"\\nBobot akhir:\", w, \"bias akhir:\", b)\n\n# Evaluasi di dataset AND\nnet_all = np.dot(X_and, w) + b\ny_pred_and = step_function(net_all, theta)\n\nresult_and = and_data.copy()\nresult_and[\"y_pred\"] = y_pred_and\nprint(\"\\nHasil prediksi perceptron manual (AND gate):\")\nprint(result_and)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:57.666198Z","iopub.execute_input":"2025-12-03T10:13:57.666509Z","iopub.status.idle":"2025-12-03T10:13:57.694726Z","shell.execute_reply.started":"2025-12-03T10:13:57.666436Z","shell.execute_reply":"2025-12-03T10:13:57.693797Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 3. EXERCISE 2 – PERCEPTRON DENGAN SCIKIT-LEARN\n# ============================================================\n\nprint(\"\\n=== Exercise 2: Perceptron dengan scikit-learn (AND gate) ===\")\n\nclf = Perceptron(\n    penalty=None,      # perceptron \"murni\"\n    alpha=0.0001,\n    max_iter=1000,\n    tol=1e-3,\n    random_state=42\n)\n\nclf.fit(X_and, t_and)\ny_pred_sklearn = clf.predict(X_and)\n\nresult_and_sklearn = and_data.copy()\nresult_and_sklearn[\"y_pred\"] = y_pred_sklearn\n\nprint(\"\\nKoefisien (bobot) sklearn:\", clf.coef_, \"bias:\", clf.intercept_)\nprint(\"\\nHasil prediksi perceptron sklearn (AND gate):\")\nprint(result_and_sklearn)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:57.696146Z","iopub.execute_input":"2025-12-03T10:13:57.696427Z","iopub.status.idle":"2025-12-03T10:13:57.709154Z","shell.execute_reply.started":"2025-12-03T10:13:57.696395Z","shell.execute_reply":"2025-12-03T10:13:57.708321Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 4. KAGGLE MLP – KONFIGURASI DASAR\n# ============================================================\n\nprint(\"\\n=== Bagian Kaggle: MLP untuk Petals to the Metal ===\")\n\nIMAGE_SIZE = (192, 192)    # ukuran gambar tfrecord\nNUM_CLASSES = 104          # jumlah kelas bunga\nAUTO = tf.data.AUTOTUNE\n\n# Coba TPU, kalau tidak ada pakai default (CPU/GPU)\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.TPUStrategy(tpu)\n    print(\"Running on TPU:\", tpu.master())\nexcept Exception as e:\n    print(\"TPU not found, using default strategy. Reason:\", e)\n    strategy = tf.distribute.get_strategy()\n\nBATCH_SIZE = 32 * strategy.num_replicas_in_sync\nEPOCHS = 12\nprint(\"Batch size per step:\", BATCH_SIZE)\n\n# Path dataset lokal Kaggle\nBASE_PATH = \"/kaggle/input/tpu-getting-started\"\nDATA_PATH = os.path.join(BASE_PATH, \"tfrecords-jpeg-192x192\")\n\nTRAINING_FILENAMES   = tf.io.gfile.glob(os.path.join(DATA_PATH, \"train/*.tfrec\"))\nVALIDATION_FILENAMES = tf.io.gfile.glob(os.path.join(DATA_PATH, \"val/*.tfrec\"))\nTEST_FILENAMES       = tf.io.gfile.glob(os.path.join(DATA_PATH, \"test/*.tfrec\"))\n\nprint(\"Jumlah file TFRecord - train :\", len(TRAINING_FILENAMES))\nprint(\"Jumlah file TFRecord - val   :\", len(VALIDATION_FILENAMES))\nprint(\"Jumlah file TFRecord - test  :\", len(TEST_FILENAMES))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:57.710117Z","iopub.execute_input":"2025-12-03T10:13:57.710485Z","iopub.status.idle":"2025-12-03T10:13:57.755363Z","shell.execute_reply.started":"2025-12-03T10:13:57.710431Z","shell.execute_reply":"2025-12-03T10:13:57.754434Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 5. FUNGSI BACA TFRECORD & TF.DATA PIPELINE\n# ============================================================\n\ndef decode_image(image_data):\n    \"\"\"Decode JPEG -> float32 [0,1] dan resize ke IMAGE_SIZE.\"\"\"\n    image = tf.image.decode_jpeg(image_data, channels=3)\n    image = tf.image.resize(image, IMAGE_SIZE)\n    image = tf.cast(image, tf.float32) / 255.0\n    return image\n\ndef read_labeled_tfrecord(example):\n    \"\"\"Parse TFRecord dengan label (train/val).\"\"\"\n    LABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"class\": tf.io.FixedLenFeature([], tf.int64),\n    }\n    example = tf.io.parse_single_example(example, LABELED_TFREC_FORMAT)\n    image = decode_image(example[\"image\"])\n    label = tf.cast(example[\"class\"], tf.int32)\n    return image, label\n\ndef read_unlabeled_tfrecord(example):\n    \"\"\"Parse TFRecord tanpa label (test).\"\"\"\n    UNLABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string),\n        \"id\": tf.io.FixedLenFeature([], tf.string),\n    }\n    example = tf.io.parse_single_example(example, UNLABELED_TFREC_FORMAT)\n    image = decode_image(example[\"image\"])\n    idnum = example[\"id\"]\n    return image, idnum\n\ndef load_dataset(filenames, labeled=True, ordered=False):\n    \"\"\"Loader umum: filenames -> tf.data.Dataset.\"\"\"\n    options = tf.data.Options()\n    if not ordered:\n        options.experimental_deterministic = False   # untuk speed\n\n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTO)\n    dataset = dataset.with_options(options)\n\n    if labeled:\n        dataset = dataset.map(read_labeled_tfrecord, num_parallel_calls=AUTO)\n    else:\n        dataset = dataset.map(read_unlabeled_tfrecord, num_parallel_calls=AUTO)\n\n    return dataset\n\ndef get_train_dataset():\n    ds = load_dataset(TRAINING_FILENAMES, labeled=True, ordered=False)\n    ds = ds.shuffle(2048)\n    ds = ds.batch(BATCH_SIZE)\n    ds = ds.prefetch(AUTO)\n    return ds\n\ndef get_valid_dataset():\n    ds = load_dataset(VALIDATION_FILENAMES, labeled=True, ordered=True)\n    ds = ds.batch(BATCH_SIZE)\n    ds = ds.cache()\n    ds = ds.prefetch(AUTO)\n    return ds\n\ndef get_test_dataset(ordered=True):\n    ds = load_dataset(TEST_FILENAMES, labeled=False, ordered=ordered)\n    ds = ds.batch(BATCH_SIZE)\n    ds = ds.prefetch(AUTO)\n    return ds\n\ntrain_ds = get_train_dataset()\nvalid_ds = get_valid_dataset()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:57.757142Z","iopub.execute_input":"2025-12-03T10:13:57.757432Z","iopub.status.idle":"2025-12-03T10:13:57.968472Z","shell.execute_reply.started":"2025-12-03T10:13:57.757409Z","shell.execute_reply":"2025-12-03T10:13:57.967297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 6. ARSITEKTUR MLP\n# ============================================================\n\nwith strategy.scope():\n    model = tf.keras.Sequential(\n        [\n            tf.keras.layers.Input(shape=(*IMAGE_SIZE, 3)),\n            tf.keras.layers.Flatten(),                 # gambar -> vektor\n            tf.keras.layers.Dense(256, activation=\"relu\"),\n            tf.keras.layers.Dropout(0.5),\n            tf.keras.layers.Dense(128, activation=\"relu\"),\n            tf.keras.layers.Dropout(0.3),\n            tf.keras.layers.Dense(NUM_CLASSES, activation=\"softmax\"),\n        ]\n    )\n\n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),\n        loss=\"sparse_categorical_crossentropy\",\n        metrics=[\"sparse_categorical_accuracy\"],\n    )\n\nmodel.summary()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:57.969974Z","iopub.execute_input":"2025-12-03T10:13:57.970353Z","iopub.status.idle":"2025-12-03T10:13:58.368708Z","shell.execute_reply.started":"2025-12-03T10:13:57.970329Z","shell.execute_reply":"2025-12-03T10:13:58.367947Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 7. TRAINING MLP\n# ============================================================\n\nhistory = model.fit(\n    train_ds,\n    epochs=EPOCHS,\n    validation_data=valid_ds,\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-03T10:13:58.369480Z","iopub.execute_input":"2025-12-03T10:13:58.369786Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 8. PLOT LOSS & ACCURACY\n# ============================================================\n\nhistory_dict = history.history\n\nplt.figure(figsize=(8,4))\nplt.plot(history_dict[\"loss\"], label=\"Train Loss\")\nplt.plot(history_dict[\"val_loss\"], label=\"Val Loss\")\nplt.title(\"Loss vs Epoch\")\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Loss\")\nplt.legend()\nplt.show()\n\nplt.figure(figsize=(8,4))\nplt.plot(history_dict[\"sparse_categorical_accuracy\"], label=\"Train Acc\")\nplt.plot(history_dict[\"val_sparse_categorical_accuracy\"], label=\"Val Acc\")\nplt.title(\"Accuracy vs Epoch\")\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Accuracy\")\nplt.legend()\nplt.show()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 9. EVALUASI DI VALIDATION SET\n# ============================================================\n\ny_true = []\ny_pred = []\n\nfor images, labels in valid_ds:\n    probs = model.predict(images, verbose=0)\n    preds = np.argmax(probs, axis=-1)\n\n    y_true.extend(labels.numpy())\n    y_pred.extend(preds)\n\ny_true = np.array(y_true)\ny_pred = np.array(y_pred)\n\nprint(\"\\n=== Evaluasi di Validation Set ===\")\nprint(\"Classification report:\")\nprint(classification_report(y_true, y_pred, digits=4))\nprint(\"Macro F1:\", f1_score(y_true, y_pred, average=\"macro\"))\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 10. PREDIKSI TEST & SUBMISSION KAGGLE\n# ============================================================\n\ntest_ds = get_test_dataset(ordered=True)\n\n# pisahkan image & id\ntest_images_ds = test_ds.map(lambda image, idnum: image)\ntest_ids_ds = test_ds.map(lambda image, idnum: idnum)\n\n# prediksi\ntest_probs = model.predict(test_images_ds, verbose=1)\ntest_pred = np.argmax(test_probs, axis=-1)\n\n# gabungkan semua id (tipe string)\ntest_ids = np.concatenate(list(test_ids_ds.as_numpy_iterator())).astype(\"U\")\n\nsubmission = pd.DataFrame({\"id\": test_ids, \"label\": test_pred})\nsubmission.to_csv(\"submission.csv\", index=False)\n\nprint(\"\\nContoh isi submission.csv:\")\nprint(submission.head())\nprint(\"\\nFile 'submission.csv' siap di-upload ke Kaggle.\")\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}