{"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":"# _Cassava Leaf Disease Detection_\n\n","metadata":{}},{"cell_type":"markdown","source":"## _Import Libraries & Load Data_","metadata":{}},{"cell_type":"code","source":"#system related imports\nimport os\nimport sys\nassert sys.version_info >= (3,5)\n#data manipulation\nimport pandas as pd\nimport numpy as np\n#visualization imports\nimport matplotlib.pyplot as plt\nfrom matplotlib.image import imread\nimport seaborn as sns\n%matplotlib inline\n# consistent plot size\nfrom pylab import rcParams\nrcParams['figure.figsize'] = 15,7\nrcParams['axes.labelsize'] = 14\nrcParams['xtick.labelsize'] = 12\nrcParams['ytick.labelsize'] = 12\nrcParams['axes.titlesize'] = 16\n#ignore warnings\nimport warnings\nwarnings.filterwarnings(action='ignore',message='')\n#deep learning framework\nimport tensorflow as tf","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:28.468377Z","iopub.execute_input":"2021-12-26T13:04:28.468618Z","iopub.status.idle":"2021-12-26T13:04:32.744107Z","shell.execute_reply.started":"2021-12-26T13:04:28.468554Z","shell.execute_reply":"2021-12-26T13:04:32.743410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## _Load the data_","metadata":{}},{"cell_type":"code","source":"'''read the train csv file'''\ntrain =  pd.read_csv('../input/cassava-leaf-disease-classification/train.csv')\ntrain.head(10)","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.745546Z","iopub.execute_input":"2021-12-26T13:04:32.745778Z","iopub.status.idle":"2021-12-26T13:04:32.785339Z","shell.execute_reply.started":"2021-12-26T13:04:32.745746Z","shell.execute_reply":"2021-12-26T13:04:32.784561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''read the disease label into a dataframe'''\ndata = {\"0\":\"Cassava Bacterial Blight (CBB)\",\n        \"1\":\"Cassava Brown Streak Disease (CBSD)\",\n        \"2\":\"Cassava Green Mottle (CGM)\",\n        \"3\":\"Cassava Mosaic Disease (CMD)\",\n        \"4\":\"Healthy\"}\ndisease_label = pd.DataFrame(data=data.values(),index=data.keys(),columns=['Disease_Name'])","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.786691Z","iopub.execute_input":"2021-12-26T13:04:32.786948Z","iopub.status.idle":"2021-12-26T13:04:32.792534Z","shell.execute_reply.started":"2021-12-26T13:04:32.786909Z","shell.execute_reply":"2021-12-26T13:04:32.791694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"disease_label","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.795099Z","iopub.execute_input":"2021-12-26T13:04:32.795395Z","iopub.status.idle":"2021-12-26T13:04:32.805947Z","shell.execute_reply.started":"2021-12-26T13:04:32.795358Z","shell.execute_reply":"2021-12-26T13:04:32.804969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_path = '../input/cassava-leaf-disease-classification/train_images'\ntest_path = '../input/cassava-leaf-disease-classification/test_images'","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.807070Z","iopub.execute_input":"2021-12-26T13:04:32.807448Z","iopub.status.idle":"2021-12-26T13:04:32.813587Z","shell.execute_reply.started":"2021-12-26T13:04:32.807413Z","shell.execute_reply":"2021-12-26T13:04:32.812808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''Join the train path'''\ndef image_path(image):\n    return os.path.join(train_path,image)\n\ntrain['image_id'] = train['image_id'].apply(image_path)","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.814818Z","iopub.execute_input":"2021-12-26T13:04:32.815998Z","iopub.status.idle":"2021-12-26T13:04:32.865038Z","shell.execute_reply.started":"2021-12-26T13:04:32.815967Z","shell.execute_reply":"2021-12-26T13:04:32.864412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.866016Z","iopub.execute_input":"2021-12-26T13:04:32.866256Z","iopub.status.idle":"2021-12-26T13:04:32.875816Z","shell.execute_reply.started":"2021-12-26T13:04:32.866223Z","shell.execute_reply":"2021-12-26T13:04:32.875172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.877203Z","iopub.execute_input":"2021-12-26T13:04:32.877842Z","iopub.status.idle":"2021-12-26T13:04:32.897599Z","shell.execute_reply.started":"2021-12-26T13:04:32.877798Z","shell.execute_reply":"2021-12-26T13:04:32.896826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['label'] = train['label'].astype('str')","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.898721Z","iopub.execute_input":"2021-12-26T13:04:32.899092Z","iopub.status.idle":"2021-12-26T13:04:32.929537Z","shell.execute_reply.started":"2021-12-26T13:04:32.899054Z","shell.execute_reply":"2021-12-26T13:04:32.928919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"str(disease_label.iloc[3])","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.932435Z","iopub.execute_input":"2021-12-26T13:04:32.932614Z","iopub.status.idle":"2021-12-26T13:04:32.937916Z","shell.execute_reply.started":"2021-12-26T13:04:32.932589Z","shell.execute_reply":"2021-12-26T13:04:32.937212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''view one of the images in the train set randomly'''\nindex = np.random.randint(0,len(train))\n\nplt.imshow(imread(train['image_id'][index]))\nplt.title('Cassava Leaf')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:32.939426Z","iopub.execute_input":"2021-12-26T13:04:32.940041Z","iopub.status.idle":"2021-12-26T13:04:33.363870Z","shell.execute_reply.started":"2021-12-26T13:04:32.940002Z","shell.execute_reply":"2021-12-26T13:04:33.363209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''check the count of the various disease types'''\nsns.countplot(train['label'])\nplt.title('Count of the various disease types in Cassava leaves')\nplt.grid()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:33.364838Z","iopub.execute_input":"2021-12-26T13:04:33.365065Z","iopub.status.idle":"2021-12-26T13:04:33.576599Z","shell.execute_reply.started":"2021-12-26T13:04:33.365035Z","shell.execute_reply":"2021-12-26T13:04:33.575965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- <b> _The Cassava Mosaic Disease or CMD is most prevalent as per the dataset_ </b>","metadata":{}},{"cell_type":"code","source":"'''display the images of the same label'''\nn_rows = 3\nn_cols = 4\n\nfor row in range(n_rows):\n    for col in range(n_cols):\n        index = n_cols * row + col\n        plt.subplot(n_rows,n_cols,index+1)\n        \n        leaf_img = np.random.randint(0,len(train))\n        image_ = imread(train.iloc[leaf_img]['image_id'])\n        \n        '''display the image'''\n        plt.imshow(image_,cmap='binary',interpolation='nearest')     \n        ","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:33.577897Z","iopub.execute_input":"2021-12-26T13:04:33.578133Z","iopub.status.idle":"2021-12-26T13:04:35.158779Z","shell.execute_reply.started":"2021-12-26T13:04:33.578101Z","shell.execute_reply":"2021-12-26T13:04:35.158167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# _Data Preparation_ ","metadata":{}},{"cell_type":"code","source":"'''image data augmentation'''\nimage_generator = tf.keras.preprocessing.image.ImageDataGenerator(rotation_range=0.5,\n                                                                 horizontal_flip=True,\n                                                                 vertical_flip=True,\n                                                                 brightness_range=[0.1,0.3],\n                                                                 zoom_range=[0.1,0.5],\n                                                                 fill_mode='nearest',\n                                                                 preprocessing_function=tf.keras.applications.xception.preprocess_input,\n                                                                 validation_split=0.2,\n                                                                  rescale = 1./255,\n                                                                  dtype='float32')","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:35.159883Z","iopub.execute_input":"2021-12-26T13:04:35.160222Z","iopub.status.idle":"2021-12-26T13:04:35.985195Z","shell.execute_reply.started":"2021-12-26T13:04:35.160190Z","shell.execute_reply":"2021-12-26T13:04:35.984421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_generator = image_generator.flow_from_dataframe(dataframe=train,\n                                                      directory=None,\n                                                      x_col='image_id',\n                                                      y_col='label',\n                                                      subset='training',\n                                                      color_mode='rgb',\n                                                      batch_size=32,\n                                                      seed=42,\n                                                      shuffle=True,\n                                                      class_mode='categorical',\n                                                      target_size=(224,224))","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:04:35.987905Z","iopub.execute_input":"2021-12-26T13:04:35.988632Z","iopub.status.idle":"2021-12-26T13:05:26.859682Z","shell.execute_reply.started":"2021-12-26T13:04:35.988588Z","shell.execute_reply":"2021-12-26T13:05:26.858454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''image generator on the validation data. \n   note: shuffle is set to false in this case'''\n\nvalidation_generator = image_generator.flow_from_dataframe(dataframe=train,\n                                                           directory=None,\n                                                           x_col='image_id',\n                                                           y_col='label',\n                                                           subset='validation',\n                                                           color_mode='rgb',\n                                                           batch_size=32,\n                                                           seed=42,\n                                                           shuffle=False,\n                                                           class_mode='categorical',\n                                                           target_size=(224,224))","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:05:26.861946Z","iopub.execute_input":"2021-12-26T13:05:26.862485Z","iopub.status.idle":"2021-12-26T13:05:34.404178Z","shell.execute_reply.started":"2021-12-26T13:05:26.862434Z","shell.execute_reply":"2021-12-26T13:05:34.403375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# _Functional API Convolutional Neural Network Model_","metadata":{}},{"cell_type":"code","source":"def cnn_model_pretrain(xception=True,shape=(224,224,3),filters=8,kernel=4,stride=1,pad='same',unit=1024,activation=tf.nn.relu,\n              regularizer=tf.keras.regularizers.L1L2(l1=0.01,l2=0.01)):\n    \n    '''function to define the cnn model architecture with or without transfer learning'''\n    \n    input_img = tf.keras.Input(shape=shape)\n    \n    base_model = tf.keras.applications.xception.Xception(include_top=False,input_shape=shape,weights='imagenet')\n    for layer in base_model.layers:\n        layer.trainable = False\n    \n    if xception:\n        pretrain = base_model(input_img)\n    else:\n        pretrain =  input_img\n        \n    '''One layer of Conv2D, Activation and Pooling layer'''\n    Z1 = tf.keras.layers.Conv2D(filters=filters,kernel_size=(kernel,kernel),strides=stride,padding=pad)(pretrain)\n    A1 = tf.keras.layers.Activation(activation)(Z1)\n    P1 = tf.keras.layers.MaxPool2D(pool_size=(filters,filters),strides=stride*8,padding=pad)(A1)\n    \n    '''Second layer of Conv2D, Activation and Pooling layer'''\n    Z2 = tf.keras.layers.Conv2D(filters=filters*2,kernel_size=(int(kernel/2),int(kernel/2)),strides=stride,\n                               padding=pad) (P1)\n    A2 = tf.keras.layers.Activation(activation)(Z2)\n    P2 = tf.keras.layers.MaxPool2D(pool_size=int(filters/2),strides=stride*4,padding=pad)(A2)\n    \n    '''Flatten the output to feed into the dense layer'''\n    F = tf.keras.layers.Flatten()(P2)\n    \n    '''Dense Layers'''\n    D1 = tf.keras.layers.Dense(units=unit,activation=activation)(F)\n    D2 = tf.keras.layers.Dense(units=unit/2,activation=activation,kernel_regularizer=regularizer)(D1)\n    D3 = tf.keras.layers.Dense(units=unit/4,activation=activation,kernel_regularizer=regularizer)(D2)\n    \n    '''Output layer'''\n    outputs = tf.keras.layers.Dense(units=5,activation=tf.nn.softmax)(D3)\n    \n    '''instantiate the model'''\n    model = tf.keras.Model(inputs=input_img,outputs=outputs)\n    return model  ","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:05:34.405678Z","iopub.execute_input":"2021-12-26T13:05:34.406114Z","iopub.status.idle":"2021-12-26T13:05:34.420523Z","shell.execute_reply.started":"2021-12-26T13:05:34.406073Z","shell.execute_reply":"2021-12-26T13:05:34.419871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"regularizer = tf.keras.regularizers.L2(l2=0.005)\nshape = (224,224,3)\n\nconv_model = cnn_model_pretrain(xception=True,shape=shape,filters=8,kernel=4,stride=1,pad='same',unit=256,activation=tf.nn.relu,\n                      regularizer=regularizer)\n\n'''compile the model'''\nconv_model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])\nconv_model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:05:34.421914Z","iopub.execute_input":"2021-12-26T13:05:34.422213Z","iopub.status.idle":"2021-12-26T13:05:38.961600Z","shell.execute_reply.started":"2021-12-26T13:05:34.422168Z","shell.execute_reply":"2021-12-26T13:05:38.960826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''fit the model'''\nhistory = conv_model.fit(train_generator,epochs=5,validation_data=validation_generator,batch_size=32)","metadata":{"execution":{"iopub.status.busy":"2021-12-26T13:05:38.964160Z","iopub.execute_input":"2021-12-26T13:05:38.964386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = pd.DataFrame(history.history)\nresults[['loss','val_loss']].plot()\nplt.title('Model Performance with pretrained')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''without pretrained xception module'''\n\nconv_model = cnn_model_pretrain(xception=False,shape=shape,filters=8,kernel=4,stride=1,pad='same',unit=256,activation=tf.nn.relu,\n                      regularizer=regularizer)\n\n'''compile the model'''\nconv_model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])\nconv_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''fit the model'''\nhistory = conv_model.fit(train_generator,epochs=5,validation_data=validation_generator,batch_size=32)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = pd.DataFrame(history.history)\nresults[['loss','val_loss']].plot()\nplt.title('Model Performance without pretrained network')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- <b> _Train for longer to see the variation_ </b>\n- <b> _Use other pretrained models like VGG16 and Reset50. Accuracy increases by atleast 6%_ </b> \n- <b> _Use GlobalAveragePooling instead of MaxPooling_ </b> \n","metadata":{}},{"cell_type":"markdown","source":"## _Upvote if you liked the notebook. Thank you !_","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}