{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":792851,"sourceType":"datasetVersion","datasetId":414522}],"dockerImageVersionId":30674,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport plotly.express as px\n\nfrom pathlib import Path\nfrom sklearn.model_selection import train_test_split\n\nimport tensorflow as tf\n\nfrom sklearn.metrics import confusion_matrix, classification_report","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-03-25T12:04:20.666700Z","iopub.execute_input":"2024-03-25T12:04:20.667414Z","iopub.status.idle":"2024-03-25T12:04:20.672808Z","shell.execute_reply.started":"2024-03-25T12:04:20.667385Z","shell.execute_reply":"2024-03-25T12:04:20.671800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"positive_dir = Path('../input/surface-crack-detection/Positive')\nnegative_dir = Path('../input/surface-crack-detection/Negative')","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:04:26.247367Z","iopub.execute_input":"2024-03-25T12:04:26.248203Z","iopub.status.idle":"2024-03-25T12:04:26.252192Z","shell.execute_reply.started":"2024-03-25T12:04:26.248172Z","shell.execute_reply":"2024-03-25T12:04:26.251273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generate_df(image_dir, label):\n    filepaths = pd.Series(list(image_dir.glob(r'*.jpg')), name='Filepath').astype(str)\n    labels = pd.Series(label, name='Label', index=filepaths.index)\n    df = pd.concat([filepaths, labels], axis=1)\n    return df","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:04:30.304455Z","iopub.execute_input":"2024-03-25T12:04:30.304824Z","iopub.status.idle":"2024-03-25T12:04:30.310434Z","shell.execute_reply.started":"2024-03-25T12:04:30.304795Z","shell.execute_reply":"2024-03-25T12:04:30.309421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"positive_df = generate_df(positive_dir, label=\"POSITIVE\")\nnegative_df = generate_df(negative_dir, label=\"NEGATIVE\")\n\nall_df = pd.concat([positive_df, negative_df], axis=0).sample(frac=1.0, random_state=1).reset_index(drop=True)\nall_df","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:04:33.495188Z","iopub.execute_input":"2024-03-25T12:04:33.495542Z","iopub.status.idle":"2024-03-25T12:04:35.388129Z","shell.execute_reply.started":"2024-03-25T12:04:33.495515Z","shell.execute_reply":"2024-03-25T12:04:35.387210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, test_df = train_test_split(\n    all_df.sample(6000, random_state=1),\n    train_size=0.7,\n    shuffle=True,\n    random_state=1\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:04:38.761458Z","iopub.execute_input":"2024-03-25T12:04:38.762397Z","iopub.status.idle":"2024-03-25T12:04:38.771707Z","shell.execute_reply.started":"2024-03-25T12:04:38.762364Z","shell.execute_reply":"2024-03-25T12:04:38.770749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_gen = tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1./255,\n    validation_split=0.2\n)\n\ntest_gen = tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1./255\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:04:53.841940Z","iopub.execute_input":"2024-03-25T12:04:53.842581Z","iopub.status.idle":"2024-03-25T12:04:53.847343Z","shell.execute_reply.started":"2024-03-25T12:04:53.842551Z","shell.execute_reply":"2024-03-25T12:04:53.846346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = train_gen.flow_from_dataframe(\n    train_df,\n    x_col='Filepath',\n    y_col='Label',\n    target_size=(120, 120),\n    color_mode='rgb',\n    class_mode='binary',\n    batch_size=32,\n    shuffle=True,\n    seed=42,\n    subset='training'\n)\n\nval_data = train_gen.flow_from_dataframe(\n    train_df,\n    x_col='Filepath',\n    y_col='Label',\n    target_size=(120, 120),\n    color_mode='rgb',\n    class_mode='binary',\n    batch_size=32,\n    shuffle=True,\n    seed=42,\n    subset='validation'\n)\ntest_data = train_gen.flow_from_dataframe(\n    test_df,\n    x_col='Filepath',\n    y_col='Label',\n    target_size=(120, 120),\n    color_mode='rgb',\n    class_mode='binary',\n    batch_size=32,\n    shuffle=False,\n    seed=42\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:06:07.175287Z","iopub.execute_input":"2024-03-25T12:06:07.175644Z","iopub.status.idle":"2024-03-25T12:06:28.365144Z","shell.execute_reply.started":"2024-03-25T12:06:07.175615Z","shell.execute_reply":"2024-03-25T12:06:28.363827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs = tf.keras.Input(shape=(120, 120, 3))\nx = tf.keras.layers.Conv2D(filters=16, kernel_size=(3, 3), activation='relu')(inputs)\nx = tf.keras.layers.MaxPool2D(pool_size=(2, 2))(x)\nx = tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu')(x)\nx = tf.keras.layers.MaxPool2D(pool_size=(2, 2))(x)\nx = tf.keras.layers.GlobalAveragePooling2D()(x)\noutputs = tf.keras.layers.Dense(1, activation='sigmoid')(x)\n\nmodel = tf.keras.Model(inputs=inputs, outputs=outputs)\n\nmodel.compile(\n    optimizer='adam',\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n\nprint(model.summary())","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:06:47.277043Z","iopub.execute_input":"2024-03-25T12:06:47.277405Z","iopub.status.idle":"2024-03-25T12:06:47.996521Z","shell.execute_reply.started":"2024-03-25T12:06:47.277378Z","shell.execute_reply":"2024-03-25T12:06:47.995670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    train_data,\n    validation_data=val_data,\n    epochs=2,   #(increase the number of epochs for better result)\n    callbacks=[\n        tf.keras.callbacks.EarlyStopping(\n            monitor='val_loss',\n            patience=3,\n            restore_best_weights=True\n        )\n    ]\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:07:40.896831Z","iopub.execute_input":"2024-03-25T12:07:40.897615Z","iopub.status.idle":"2024-03-25T12:08:23.338705Z","shell.execute_reply.started":"2024-03-25T12:07:40.897585Z","shell.execute_reply":"2024-03-25T12:08:23.337892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.line(\n    history.history,\n    y=['loss', 'val_loss'],\n    labels={'index': \"Epoch\", 'value': \"Loss\"},\n    title=\"Training and Validation Loss Over Time\"\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:08:44.613723Z","iopub.execute_input":"2024-03-25T12:08:44.614077Z","iopub.status.idle":"2024-03-25T12:08:46.137794Z","shell.execute_reply.started":"2024-03-25T12:08:44.614052Z","shell.execute_reply":"2024-03-25T12:08:46.136898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evaluate_model(model, test_data):\n    \n    results = model.evaluate(test_data, verbose=0)\n    loss = results[0]\n    acc = results[1]\n    \n    print(\"    Test Loss: {:.5f}\".format(loss))\n    print(\"Test Accuracy: {:.2f}%\".format(acc * 100))\n    \n    y_pred = np.squeeze((model.predict(test_data) >= 0.5).astype(np.int))\n    cm = confusion_matrix(test_data.labels, y_pred)\n    clr = classification_report(test_data.labels, y_pred, target_names=[\"NEGATIVE\", \"POSITIVE\"])\n    \n    plt.figure(figsize=(6, 6))\n    sns.heatmap(cm, annot=True, fmt='g', vmin=0, cmap='Blues', cbar=False)\n    plt.xticks(ticks=np.arange(2) + 0.5, labels=[\"NEGATIVE\", \"POSITIVE\"])\n    plt.yticks(ticks=np.arange(2) + 0.5, labels=[\"NEGATIVE\", \"POSITIVE\"])\n    plt.xlabel(\"Predicted\")\n    plt.ylabel(\"Actual\")\n    plt.title(\"Confusion Matrix\")\n    plt.show()\n    \n    print(\"Classification Report:\\n----------------------\\n\", clr)","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:09:14.626687Z","iopub.execute_input":"2024-03-25T12:09:14.627541Z","iopub.status.idle":"2024-03-25T12:09:14.636033Z","shell.execute_reply.started":"2024-03-25T12:09:14.627512Z","shell.execute_reply":"2024-03-25T12:09:14.635033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#evaluate_model(model, test_data)","metadata":{"execution":{"iopub.status.busy":"2024-03-25T12:09:26.778184Z","iopub.execute_input":"2024-03-25T12:09:26.778874Z","iopub.status.idle":"2024-03-25T12:09:44.486334Z","shell.execute_reply.started":"2024-03-25T12:09:26.778838Z","shell.execute_reply":"2024-03-25T12:09:44.484961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}