{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Introduction\nThis is a starter kernel for IncepresnetV2. If you are using this to develop further, please remove the test.head(10) line from the test cell before submitting. I added it so that the kernel runs fast.\n\nI performed my EDA in a separate kernel. Please look at https://www.kaggle.com/viiids/stage-1-eda-for-beginners if you are looking for Eploratory Data Analysis on this data. There are some useful findings summarized at the end of that kernel.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport keras\nfrom keras import layers\nfrom keras.layers import Input, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D\nfrom keras.layers import AveragePooling2D, MaxPooling2D, Dropout, GlobalMaxPooling2D, GlobalAveragePooling2D\nfrom keras.preprocessing.image import load_img\nfrom keras import regularizers\nfrom keras.models import Model\nfrom keras.preprocessing import image\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.applications.inception_resnet_v2 import InceptionResNetV2, preprocess_input\nfrom keras.applications import imagenet_utils\nfrom keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import img_to_array\nfrom keras.callbacks.callbacks import EarlyStopping\nfrom keras.callbacks.callbacks import ReduceLROnPlateau\nfrom keras.callbacks.callbacks import ModelCheckpoint\nimport pydot\nfrom IPython.display import SVG\nfrom keras.utils import plot_model\nfrom keras.utils import to_categorical\nfrom random import randint\n\nfrom sklearn.utils import class_weight\nfrom sklearn.model_selection import train_test_split\n\nimport keras.backend as K\nK.set_image_data_format('channels_last')\nimport matplotlib.pyplot as plt\nfrom matplotlib.pyplot import imshow\n\n%matplotlib inline\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt; plt.rcdefaults()\nimport random\nimport cv2\n\nimport tensorflow as tf\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Setting up TPU.\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    strategy = tf.distribute.get_strategy() \nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Initial setup\n1. Loading data\n2. Defining some constants.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"ROOT = '/kaggle/input/siim-isic-melanoma-classification/'\nTRAIN_IMAGES_PATH = ROOT + 'jpeg/train/'\nTEST_IMAGES_PATH = ROOT + 'jpeg/test/'\nEXTENSION = '.jpg'\nIMAGE_DIM_X = 299\nIMAGE_DIM_Y = 299\nBATCH_SIZE = 8\n\ninception_preprocess = preprocess_input\n\ntrain_data = pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/train.csv')\ntest_data = pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/test.csv')\nsample_submission = pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/sample_submission.csv')\nTEST_SIZE = len(test_data)\n\ntrain_data.rename(columns={\n    'anatom_site_general_challenge': 'area', \n    'benign_malignant': 'class',\n    'target': 'label'\n}, inplace=True)\n\nimg_path = TRAIN_IMAGES_PATH + train_data.iloc[0].image_name + EXTENSION\nimg = load_img(img_path)\nnp_img = img_to_array(img).astype(int)\nnp_img.shape\nRGB = np_img.shape[2]\n# Output: (4000, 6000, 3) = Very high resolution RGB images\n\ntrain_data['image_name'] = train_data['image_name'].apply(\n    lambda image_name : TRAIN_IMAGES_PATH + image_name + EXTENSION)\ntest_data['image'] = test_data['image_name']\ntest_data['image_name'] = test_data['image_name'].apply(\n    lambda image_name : TEST_IMAGES_PATH + image_name + EXTENSION)\n\nprint(train_data.iloc[1].image_name)\nprint(test_data.iloc[1].image_name)\nprint(len(train_data))\ntrain_data.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(test_data.iloc[0].image_name)\ntest_data.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Oversampling Malignant\nGenerating class weights since we have very little samples of Malignant and we want training to encounter Malignant and Bening in equal proportions.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class_weights = class_weight.compute_class_weight(\n    'balanced',\n    train_data['label'].unique(),\n    train_data[['label']].to_numpy().reshape(-1)\n)\n\nprint('benign weight: ' + str(class_weights[0]))\nprint('malignant weight: ' + str(class_weights[1]))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Standard test train split","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train, X_val = train_test_split(train_data, test_size=0.1, shuffle=True)\n\nX_train.head()\nX_val.head()\n\nTRAIN_SIZE = len(X_train)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Defining a DataGenerator\nThis is needed because the images are very large in size and each batch requires to be sampled.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def image_walker(input_data, image_name_col, label_cols, is_test=False):\n    \"\"\"\n    Creates an ImageDataGenerator which serves two purposes:\n    1. Loads images from a predefined directory and prepares batches for Gradient Descent.\n    2. Performs data augmentation on those images.\n    \n    Parameters\n    ----------\n    input_paths : Dataframe containing a columns \"paths\" representing different paths from which an image\n    is expected to be loaded.\n    It is assumed that all the images are in the input/siim-isic-melanoma-classification/jpeg directory\n    \n    Returns\n    -------\n    iterator to the created ImageDataGenerator\n    \"\"\"\n    data_generator = ImageDataGenerator(\n        preprocessing_function=preprocess_input,\n        rotation_range=45,\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'\n    )\n    iterator = data_generator.flow_from_dataframe(\n        input_data, \n        directory=None, \n        x_col=image_name_col, \n        y_col=label_cols,                                \n        target_size=(IMAGE_DIM_X, IMAGE_DIM_Y),\n        seed=42, \n        class_mode='raw',\n        batch_size=BATCH_SIZE,\n        shuffle=False,\n        subset='training'\n    )\n    return iterator","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"[INFO] loading {}...\".format(\"inception\"))\nbase_model = InceptionResNetV2(\n    weights='imagenet', \n    include_top=False, \n    input_shape=(IMAGE_DIM_X, IMAGE_DIM_Y, RGB))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"CLASSES = 1\nX = base_model.output\nX = GlobalAveragePooling2D(name='avg_pool')(X)\npredictions = Dense(CLASSES, activation='sigmoid')(X)\nmodel = Model(inputs=base_model.input, outputs=predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer='adam',\n              loss='binary_crossentropy',\n              metrics=['accuracy']\n             )\n\nearly = EarlyStopping(monitor='accuracy', min_delta=0.1, patience=5, verbose=0, mode='auto', restore_best_weights=True)\n\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=4, min_lr=0.0001, mode='auto')\n\nmodel_checkpoint = ModelCheckpoint('incepresnetv2_ol.model', monitor='loss', save_best_only=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"EPOCHS = 2\nMODEL_FILE = 'filename_ol_dense.model'\ndef train():\n    history = model.fit_generator(\n        image_walker(X_train, 'image_name', 'label'),\n        shuffle=True,\n        epochs=EPOCHS,\n        steps_per_epoch=int(TRAIN_SIZE/BATCH_SIZE),\n        callbacks=[model_checkpoint, reduce_lr],\n        validation_data=image_walker(X_val, 'image_name', 'label'),\n        validation_steps=18,\n        class_weight=class_weights\n    )\n    model.save(MODEL_FILE)\n    return history\n\n# Enable this if training is needed\n# history = train()\n\n# Use this if trained and ready for predictions\nmodel = keras.models.load_model('/kaggle/input/incepresnet-v2/filename_ol_dense.model')\nprint('Finished loading/training model')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Submission Generator\n**Note that if you are using this kernel for final submission, remove the test_data = test_data.head(100) line.**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# REMOVE THIS LINE if you are using this notebook to submit.\ntest_data = test_data.head(100)\n\nprint(len(test_data))\nTEST_BATCH_SIZE = 1\n\ntest_generator = ImageDataGenerator(preprocessing_function=preprocess_input)\ntest_predictions = model.predict_generator(\n    test_generator.flow_from_dataframe(\n        test_data, \n        x_col='image_name', \n        y_col=None,\n        class_mode=None,\n        target_size=(IMAGE_DIM_X, IMAGE_DIM_Y),\n        batch_size=TEST_BATCH_SIZE, \n        shuffle=False), \n    steps=len(test_data)/TEST_BATCH_SIZE,\n    verbose=1\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(test_predictions.shape)\nsample_submission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data['target'] = test_predictions[:, 0]\ntest_data = test_data[['image', 'target']]\ntest_data.rename(columns={'image': 'image_name'}, inplace=True)\ntest_data.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data.to_csv('submission.csv', index=False)","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}