{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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\nimport numpy as np # linear algebra\nimport 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\nimport os\nfor 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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport glob\nimport shutil\nimport json\nimport keras\nimport itertools\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport tensorflow as tf\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom collections import Counter\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom tensorflow.keras.optimizers import RMSprop, Adam, SGD\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\n# Defining the working directories\n\nwork_dir = '../input/cassava-leaf-disease-classification/'\nos.listdir(work_dir) \ntrain_path = '/kaggle/input/cassava-leaf-disease-classification/train_images'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n#%% IMPORTING DATA\n\n# Importing train.csv\n\ndata = pd.read_csv(work_dir + 'train.csv')\nprint(Counter(data['label'])) # Checking the frequencies of the labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data['label'].hist()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Importing the json file with labels\n\nf = open(work_dir + 'label_num_to_disease_map.json')\nreal_labels = json.load(f)\nreal_labels = {int(k):v for k,v in real_labels.items()}\n\n# Defining the working dataset\ndata['class_name'] = data.label.map(real_labels)\nprint(data.head(10))\nprint(data['class_name'].unique())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def showImages(images):\n\n    # Extract 16 random images from it\n    random_images = [np.random.choice(images) for i in range(16)]\n\n    # Adjust the size of your images\n    plt.figure(figsize=(16,12))\n\n    # Iterate and plot random images\n    for i in range(16):\n        plt.subplot(4,4, i + 1)\n        img = plt.imread(train_path+'/'+random_images[i])\n        plt.imshow(img, cmap='gray')\n        plt.axis('off')\n\n    # Adjust subplot parameters to give specified padding\n    plt.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = data['label'] ==4\nclassHealthy = data[mask]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"showImages(classHealthy['image_id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = data['label'] ==3\nclassCMD = data[mask]\n\nshowImages(classCMD['image_id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = data['label'] ==2\nclassCGM = data[mask]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"showImages(classCGM['image_id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = data['label'] ==1\nclassCBSD = data[mask]\n\nshowImages(classCBSD['image_id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = data['label'] ==0\nclassCBB = data[mask]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"showImages(classCBB['image_id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Class \"0\" taken as 0.99, since its minority class\nclass0 = classCBB.sample(frac=0.99)\nclass1 = classCBSD.sample(frac=0.9)\nclass2 = classCGM.sample(frac=0.9)\nclass3 = classCMD.sample(frac=0.9)\nclass4 = classHealthy.sample(frac=0.9)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"frames=[class0,class1,class2,class3,class4]\nfinalData = pd.concat(frames)\nfinalData.head(10)\nprint(len(finalData))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"finalData","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\"stratify\" parameter used in train_test_split will preserve the proportion of target as in original dataset, in the train and test datasets as well.\n\nSo if your original dataset df has target/label as [0,1,2] in the ratio say, 40:30:30. That is, for every 100 datasets, you can find 40, 30 and 30 observations of target 0,1 and 2 respectively.\n\nNow when you split this original using the train_test_split(x,y,test_size=0.1,stratify=y), the methods returns train and test datasets in the ratio of 90:10. Now in each of these datasets, the target/label data proportion is preserved as 40:30:30 for the classes [0,1,2]."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Spliting the data\nfrom sklearn.model_selection import train_test_split\n\ntrain,val = train_test_split(finalData, test_size = 0.05, random_state = 42, stratify = finalData['class_name'])\n\n# Importing the data using ImageDataGenerator\n\nfrom keras.preprocessing.image import ImageDataGenerator\n\nIMG_SIZE = 300\nsize = (IMG_SIZE,IMG_SIZE)\nn_CLASS = 5\n\ndatagen = ImageDataGenerator(\n                    preprocessing_function = tf.keras.applications.efficientnet.preprocess_input,\n                    rotation_range = 60,\n                    width_shift_range = 0.2,\n                    height_shift_range = 0.2,\n                    shear_range = 0.2,\n                    zoom_range = 0.2,\n                    horizontal_flip = True,\n                    vertical_flip = True,\n                    fill_mode = 'nearest')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_set = datagen.flow_from_dataframe(train,\n                         directory = train_path,\n                         seed=42,\n                         x_col = 'image_id',\n                         y_col = 'class_name',\n                         target_size = size,\n                         class_mode = 'categorical',\n                         interpolation = 'nearest',\n                         shuffle = True,\n                         batch_size = 32)\n\nval_set = datagen.flow_from_dataframe(val,\n                         directory = train_path,\n                         seed=42,\n                         x_col = 'image_id',\n                         y_col = 'class_name',\n                         target_size = size,\n                         class_mode = 'categorical',\n                         interpolation = 'nearest',\n                         shuffle = True,\n                         batch_size = 32)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_model():\n    \n    model = Sequential()\n    # initialize the model with input shape as (224,224,3)\n    model.add(tf.keras.applications.EfficientNetB3(input_shape = (IMG_SIZE, IMG_SIZE, 3), include_top = False, weights = 'imagenet' ))\n    model.add(GlobalAveragePooling2D())\n    model.add(Flatten())\n    model.add(Dense(256, activation = 'relu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    #model.add(Dropout(0.7))\n    model.add(Dense(32, activation = 'relu', bias_regularizer=tf.keras.regularizers.L1L2(l1=0.01, l2=0.001)))\n    #model.add(Dropout(0.7))\n    model.add(Dense(n_CLASS, activation = 'softmax'))\n    \n    return model\n\nleaf_model = create_model()\nleaf_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"EPOCHS = 3\nSTEP_SIZE_TRAIN = train_set.n//train_set.batch_size\nSTEP_SIZE_VALID = val_set.n//val_set.batch_size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#%% FITTING THE MODEL\n\ndef Model_fit():\n    \n    #leaf_model = None\n    \n    leaf_model = create_model()\n    \n    '''Compiling the model'''\n    \n    loss = tf.keras.losses.CategoricalCrossentropy(from_logits = False,\n                                                   label_smoothing=0.001,\n                                                   name='categorical_crossentropy' )\n    \n    leaf_model.compile(optimizer = Adam(learning_rate = 2e-4),\n                        loss = loss, #'categorical_crossentropy'\n                        metrics = ['categorical_accuracy']) #'acc'\n    \n    # Stop training when the val_loss has stopped decreasing for 5 epochs.\n    es = EarlyStopping(monitor='val_loss', mode='min', patience=5,\n                       restore_best_weights=True, verbose=1)\n    \n    # Save the model with the minimum validation loss\n    checkpoint_cb = ModelCheckpoint(\"Cassava_best_modelEffNetB3.h5\",\n                                    save_best_only=True,\n                                    monitor = 'val_loss',\n                                    mode='min')\n    \n    # reduce learning rate\n    reduce_lr = ReduceLROnPlateau(monitor = 'val_loss',\n                                  factor = 0.3,\n                                  patience = 3,\n                                  min_lr = 1e-6,\n                                  mode = 'min',\n                                  verbose = 1)\n    \n    history = leaf_model.fit(train_set,\n                             validation_data = val_set,\n                             epochs= EPOCHS,\n                             batch_size = 32,\n                             steps_per_epoch = STEP_SIZE_TRAIN,\n                             validation_steps = STEP_SIZE_VALID,\n                             callbacks=[es, checkpoint_cb, reduce_lr])\n    \n    leaf_model.save('Cassava_modelEffNetB3'+'.h5')  \n    \n    return history","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = Model_fit()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"acc = history.history['categorical_accuracy']\nval_acc = history.history['val_categorical_accuracy']\n\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs_range = range(EPOCHS)\n\nplt.figure(figsize=(8, 8))\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label='Training Accuracy')\nplt.plot(epochs_range, val_acc, label='Validation Accuracy')\nplt.legend(loc='lower right')\nplt.title('Training and Validation Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(epochs_range, loss, label='Training Loss')\nplt.plot(epochs_range, val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.title('Training and Validation Loss')\nplt.show()","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}