{"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_minor":4,"nbformat":4,"cells":[{"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)\n\nimport cv2\nimport keras\nimport tensorflow as tf\n\nfrom keras_preprocessing.image import ImageDataGenerator\nfrom keras.layers import Dense, Activation, Flatten, Dropout, BatchNormalization\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras import regularizers, optimizers\nfrom sklearn.utils import class_weight\nimport os","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:32.040808Z","iopub.execute_input":"2022-11-28T10:47:32.041246Z","iopub.status.idle":"2022-11-28T10:47:37.626856Z","shell.execute_reply.started":"2022-11-28T10:47:32.041165Z","shell.execute_reply":"2022-11-28T10:47:37.625411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ntf.test.is_gpu_available()","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:37.629000Z","iopub.execute_input":"2022-11-28T10:47:37.629636Z","iopub.status.idle":"2022-11-28T10:47:40.185148Z","shell.execute_reply.started":"2022-11-28T10:47:37.629597Z","shell.execute_reply":"2022-11-28T10:47:40.184134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Understanding train data\ntrain_df=pd.read_csv(r\"/kaggle/input/siim-isic-melanoma-classification/train.csv\")\ntest_df=pd.read_csv(r\"/kaggle/input/siim-isic-melanoma-classification/test.csv\")","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.186604Z","iopub.execute_input":"2022-11-28T10:47:40.186915Z","iopub.status.idle":"2022-11-28T10:47:40.300937Z","shell.execute_reply.started":"2022-11-28T10:47:40.186890Z","shell.execute_reply":"2022-11-28T10:47:40.300027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['target'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.303335Z","iopub.execute_input":"2022-11-28T10:47:40.303610Z","iopub.status.idle":"2022-11-28T10:47:40.318431Z","shell.execute_reply.started":"2022-11-28T10:47:40.303585Z","shell.execute_reply":"2022-11-28T10:47:40.317303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['target'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.320173Z","iopub.execute_input":"2022-11-28T10:47:40.320815Z","iopub.status.idle":"2022-11-28T10:47:40.331097Z","shell.execute_reply.started":"2022-11-28T10:47:40.320780Z","shell.execute_reply":"2022-11-28T10:47:40.330126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain,validation,train_y,validation_y=train_test_split(train_df.iloc[:,[0,-1]],train_df.loc[:,[\"target\"]],test_size=0.20,random_state=42,stratify=train_df.loc[:,'target'])\n","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.334242Z","iopub.execute_input":"2022-11-28T10:47:40.334496Z","iopub.status.idle":"2022-11-28T10:47:40.422034Z","shell.execute_reply.started":"2022-11-28T10:47:40.334474Z","shell.execute_reply":"2022-11-28T10:47:40.421088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# n = 2\n# train=train.head(int(len(train)*(n/100)))\n# validation=validation.head(int(len(validation)*(n/100)))","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.423467Z","iopub.execute_input":"2022-11-28T10:47:40.423890Z","iopub.status.idle":"2022-11-28T10:47:40.429012Z","shell.execute_reply.started":"2022-11-28T10:47:40.423853Z","shell.execute_reply":"2022-11-28T10:47:40.428022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_partition={'train':list(train['image_name']),'validation':list(validation['image_name'])}","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.430530Z","iopub.execute_input":"2022-11-28T10:47:40.430941Z","iopub.status.idle":"2022-11-28T10:47:40.441599Z","shell.execute_reply.started":"2022-11-28T10:47:40.430908Z","shell.execute_reply":"2022-11-28T10:47:40.440577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Preparation for Model Training","metadata":{}},{"cell_type":"code","source":"def zoom_at(img, zoom=1, angle=0, coord=None):\n    \n    cy, cx = [ i/2 for i in img.shape[:-1] ] if coord is None else coord[::-1]\n    \n    rot_mat = cv2.getRotationMatrix2D((cx,cy), angle, zoom)\n    result = cv2.warpAffine(img, rot_mat, img.shape[1::-1], flags=cv2.INTER_LINEAR)\n    \n    return result","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.443625Z","iopub.execute_input":"2022-11-28T10:47:40.444220Z","iopub.status.idle":"2022-11-28T10:47:40.452167Z","shell.execute_reply.started":"2022-11-28T10:47:40.444185Z","shell.execute_reply":"2022-11-28T10:47:40.451265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def image_preprocessing(animage):\n\n#     animage=cv2.imread(path)\n    animage = cv2.resize(animage, (256,256))\n    # animage=animage.astype(np.uint8)\n    animage = cv2.cvtColor(animage, cv2.COLOR_BGR2RGB)\n\n    kernel = np.ones((2,2), np.uint8)\n    # animage = cv2.dilate(animage, kernel, iterations=1)\n    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(256,256))\n    animage[:, :, 0] = clahe.apply(animage[:, :, 0])\n    # animage = cv2.medianBlur(animage, 5)\n    animage=cv2.addWeighted (animage,4, cv2.GaussianBlur( animage , (0,0) , 256/10) ,-4 ,128)\n    # animage = cv2.dilate(animage, kernel, iterations=1)\n\n    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(256,256))\n    animage[:, :, 0] = clahe.apply(animage[:, :, 0])\n    animage=zoom_at(animage, zoom=1.1, angle=0, coord=None)\n    animage = tf.convert_to_tensor(animage, dtype=tf.float32)\n    \n    return animage","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.458127Z","iopub.execute_input":"2022-11-28T10:47:40.458433Z","iopub.status.idle":"2022-11-28T10:47:40.466903Z","shell.execute_reply.started":"2022-11-28T10:47:40.458381Z","shell.execute_reply":"2022-11-28T10:47:40.465894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Building DataGenerator","metadata":{}},{"cell_type":"code","source":"class DataGenerator(keras.utils.all_utils.Sequence):\n    \"\"\"Generates data for Keras\"\"\"\n    def __init__(self, list_IDs, labels, batch_size=32, dim=(256,256), n_channels=3,\n                n_classes=2, shuffle=True):\n                self.dim = dim\n                self.batch_size = batch_size\n                self.labels = labels\n                self.list_IDs = list_IDs\n                self.n_channels = n_channels\n                self.n_classes = n_classes\n                self.shuffle = shuffle\n                self.size=len(list_IDs)\n                self.on_epoch_end()\n\n    def __len__(self):\n        return int(np.floor(len(self.list_IDs) / self.batch_size))\n\n    def __getitem__(self, index):\n\n        # Generate indexes of the batch\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n\n        # Find list of IDs\n        list_IDs_temp = [self.list_IDs[k] for k in indexes]\n\n        # Generate data\n        X, y = self.__data_generation(list_IDs_temp)\n\n        return X, y\n\n    def on_epoch_end(self):\n        self.indexes = np.arange(len(self.list_IDs))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __data_generation(self, list_IDs_temp):\n     # X : (n_samples, *dim, n_channels)\n    # Initialization\n        X = np.empty((self.batch_size, *self.dim, self.n_channels))\n        y = np.empty((self.batch_size), dtype=int)\n\n        # Generate data\n        for i, ID in enumerate(list_IDs_temp):            \n            # Store sample\n            path=os.path.join(r'/kaggle/input/siim-isic-melanoma-classification/jpeg/train',ID+ \".jpg\")\n            image = tf.keras.preprocessing.image.load_img(path)\n            image_arr = tf.keras.preprocessing.image.img_to_array(image,dtype=np.uint8)\n            image_arr=image_preprocessing(image_arr)\n            \n            \n            X[i]=image_arr\n\n            # Store class\n            y[i] = self.labels[ID]\n        X=tf.convert_to_tensor(X, dtype=tf.float32)\n        y=tf.convert_to_tensor(y, dtype=tf.float32)\n        return X, y","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.468515Z","iopub.execute_input":"2022-11-28T10:47:40.468883Z","iopub.status.idle":"2022-11-28T10:47:40.484113Z","shell.execute_reply.started":"2022-11-28T10:47:40.468850Z","shell.execute_reply":"2022-11-28T10:47:40.483204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Defining Model","metadata":{}},{"cell_type":"code","source":"base_model = tf.keras.applications.EfficientNetB0(include_top=False,weights='imagenet')\n\nbase_model.trainable = True\n\n# Freeze all layers except for the last 5\nfor layer in base_model.layers[:-5]:\n    layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:40.485863Z","iopub.execute_input":"2022-11-28T10:47:40.486187Z","iopub.status.idle":"2022-11-28T10:47:42.823297Z","shell.execute_reply.started":"2022-11-28T10:47:40.486163Z","shell.execute_reply":"2022-11-28T10:47:42.822335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs = tf.keras.layers.Input(shape=(256, 256, 3), name=\"input_layer\")\n# print(f\"Shape after base_model: {x.shape}\")\nx=base_model(inputs)\n# 6. Average pool the outputs of the base model (aggregate all the most important information, reduce number of computations)\nx = tf.keras.layers.GlobalAveragePooling2D(name=\"global_average_pooling_layer\")(x)\n\n# 7. Create the output activation layer\noutputs = tf.keras.layers.Dense(1, activation=\"sigmoid\", name=\"output_layer\")(x)\n\n# 8. Combine the inputs with the outputs into a model\nmodel_0 = tf.keras.Model(inputs, outputs)\n\nmodel_0.compile(loss='binary_crossentropy',\n              optimizer=tf.keras.optimizers.Adam(),\n              metrics=[\"accuracy\"])\n\n# STEP_SIZE_TRAIN=len(train)//32\n\n# STEP_SIZE_VALID=len(validation)//32","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:42.824705Z","iopub.execute_input":"2022-11-28T10:47:42.825110Z","iopub.status.idle":"2022-11-28T10:47:43.567646Z","shell.execute_reply.started":"2022-11-28T10:47:42.825055Z","shell.execute_reply":"2022-11-28T10:47:43.566733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_label=dict(zip(train.image_name,train.target))","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:43.569344Z","iopub.execute_input":"2022-11-28T10:47:43.570008Z","iopub.status.idle":"2022-11-28T10:47:43.589232Z","shell.execute_reply.started":"2022-11-28T10:47:43.569971Z","shell.execute_reply":"2022-11-28T10:47:43.588325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_label=dict(zip(validation.image_name,validation.target))","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:43.590756Z","iopub.execute_input":"2022-11-28T10:47:43.591439Z","iopub.status.idle":"2022-11-28T10:47:43.604748Z","shell.execute_reply.started":"2022-11-28T10:47:43.591403Z","shell.execute_reply":"2022-11-28T10:47:43.603768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters\nparams = {'dim': (256,256),\n          'batch_size': 64,\n          'n_classes': 2,\n          'n_channels': 3,\n          'shuffle': True}\n\n# Datasets\npartition = data_partition\nlabel=dict(zip(train.image_name,train.target))\n\n# Generators\ntraining_generator = DataGenerator(partition['train'],labels=train_label, **params)\nvalidation_generator = DataGenerator(partition['validation'],labels=validation_label, **params)\n","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:43.607129Z","iopub.execute_input":"2022-11-28T10:47:43.608346Z","iopub.status.idle":"2022-11-28T10:47:43.629988Z","shell.execute_reply.started":"2022-11-28T10:47:43.608301Z","shell.execute_reply":"2022-11-28T10:47:43.629122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tf.device('/GPU:0'):\n    history_melanoma=model_0.fit(training_generator,\n                    steps_per_epoch = training_generator.size // training_generator.batch_size,\n                    validation_data=validation_generator,\n                    validation_steps=validation_generator.size // validation_generator.batch_size,\n                    epochs=10\n                    )","metadata":{"execution":{"iopub.status.busy":"2022-11-28T10:47:43.634104Z","iopub.execute_input":"2022-11-28T10:47:43.636347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_0.save(\"Pehla_Model.h5\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(model_0)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.getcwd()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Testing Stage","metadata":{}},{"cell_type":"code","source":"#Loading My Model\n\neff_net_model = keras.models.load_model(\"D:\\Culinda\\Pehla_Model.h5\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def prep_test_image(image_path):\n    image=cv2.imread(image_path)\n    image = cv2.resize(image, (256, 256))\n    image = image.reshape(1, image.shape[0], image.shape[1], image.shape[2])\n    return image","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animage=prep_test_image(r\"D:\\Culinda\\Data\\Melanoma\\train\\ISIC_0232767.jpg\")\na=eff_net_model.predict(animage)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a[0][0]*100","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if a[0][0]>0.5:\n    print('Melanoma')\nelse:\n    print('No Melanoma')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mel_df.iloc[:,0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mel_df=train_df[train_df['target']==1]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_mel_path=r\"D:\\Culinda\\Data\\Melanoma\\train\"\ntrainmel_image_path=[os.path.join(train_mel_path,i+'.jpg') for i in mel_df.iloc[:,0]]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def image_preprocessing(path):\n\n    animage=cv2.imread(path)\n    animage = cv2.resize(animage, (256,256))\n    # animage=animage.astype(np.uint8)\n    animage = cv2.cvtColor(animage, cv2.COLOR_BGR2RGB)\n\n    kernel = np.ones((2,2), np.uint8)\n    # animage = cv2.dilate(animage, kernel, iterations=1)\n    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(256,256))\n    animage[:, :, 0] = clahe.apply(animage[:, :, 0])\n    # animage = cv2.medianBlur(animage, 5)\n    animage=cv2.addWeighted (animage,4, cv2.GaussianBlur( animage , (0,0) , 256/10) ,-4 ,128)\n    # animage = cv2.dilate(animage, kernel, iterations=1)\n\n    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(256,256))\n    animage[:, :, 0] = clahe.apply(animage[:, :, 0])\n    animage=zoom_at(animage, zoom=1.1, angle=0, coord=None)\n    \n    return animage","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_path=r\"D:\\Culinda\\Data\\Melanoma\\test\"\ntest_image_path=[os.path.join(test_path,i+'.jpg') for i in test_df.iloc[:,0]]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image_predict_proba=[]\nfor i in trainmel_image_path:\n    image=image_preprocessing(i)\n    image = image.reshape(1, image.shape[0], image.shape[1], image.shape[2])\n    prediction=eff_net_model.predict(image)\n    train_image_predict_proba.append(prediction)\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"count=0\nfor i in train_image_predict_proba:\n    if i>=0.5:\n        count+=1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"count","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Actual Testing","metadata":{}},{"cell_type":"code","source":"import glob, os\nos.chdir(r\"D:\\Culinda\\Data\\Actual Test\\Skin Image Data Set-1\\skin_data\\melanoma\")\nfor file in glob.glob(\"*.jpg\"):\n    print(file)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.getcwd()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport shutil\n\nsource_path=r\"D:\\Culinda\\Data\\Actual Test\\Skin Image Data Set-2\\skin_data\\notmelanoma\\dermquest\"\ndestination_path=r\"D:\\Culinda\\Data\\Melanoma Model Test\\Non Melanoma\"\nfor file in os.listdir(r\"D:\\Culinda\\Data\\Actual Test\\Skin Image Data Set-2\\skin_data\\notmelanoma\\dermquest\"):\n    if file.endswith(\".jpg\"):\n        image_path=os.path.join(source_path,file)\n        shutil.copy(image_path, destination_path)\n\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nmelanoma_dict={}\nmelanoma_id=list(os.listdir('D:\\Culinda\\Data\\Melanoma Model Test\\Melanoma'))\nmelanoma_dict['image_id']=melanoma_id\nmelanoma_df=pd.DataFrame(melanoma_dict)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"nomelanoma_dict={}\n\nnomelanoma_id=list(os.listdir(r\"D:\\Culinda\\Data\\Melanoma Model Test\\Non Melanoma\"))\nnomelanoma_dict['image_id']=nomelanoma_id\nnomelanoma_df=pd.DataFrame(nomelanoma_dict)\nnomelanoma_df['target']=0","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"frames=[melanoma_df,nomelanoma_df]\nfinal_df=pd.concat(frames)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_path=[]\nmel_path=r'D:\\Culinda\\Data\\Melanoma Model Test\\Melanoma'\nnonmel_path=r\"D:\\Culinda\\Data\\Melanoma Model Test\\Non Melanoma\"\nfor i in range(len(final_df)):\n    if final_df.iloc[i,-1]==1:\n        image_path.append(os.path.join(mel_path,final_df.iloc[i,0]))\n    else:\n        image_path.append(os.path.join(nonmel_path,final_df.iloc[i,0]))\n        \n\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_df['path']=image_path","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_df.iloc[0,1]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"actual=[]\npredicted=[]\n\nfor ind,i in enumerate(final_df['path']):\n    image=image_preprocessing(i)\n    image = image.reshape(1, image.shape[0], image.shape[1], image.shape[2])\n    prediction=eff_net_model.predict(image)\n    if prediction[0][0]>=0.4:\n        predicted.append(1)\n        actual.append(final_df.iloc[ind,1])\n    else:\n        predicted.append(0)\n        actual.append(final_df.iloc[ind,1])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results_df=pd.DataFrame()\nresults_df['Actual']=actual\nresults_df['Predicted']=predicted","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Our function needs a different name to sklearn's plot_confusion_matrix\ndef make_confusion_matrix(y_true, y_pred, classes=None, figsize=(10, 10), text_size=15): \n  \"\"\"Makes a labelled confusion matrix comparing predictions and ground truth labels.\n\n  If classes is passed, confusion matrix will be labelled, if not, integer class values\n  will be used.\n\n  Args:\n    y_true: Array of truth labels (must be same shape as y_pred).\n    y_pred: Array of predicted labels (must be same shape as y_true).\n    classes: Array of class labels (e.g. string form). If `None`, integer labels are used.\n    figsize: Size of output figure (default=(10, 10)).\n    text_size: Size of output figure text (default=15).\n  \n  Returns:\n    A labelled confusion matrix plot comparing y_true and y_pred.\n\n  Example usage:\n    make_confusion_matrix(y_true=test_labels, # ground truth test labels\n                          y_pred=y_preds, # predicted labels\n                          classes=class_names, # array of class label names\n                          figsize=(15, 15),\n                          text_size=10)\n  \"\"\"  \n  # Create the confustion matrix\n  cm = confusion_matrix(y_true, y_pred)\n  cm_norm = cm.astype(\"float\") / cm.sum(axis=1)[:, np.newaxis] # normalize it\n  n_classes = cm.shape[0] # find the number of classes we're dealing with\n\n  # Plot the figure and make it pretty\n  fig, ax = plt.subplots(figsize=figsize)\n  cax = ax.matshow(cm, cmap=plt.cm.Blues) # colors will represent how 'correct' a class is, darker == better\n  fig.colorbar(cax)\n\n  # Are there a list of classes?\n  if classes:\n    labels = classes\n  else:\n    labels = np.arange(cm.shape[0])\n  \n  # Label the axes\n  ax.set(title=\"Confusion Matrix\",\n         xlabel=\"Predicted label\",\n         ylabel=\"True label\",\n         xticks=np.arange(n_classes), # create enough axis slots for each class\n         yticks=np.arange(n_classes), \n         xticklabels=labels, # axes will labeled with class names (if they exist) or ints\n         yticklabels=labels)\n  \n  # Make x-axis labels appear on bottom\n  ax.xaxis.set_label_position(\"bottom\")\n  ax.xaxis.tick_bottom()\n\n  # Set the threshold for different colors\n  threshold = (cm.max() + cm.min()) / 2.\n\n  # Plot the text on each cell\n  for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n    plt.text(j, i, f\"{cm[i, j]} ({cm_norm[i, j]*100:.1f}%)\",\n             horizontalalignment=\"center\",\n             color=\"white\" if cm[i, j] > threshold else \"black\",\n             size=text_size)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix\nimport matplotlib.pyplot as plt\nimport itertools\nmake_confusion_matrix(results_df['Actual'],results_df['Predicted'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}