{"metadata":{"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":11848,"databundleVersionId":862157,"sourceType":"competition"}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true},"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.9.18"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Histopathologic Cancer","metadata":{}},{"cell_type":"markdown","source":"# Import Packages","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nfrom sklearn.model_selection import train_test_split\nimport tifffile as tiff\nimport pickle\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout, BatchNormalization, CenterCrop\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Training DataFrame","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/histopathologic-cancer-detection/train_labels.csv\")\ntrain['id'] = train['id'].apply(lambda x:f'{x}.tif')\nprint(train.shape)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Label Distribution","metadata":{}},{"cell_type":"code","source":"prop_df = pd.DataFrame(train['label'].value_counts()/train['label'].count())\nprop_df","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# View Sample of Images","metadata":{}},{"cell_type":"code","source":"sample_df = train.sample(16)\nimages = []\nlabels = sample_df['label'].to_numpy()\nfindex=0\nlindex=0\nfor row in sample_df['id']:\n    image = tiff.imread('/kaggle/input/histopathologic-cancer-detection/train/'+row)\n    images.append(image)\n\ndataset = tf.data.Dataset.from_tensor_slices((images,labels))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(6, 6))\ni=1\nfor sample in dataset:\n    ax = plt.subplot(4, 4, i)\n    plt.imshow(sample[0].numpy().astype(\"uint8\"),vmin=0,vmax=255)\n    plt.title(sample[1].numpy())\n    plt.axis(\"off\")\n    i=i+1","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Generators","metadata":{}},{"cell_type":"code","source":"train_df, valid_df = train_test_split(train, test_size=0.2, stratify=train['label'], random_state=42)\ntrain_df['label'] = train_df['label'].astype(str)\nvalid_df['label'] = valid_df['label'].astype(str)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.values[0][0]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_gen = ImageDataGenerator(rescale=1/255)\n\nvalid_gen = ImageDataGenerator(rescale=1/255)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 100\n\ntrain_loader = train_gen.flow_from_dataframe(\n    dataframe = train_df,\n    directory = '/kaggle/input/histopathologic-cancer-detection/train/',\n    x_col = 'id',    \n    y_col = 'label',\n    batch_size = BATCH_SIZE,    \n    seed = 1,\n    shuffle = True,\n    class_mode = 'categorical',\n    target_size = (96,96))\n\nvalid_loader = valid_gen.flow_from_dataframe(\n    dataframe = valid_df,    \n    directory = '/kaggle/input/histopathologic-cancer-detection/train/',    \n    x_col = 'id',    \n    y_col = 'label',    \n    batch_size = BATCH_SIZE,    \n    seed = 1,    \n    shuffle = True,   \n    class_mode = 'categorical',    \n    target_size = (96,96))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TR_STEPS = len(train_loader)\nVA_STEPS = len(valid_loader)\n\nprint(TR_STEPS)\nprint(VA_STEPS)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Build Network","metadata":{}},{"cell_type":"code","source":"np.random.seed(1)\ntf.random.set_seed(1)\n\ncnn = Sequential([\n    keras.Input(shape=(96,96,3)),    \n    CenterCrop(32,32,'channels_last'),    \n    \n    Conv2D(32, 3, padding='same', activation='selu'),\n    Dropout(.1),\n    MaxPooling2D(),\n    \n    Conv2D(64, 3, padding='same', activation='selu'),\n    Dropout(.2),\n    MaxPooling2D(),\n    \n    Conv2D(128, 3, padding='same', activation='selu'),\n    Dropout(.25),    \n    MaxPooling2D(),\n    \n    Conv2D(128, 3, padding='same', activation='selu'),    \n    Dropout(.3),    \n    MaxPooling2D(),  \n    \n    Conv2D(64, 3, padding='same', activation='selu'),    \n    Dropout(.25), \n    \n    Flatten(),    \n    Dense(32, activation='selu'),    \n    Dense(len(prop_df), activation='sigmoid') \n])\n\ncnn.summary()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train Network","metadata":{}},{"cell_type":"code","source":"myopt = keras.optimizers.Nadam(learning_rate=.001)\ncnn.compile(optimizer=myopt,loss='categorical_crossentropy', metrics=['accuracy'])\nruns=0","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nearly_stopping = EarlyStopping(    \n    monitor='val_accuracy',     \n    patience=5,    \n    min_delta=0.001,   \n    mode='max')\n\nhistory = cnn.fit( \n    train_loader, \n    validation_data=valid_loader,  \n    epochs=5, \n    verbose = 1, \n    callbacks=[early_stopping])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"h1 = pd.DataFrame(history.history)\nh1ep = history.epoch\ntf.keras.backend.set_value(cnn.optimizer.learning_rate.value,.0001)\nhistory2 = cnn.fit(  train_loader,  validation_data=valid_loader,  epochs=20,  verbose = 1,  callbacks=[early_stopping])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history2.epoch = [x+history.epoch[-1] for x in history2.epoch]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\ntrain_history = pd.concat([h1,pd.DataFrame(history2.history)])\n\ntrain_history['epoch'] = pd.DataFrame(h1ep+history2.epoch)\n\nsns.lineplot(x='epoch', y ='accuracy', data =train_history)\nsns.lineplot(x='epoch', y ='val_accuracy', data =train_history)\nplt.legend(labels=['train_accuracy', 'val_accuracy'])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Save Model and History","metadata":{}},{"cell_type":"code","source":"with open('train_history.pkl', 'wb') as file:    \n    pickle.dump(train_history, file)\n    \ncnn.save('cnn_model.h5')","metadata":{},"execution_count":null,"outputs":[]}]}