{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.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":5048,"databundleVersionId":868335,"sourceType":"competition"},{"sourceId":706935,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":536774,"modelId":550215}],"dockerImageVersionId":31236,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Imports & Config**","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import MobileNet","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T19:16:44.890586Z","iopub.execute_input":"2026-01-02T19:16:44.890908Z","iopub.status.idle":"2026-01-02T19:17:07.428521Z","shell.execute_reply.started":"2026-01-02T19:16:44.890879Z","shell.execute_reply":"2026-01-02T19:17:07.427935Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Preprocessing Pipeline + Augmentation**","metadata":{}},{"cell_type":"markdown","source":"✔ Resize\n✔ Grayscale\n✔ Histogram Equalization\n✔ Normalize","metadata":{}},{"cell_type":"code","source":"# IMG_SIZE = 96\nIMG_SIZE = 128\nBATCH_SIZE = 32\n\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    rotation_range=10,\n    width_shift_range=0.1,\n    height_shift_range=0.1,\n    brightness_range=[0.6, 1.4],\n    horizontal_flip=True,\n    validation_split=0.2\n)\n\ntrain_generator = train_datagen.flow_from_directory(\n    '../input/state-farm-distracted-driver-detection/imgs/train',\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    subset='training',\n    shuffle=True\n)\n\nval_generator = train_datagen.flow_from_directory(\n    '../input/state-farm-distracted-driver-detection/imgs/train',\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    subset='validation',\n    shuffle=False\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T19:17:07.429526Z","iopub.execute_input":"2026-01-02T19:17:07.430045Z","iopub.status.idle":"2026-01-02T19:17:29.494731Z","shell.execute_reply.started":"2026-01-02T19:17:07.430020Z","shell.execute_reply":"2026-01-02T19:17:29.494018Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **MobileNet Model (Grayscale Input)**","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import MobileNet\n\ninput_layer = layers.Input(shape=(IMG_SIZE, IMG_SIZE, 3))\n# x = layers.Concatenate()([input_layer, input_layer, input_layer])  # 1->3 channels\n\nbase_model = MobileNet(\n    input_shape=(IMG_SIZE, IMG_SIZE, 3),\n    include_top=False,\n    weights='imagenet',\n    alpha=0.5\n)\n# base_model = tf.keras.applications.MobileNetV2(\n#     input_shape=(96, 96, 3),\n#     include_top=False,\n#     weights='imagenet', \n#     alpha=0.5  \n# )\nbase_model.trainable = False\n\nx = base_model(input_layer)\nx = layers.GlobalAveragePooling2D()(x)\nx = layers.Dense(128, activation='relu')(x)\nx = layers.Dropout(0.3)(x)\noutput = layers.Dense(10, activation='softmax')(x)\n\nmodel = models.Model(inputs=input_layer, outputs=output)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T13:48:40.369919Z","iopub.execute_input":"2025-12-31T13:48:40.370658Z","iopub.status.idle":"2025-12-31T13:48:43.249102Z","shell.execute_reply.started":"2025-12-31T13:48:40.370628Z","shell.execute_reply":"2025-12-31T13:48:43.248388Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T13:48:44.446472Z","iopub.execute_input":"2025-12-31T13:48:44.446762Z","iopub.status.idle":"2025-12-31T13:48:44.466823Z","shell.execute_reply.started":"2025-12-31T13:48:44.446738Z","shell.execute_reply":"2025-12-31T13:48:44.466165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.utils import plot_model\n\nplot_model(model, to_file='model_architecture.png', show_shapes=True, show_layer_names=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T13:48:47.206245Z","iopub.execute_input":"2025-12-31T13:48:47.206540Z","iopub.status.idle":"2025-12-31T13:48:47.472411Z","shell.execute_reply.started":"2025-12-31T13:48:47.206516Z","shell.execute_reply":"2025-12-31T13:48:47.471661Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_model(\n    model,                    \n    to_file='model_architecture.png', \n    show_shapes=True,         \n    show_layer_names=True,     \n    dpi=96                      \n)\n\nprint(\"✅ Model architecture saved as 'model_architecture.png'\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T13:48:47.823288Z","iopub.execute_input":"2025-12-31T13:48:47.823985Z","iopub.status.idle":"2025-12-31T13:48:47.897751Z","shell.execute_reply.started":"2025-12-31T13:48:47.823960Z","shell.execute_reply":"2025-12-31T13:48:47.897208Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Compile Model**","metadata":{}},{"cell_type":"code","source":"model = tf.keras.models.load_model('/kaggle/input/final-mobilnet128-h5/tensorflow2/default/1/final_MobilNet128.h5')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T19:17:29.495986Z","iopub.execute_input":"2026-01-02T19:17:29.496275Z","iopub.status.idle":"2026-01-02T19:17:33.821523Z","shell.execute_reply.started":"2026-01-02T19:17:29.496252Z","shell.execute_reply":"2026-01-02T19:17:33.820809Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(\n    optimizer='adam',\n    loss='categorical_crossentropy',\n    metrics=['accuracy']\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T19:17:33.822507Z","iopub.execute_input":"2026-01-02T19:17:33.822825Z","iopub.status.idle":"2026-01-02T19:17:33.829921Z","shell.execute_reply.started":"2026-01-02T19:17:33.822791Z","shell.execute_reply":"2026-01-02T19:17:33.829231Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Train Model**","metadata":{}},{"cell_type":"code","source":"# IMG_SIZE = 128\nEPOCHS = 15\n\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=EPOCHS\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T19:18:15.628952Z","iopub.execute_input":"2026-01-02T19:18:15.629537Z","iopub.status.idle":"2026-01-02T19:59:01.503212Z","shell.execute_reply.started":"2026-01-02T19:18:15.629509Z","shell.execute_reply":"2026-01-02T19:59:01.502596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# IMG_SIZE = 128\nEPOCHS = 15\n\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=EPOCHS\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T20:01:34.834657Z","iopub.execute_input":"2026-01-02T20:01:34.835392Z","iopub.status.idle":"2026-01-02T20:38:59.730898Z","shell.execute_reply.started":"2026-01-02T20:01:34.835364Z","shell.execute_reply":"2026-01-02T20:38:59.730115Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# IMG_SIZE = 96\nEPOCHS = 15\n\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=EPOCHS\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T12:46:53.040575Z","iopub.execute_input":"2025-12-31T12:46:53.041301Z","iopub.status.idle":"2025-12-31T13:09:09.625334Z","shell.execute_reply.started":"2025-12-31T12:46:53.041262Z","shell.execute_reply":"2025-12-31T13:09:09.624718Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Test / Inference**","metadata":{}},{"cell_type":"code","source":"test_dir = '../input/state-farm-distracted-driver-detection/imgs/test'\nimport glob\n\nfor img_path in glob.glob(f\"{test_dir}/*.jpg\"):\n    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)\n    img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))\n    img = img / 255.0\n    img = np.expand_dims(img, axis=(0,-1))  # shape = (1,128,128,1)\n    \n    pred = model.predict(img)\n    class_idx = np.argmax(pred)\n    confidence = np.max(pred)\n    print(f\"{img_path} -> Class: {class_idx}, Confidence: {confidence:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T08:50:24.049482Z","iopub.execute_input":"2025-12-31T08:50:24.049858Z","execution_failed":"2025-12-31T09:40:46.233Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Save Model + Convert to TFLite INT8**","metadata":{}},{"cell_type":"code","source":"model.save(\"driver_monitor_modelv96.h5\")  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T12:43:22.898464Z","iopub.execute_input":"2025-12-31T12:43:22.899299Z","iopub.status.idle":"2025-12-31T12:43:23.158882Z","shell.execute_reply.started":"2025-12-31T12:43:22.899265Z","shell.execute_reply":"2025-12-31T12:43:23.158108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"converter = tf.lite.TFLiteConverter.from_keras_model(model)\ntflite_model = converter.convert()\n\nwith open(\"driver_model.tflite\", \"wb\") as f:\n    f.write(tflite_model)\n\nprint(\"✅ TFLite model saved successfully!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-31T12:07:47.950489Z","iopub.execute_input":"2025-12-31T12:07:47.950872Z","iopub.status.idle":"2025-12-31T12:07:53.618292Z","shell.execute_reply.started":"2025-12-31T12:07:47.950840Z","shell.execute_reply":"2025-12-31T12:07:53.617660Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save(\"final_MobilNet128v3.h5\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T20:43:09.085604Z","iopub.execute_input":"2026-01-02T20:43:09.086357Z","iopub.status.idle":"2026-01-02T20:43:09.225503Z","shell.execute_reply.started":"2026-01-02T20:43:09.086327Z","shell.execute_reply":"2026-01-02T20:43:09.224873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nimport numpy as np\n\n\n# model = tf.keras.models.load_model('final_MobilNet128.h5')\n\n\ndef representative_data_gen():\n    \n    \n    count = 0\n    for imgs, labels in val_generator:\n        for i in range(imgs.shape[0]):\n           \n            data = np.expand_dims(imgs[i], axis=0).astype(np.float32)\n            yield [data]\n            count += 1\n            if count >= 200: \n                return\n\n\nconverter = tf.lite.TFLiteConverter.from_keras_model(model)\nconverter.optimizations = [tf.lite.Optimize.DEFAULT]\nconverter.representative_dataset = representative_data_gen\n\n\nconverter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]\n\n\nconverter.inference_input_type = tf.uint8 \nconverter.inference_output_type = tf.uint8\n\n\ntry:\n    tflite_model_quant = converter.convert()\n    with open('mobilenet128_aint8v3.tflite', 'wb') as f:\n        f.write(tflite_model_quant)\n    print(\"Converted to tflite\")\nexcept Exception as e:\n    print(f\"Error during conversion: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-02T20:43:16.941100Z","iopub.execute_input":"2026-01-02T20:43:16.941360Z","iopub.status.idle":"2026-01-02T20:43:25.563349Z","shell.execute_reply.started":"2026-01-02T20:43:16.941339Z","shell.execute_reply":"2026-01-02T20:43:25.562394Z"}},"outputs":[],"execution_count":null}]}