{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nimport time\nimport matplotlib.pyplot as plt\nimport os\nfrom PIL import Image\n\nos.listdir(\"../input/cassava-leaf-disease-classification\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# code from https://www.kaggle.com/ryanholbrook/the-convolutional-classifier\n# Reproducability \ndef set_seed(seed=2020):\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\n    \nset_seed()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(\"../input/cassava-leaf-disease-classification/train.csv\")\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df[\"label\"].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df[\"label\"] = train_df[\"label\"].astype(str)\ntrain_df.dtypes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import json\n\nwith open(\"../input/cassava-leaf-disease-classification/label_num_to_disease_map.json\") as json_file:\n    for k,v in json.load(json_file).items():\n        print(f\"{k}: {v}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# checking some sample images"},{"metadata":{},"cell_type":"markdown","source":"## sample images of label 0: Cassava Bacterial Blight (CBB)\nSome leaves looks getting yellow or blown(maybe some cells are dead)"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images_dir = \"../input/cassava-leaf-disease-classification/train_images\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"label0_sample_image_filenames = train_df[train_df[\"label\"] == \"0\"][:16][\"image_id\"].to_list()\nlabel0_sample_images = [Image.open(os.path.join(train_images_dir, path)) for path in label0_sample_image_filenames]\n\nplt.figure(figsize=(16, 16))\nfor i in range(16):\n    plt.title(label0_sample_image_filenames[i])\n    plt.subplot(4, 4, i+1)\n    plt.imshow(label0_sample_images[i])\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## sample images of label 1: Cassava Brown Streak Disease (CBSD)\nSome leaves are getting yellow, so it's hard for me to distinguish with label0(CBB)  \nI don't know why some cassava potatos are labeled as CBSD.🤔"},{"metadata":{"trusted":true},"cell_type":"code","source":"label1_sample_image_filenames = train_df[train_df[\"label\"] == \"1\"][:16][\"image_id\"].to_list()\nlabel1_sample_images = [Image.open(os.path.join(train_images_dir, path)) for path in label1_sample_image_filenames]\n\nplt.figure(figsize=(16, 16))\nfor i in range(16):\n    plt.title(label1_sample_image_filenames[i])\n    plt.subplot(4, 4, i+1)\n    plt.imshow(label1_sample_images[i])\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## sample images of label 2: Cassava Green Mottle (CGM)\nSome leaves have some white mottle."},{"metadata":{"trusted":true},"cell_type":"code","source":"label2_sample_image_filenames = train_df[train_df[\"label\"] == \"2\"][:16][\"image_id\"].to_list()\nlabel2_sample_images = [Image.open(os.path.join(train_images_dir, path)) for path in label2_sample_image_filenames]\n\nplt.figure(figsize=(16, 16))\nfor i in range(16):\n    plt.title(label2_sample_image_filenames[i])\n    plt.subplot(4, 4, i+1)\n    plt.imshow(label2_sample_images[i])\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## sample images of label 3: Cassava Mosaic Disease (CMD)\nSome leaves's have weird shape."},{"metadata":{"trusted":true},"cell_type":"code","source":"label3_sample_image_filenames = train_df[train_df[\"label\"] == \"3\"][:16][\"image_id\"].to_list()\nlabel3_sample_images = [Image.open(os.path.join(train_images_dir, path)) for path in label3_sample_image_filenames]\n\nplt.figure(figsize=(16, 16))\nfor i in range(16):\n    plt.title(label3_sample_image_filenames[i])\n    plt.subplot(4, 4, i+1)\n    plt.imshow(label3_sample_images[i])\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## sample images of label 4: Healthy(...Really?)\nSome leaves are nice and green, with no yellow part or white mottle.  \nBut the top left image(1003442061.jpg) seems far from healthy..."},{"metadata":{"trusted":true},"cell_type":"code","source":"label4_sample_image_filenames = train_df[train_df[\"label\"] == \"4\"][:16][\"image_id\"].to_list()\nlabel4_sample_images = [Image.open(os.path.join(train_images_dir, path)) for path in label4_sample_image_filenames]\n\nplt.figure(figsize=(16, 16))\nfor i in range(16):\n    plt.title(label4_sample_image_filenames[i])\n    plt.subplot(4, 4, i+1)\n    plt.imshow(label4_sample_images[i])\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Is it OK to resize the images? Can we still find the yellow part or white mottle?\nOriginal images have the shape of 800 by 600. It's a little too big.  \nSo let's try resizing some images down to 300 by 300"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(16, 16))\nfor i in range(16):\n    plt.title(label0_sample_image_filenames[i])\n    plt.subplot(4, 4, i+1)\n    plt.imshow(label0_sample_images[i].resize((300, 300)))\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As you can see, we can still find the yellow or blown parts, so it's seems fine to resize."},{"metadata":{},"cell_type":"markdown","source":"# making ImageDataGenerator"},{"metadata":{"trusted":true},"cell_type":"code","source":"target_size = (299, 299)\ninput_shape = (299, 299, 3)\nbatch_size = 64","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(validation_split=0.05)\n\ntrain_generator = datagen.flow_from_dataframe(\n    train_df,\n    directory=\"../input/cassava-leaf-disease-classification/train_images\",\n    x_col=\"image_id\",\n    y_col=\"label\",\n    target_size=target_size,\n    batch_size=batch_size,\n    class_mode=\"sparse\",\n    subset=\"training\",\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"val_generator = datagen.flow_from_dataframe(\n    train_df,\n    directory=\"../input/cassava-leaf-disease-classification/train_images\",\n    x_col=\"image_id\",\n    y_col=\"label\",\n    target_size=target_size,\n    batch_size=batch_size,\n    class_mode=\"sparse\",\n    subset=\"validation\",\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# making a model with InceptionResNetV2"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.applications import DenseNet169, ResNet50V2, InceptionResNetV2\n\ninception_resnet_v2 = InceptionResNetV2(\n    include_top=False,\n    weights=\"../input/inceptionresnetv2/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5\",\n    input_shape=input_shape,\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(inception_resnet_v2.layers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.layers import Input, GlobalAveragePooling2D, Conv2D, MaxPooling2D, Flatten, Dense, BatchNormalization, Dropout, LeakyReLU\nfrom tensorflow.keras.layers.experimental.preprocessing import RandomRotation, RandomFlip, RandomZoom, CenterCrop, Rescaling\nfrom tensorflow.keras.applications.inception_resnet_v2 import preprocess_input\n\ndef create_model():\n    inputs = Input(input_shape)\n    \n    x = preprocess_input(inputs)\n    x = Rescaling(1./255)(x)\n    \n    # some layers for data augmentation\n    x = RandomFlip()(x)\n    x = RandomRotation(factor=0.3)(x)\n    \n    x = BatchNormalization()(x)\n    \n    x = inception_resnet_v2(x)\n\n    x = MaxPooling2D((2, 2))(x)\n    x = Conv2D(256, (1, 1), activation=LeakyReLU())(x)\n    x = BatchNormalization()(x)\n    \n    x = Flatten()(x)\n    x = Dropout(0.75)(x)\n\n    x = Dense(256, activation=LeakyReLU())(x)\n    x = Dropout(0.75)(x)\n    x = BatchNormalization()(x)\n    \n    outputs = Dense(5, activation=\"softmax\")(x)\n    \n    model = tf.keras.Model(inputs, outputs)\n    \n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(0.001),\n        loss=\"sparse_categorical_crossentropy\",\n        metrics=[\"accuracy\"]\n    )\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = create_model()\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\n\ncp = ModelCheckpoint(\n    \"best_model_weights.h5\",\n    monitor=\"val_loss\",\n    save_best_only=True,\n    save_weights_only=True,\n)\n\nes = EarlyStopping(\n    monitor=\"val_loss\",\n    patience=10,\n)\n\nreduce_lr = ReduceLROnPlateau(\n    monitor=\"val_loss\",\n    patience=2,\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.utils import class_weight\n\nclass_weights = class_weight.compute_class_weight('balanced',\n                                                 np.unique(train_df[\"label\"]),\n                                                 train_df[\"label\"])\n\nclass_weights = dict(enumerate(class_weights))\n\nclass_weights","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# training my model"},{"metadata":{"trusted":true},"cell_type":"code","source":"tic = time.time()\n\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=100,\n    callbacks=[cp, es, reduce_lr],\n    class_weight=class_weights,\n)\n\ntoc = time.time()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f\"model training took {int((toc - tic) / 60)} minutes\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# code from https://www.kaggle.com/ryanholbrook/the-convolutional-classifier\nhistory_frame = pd.DataFrame(history.history)\nhistory_frame.loc[:, ['loss', 'val_loss']].plot(ylim=(0, 3))\nhistory_frame.loc[:, ['accuracy', 'val_accuracy']].plot(ylim=(0., 1.))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.evaluate_generator(val_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_weights(\"best_model_weights.h5\")\nmodel.evaluate_generator(val_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.metrics_names","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df = pd.read_csv(\"../input/cassava-leaf-disease-classification/sample_submission.csv\")\nsubmission_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test_datagen = ImageDataGenerator()\n\n# test_generator = test_datagen.flow_from_dataframe(\n#     submission_df,\n#     directory=\"../input/cassava-leaf-disease-classification/test_images\",\n#     x_col=\"image_id\",\n#     target_size=target_size,\n#     batch_size=batch_size,\n#     class_mode=None\n# )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# y_pred = model.predict(test_generator)\n# y_pred","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from PIL import Image\n\n# code from https://www.kaggle.com/sinamhd9/keras-available-models-part-2-inference\ntest_images = os.listdir('/kaggle/input/cassava-leaf-disease-classification/test_images/')\ny_preds = []\n\nfor i in test_images:\n    image = Image.open(f'/kaggle/input/cassava-leaf-disease-classification/test_images/{i}')\n    image = image.resize(target_size)\n    image = np.expand_dims(image, axis=0)\n    y_preds.append(np.argmax(model.predict(image)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_sub = pd.DataFrame({'image_id': test_images, 'label': y_preds})\ndisplay(df_sub)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# y_pred = np.argmax(y_pred, axis=1)\n# y_pred","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# submission_df[\"label\"] = y_pred\n# submission_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# submission_df.to_csv(\"submission.csv\", index=None)\ndf_sub.to_csv(\"submission.csv\", index=None)","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}