{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow\nprint(tensorflow.__version__)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"!pip install livelossplot","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport cv2\nimport PIL\nfrom IPython.display import Image, display\nfrom keras.applications.vgg16 import VGG16,preprocess_input\n# Plotly for the interactive viewer (see last section)\nimport plotly.graph_objs as go\nimport plotly.graph_objects as go\nfrom sklearn.metrics import cohen_kappa_score\nfrom sklearn.model_selection import train_test_split\nfrom keras.models import Sequential, Model,load_model\nfrom keras.applications.vgg16 import VGG16,preprocess_input\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.preprocessing.image import ImageDataGenerator,load_img, img_to_array\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Input, Flatten,BatchNormalization,Activation\nfrom keras.layers import GlobalMaxPooling2D\nfrom keras.models import Model\nfrom keras.optimizers import Adam, SGD, RMSprop\nfrom keras.callbacks import ModelCheckpoint, Callback, EarlyStopping\nfrom keras.utils import to_categorical\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nimport gc\nimport skimage.io\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom tensorflow.python.keras import backend as K\nfrom livelossplot import PlotLossesKeras","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's use the jpeg files for training and testing.","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_dir='/kaggle/input/siim-isic-melanoma-classification/jpeg/train/'\ntest_dir='/kaggle/input/siim-isic-melanoma-classification/jpeg/test/'\ntrain=pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/train.csv')\ntest=pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/test.csv')\nsubmission=pd.read_csv('/kaggle/input/siim-isic-melanoma-classification/sample_submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Under sampling\nAs we have already seen in the EDA notebook, our training data is heavily biased with benign cases. So we are going to undersample our training set by picking random 2000 record from the benign cases,and all records from the malignant cases.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"## Original train data\ntrain['target'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Undersampled train data\ndf_0=train[train['target']==0].sample(2000)\ndf_1=train[train['target']==1]\ntrain=pd.concat([df_0,df_1])\ntrain=train.reset_index()\ntrain['target'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Preparing the Datasets","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"labels=[]\ndata=[]\nfor i in range(train.shape[0]):\n    data.append(train_dir + train['image_name'].iloc[i]+'.jpg')\n    labels.append(train['target'].iloc[i])\ndf=pd.DataFrame(data)\ndf.columns=['images']\ndf['target']=labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data=[]\nfor i in range(test.shape[0]):\n    test_data.append(test_dir + test['image_name'].iloc[i]+'.jpg')\ndf_test=pd.DataFrame(test_data)\ndf_test.columns=['images']","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Creating a hold-out Validation Set","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train, X_val, y_train, y_val = train_test_split(df['images'],df['target'], test_size=0.2, random_state=1234)\n\ntrain=pd.DataFrame(X_train)\ntrain.columns=['images']\ntrain['target']=y_train\n\nvalidation=pd.DataFrame(X_val)\nvalidation.columns=['images']\nvalidation['target']=y_val","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Preprocessing Images\n\n* normalizing\n* reshaping all images to size 224 x 224\n* augmentation using the Keras library function ImageDataGenerator (only for train data)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1./255,rotation_range=20,\n    width_shift_range=0.2,\n    height_shift_range=0.2,horizontal_flip=True)\n\nval_datagen=ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train,\n    x_col='images',\n    y_col='target',\n    target_size=(224, 224),\n    batch_size=8,\n    shuffle=True,\n    class_mode='raw')\n\nvalidation_generator = val_datagen.flow_from_dataframe(\n    validation,\n    x_col='images',\n    y_col='target',\n    target_size=(224, 224),\n    shuffle=False,\n    batch_size=8,\n    class_mode='raw')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Modeling\n\nUsing pretrained VGG-16 and adding the last dense layer.\nThe competition is evaluated on AUC scores, so we'll use that as a metric.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def vgg16_model( num_classes=None):\n\n    model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))\n    x=Flatten()(model.output)\n    output=Dense(1,activation='sigmoid')(x) # because we have to predict the AUC\n    model=Model(model.input,output)\n    \n    return model\n\nvgg_conv=vgg16_model(1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Because of class imbalance it's better to use **focal loss** rather than normal **binary_crossentropy**.\n[Source](https://arxiv.org/abs/1708.02002)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def focal_loss(alpha=0.25,gamma=2.0):\n    def focal_crossentropy(y_true, y_pred):\n        bce = K.binary_crossentropy(y_true, y_pred)\n        \n        y_pred = K.clip(y_pred, K.epsilon(), 1.- K.epsilon())\n        p_t = (y_true*y_pred) + ((1-y_true)*(1-y_pred))\n        \n        alpha_factor = 1\n        modulating_factor = 1\n\n        alpha_factor = y_true*alpha + ((1-alpha)*(1-y_true))\n        modulating_factor = K.pow((1-p_t), gamma)\n\n        # compute the final loss and return\n        return K.mean(alpha_factor*modulating_factor*bce, axis=-1)\n    return focal_crossentropy","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"opt = Adam(lr=1e-5)\nvgg_conv.compile(loss=focal_loss(), metrics=[tf.keras.metrics.AUC()],optimizer=opt)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"nb_epochs = 2\nbatch_size=8\nnb_train_steps = train.shape[0]//batch_size\nnb_val_steps=validation.shape[0]//batch_size\nprint(\"Number of training and validation steps: {} and {}\".format(nb_train_steps,nb_val_steps))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cb = [PlotLossesKeras()]\nvgg_conv.fit_generator(\n    train_generator,\n    steps_per_epoch=nb_train_steps,\n    epochs=nb_epochs,\n    validation_data=validation_generator,\n    callbacks=cb,\n    validation_steps=nb_val_steps)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Submission","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"target=[]\nfor path in df_test['images']:\n    img=cv2.imread(str(path))\n    img = cv2.resize(img, (224,224))\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    img = img.astype(np.float32)/255.\n    img=np.reshape(img,(1,224,224,3))\n    prediction=vgg_conv.predict(img)\n    target.append(prediction[0][0])\n\nsubmission['target']=target","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.to_csv('submission.csv', index=False)\nsubmission.head()","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}