{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"}],"dockerImageVersionId":30786,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# # This Python 3 environment comes with many helpful analytics libraries installed\n# # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# # For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# # Input data files are available in the read-only \"../input/\" directory\n# # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:16.841056Z","iopub.execute_input":"2024-12-16T14:48:16.841286Z","iopub.status.idle":"2024-12-16T14:48:16.846302Z","shell.execute_reply.started":"2024-12-16T14:48:16.841261Z","shell.execute_reply":"2024-12-16T14:48:16.845463Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nfrom sklearn.model_selection import train_test_split\nimport pickle\nimport tensorflow as tf\nimport keras_tuner as kt\nimport tensorflow.keras as keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.distribute import *\n","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:16.847355Z","iopub.execute_input":"2024-12-16T14:48:16.847595Z","iopub.status.idle":"2024-12-16T14:48:20.348556Z","shell.execute_reply.started":"2024-12-16T14:48:16.847570Z","shell.execute_reply":"2024-12-16T14:48:20.347870Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load Training DataFrame #","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/cassava-leaf-disease-classification/train.csv\")\nprint(train.shape)\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:20.349566Z","iopub.execute_input":"2024-12-16T14:48:20.350055Z","iopub.status.idle":"2024-12-16T14:48:20.563701Z","shell.execute_reply.started":"2024-12-16T14:48:20.350026Z","shell.execute_reply":"2024-12-16T14:48:20.562870Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Label Distribution ##","metadata":{}},{"cell_type":"code","source":"labels = sorted(pd.unique(train[\"label\"]))\nprint(labels)\n\ndef showProportions(dataset):\n    prop_df = pd.DataFrame(columns = [\"proportion\"], index = labels)\n    observations = len(dataset)\n    for idx in labels:\n        prop_df.iloc[idx] = sum(dataset[\"label\"]==idx)/observations\n    print(prop_df)","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:20.565779Z","iopub.execute_input":"2024-12-16T14:48:20.566089Z","iopub.status.idle":"2024-12-16T14:48:20.578198Z","shell.execute_reply.started":"2024-12-16T14:48:20.566063Z","shell.execute_reply":"2024-12-16T14:48:20.577284Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"showProportions(train)\nprint(len(train))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:20.579278Z","iopub.execute_input":"2024-12-16T14:48:20.579593Z","iopub.status.idle":"2024-12-16T14:48:20.600626Z","shell.execute_reply.started":"2024-12-16T14:48:20.579567Z","shell.execute_reply":"2024-12-16T14:48:20.599881Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# modify training set to be more evenly distributed\nskipCount = 0\nlength = len(train)\nskips = []\nfor x in range(length):\n    if(train.iloc[x].loc['label'] == 3):\n        skipCount += 1\n        if(skipCount < 5):\n            skips.append(x)\n        else:\n            skipCount = 0\n\ntrain.drop(labels=skips, axis=0, inplace=True)\nshowProportions(train)\nprint(train.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:20.601489Z","iopub.execute_input":"2024-12-16T14:48:20.601726Z","iopub.status.idle":"2024-12-16T14:48:21.531349Z","shell.execute_reply.started":"2024-12-16T14:48:20.601702Z","shell.execute_reply":"2024-12-16T14:48:21.530454Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":" ## View Sample of Images ##","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(6,6))\ni=0\nfor image in train[\"image_id\"].sample(n=16, random_state=1):\n#     print(str(image))\n    ax = plt.subplot(4, 4, i + 1)\n    plt.imshow(X=mpimg.imread(\"/kaggle/input/cassava-leaf-disease-classification/train_images/\"+str(image)))\n    plt.axis(\"off\")\n    i+=1","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:21.532558Z","iopub.execute_input":"2024-12-16T14:48:21.533058Z","iopub.status.idle":"2024-12-16T14:48:23.373320Z","shell.execute_reply.started":"2024-12-16T14:48:21.533017Z","shell.execute_reply":"2024-12-16T14:48:23.372401Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Data Generators ##","metadata":{}},{"cell_type":"code","source":"# splitting dataframe into training (70%) and validation (30%) while maintaining label proportions\ntrain_df , valid_df = train_test_split(train, test_size=0.30, stratify =train['label'], random_state=1)","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:23.374456Z","iopub.execute_input":"2024-12-16T14:48:23.374746Z","iopub.status.idle":"2024-12-16T14:48:23.387358Z","shell.execute_reply.started":"2024-12-16T14:48:23.374718Z","shell.execute_reply":"2024-12-16T14:48:23.386306Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import json\n# # tf_config = {\n# #     'cluster': {\n# #         'worker': []\n# #     },\n# #     'task': {'type': 'worker', 'index': 0},\n# #     'task': {'type': 'worker', 'index': 1},\n# #     'task': {'type': 'worker', 'index': 2},\n# # }\n# os.environ['TF_CONFIG'] = json.dumps({ 'cluster': { 'worker': [\"localhost:12345\", \"localhost:23456\"] }, 'task': {'type': 'worker', 'index': 0} })","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:23.388500Z","iopub.execute_input":"2024-12-16T14:48:23.388868Z","iopub.status.idle":"2024-12-16T14:48:23.394911Z","shell.execute_reply.started":"2024-12-16T14:48:23.388830Z","shell.execute_reply":"2024-12-16T14:48:23.394193Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# gpus = tf.config.list_physical_devices()\n# print(gpus)\n# if gpus:\n#   # Create 2 virtual GPUs with 1GB memory each\n#   try:\n#     tf.config.set_logical_device_configuration(\n#         gpus[0],\n#         [tf.config.LogicalDeviceConfiguration(memory_limit=1024*15),\n#          tf.config.LogicalDeviceConfiguration(memory_limit=1024*15)])\n#     logical_gpus = tf.config.list_logical_devices('GPU')\n#     print(len(gpus), \"Physical GPU,\", len(logical_gpus), \"Logical GPUs\")\n#   except RuntimeError as e:\n#     # Virtual devices must be set before GPUs have been initialized\n#     print(e)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:23.395935Z","iopub.execute_input":"2024-12-16T14:48:23.396175Z","iopub.status.idle":"2024-12-16T14:48:23.407120Z","shell.execute_reply.started":"2024-12-16T14:48:23.396151Z","shell.execute_reply":"2024-12-16T14:48:23.406494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# from PIL import Image\n# import os\n\n# def crop_images(folder_path, output_folder, left, top, right, bottom):\n#     \"\"\"Crops all images in a folder and saves them to a new folder.\"\"\"\n\n#     if not os.path.exists(output_folder):\n#         os.makedirs(output_folder)\n\n#     for filename in os.listdir(folder_path):\n#         if filename.endswith(('.jpg', '.jpeg', '.png')):\n#             img_path = os.path.join(folder_path, filename)\n#             img = Image.open(img_path)\n\n#             # Crop the image\n#             cropped_img = img.crop((left, top, right, bottom))\n\n#             # Save the cropped image\n#             cropped_img_path = os.path.join(output_folder, filename)\n#             cropped_img.save(cropped_img_path)\n","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:23.408315Z","iopub.execute_input":"2024-12-16T14:48:23.408605Z","iopub.status.idle":"2024-12-16T14:48:23.422412Z","shell.execute_reply.started":"2024-12-16T14:48:23.408576Z","shell.execute_reply":"2024-12-16T14:48:23.421786Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"folder_path = \"/kaggle/input/cassava-leaf-disease-classification/train_images\"  # Replace with your folder path\noutput_folder = \"/kaggle/working/train_images\"  # Replace with your output folder path\nleft = 44  # Adjust crop coordinates as needed\ntop = 44\nright = 512 + 44\nbottom = 512 + 44","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:23.423319Z","iopub.execute_input":"2024-12-16T14:48:23.423574Z","iopub.status.idle":"2024-12-16T14:48:23.438913Z","shell.execute_reply.started":"2024-12-16T14:48:23.423550Z","shell.execute_reply":"2024-12-16T14:48:23.438265Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# only run once as needed\n# crop_images(folder_path, output_folder, left, top, right, bottom)","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:23.441923Z","iopub.execute_input":"2024-12-16T14:48:23.442176Z","iopub.status.idle":"2024-12-16T14:48:23.450670Z","shell.execute_reply.started":"2024-12-16T14:48:23.442142Z","shell.execute_reply":"2024-12-16T14:48:23.449863Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# create the image data generators for both data sets\n\nstrategy = tf.distribute.MirroredStrategy(devices=[\"/cpu:0\", \"/gpu:0\", \"/gpu:1\"])\n\nwith strategy.scope():\n    train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1/255, \n        validation_split=0.30,\n        rotation_range = 90,\n        width_shift_range = 0.25, \n        height_shift_range = 0.25, \n        shear_range = 0.25, \n        zoom_range = 0.25, \n        horizontal_flip = True, \n        vertical_flip = True )\n    test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1/255,                                                              \n        # rotation_range = 45,\n        # width_shift_range = 0.1, \n        # height_shift_range = 0.1, \n        # shear_range = 0.1, \n        # zoom_range = 0.1, \n        # horizontal_flip = False, \n        # vertical_flip = False\n        )","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:23.451599Z","iopub.execute_input":"2024-12-16T14:48:23.451868Z","iopub.status.idle":"2024-12-16T14:48:24.213134Z","shell.execute_reply.started":"2024-12-16T14:48:23.451832Z","shell.execute_reply":"2024-12-16T14:48:24.212113Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create the data loaders\n\nwith strategy.scope():\n    BATCH_SIZE = 64\n    train_df[\"label\"] = train_df[\"label\"].astype(str)\n    train_loader = train_datagen.flow_from_dataframe(\n        dataframe = train_df,\n        # directory = \"/kaggle/input/cassava-leaf-disease-classification/train_images\",\n        directory = \"/kaggle/working/train_images\",\n        x_col = \"image_id\",\n        y_col = \"label\",\n        color_mode='rgb',\n        batch_size = BATCH_SIZE,\n        seed = 1,\n        shuffle = True,\n        class_mode = 'categorical',\n        interpolation='nearest',\n        # target_size = (600,600)\n        target_size = (512,512)\n    )\n\n    valid_df[\"label\"] = valid_df[\"label\"].astype(str)\n    valid_loader = test_datagen.flow_from_dataframe(\n        dataframe = valid_df,\n        # directory = \"/kaggle/input/cassava-leaf-disease-classification/train_images\",\n        directory = \"/kaggle/working/train_images\",\n        x_col = \"image_id\",\n        y_col = \"label\",\n        color_mode='rgb',\n        batch_size = BATCH_SIZE,\n        seed = 1,\n        shuffle = True,\n        class_mode = 'categorical',\n        interpolation='nearest',\n        # target_size = (600,600)\n        target_size = (512,512)\n    )","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:24.214256Z","iopub.execute_input":"2024-12-16T14:48:24.214625Z","iopub.status.idle":"2024-12-16T14:48:24.327376Z","shell.execute_reply.started":"2024-12-16T14:48:24.214584Z","shell.execute_reply":"2024-12-16T14:48:24.326552Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#define number of training and validation steps\nwith strategy.scope():\n    TR_STEPS = len(train_loader)\n    VA_STEPS = len(valid_loader)\n\n    print(TR_STEPS)\n    print(VA_STEPS)","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:24.328445Z","iopub.execute_input":"2024-12-16T14:48:24.328779Z","iopub.status.idle":"2024-12-16T14:48:24.335077Z","shell.execute_reply.started":"2024-12-16T14:48:24.328741Z","shell.execute_reply":"2024-12-16T14:48:24.334084Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Build the network ##","metadata":{"execution":{"iopub.status.busy":"2024-12-15T21:39:52.070799Z","iopub.execute_input":"2024-12-15T21:39:52.071225Z","iopub.status.idle":"2024-12-15T21:39:52.076526Z","shell.execute_reply.started":"2024-12-15T21:39:52.071183Z","shell.execute_reply":"2024-12-15T21:39:52.075329Z"}}},{"cell_type":"code","source":"\ndef model_builder(hp):\n  model = Sequential()\n\n  model.add(Input(shape=(512,512,3), batch_size=BATCH_SIZE))\n  # model.add(Input(shape=(600,600,3), batch_size=BATCH_SIZE))\n  # model.add(CenterCrop(512,512))\n  # Search the dropout rate in the first input layer in the range of 0.2-0.8 with a stepsize of 0.1.\n  hp_contrast = hp.Float('factor', min_value = 0.2, max_value = 0.8, step = 0.1)\n  model.add(RandomContrast(factor = hp_contrast))        #  model.add(RandomContrast(0.2))\n  model.add(Conv2D(64, 3, padding='same', activation='relu'))\n  model.add(MaxPooling2D(4,4))\n  model.add(Conv2D(32, 3, padding='same', activation='relu'))\n  model.add(MaxPooling2D(4,4))\n    \n  model.add(BatchNormalization())\n  model.add(Flatten())\n    \n  # Tune the number of units in the first hidden layer\n  # Search the number of neurons in the first input layer.\n  hp_units1 = hp.Int('units1', min_value = 64, max_value = 128, step = 16)\n  model.add(Dense(units = hp_units1, activation = 'relu'))\n  # Tune the dropout rate in the first input layer\n  # Search the dropout rate in the first input layer in the range of 0.2-0.8 with a stepsize of 0.1.\n  hp_dropout1 = hp.Float('rate', min_value = 0.2, max_value = 0.8, step = 0.1)\n  model.add(Dropout(rate = hp_dropout1))\n    \n  # Search the number of neurons in the second input layer.\n  hp_units2 = hp.Int('units2', min_value = 32, max_value = 64, step = 8)\n  model.add(Dense(units = hp_units2, activation = 'relu'))\n  model.add(Dropout(rate = hp_dropout1))\n\n  # Output layer has 5 neurons\n  model.add(Dense( units = 5, activation='softmax'))\n  # Tune the learning rate for the optimizer \n  # Search the lerning rate from 0.01, 0.001, or 0.0001.\n  hp_learning_rate = hp.Choice('learning_rate', values = [1e-2, 1e-3, 1e-4]) \n\n  model.compile(optimizer = keras.optimizers.Adam(learning_rate = hp_learning_rate),\n                loss = 'categorical_crossentropy', \n                metrics = ['accuracy'])\n\n  return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:24.336035Z","iopub.execute_input":"2024-12-16T14:48:24.336287Z","iopub.status.idle":"2024-12-16T14:48:24.346631Z","shell.execute_reply.started":"2024-12-16T14:48:24.336262Z","shell.execute_reply":"2024-12-16T14:48:24.345827Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tuner = kt.Hyperband(model_builder, #Specify the model\n                     objective = 'val_loss', #Specify the objective funciton\n                     max_epochs = 100, #Specify the maximum epochs\n                     directory = '/kaggle/working/hyper', #Specify the file path\n                     project_name = 'tuningRegression')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:24.347712Z","iopub.execute_input":"2024-12-16T14:48:24.348185Z","iopub.status.idle":"2024-12-16T14:48:24.429474Z","shell.execute_reply.started":"2024-12-16T14:48:24.348146Z","shell.execute_reply":"2024-12-16T14:48:24.428732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import IPython\n#Clear all the training outputs\nclass ClearTrainingOutput(tf.keras.callbacks.Callback):\n  def on_train_end(*args, **kwargs):\n    IPython.display.clear_output(wait = True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:24.430546Z","iopub.execute_input":"2024-12-16T14:48:24.430766Z","iopub.status.idle":"2024-12-16T14:48:24.434986Z","shell.execute_reply.started":"2024-12-16T14:48:24.430745Z","shell.execute_reply":"2024-12-16T14:48:24.434064Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Perform the search on the defined hyperparameter space by specifying the callback to clear the training outputs\n# tuner.search(x=train_loader, epochs = 100, validation_data = valid_loader, callbacks = [ClearTrainingOutput()])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:24.436161Z","iopub.execute_input":"2024-12-16T14:48:24.436379Z","iopub.status.idle":"2024-12-16T14:48:24.449469Z","shell.execute_reply.started":"2024-12-16T14:48:24.436357Z","shell.execute_reply":"2024-12-16T14:48:24.448862Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hpv_units1=112\nhpv_factor=0.8\nhpv_dropout1=0.6\n\nhpv_units2=64\nhpv_dropout2=0.8\nhpv_learning_rate=0.0005","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:24.450316Z","iopub.execute_input":"2024-12-16T14:48:24.450565Z","iopub.status.idle":"2024-12-16T14:48:24.460788Z","shell.execute_reply.started":"2024-12-16T14:48:24.450542Z","shell.execute_reply":"2024-12-16T14:48:24.460029Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nnp.random.seed(1)\ntf.random.set_seed(1)\n\nwith strategy.scope():\n    cnn = Sequential([\n        # Input(shape=(600,600,3), batch_size=BATCH_SIZE),\n        # CenterCrop(512,512),\n        Input(shape=(512,512,3), batch_size=BATCH_SIZE),\n        RandomContrast(hpv_factor),\n\n        Conv2D(64, 3, padding='same', activation='relu'),\n        MaxPooling2D(4,4),\n        Conv2D(32, 3, padding='same', activation='relu'),\n        MaxPooling2D(4,4),\n        \n        BatchNormalization(),\n        Flatten(),\n        Dense(hpv_units1, activation='relu'),\n        Dropout(rate=hpv_dropout1 ),\n        Dense(hpv_units2, activation='relu'),\n        Dropout(rate=hpv_dropout2 ),\n        \n        Dense(len(labels), activation='softmax')\n    ])\n\ncnn.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:24.461664Z","iopub.execute_input":"2024-12-16T14:48:24.461939Z","iopub.status.idle":"2024-12-16T14:48:25.420920Z","shell.execute_reply.started":"2024-12-16T14:48:24.461914Z","shell.execute_reply":"2024-12-16T14:48:25.419749Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Train the Network ## ","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n    lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(\n        initial_learning_rate=hpv_learning_rate,\n        decay_steps=1000,\n        decay_rate=0.9)\n    opt = tf.keras.optimizers.Adam(learning_rate=lr_schedule)\n\n    cnn.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T14:48:25.422049Z","iopub.execute_input":"2024-12-16T14:48:25.422361Z","iopub.status.idle":"2024-12-16T14:48:25.449261Z","shell.execute_reply.started":"2024-12-16T14:48:25.422329Z","shell.execute_reply":"2024-12-16T14:48:25.448311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\n# Complete training runs. \nwith strategy.scope():\n    h1 = cnn.fit(\n        x=train_loader, \n        epochs=20,\n        validation_data=valid_loader, \n        verbose=1\n    )","metadata":{"execution":{"iopub.status.busy":"2024-12-16T14:48:25.450319Z","iopub.execute_input":"2024-12-16T14:48:25.450592Z","iopub.status.idle":"2024-12-16T19:15:04.392140Z","shell.execute_reply.started":"2024-12-16T14:48:25.450564Z","shell.execute_reply":"2024-12-16T19:15:04.391081Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Display training curves after each run.\nhistory = h1.history\nn_epochs = len(history['loss'])\n\nplt.figure(figsize=[10,4])\nplt.subplot(1,2,1)\nplt.plot(range(1, n_epochs+1), history['loss'], label='Training')\nplt.plot(range(1, n_epochs+1), history['val_loss'], label='Validation')\nplt.xlabel('Epoch'); plt.ylabel('Loss'); plt.title('Loss')\nplt.legend()\nplt.subplot(1,2,2)\nplt.plot(range(1, n_epochs+1), history['accuracy'], label='Training')\nplt.plot(range(1, n_epochs+1), history['val_accuracy'], label='Validation')\nplt.xlabel('Epoch'); plt.ylabel('Accuracy'); plt.title('Accuracy')\nplt.legend()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T19:15:04.393544Z","iopub.execute_input":"2024-12-16T19:15:04.393931Z","iopub.status.idle":"2024-12-16T19:15:04.819637Z","shell.execute_reply.started":"2024-12-16T19:15:04.393891Z","shell.execute_reply":"2024-12-16T19:15:04.818783Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Save the Model and History ##","metadata":{}},{"cell_type":"code","source":"import joblib\njoblib.dump(h1, 'history.joblib')\njoblib.dump(cnn, 'final_model.joblib')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T19:15:04.820663Z","iopub.execute_input":"2024-12-16T19:15:04.820942Z","iopub.status.idle":"2024-12-16T19:15:05.356407Z","shell.execute_reply.started":"2024-12-16T19:15:04.820916Z","shell.execute_reply":"2024-12-16T19:15:05.355174Z"}},"outputs":[],"execution_count":null}]}