{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# !pip uninstall pandas-profiling\n# !pip install pandas-profiling[notebook,html]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd # used for data analysis => library for manipulating Dataframes and Series (advanced data holding structures)\nimport numpy as np #library for manipulating arrays contains array data and basic operations such as sorting, indexing)\nimport sklearn #widely used machine learning library\nfrom pandas_profiling import ProfileReport #one-stop-shop tool for data summarization and visualization (aka Exploratory Data Analysis or EDA) https://pandas-profiling.github.io/pandas-profiling/docs/master/index.html\nimport matplotlib.pyplot as plt #Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations in Python. \nimport seaborn as sns # ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Problem Statement**\n\n—Breast cancer is one of the most common causes of death in women worldwide. Upon that, it is the most common form of cancer in women. Clearly, breast cancer is a global issue. Research tells us that early detection and early treatement is vital because it greatly increases survival rates\n\n- The tumors that cause breast cancer can be subdivided into malignant (cancerous) and benign (noncancerous) types, based on a variety of cell characteristics. Therefore, being able to differentiate the two types of tumors is key to early detection. Many health care operations leave their patients waiting for long periods of time before getting a result (often times innacurate). This flaw is why breast cancer is the most common cause of death in women worldwide\n\n- I have set up a pathway for a different option, one that could drastically increases surivial rates. I created a model that can provide automatic breast cancer predictions. I believe this method is an improvement because it can give early diagnosis to patients with precision and accuracy","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# **Dataset**\n\n* **Histopathologic-Cancer-Detection**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"data = pd.read_csv('/kaggle/input/histopathologic-cancer-detection/train_labels.csv')\n\nprint(data.shape) # number of rows and columns\nprint('-'*125)\ndata.head(5) #","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data.sample(5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Exploratory Data Analysis**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"data.describe()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Data Cleaning**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data Cleansing: dropping the highly correlated features discovered in the data profile report\ndata_trim = data.drop(labels =['id'], axis = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(data.shape)\nprint(data_trim.shape)\ndata_trim.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Feature Engineering/Selection**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#Data Trimming - splitting the variables into target and predictor\ny = data_trim['label']\nprint(y.sample(5))\n\nX = data_trim.drop(labels = 'label', axis = 1)\nprint(X.sample(5))\n\ntype(y)\nX.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\n# encode class values as integers\nprint(\"Before encoding: \")\nprint(y[100:110]) \n\nlabelencoder_X_1 = LabelEncoder()\ny = labelencoder_X_1.fit_transform(y)\n\nprint(\"\\nAfter encoding: \")\nprint(y[100:110])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Keras**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential, model_from_json\nfrom keras.layers import Conv2D, MaxPooling2D, MaxPool2D, Dropout, Activation, Flatten, Dense\nfrom keras.optimizers import Adam\nfrom keras import backend as k\nimport tensorflow as tf","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore', category= DeprecationWarning)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Data Preprocessing**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"img_width, img_height = 224, 224\nimg_size = (224, 224)\n\n# saving the directory/folder location for training and validation image folders to variables\ntrain_data_dir = '../input/histopathologic-cancer-detection'\ntest_data_dir = '../input/histopathologic-cancer-detection'\n\n# Saving the batch_size and epochs for training to variables\nbatch_size = 32 #usually in powers of 2 - 8, 16, 32, 64, 128\nepochs = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1./255, #normalization\n                                   validation_split=0.2,\n                                   shear_range = 0.2, # extent of shearing - 20% \n                                   zoom_range = 0.2, # extent of adjusting the zoom in images - 20%\n                                   horizontal_flip= True, # randomly flipping to get mirror images \n                                   rotation_range=0.1)\n                                   \n\n# Validation ImageDataGenerator with rescaling.\n# You should not apply any other transformations to the validation set because it has to reflect real world data\nvalid_datagen = ImageDataGenerator(rescale=1./255, \n                                   validation_split=0.2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = train_datagen.flow_from_directory(train_data_dir, \n                                              subset='training',\n                                              shuffle=True, \n                                              seed=42, \n                                              target_size=img_size,\n                                              batch_size=batch_size,\n                                              class_mode='binary')\n\n# Create a flow from the directory for validation data - seed=42\nvalidation_generator = valid_datagen.flow_from_directory(train_data_dir, \n                                              subset='validation',\n                                              seed=42, \n                                              target_size=img_size,\n                                              batch_size = batch_size,\n                                              class_mode='binary')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if k.image_data_format() == \"channels_first\":\n    input_shape = (3, img_width, img_height)\nelse:\n    input_shape = (img_width, img_height, 3)\n    \ninput_shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Convolutional Net**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.optimizers import RMSprop\nmodel = tf.keras.models.Sequential([\n    # First Convolution\n    tf.keras.layers.Conv2D(16, (3, 3), activation='relu', input_shape=input_shape),\n    tf.keras.layers.MaxPooling2D(2, 2),\n    # Second Convolution\n    tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),\n    tf.keras.layers.MaxPooling2D(2, 2),\n    # Third Convolution\n    tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),\n    tf.keras.layers.MaxPooling2D(2, 2),\n    # Flatten\n    tf.keras.layers.Flatten(),\n    # Dense layer\n    tf.keras.layers.Dense(512, activation='relu'),\n    tf.keras.layers.Dense(1, activation='sigmoid')\n])\n\nmodel.compile(\n    loss='binary_crossentropy',\n    optimizer=Adam(lr=0.001),\n    metrics=['accuracy']\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(train_generator,epochs = epochs,\n                             validation_data= validation_generator)\n\n# Writing the model to a JSON file\nmodel_json = model.to_json()\nwith open(\"model.json\", \"w\") as json_file:\n    json_file.write(model_json)\n\n# serialize weights to HDF5\nmodel.save_weights(\"model.h5\")\nprint(\"Saved model to disk\")\n\n# save model and architecture to single file\nmodel.save(\"full_model.h5\")\nprint(\"Saved full model to disk\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(history.history.keys()) # prints what the history has stored (stored in a dictionary format (key-value pairs))\n\n# summarize history for accuracy on a line chart\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'valid'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'validation'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Evaluate Model Performance**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"json_file = open('model.json', 'r')\nloaded_model_json = json_file.read()\njson_file.close()\nloaded_model = model_from_json(loaded_model_json)\n# load weights into new model\nloaded_model.load_weights(\"model.h5\")\nprint(\"Loaded model from disk\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import load_model #to load the model saved as a h5 file\n# load model\nfull_model = load_model('full_model.h5')\n# summarize model.\nfull_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prints out the model loss and accuracy\nmodel.evaluate_generator(validation_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# load test dataset\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\n# Create a flow from the directory for validation data - seed=42\ntest_generator = test_datagen.flow_from_directory(test_data_dir,  \n                                              target_size=img_size,\n                                              batch_size = batch_size,\n                                              class_mode='binary')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prints out the model loss and accuracy\nmodel.evaluate_generator(test_generator)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Transfer Learning**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.optimizers import RMSprop\ntf.keras.applications.NASNetLarge(\n    input_shape=None,\n    include_top=True,\n    weights=\"imagenet\",\n    input_tensor=None,\n    pooling=None,\n    classes=1000,\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.applications.resnet import ResNet50\nfrom keras.applications.vgg16 import VGG16\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3\n\nfrom keras.models import Sequential, Model,\n# loading the pretrained model\nvgg_pre_trained_model = VGG16(input_shape = input_shape, \n                                include_top = False, \n                                weights = 'imagenet')\n\n# inception_pre_trained_model = InceptionV3(input_shape = input_shape, \n# #                                 include_top = False, \n# #                                 weights = 'imagenet')\n\n# resnet_pre_trained_model = ResNet50(input_shape = input_shape, \n# #                                 include_top = False, \n# #                                 weights = 'imagenet')\n\n# freezing parameters in convolutional layers\nfor layer in pre_trained_model.layers:\n    layer.trainable = False\n\npre_trained_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def build_my_model(model_name):\n \n    new_model = Sequential()\n    model = vgg_pre_trained_model\n    # Add the convolutional part of the VGG16 model from above.\n    new_model.add(model)\n    # Create a custom classifier \n    new_model.add(Flatten())\n    new_model.add(Dense(1024, activation='relu'))\n    new_model.add(Dropout(0.5))\n    new_model.add(Dense(512, activation='relu'))\n    new_model.add(Dropout(0.5))\n    new_model.add(Dense(256, activation='relu'))\n    new_model.add(Dropout(0.5))\n    new_model.add(Dense(1, activation='sigmoid'))\n    \n    return new_model\n# building vggnet model\nmy_vgg_model = build_my_model(vgg_pre_trained_model)\n\n# building resnet model\nmy_resnet_model = build_my_model(resnet_pre_trained_model)\n\n\nmy_vgg_model.summary()\n\nmy_model = my_vgg_model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.callbacks import ModelCheckpoint, EarlyStopping\n\n## Set our optimizer, loss function, and learning rate\noptimizer = Adam(lr=1e-3) # RMSprop(learning_rate=1e-4)\nloss = 'binary_crossentropy'\nmetrics = ['accuracy']\n\nweight_path=\"{}_my_model.bestv.hdf5\".format('class')\n\n# save the weights of the best model during training\ncheckpoint = ModelCheckpoint(weight_path, \n                             monitor= 'val_loss', \n                             verbose=1, \n                             save_best_only=True, \n                             mode= 'auto', \n                             save_weights_only = True)\n\n# if results have not improved after a certain number of epochs, stop training.\nearly = EarlyStopping(monitor= 'val_loss', \n                      mode= 'auto', \n                      patience=10)\n\ncallbacks_list = [checkpoint, early]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"my_model.compile(optimizer=optimizer, loss=loss, metrics=metrics)\n\n# my_model.load_weights(weight_path)\n# Saving the history of training epochs and associated metrics to a variable (history) \nhistory = my_model.fit(train_generator, \n                          validation_data = validation_generator, \n                          epochs = 1 , \n                          callbacks = callbacks_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(history.history.keys()) # prints what the history has stored (stored in a dictionary format (key-value pairs))\n\n# summarize history for accuracy on a line chart\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'valid'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# summarize history for loss on a line chart\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'validation'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Evaluate Performance on Test Set**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# load test dataset\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\n# Create a flow from the directory for validation data - seed=42\ntest_generator = test_datagen.flow_from_directory(test_data_dir,  \n                                              target_size=img_size,\n                                              batch_size = batch_size,\n                                              class_mode='binary')\n\nmy_model.evaluate(test_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test_data = []\n# test_labels = []\n# batch_index = 0\n\n# while batch_index <= test_generator.batch_index:\n#     data = next(test_generator)\n#     test_data.append(data[0])\n#     test_labels.append(data[1])\n#     batch_index = batch_index + 1\n\n# test_data_array = np.asarray(test_data)\n# test_labels_array = np.asarray(test_labels)\n# y_true = test_labels_array\n\n# test_data_array.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_true = test_generator.classes\n\n# Get prediction probabilities from model\nprobabilities = my_model.predict(test_generator)\n# Because this is a binary classification problem, you have to find predicted labels\ny_pred = probabilities > 0.5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import accuracy_score,classification_report, confusion_matrix\n\n# Classification report will show us precision, recall and F1 Score of the model\nprint(classification_report(y_true, y_pred))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"accuracy = accuracy_score(y_true, y_pred)\nprint(accuracy)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conf_mat = confusion_matrix(y_true, y_pred)\nprint(conf_mat)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Using Seaborn to display Confusion Matrix Beautifully\n# Transform to df for easier plotting\n\ncm_df = pd.DataFrame(conf_mat,\n                     index = ['M','B'], \n                     columns = ['M','B'])\n\nplt.figure(figsize=(8,6))\nsns.heatmap(cm_df, annot=True)\nplt.title('Dogs and Cats Classificaiton Confusion Matrx\\n CNN')\nplt.ylabel('True label')\nplt.xlabel('Predicted label')\n# plt.figtext(1.30, 0.01, 'Accuracy: {}%\\n Sensitivity: {}\\n Specificity: {} '.format(round(svc_accuracy, 2),round(sensitivity, 2),round(specificity, 2)), horizontalalignment='right')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# **Dispaly Results**","execution_count":null},{"metadata":{},"cell_type":"raw","source":"","execution_count":null}],"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}