{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Bailie Geddes, 17beg, 20099792\n\n# **Implementing ResNet for Image Classification:**\n\nThis notebook has portions taken from published source on Kaggle and has been extended by modifying:\n- add image data generator for all pre-processing functions\n    - rotation, width shift, height shift, horizontal flip, brightness, etc.\n- changing the ResNet50 model by adding additional dense layers\n    - add dense layers for additional simple layers of neurons\n    - add new dropout layer\n- changing the classification by altering the class weights \n    - redistributes the balance of images in each class, adding classweights by calculating proportions and inversing them\n- adding batch normalization\n    - standardizes the inputs to a layer for each mini-batch to reduce number of epochs needed\n  \n\nThe dataset that will be worked with is the State Farm Distracted Driver Detection dataset found on Kaggle.com (https://www.kaggle.com/c/state-farm-distracted-driver-detection/data).\n\nThere are 10 different classes, and 79.7 thousand images. The classes are safe driving, texting with right hand, talking on the phone with right hand, texting with left hand, talking on the phone with left hand, operating the radio, drinking, reaching behind, hair and makeup and talking to passenger. \n\nUsing this Dataset, I’m going to present results of Residual neural networks (ResNet) used for Image classification to test the accuracy they present for these images, first creating it piece by piece and then importing and adapting a pre trained ResNet.","metadata":{"execution":{"iopub.status.busy":"2021-11-24T13:11:32.643725Z","iopub.execute_input":"2021-11-24T13:11:32.644021Z","iopub.status.idle":"2021-11-24T13:11:37.067149Z","shell.execute_reply.started":"2021-11-24T13:11:32.643963Z","shell.execute_reply":"2021-11-24T13:11:37.06624Z"}}},{"cell_type":"markdown","source":"# 1. Import libraries","metadata":{}},{"cell_type":"code","source":"import os\nimport tensorflow as tf\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image, ImageDraw, ImageEnhance\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:23.131990Z","iopub.execute_input":"2021-12-12T13:46:23.132282Z","iopub.status.idle":"2021-12-12T13:46:28.110079Z","shell.execute_reply.started":"2021-12-12T13:46:23.132256Z","shell.execute_reply":"2021-12-12T13:46:28.109319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.__version__","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.111843Z","iopub.execute_input":"2021-12-12T13:46:28.112215Z","iopub.status.idle":"2021-12-12T13:46:28.119773Z","shell.execute_reply.started":"2021-12-12T13:46:28.112174Z","shell.execute_reply":"2021-12-12T13:46:28.118856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Get data","metadata":{}},{"cell_type":"code","source":"# sample_path = \"/kaggle/input/state-farm-distracted-driver-detection/sample_submission.csv\"\nimgs_list_path = \"/kaggle/input/state-farm-distracted-driver-detection/driver_imgs_list.csv\"\ntrain_path = \"/kaggle/input/state-farm-distracted-driver-detection/imgs/train\"","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.121298Z","iopub.execute_input":"2021-12-12T13:46:28.121900Z","iopub.status.idle":"2021-12-12T13:46:28.128846Z","shell.execute_reply.started":"2021-12-12T13:46:28.121860Z","shell.execute_reply":"2021-12-12T13:46:28.128085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3.Check data distribution","metadata":{}},{"cell_type":"code","source":"# read csv file to get class names\ndriver_imgs_list = pd.read_csv(imgs_list_path)\ndriver_imgs_list.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.131051Z","iopub.execute_input":"2021-12-12T13:46:28.131667Z","iopub.status.idle":"2021-12-12T13:46:28.181760Z","shell.execute_reply.started":"2021-12-12T13:46:28.131630Z","shell.execute_reply":"2021-12-12T13:46:28.181019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir(train_path)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.185087Z","iopub.execute_input":"2021-12-12T13:46:28.185516Z","iopub.status.idle":"2021-12-12T13:46:28.197185Z","shell.execute_reply.started":"2021-12-12T13:46:28.185487Z","shell.execute_reply":"2021-12-12T13:46:28.196344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sort through to organize dataset by class rather then random\ndef pair_sort(className,values):\n    for j in range(0,len(className)-1):\n        for i in range(0,len(className)-1):\n            if values[i] > values[i+1]:\n                temp =  values[i+1]\n                values[i+1] = values[i]\n                values[i] = temp\n\n                N_temp =  className[i+1]\n                className[i+1] = className[i]\n                className[i] = N_temp\n    \n    return className,values","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.200275Z","iopub.execute_input":"2021-12-12T13:46:28.200508Z","iopub.status.idle":"2021-12-12T13:46:28.207455Z","shell.execute_reply.started":"2021-12-12T13:46:28.200485Z","shell.execute_reply":"2021-12-12T13:46:28.206567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create graph to display class weight and number of images in each class\nfrom matplotlib.pyplot import figure\nfigure(num=None, figsize=(15, 5), dpi=80, facecolor='w', edgecolor='k')\n\nclass_names = np.unique(driver_imgs_list['classname'])\nclass_image_list = [len(driver_imgs_list[driver_imgs_list['classname'] == current_class]) for current_class in class_names]\n\nclass_names,class_image_list=  pair_sort(class_names,class_image_list)\n\n#plt.figure()\nplt.suptitle('Number of images per Class')\nplt.bar(class_names,class_image_list,color=(0.2, 0.4, 0.6, 0.6))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.208945Z","iopub.execute_input":"2021-12-12T13:46:28.209562Z","iopub.status.idle":"2021-12-12T13:46:28.444612Z","shell.execute_reply.started":"2021-12-12T13:46:28.209523Z","shell.execute_reply":"2021-12-12T13:46:28.443844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create graph to display number of images per subject\nfrom matplotlib.pyplot import figure\nsub_names = np.unique(driver_imgs_list['subject'])\nsub_image_list = [len(driver_imgs_list[driver_imgs_list['subject'] == current_sub]) for current_sub in sub_names]\nsub_names,sub_image_list=  pair_sort(sub_names,sub_image_list)\n\nfigure(num=None, figsize=(15, 10), dpi=80, facecolor='w', edgecolor='k')\n\ny_pos = np.arange(len(sub_names))\n# Create horizontal bars\nplt.barh(y_pos, sub_image_list,color=(0.2, 0.4, 0.6, 0.6))\n \n# Create names on the y-axis\nplt.yticks(y_pos,sub_names )\nplt.suptitle('Number of images per subject')\n\n# Show graphic\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.445776Z","iopub.execute_input":"2021-12-12T13:46:28.446148Z","iopub.status.idle":"2021-12-12T13:46:28.783857Z","shell.execute_reply.started":"2021-12-12T13:46:28.446095Z","shell.execute_reply":"2021-12-12T13:46:28.782921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# hyperparameters\nimg_width,img_height = (256,256)\nmodel_input_shape = (img_width,img_height,3)\nbatch_size = 16\ninput_image = (img_width,img_height)\n\n# get image path from dataset\ndef load_image(path):\n    read_path = train_path+\"/\"+path\n    image = Image.open(read_path)\n    image = image.resize(input_image)\n    \n    return np.asarray(image)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.785129Z","iopub.execute_input":"2021-12-12T13:46:28.785593Z","iopub.status.idle":"2021-12-12T13:46:28.792693Z","shell.execute_reply.started":"2021-12-12T13:46:28.785556Z","shell.execute_reply":"2021-12-12T13:46:28.791862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load image pixels from input data\ndef show_images(image_ids,class_names):\n    pixels = [load_image(path) for path in image_ids]\n    num_of_images = len(image_ids)\n    fig, axes = plt.subplots(\n        1, \n        num_of_images, \n        figsize=(5 * num_of_images, 5 * num_of_images),\n        \n    )\n   \n    # convert enumeration value to integer\n    for i, image_pixels in enumerate(pixels):\n        axes[i].imshow(image_pixels)\n        axes[i].axis(\"off\")\n        axes[i].set_title(class_names[i])","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.795008Z","iopub.execute_input":"2021-12-12T13:46:28.795667Z","iopub.status.idle":"2021-12-12T13:46:28.804356Z","shell.execute_reply.started":"2021-12-12T13:46:28.795613Z","shell.execute_reply":"2021-12-12T13:46:28.803512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4.Plot class images","metadata":{}},{"cell_type":"code","source":"# checking input data\nsub_names_imgs = [ current_class+\"/\"+driver_imgs_list[driver_imgs_list['classname'] == current_class]['img'].values[0] for current_class in class_names]\n\nshow_images(sub_names_imgs[:5],class_names[:5])\nshow_images(sub_names_imgs[5:],class_names[5:])","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:28.807715Z","iopub.execute_input":"2021-12-12T13:46:28.808068Z","iopub.status.idle":"2021-12-12T13:46:29.794047Z","shell.execute_reply.started":"2021-12-12T13:46:28.808021Z","shell.execute_reply":"2021-12-12T13:46:29.793273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Split and load Train/Validation ","metadata":{}},{"cell_type":"code","source":"# get test and train data\ntrain_path = \"/kaggle/input/state-farm-distracted-driver-detection/imgs/train\"\ntest_path = \"/kaggle/input/state-farm-distracted-driver-detection/imgs/test\"","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:29.795299Z","iopub.execute_input":"2021-12-12T13:46:29.795804Z","iopub.status.idle":"2021-12-12T13:46:29.800287Z","shell.execute_reply.started":"2021-12-12T13:46:29.795765Z","shell.execute_reply":"2021-12-12T13:46:29.799198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# x_train = []\n# y_train = []\n\n# x_val = []\n# y_val = []\n\n# # The data is split into a test set and a training set\n# # a driver can only appear in one of the training set or the testing set\n# split_rate = 0.8\n\n# # go through dataset and collecting train and test data suing split factor\n# # training neural network\n# for current_class in class_names:\n#     select_df = driver_imgs_list[driver_imgs_list['classname'] == current_class ]\n#     image_list = select_df['img'].values\n#     train_amount = int(len(image_list)*split_rate)\n#     train_list = image_list[:train_amount]\n#     val_list = image_list[train_amount:]\n    \n#     for filename in train_list:\n#         x_train.append(load_image(current_class+\"/\"+filename))\n#         y_train.append(current_class.replace('c',''))\n\n#     for filename in val_list:\n#         x_val.append(load_image(current_class+\"/\"+filename))\n#         y_val.append(current_class.replace('c',''))\n","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:29.801587Z","iopub.execute_input":"2021-12-12T13:46:29.802083Z","iopub.status.idle":"2021-12-12T13:46:29.811193Z","shell.execute_reply.started":"2021-12-12T13:46:29.802046Z","shell.execute_reply":"2021-12-12T13:46:29.810297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# search dataset to organize\ndriver_imgs_list[\"img_path\"] = driver_imgs_list[\"classname\"]+\"/\"+driver_imgs_list[\"img\"]\ndriver_imgs_list","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:29.812524Z","iopub.execute_input":"2021-12-12T13:46:29.813051Z","iopub.status.idle":"2021-12-12T13:46:29.859927Z","shell.execute_reply.started":"2021-12-12T13:46:29.813014Z","shell.execute_reply":"2021-12-12T13:46:29.859135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# display data\nlabels = driver_imgs_list[\"classname\"]\ndata_x = driver_imgs_list[\"img_path\"]\ntrain_df, val_df = train_test_split(driver_imgs_list, test_size = 0.2)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:29.861399Z","iopub.execute_input":"2021-12-12T13:46:29.862502Z","iopub.status.idle":"2021-12-12T13:46:29.872011Z","shell.execute_reply.started":"2021-12-12T13:46:29.862459Z","shell.execute_reply":"2021-12-12T13:46:29.871258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# display data\nlen(train_df), len(val_df)\nval_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:29.873674Z","iopub.execute_input":"2021-12-12T13:46:29.874459Z","iopub.status.idle":"2021-12-12T13:46:29.899768Z","shell.execute_reply.started":"2021-12-12T13:46:29.874423Z","shell.execute_reply":"2021-12-12T13:46:29.896925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 6. Image Pre-processing","metadata":{}},{"cell_type":"code","source":"# image pre-processing using data generator\ndatagen = ImageDataGenerator(\n        rotation_range=10, # rotation\n        width_shift_range=0.2, # horizontal shift\n        height_shift_range=0.2, # vertical shift\n        zoom_range=0.2, # zoom\n        horizontal_flip=True, # horizontal flip\n        brightness_range=[0.2,1.2]) # brightness\n\n# process train data\ntrain_generator_df = datagen.flow_from_dataframe(dataframe=train_df, \n                                              directory=train_path+\"/\",\n                                              x_col=\"img_path\", \n                                              y_col=\"classname\", \n                                              class_mode=\"categorical\", \n                                              target_size=(256, 256), \n                                              batch_size=32,\n                                              rescale=1.0/255)\n# process val data\nval_generator_df = datagen.flow_from_dataframe(dataframe=val_df, \n                                              directory=train_path+\"/\",\n                                              x_col=\"img_path\", \n                                              y_col=\"classname\", \n                                              class_mode=\"categorical\", \n                                              target_size=(256, 256), \n                                              batch_size=32,\n                                              rescale=1.0/255)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:46:29.901253Z","iopub.execute_input":"2021-12-12T13:46:29.904624Z","iopub.status.idle":"2021-12-12T13:47:13.227645Z","shell.execute_reply.started":"2021-12-12T13:46:29.904584Z","shell.execute_reply":"2021-12-12T13:47:13.226738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 7. Encode Labels","metadata":{}},{"cell_type":"code","source":"# # convert vector to matrix\n# x_train = np.asarray(x_train)\n# y_train = tf.keras.utils.to_categorical(y_train, num_classes=10)\n# x_val = np.asarray(x_val)\n# y_val =tf.keras.utils.to_categorical(y_val, num_classes=10)\n\n# print(\"Train x Shape: \",x_train.shape)\n# print(\"Test x Shape: \",x_val.shape)\n","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:13.228973Z","iopub.execute_input":"2021-12-12T13:47:13.229345Z","iopub.status.idle":"2021-12-12T13:47:13.233538Z","shell.execute_reply.started":"2021-12-12T13:47:13.229307Z","shell.execute_reply":"2021-12-12T13:47:13.232385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print(\"Train y Shape: \",y_train.shape)\n# print(\"Test y Shape: \",y_val.shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:13.235309Z","iopub.execute_input":"2021-12-12T13:47:13.235668Z","iopub.status.idle":"2021-12-12T13:47:13.244964Z","shell.execute_reply.started":"2021-12-12T13:47:13.235634Z","shell.execute_reply":"2021-12-12T13:47:13.243940Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 8. Create Model\n","metadata":{}},{"cell_type":"code","source":"# create our Resnet model\n# include_top is false to allow us to modify classification\nbase_model  = tf.keras.applications.resnet.ResNet50(include_top = False,\n                                                  weights = 'imagenet',\n                                                  input_shape = model_input_shape)\n# base_model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:13.246846Z","iopub.execute_input":"2021-12-12T13:47:13.247514Z","iopub.status.idle":"2021-12-12T13:47:17.875003Z","shell.execute_reply.started":"2021-12-12T13:47:13.247476Z","shell.execute_reply":"2021-12-12T13:47:17.873901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# x = base_model.output\n# x = tf.keras.layers.Flatten()(x)\n# x = tf.keras.layers.Dropout(0.5)(x)\n\n# output =tf.keras.layers.Dense(units = len(class_names),activation = tf.nn.softmax)(x)\n# model = tf.keras.models.Model(inputs=base_model.inputs, outputs=output)\n\n# model.compile(optimizer=tf.keras.optimizers.Adam(0.0001),\n#               loss=tf.keras.losses.CategoricalCrossentropy(from_logits = False),\n#               metrics=['accuracy'])\n\n# model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:17.878816Z","iopub.execute_input":"2021-12-12T13:47:17.879107Z","iopub.status.idle":"2021-12-12T13:47:17.885061Z","shell.execute_reply.started":"2021-12-12T13:47:17.879069Z","shell.execute_reply":"2021-12-12T13:47:17.884025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# calculating class weights which are inversely proportional to number of training examples\nclasses, counts = np.unique(train_df[\"classname\"], return_counts = True)\ntotal = sum(counts)\nratios = 1/(counts/total)\n\nclass_weights = dict()\n\nfor i in range(10):\n    class_weights[i] = ratios[i]","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:17.886534Z","iopub.execute_input":"2021-12-12T13:47:17.887159Z","iopub.status.idle":"2021-12-12T13:47:17.912867Z","shell.execute_reply.started":"2021-12-12T13:47:17.887123Z","shell.execute_reply":"2021-12-12T13:47:17.912184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_weights","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:17.914392Z","iopub.execute_input":"2021-12-12T13:47:17.914836Z","iopub.status.idle":"2021-12-12T13:47:17.921626Z","shell.execute_reply.started":"2021-12-12T13:47:17.914743Z","shell.execute_reply":"2021-12-12T13:47:17.920524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#modified model of ResNet\nx = base_model.output\n# flattens input layer to pass  data into every single neuron of the model \nx = tf.keras.layers.Flatten()(x)\nx = tf.keras.layers.Dense(units = 1068, activation = tf.nn.relu)(x)\n# help reduce overfitting\nx = tf.keras.layers.Dropout(0.25)(x)\n# additional dense layers added\nx = tf.keras.layers.Dense(units = 768, activation = tf.nn.relu)(x)\n# normalize flow of data to increase learning rate\nx = tf.keras.layers.BatchNormalization()(x)\n# feeds output to neurons from previous layer\nx = tf.keras.layers.Dense(units = 512, activation = tf.nn.relu)(x)\nx = tf.keras.layers.Dense(units = 256, activation = tf.nn.relu)(x)\nx = tf.keras.layers.Dropout(0.25)(x)\n\noutput =tf.keras.layers.Dense(units = len(class_names),activation = tf.nn.softmax)(x)\nmodel = tf.keras.models.Model(inputs=base_model.inputs, outputs=output)\n\n# Adam = optimization algorithm for stochastic gradient descent - help handle noise\nmodel.compile(optimizer=tf.keras.optimizers.Adam(0.0001),\n              loss=tf.keras.losses.CategoricalCrossentropy(from_logits = False),\n              metrics=['accuracy'])\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:17.923721Z","iopub.execute_input":"2021-12-12T13:47:17.924227Z","iopub.status.idle":"2021-12-12T13:47:18.118897Z","shell.execute_reply.started":"2021-12-12T13:47:17.924128Z","shell.execute_reply":"2021-12-12T13:47:18.117942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 40\ndef lr_schedule(epoch,lr):\n    # Learning Rate Schedule\n\n    lr = lr\n    total_epochs = num_epochs\n\n    # reduce the learning rate as as epochs increase\n    check_1 = int(total_epochs * 0.9)\n    check_2 = int(total_epochs * 0.8)\n    check_3 = int(total_epochs * 0.6)\n    check_4 = int(total_epochs * 0.4)\n\n    if epoch > check_1:\n        lr *= 1e-4\n    elif epoch > check_2:\n        lr *= 1e-3\n    elif epoch > check_3:\n        lr *= 1e-2\n    elif epoch > check_4:\n        lr *= 1e-1\n\n    print(\"[+] Current Lr rate : {} \".format(lr))\n    return lr\nlr_callback = tf.keras.callbacks.LearningRateScheduler(lr_schedule)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:18.123210Z","iopub.execute_input":"2021-12-12T13:47:18.123584Z","iopub.status.idle":"2021-12-12T13:47:18.137094Z","shell.execute_reply.started":"2021-12-12T13:47:18.123553Z","shell.execute_reply":"2021-12-12T13:47:18.136145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # setting hyperparameters for using with model\n# history = model.fit(\n#       x = x_train,y=y_train,\n#       validation_data=(x_val,y_val),\n#       steps_per_epoch=141, # will reduce the training data to 128 images per class\n#       batch_size = 40,\n#       epochs=75,\n#     class_weight=class_weights,\n#     callbacks = [lr_callback],\n#       verbose=1)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:18.140772Z","iopub.execute_input":"2021-12-12T13:47:18.141200Z","iopub.status.idle":"2021-12-12T13:47:18.148084Z","shell.execute_reply.started":"2021-12-12T13:47:18.141163Z","shell.execute_reply":"2021-12-12T13:47:18.147169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 9. Train and Test","metadata":{}},{"cell_type":"code","source":"# setting hyperparameters for using with model\nhistory = model.fit_generator(\n      train_generator_df,\n      validation_data=val_generator_df,\n      # usually 100 - for testing we will use 50\n      steps_per_epoch=100, # will reduce the training data to 128 images per class\n#       batch_size = 40,\n      # usually epoch = 40 - for testing we will use 4\n      epochs=40,\n    class_weight=class_weights,\n    callbacks = [lr_callback],\n      verbose=1)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T13:47:18.150216Z","iopub.execute_input":"2021-12-12T13:47:18.151693Z","iopub.status.idle":"2021-12-12T15:40:49.991029Z","shell.execute_reply.started":"2021-12-12T13:47:18.151649Z","shell.execute_reply":"2021-12-12T15:40:49.990175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 10. Model Evaluation","metadata":{}},{"cell_type":"code","source":"# # create graphs to display training and validation loss and accuracy of the model\n# fig, ax = plt.subplots(1, 2, figsize=(15, 5))\n\n# ax[0].set_title('Training vs Validation Accuracy')\n# ax[0].plot(history.history['accuracy'])\n# ax[0].plot(history.history['val_accuracy'])\n# plt.ylabel('Accuracy')\n# plt.xlabel('Epochs')\n# plt.show()\n\n# ax[1].set_title('Training vs Validation Loss')\n# ax[1].plot(history.history['loss'])\n# ax[1].plot(history.history['val_loss'])\n# plt.ylabel('Loss')\n# plt.xlabel('Epochs')","metadata":{"execution":{"iopub.status.busy":"2021-12-12T15:40:49.993915Z","iopub.execute_input":"2021-12-12T15:40:49.994304Z","iopub.status.idle":"2021-12-12T15:40:49.999371Z","shell.execute_reply.started":"2021-12-12T15:40:49.994272Z","shell.execute_reply":"2021-12-12T15:40:49.998310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create graphs to display training and validation loss of the model\nloss_train = history.history['loss']\nloss_val = history.history['val_loss']\n# usually up to 41 but for testing changing it to 5\nepochs = range(1,41)\nplt.plot(epochs, loss_train, 'g', label='Training loss')\nplt.plot(epochs, loss_val, 'b', label='validation loss')\nplt.title('Training and Validation loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend(loc = \"upper right\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T15:40:50.001189Z","iopub.execute_input":"2021-12-12T15:40:50.001558Z","iopub.status.idle":"2021-12-12T15:40:50.182740Z","shell.execute_reply.started":"2021-12-12T15:40:50.001520Z","shell.execute_reply":"2021-12-12T15:40:50.181586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create graphs to display training and validation accuracy of the model\nloss_train = history.history['accuracy']\nloss_val = history.history['val_accuracy']\n# usually up to 41 but for testing changing it to 5\nepochs = range(1,41)\nplt.plot(epochs, loss_train, 'g', label='Training accuracy')\nplt.plot(epochs, loss_val, 'b', label='validation accuracy')\nplt.title('Training and Validation Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend(loc = \"upper right\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T15:40:50.184364Z","iopub.execute_input":"2021-12-12T15:40:50.184994Z","iopub.status.idle":"2021-12-12T15:40:50.360447Z","shell.execute_reply.started":"2021-12-12T15:40:50.184946Z","shell.execute_reply":"2021-12-12T15:40:50.359409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 11. Prediction","metadata":{}},{"cell_type":"code","source":"#  display the evaluation results of prediction using part of dataset\ny_pred = model.evaluate_generator(val_generator_df) #predict on x_val\n# y_pred = np.argmax(y_pred, axis = 1) # convert output to class numbers\n# print(\"Predictions:\", y_pred)\n# print(\"True labels:\", np.argmax(y_val, axis = 1)) # print the prediction and true labels for first 10 test images","metadata":{"execution":{"iopub.status.busy":"2021-12-12T15:40:50.362390Z","iopub.execute_input":"2021-12-12T15:40:50.362790Z","iopub.status.idle":"2021-12-12T15:42:24.099912Z","shell.execute_reply.started":"2021-12-12T15:40:50.362746Z","shell.execute_reply":"2021-12-12T15:42:24.098606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# our prediction accuracy using sample set\nprint(\"Accuracy on test set\")\nprint(y_pred[1])","metadata":{"execution":{"iopub.status.busy":"2021-12-12T15:42:24.110630Z","iopub.execute_input":"2021-12-12T15:42:24.113364Z","iopub.status.idle":"2021-12-12T15:42:24.127394Z","shell.execute_reply.started":"2021-12-12T15:42:24.113312Z","shell.execute_reply":"2021-12-12T15:42:24.124565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create graphs to display prediction of sample data\nval = history.history['accuracy']\n# usually up to 41 but for testing changing it to 5\nepochs = range(1,41)\nplt.plot(epochs, val, 'g', label='Training accuracy')\nplt.title('Prediction Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend(loc = \"lower right\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-12T15:42:24.132372Z","iopub.execute_input":"2021-12-12T15:42:24.132966Z","iopub.status.idle":"2021-12-12T15:42:24.391998Z","shell.execute_reply.started":"2021-12-12T15:42:24.132923Z","shell.execute_reply":"2021-12-12T15:42:24.391058Z"},"trusted":true},"execution_count":null,"outputs":[]}]}