{"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 os\nimport gc\nimport cv2\nimport tensorflow as tf\nimport seaborn as sn\nimport matplotlib.pyplot as plt\nimport keras\nfrom keras.layers import *\nfrom keras.models import Model\nfrom keras.utils import plot_model\nfrom keras.applications.resnet_v2 import ResNet50V2\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\n\n\nprint(tf.__version__)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"training = pd.read_csv('../input/siim-isic-melanoma-classification/train.csv')\nprint(training.head(10))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(training[\"target\"].value_counts())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We take a very small sample of the benign data to balance out the malignant data.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"m = training[training[\"target\"]==1]\nb = training[training[\"target\"]==0].sample(3000)\ndf = pd.concat([m,b])        \ndf.reset_index(inplace=True)\ndf.drop(labels=[\"index\", \"patient_id\", \"sex\", \"age_approx\", \"anatom_site_general_challenge\", \"diagnosis\", \"benign_malignant\"], axis=1, inplace=True)\ndf[\"image_name\"] = \"../input/images-siim-512x512/train/train_512x512/\" + df[\"image_name\"].astype(str) + \".jpg\"\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"imgs = []\nlabels = []\nfor index, row in tqdm(df.iterrows()):\n    img = cv2.imread(str(row[\"image_name\"]))\n    img = cv2.resize(img, (300,300))\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    imgs.append(img)\n    labels.append(row[\"target\"])\nimgs = np.array(imgs)\nlabels = np.array(labels)\nprint(imgs.shape)\nprint(labels.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with open(\"res_imgs4k.npz\", \"wb\") as file:\n    np.savez_compressed(file, images=imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with open(\"./res_imgs4k.npz\", \"rb\") as file:\n    imgs = np.load(file)[\"images\"]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Note that we set the random_state in the train-test split as 888. This means the model will be very lucky.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"labels = np.concatenate([np.full(584,1),np.full(3000,0)])\nprint(imgs.shape)\nprint(labels.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainX, valX, trainY, valY = train_test_split(imgs, labels, test_size=0.2, random_state=888)\nplt.imshow(trainX[0])\ndel imgs, labels\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# trainX, valX, trainY, valY = train_test_split(\n#     df[\"image_name\"], \n#     df[\"target\"],\n#     test_size = 0.2, \n#     random_state = 888\n# )\n# train = list(zip(trainX, trainY))\n# train = pd.DataFrame(train, columns = [\"images\", \"target\"])\n# val = list(zip(valX, valY))\n# val = pd.DataFrame(val, columns = [\"images\", \"target\"])\n\n# train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_aug = ImageDataGenerator(rescale=1./255,\n                     rotation_range=80,\n                     width_shift_range=0.25, \n                     height_shift_range=0.25,\n                     shear_range=0.2,\n                     horizontal_flip=True,\n                     vertical_flip=True)\n\nval_aug = ImageDataGenerator(rescale=1./255)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_gen = train_aug.flow(trainX, trainY, batch_size = 12, shuffle = True)\nval_gen = val_aug.flow(valX, valY, batch_size = 12, shuffle = False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Flow from dataframe reads in images from disk given the filepaths (stored under column \"images\").","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# train_gen = train_aug.flow_from_dataframe(train, x_col=\"images\", y_col=\"target\", batch_size = 8, target_size=(224,224),shuffle = True, class_mode=\"raw\")\n# val_gen = val_aug.flow_from_dataframe(val, x_col=\"images\", y_col=\"target\", batch_size = 8, target_size=(224,224),shuffle = False, class_mode=\"raw\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nearly_stop = EarlyStopping(monitor='val_loss', patience=2)\ncheckpoint = ModelCheckpoint(\"{val_loss:.2f}-{epoch:02d}.hdf5\",monitor = 'val_loss',verbose = 1,save_best_only = True,mode = 'min')\n\ncallbacks = [early_stop, checkpoint]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"optimizer = keras.optimizers.Adam(lr=1e-3)\nauc = keras.metrics.AUC()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"ResNet with our own top layer. ResNet is frozen.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install git+https://github.com/qubvel/efficientnet","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import efficientnet.keras as efn ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet = efn.EfficientNetB3(\n    include_top=True,\n    weights=\"imagenet\",\n    input_shape=(300,300,3)\n)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"effnet.trainable=False\nflat = Flatten()(effnet.output)\n# gap = GlobalAveragePooling2D()(resnet.output)\nfinal = Dropout(0.2)(flat)\nfinal = Dense(256, activation='relu', kernel_regularizer=keras.regularizers.l2(0.001))(final)\nfinal = Dropout(0.2)(final)\nfinal = Dense(1, activation=\"sigmoid\")(final)\nmodel = Model(effnet.input,final)\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss=\"binary_crossentropy\", metrics=[\"accuracy\"], optimizer=\"adam\")\n\nhistory = model.fit_generator(\n    train_gen,\n    steps_per_epoch = trainX.shape[0] // 12,\n    epochs = 3, \n    validation_data = val_gen,\n    validation_steps = valX.shape[0] // 12\n)\n\n# model.save('resnet2.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer in effnet.layers[120:]:\n   layer.trainable = True\nfor i, layer in enumerate(effnet.layers):\n   print(i, layer.name, layer.trainable)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"opt = keras.optimizers.Adamax(learning_rate=1e-3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss=\"binary_crossentropy\", metrics=[\"accuracy\"], optimizer=opt)\n\nhistory = model.fit_generator(\n    train_gen,\n    steps_per_epoch = trainX.shape[0] // 12,\n    epochs = 5, \n    validation_data = val_gen,\n    validation_steps = valX.shape[0] // 12,\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(\n    train_gen,\n    steps_per_epoch = trainX.shape[0] // 12,\n    epochs = 10, \n    validation_data = val_gen,\n    validation_steps = valX.shape[0] // 12,\n    callbacks = callbacks\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hist = pd.DataFrame(history.history)\nhist['epoch'] = history.epoch\n\nplt.figure()\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.plot(hist['epoch'], hist['loss'], label='Train Error')\nplt.plot(hist['epoch'], hist['val_loss'], label='Val Error')\nplt.ylim([0, 0.5])\nplt.legend()\n\nplt.figure()\nplt.xlabel('Epoch')\nplt.ylabel('accuracy')\nplt.plot(hist['epoch'], hist['accuracy'], label='Train Acc')\nplt.plot(hist['epoch'], hist['val_accuracy'], label='Val Acc')\nplt.ylim([0, 1])\nplt.legend()\nplt.show()","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}