{"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-15T11:05:33.904080Z","iopub.execute_input":"2021-12-15T11:05:33.904351Z","iopub.status.idle":"2021-12-15T11:05:38.519829Z","shell.execute_reply.started":"2021-12-15T11:05:33.904323Z","shell.execute_reply":"2021-12-15T11:05:38.519136Z"},"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-15T11:05:38.522558Z","iopub.execute_input":"2021-12-15T11:05:38.523041Z","iopub.status.idle":"2021-12-15T11:05:38.564630Z","shell.execute_reply.started":"2021-12-15T11:05:38.522991Z","shell.execute_reply":"2021-12-15T11:05:38.563957Z"},"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-15T11:05:38.565923Z","iopub.execute_input":"2021-12-15T11:05:38.566151Z","iopub.status.idle":"2021-12-15T11:05:38.571341Z","shell.execute_reply.started":"2021-12-15T11:05:38.566119Z","shell.execute_reply":"2021-12-15T11:05:38.570538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"disease_label","metadata":{"execution":{"iopub.status.busy":"2021-12-15T11:05:38.573445Z","iopub.execute_input":"2021-12-15T11:05:38.573920Z","iopub.status.idle":"2021-12-15T11:05:38.584835Z","shell.execute_reply.started":"2021-12-15T11:05:38.573884Z","shell.execute_reply":"2021-12-15T11:05:38.584149Z"},"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-15T11:05:38.591465Z","iopub.execute_input":"2021-12-15T11:05:38.592105Z","iopub.status.idle":"2021-12-15T11:05:38.597451Z","shell.execute_reply.started":"2021-12-15T11:05:38.592062Z","shell.execute_reply":"2021-12-15T11:05:38.596693Z"},"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-15T11:05:38.599123Z","iopub.execute_input":"2021-12-15T11:05:38.599767Z","iopub.status.idle":"2021-12-15T11:05:38.646926Z","shell.execute_reply.started":"2021-12-15T11:05:38.599731Z","shell.execute_reply":"2021-12-15T11:05:38.646339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T11:05:38.648026Z","iopub.execute_input":"2021-12-15T11:05:38.648269Z","iopub.status.idle":"2021-12-15T11:05:38.657787Z","shell.execute_reply.started":"2021-12-15T11:05:38.648236Z","shell.execute_reply":"2021-12-15T11:05:38.656983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T11:05:38.659120Z","iopub.execute_input":"2021-12-15T11:05:38.659727Z","iopub.status.idle":"2021-12-15T11:05:38.678614Z","shell.execute_reply.started":"2021-12-15T11:05:38.659691Z","shell.execute_reply":"2021-12-15T11:05:38.677963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['label'] = train['label'].astype('str')","metadata":{"execution":{"iopub.status.busy":"2021-12-15T11:05:38.679736Z","iopub.execute_input":"2021-12-15T11:05:38.680162Z","iopub.status.idle":"2021-12-15T11:05:38.707859Z","shell.execute_reply.started":"2021-12-15T11:05:38.680128Z","shell.execute_reply":"2021-12-15T11:05:38.707242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"str(disease_label.iloc[3])","metadata":{"execution":{"iopub.status.busy":"2021-12-15T11:05:38.710165Z","iopub.execute_input":"2021-12-15T11:05:38.710439Z","iopub.status.idle":"2021-12-15T11:05:38.716357Z","shell.execute_reply.started":"2021-12-15T11:05:38.710387Z","shell.execute_reply":"2021-12-15T11:05:38.715649Z"},"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-15T11:05:38.717691Z","iopub.execute_input":"2021-12-15T11:05:38.718274Z","iopub.status.idle":"2021-12-15T11:05:39.077647Z","shell.execute_reply.started":"2021-12-15T11:05:38.718235Z","shell.execute_reply":"2021-12-15T11:05:39.076450Z"},"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-15T11:05:39.078515Z","iopub.execute_input":"2021-12-15T11:05:39.078717Z","iopub.status.idle":"2021-12-15T11:05:39.292722Z","shell.execute_reply.started":"2021-12-15T11:05:39.078690Z","shell.execute_reply":"2021-12-15T11:05:39.292025Z"},"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-15T11:05:39.294139Z","iopub.execute_input":"2021-12-15T11:05:39.294401Z","iopub.status.idle":"2021-12-15T11:05:40.818695Z","shell.execute_reply.started":"2021-12-15T11:05:39.294366Z","shell.execute_reply":"2021-12-15T11:05:40.818026Z"},"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-15T11:05:40.819936Z","iopub.execute_input":"2021-12-15T11:05:40.822355Z","iopub.status.idle":"2021-12-15T11:05:41.640600Z","shell.execute_reply.started":"2021-12-15T11:05:40.822314Z","shell.execute_reply":"2021-12-15T11:05:41.639871Z"},"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-15T11:05:41.643051Z","iopub.execute_input":"2021-12-15T11:05:41.643532Z","iopub.status.idle":"2021-12-15T11:06:04.792780Z","shell.execute_reply.started":"2021-12-15T11:05:41.643494Z","shell.execute_reply":"2021-12-15T11:06:04.792031Z"},"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-15T11:06:04.794071Z","iopub.execute_input":"2021-12-15T11:06:04.794499Z","iopub.status.idle":"2021-12-15T11:06:10.284375Z","shell.execute_reply.started":"2021-12-15T11:06:04.794452Z","shell.execute_reply":"2021-12-15T11:06:10.282884Z"},"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-15T11:08:21.717171Z","iopub.execute_input":"2021-12-15T11:08:21.718010Z","iopub.status.idle":"2021-12-15T11:08:21.733340Z","shell.execute_reply.started":"2021-12-15T11:08:21.717964Z","shell.execute_reply":"2021-12-15T11:08:21.732485Z"},"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-15T11:11:41.927694Z","iopub.execute_input":"2021-12-15T11:11:41.928268Z","iopub.status.idle":"2021-12-15T11:11:43.615848Z","shell.execute_reply.started":"2021-12-15T11:11:41.928220Z","shell.execute_reply":"2021-12-15T11:11:43.615119Z"},"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-15T11:11:43.618749Z","iopub.execute_input":"2021-12-15T11:11:43.618943Z","iopub.status.idle":"2021-12-15T11:47:20.575975Z","shell.execute_reply.started":"2021-12-15T11:11:43.618918Z","shell.execute_reply":"2021-12-15T11:47:20.575257Z"},"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":{"execution":{"iopub.status.busy":"2021-12-15T11:47:20.577778Z","iopub.execute_input":"2021-12-15T11:47:20.578110Z","iopub.status.idle":"2021-12-15T11:47:20.812581Z","shell.execute_reply.started":"2021-12-15T11:47:20.578074Z","shell.execute_reply":"2021-12-15T11:47:20.811927Z"},"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":{"execution":{"iopub.status.busy":"2021-12-15T11:47:20.813845Z","iopub.execute_input":"2021-12-15T11:47:20.814084Z","iopub.status.idle":"2021-12-15T11:47:21.915963Z","shell.execute_reply.started":"2021-12-15T11:47:20.814051Z","shell.execute_reply":"2021-12-15T11:47:21.915255Z"},"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-15T11:47:21.917792Z","iopub.execute_input":"2021-12-15T11:47:21.918036Z","iopub.status.idle":"2021-12-15T12:19:40.258578Z","shell.execute_reply.started":"2021-12-15T11:47:21.918001Z","shell.execute_reply":"2021-12-15T12:19:40.257830Z"},"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":{"execution":{"iopub.status.busy":"2021-12-15T12:19:40.260145Z","iopub.execute_input":"2021-12-15T12:19:40.260431Z","iopub.status.idle":"2021-12-15T12:19:40.871742Z","shell.execute_reply.started":"2021-12-15T12:19:40.260393Z","shell.execute_reply":"2021-12-15T12:19:40.871030Z"},"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":[]}]}