{"cells":[{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"#-------Import Dependencies-------#\nimport pandas as pd\nimport os,shutil,math\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfrom sklearn.utils import shuffle\nfrom sklearn.metrics import classification_report\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix,roc_curve,auc\n\nfrom PIL import Image\nfrom PIL import ImageDraw\nfrom glob import glob\nfrom tqdm import tqdm\nfrom skimage.io import imread\nfrom IPython.display import SVG\n\nfrom keras.utils.vis_utils import model_to_dot\nfrom keras.applications.vgg19 import VGG19,preprocess_input\nfrom keras.applications.xception import Xception\nfrom keras.applications.nasnet import NASNetMobile\nfrom keras.models import Sequential,Input,Model\nfrom keras.layers import Dense,Flatten,Dropout,Concatenate,GlobalAveragePooling2D\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.optimizers import Adam,SGD\nfrom keras.utils.vis_utils import plot_model\nfrom keras.callbacks import ModelCheckpoint,EarlyStopping,TensorBoard,CSVLogger,ReduceLROnPlateau,LearningRateScheduler","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"34ec65cfa4ddef229302e5d067324143ed5094f9"},"cell_type":"code","source":"#-----In case you want to use a learning rate scheduler from keras this is a good step decay function to play around with-----#\ndef step_decay(epoch):\n    initial_lrate=0.1\n    drop=0.6\n    epochs_drop = 3.0\n    lrate= initial_lrate * math.pow(drop,math.floor((1+epoch)/epochs_drop))\n    return lrate","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"2c8d8745d66af1e77e5e8a4648d3f5d3c7ab2d57"},"cell_type":"code","source":"#----Custom function to visualize the training of the model------#\ndef show_final_history(history):\n    fig, ax = plt.subplots(1, 2, figsize=(15,5))\n    ax[0].set_title('loss')\n    ax[0].plot(history.epoch, history.history[\"loss\"], label=\"Train loss\")\n    ax[0].plot(history.epoch, history.history[\"val_loss\"], label=\"Validation loss\")\n    ax[1].set_title('acc')\n    ax[1].plot(history.epoch, history.history[\"acc\"], label=\"Train acc\")\n    ax[1].plot(history.epoch, history.history[\"val_acc\"], label=\"Validation acc\")\n    ax[0].legend()\n    ax[1].legend()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2914bdc95d3cc38fcf4669456c168a650a23fa36"},"cell_type":"code","source":"TRAINING_LOGS_FILE = \"training_logs.csv\"\nMODEL_SUMMARY_FILE = \"model_summary.txt\"\nMODEL_FILE = \"histopathologic_cancer_detector.h5\"\nTRAINING_PLOT_FILE = \"training.png\"\nVALIDATION_PLOT_FILE = \"validation.png\"\nROC_PLOT_FILE = \"roc.png\"\nKAGGLE_SUBMISSION_FILE = \"kaggle_submission.csv\"\nINPUT_DIR = '../input/'\nSAMPLE_COUNT = 60000\nTESTING_BATCH_SIZE = 5000","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1fa1b8b5c7947cf89f737ba9267fa74fbb63b315"},"cell_type":"code","source":"training_dir = INPUT_DIR + 'train/'\n\ndf = pd.DataFrame({'path': glob(os.path.join(training_dir,'*.tif'))})\n\ndf['id'] = df.path.map(lambda x: x.split('/')[3].split('.')[0])\n\nlabels = pd.read_csv(INPUT_DIR + 'train_labels.csv')\n\ndf = df.merge(labels,on='id')\n\nnegative_values = df[df.label == 0].sample(SAMPLE_COUNT)\npositive_values = df[df.label == 1].sample(SAMPLE_COUNT)\n\ndf = pd.concat([negative_values,positive_values]).reset_index()\n\ndf = df[['path','id','label']]\ndf['image'] = df['path'].map(imread)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bd00eda3d6a914c1bcb4bf5fc8e8225d4cd6274c"},"cell_type":"code","source":"train_path = '../training'\nval_path = '../validation'\n\nfor directory in [train_path,val_path]:\n    for sub_directory in ['0','1']:\n        path = os.path.join(directory,sub_directory)\n        os.makedirs(path,exist_ok=True)\n        \ntrain,val = train_test_split(df,train_size=0.8,stratify=df['label'])\ndf.set_index('id',inplace=True)\n\nfor images_paths in [(train,train_path),(val,val_path)]:\n    images = images_paths[0]\n    path = images_paths[1]\n    for image in images['id'].values:\n        file_name = image + '.tif'\n        label = str(df.loc[image,'label'])\n        destination = os.path.join(path,label,file_name)\n        if not os.path.exists(destination):\n            source = os.path.join(INPUT_DIR + 'train',file_name)\n            shutil.copyfile(source,destination)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"be4dc5bcd985b336695853c147ac9d62aad2fe4a"},"cell_type":"code","source":"#------Generators------------#\ntrain_augs = ImageDataGenerator(\n    rescale=1./255,\n    horizontal_flip=True,\n    vertical_flip=True,\n    rotation_range=90,\n    zoom_range=0.2, \n    width_shift_range=0.1,\n    height_shift_range=0.1,\n    shear_range=0.05,\n    channel_shift_range=0.1\n)\n\n\nval_augs = ImageDataGenerator(rescale=1./255)\n\ntrain_gen = train_augs.flow_from_directory(\n    train_path,\n    target_size=(96,96),\n    batch_size=10,\n    class_mode='binary')\n\nval_gen = val_augs.flow_from_directory(\n    val_path,\n    target_size=(96,96),\n    batch_size=10,\n    class_mode='binary')\nprint(train_gen.class_indices)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"206e3ec4ae5f54320dd03c6fa8761f47ffb563f2"},"cell_type":"code","source":"base_model = VGG19(include_top=False,\n                  input_shape = (96,96,3),\n                  weights = 'imagenet')\n\nfor layer in base_model.layers[:-15]:\n    layer.trainable = False\n    \nfor layer in base_model.layers:\n    print(layer,layer.trainable)\n\nmodel = Sequential()\nmodel.add(base_model)\nmodel.add(Flatten())\nmodel.add(Dense(1024,activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(1,activation='sigmoid'))\nmodel.summary()\n\nSVG(model_to_dot(model).create(prog='dot', format='svg'))\nplot_model(model, to_file='model_plot.png', show_shapes=True, show_layer_names=True, expand_nested=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dab0c15897d01047dc8776d4a6daf5fb056d65f6"},"cell_type":"code","source":"#-------Callbacks-------------#\ncheckpoint = ModelCheckpoint(\n    './base.model',\n    monitor='val_loss',\n    verbose=1,\n    save_best_only=True,\n    mode='min',\n    save_weights_only=False,\n    period=1\n)\nearlystop = EarlyStopping(\n    monitor='val_loss',\n    min_delta=0.001,\n    patience=10,\n    verbose=1,\n    mode='auto'\n)\ntensorboard = TensorBoard(\n    log_dir = './logs',\n    histogram_freq=0,\n    batch_size=16,\n    write_graph=True,\n    write_grads=True,\n    write_images=False,\n)\n\ncsvlogger = CSVLogger(\n    filename= \"training_csv.log\",\n    separator = \",\",\n    append = False\n)\n\n#lrsched = LearningRateScheduler(step_decay,verbose=1)\n\nreduce = ReduceLROnPlateau(\n    monitor='val_loss',\n    factor=0.3,\n    patience=2,\n    verbose=1, \n    mode='auto',\n    cooldown=1 \n)\n\ncallbacks = [checkpoint,tensorboard,csvlogger,reduce]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"575ff7e88addfca076d524b845d7ce4851325923"},"cell_type":"code","source":"#------------Train The Model----------#\n#-------Use SGD with momentum and play with the learning rate and momentum----------#\n#------Good Momentum values: 0.9,0.99,0.5----------#\nopt = SGD(lr=1e-4,momentum=0.99)\nopt1 = Adam(lr=2e-4)\n\nmodel.compile(\n    loss='binary_crossentropy',\n    optimizer=opt,\n    metrics=['accuracy']\n)\n    \nhistory = model.fit_generator(\n    train_gen, \n    steps_per_epoch  = 2000, \n    validation_data  = val_gen,\n    validation_steps = 2000,\n    epochs = 30, \n    verbose = 1,\n    callbacks=callbacks\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"92c8ecbf0c80a5be3b41bbbf3210d94d8c832a42"},"cell_type":"code","source":"show_final_history(history)\nprint(\"Validation Accuracy: \" + str(history.history['val_acc'][-1:]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"838074682657d960e42feba3f945d38a8d03472d"},"cell_type":"code","source":"roc_validation_generator = ImageDataGenerator(rescale=1./255).flow_from_directory(val_path,\n                                                                                  target_size=(96,96),\n                                                                                  batch_size=10,\n                                                                                  class_mode='binary',\n                                                                                  shuffle=False)\npredictions = model.predict_generator(roc_validation_generator, steps=len(roc_validation_generator), verbose=1)\nfalse_positive_rate, true_positive_rate, threshold = roc_curve(roc_validation_generator.classes, predictions)\narea_under_curve = auc(false_positive_rate, true_positive_rate)\n\nplt.plot([0, 1], [0, 1], 'k--')\nplt.plot(false_positive_rate, true_positive_rate, label='AUC = {:.3f}'.format(area_under_curve))\nplt.xlabel('False positive rate')\nplt.ylabel('True positive rate')\nplt.title('ROC curve')\nplt.legend(loc='best')\nplt.savefig(ROC_PLOT_FILE, bbox_inches='tight')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"665b87ded2d2bfc2f01ec992f64d8a3bd952bc97"},"cell_type":"code","source":"testing_files = glob(os.path.join(INPUT_DIR+'test/','*.tif'))\nsubmission = pd.DataFrame()\nfor index in range(0, len(testing_files), TESTING_BATCH_SIZE):\n    data_frame = pd.DataFrame({'path': testing_files[index:index+TESTING_BATCH_SIZE]})\n    data_frame['id'] = data_frame.path.map(lambda x: x.split('/')[3].split(\".\")[0])\n    data_frame['image'] = data_frame['path'].map(imread)\n    images = np.stack(data_frame.image, axis=0)\n    predicted_labels = [model.predict(np.expand_dims(image/255.0, axis=0))[0][0] for image in images]\n    predictions = np.array(predicted_labels)\n    data_frame['label'] = predictions\n    submission = pd.concat([submission, data_frame[[\"id\", \"label\"]]])\nsubmission.to_csv(KAGGLE_SUBMISSION_FILE, index=False, header=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f70af50009579233fbc8eea65ce7a9e1751a0564"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}