{"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\nimport pandas as pd\nimport os\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report, accuracy_score, precision_score, recall_score, f1_score, confusion_matrix","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:28.661511Z","iopub.execute_input":"2023-10-24T06:24:28.661968Z","iopub.status.idle":"2023-10-24T06:24:39.652779Z","shell.execute_reply.started":"2023-10-24T06:24:28.661942Z","shell.execute_reply":"2023-10-24T06:24:39.650875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def append_ext(fn):\n    return fn + \".png\"\n\n# Load the dataset\ntrain_dataframe = pd.read_csv(\"/kaggle/input/aptos2019-blindness-detection/train.csv\", dtype=str)\ntrain_dataframe['id_code'] = train_dataframe['id_code'].apply(append_ext)\ntrain_dataframe.head()\n","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:39.654527Z","iopub.execute_input":"2023-10-24T06:24:39.655119Z","iopub.status.idle":"2023-10-24T06:24:39.694839Z","shell.execute_reply.started":"2023-10-24T06:24:39.655090Z","shell.execute_reply":"2023-10-24T06:24:39.693785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"diagnosis_counts = train_dataframe.groupby('diagnosis')['id_code'].count()\n\n# Plot the counts\ndiagnosis_counts.plot(kind='bar')\n\n# Add labels and title to the plot\nplt.xlabel('Diagnosis')\nplt.ylabel('Count')\nplt.title('Count of id_code for each diagnosis')\n\n# Display the plot\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:39.696957Z","iopub.execute_input":"2023-10-24T06:24:39.697207Z","iopub.status.idle":"2023-10-24T06:24:39.942998Z","shell.execute_reply.started":"2023-10-24T06:24:39.697187Z","shell.execute_reply":"2023-10-24T06:24:39.942317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\n# Split the dataset into training, validation, and test sets\nX = train_dataframe['id_code']\ny = train_dataframe['diagnosis']\nX_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.1, random_state=42, shuffle=True)\nX_train, X_test, y_train, y_test = train_test_split(X_train, y_train, test_size=0.1, random_state=42, shuffle=True)\ntrain_df = pd.DataFrame({'id_code': X_train, 'diagnosis': y_train}).reset_index(drop=True)\nvalid_df = pd.DataFrame({'id_code': X_valid, 'diagnosis': y_valid}).reset_index(drop=True)\ntest_df = pd.DataFrame({'id_code': X_test, 'diagnosis': y_test}).reset_index(drop=True)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:39.944151Z","iopub.execute_input":"2023-10-24T06:24:39.944561Z","iopub.status.idle":"2023-10-24T06:24:39.956656Z","shell.execute_reply.started":"2023-10-24T06:24:39.944536Z","shell.execute_reply":"2023-10-24T06:24:39.955438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Define a function to append file extensions to file names\n\n# Create data generators for image data\ntrain_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1 / 255.0,\n                                                               rotation_range=10,\n                                                               zoom_range=0.30,\n                                                               shear_range=0.30,\n                                                               fill_mode=\"nearest\")\n\ntest_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1 / 255.0)","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:39.957662Z","iopub.execute_input":"2023-10-24T06:24:39.958219Z","iopub.status.idle":"2023-10-24T06:24:39.964327Z","shell.execute_reply.started":"2023-10-24T06:24:39.958191Z","shell.execute_reply":"2023-10-24T06:24:39.963512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images_directory = \"/kaggle/input/aptos2019-blindness-detection/train_images\"\nbatch_size = 16\ntrain_generator = train_datagen.flow_from_dataframe(dataframe=train_df,\n                                                    directory=images_directory,\n                                                    x_col='id_code',\n                                                    y_col='diagnosis',\n                                                    target_size=(224, 224),\n                                                    color_mode='rgb',\n                                                    class_mode='categorical',\n                                                    batch_size=batch_size)\n\nvalid_generator = test_datagen.flow_from_dataframe(dataframe=valid_df,\n                                                    directory=images_directory,\n                                                    x_col='id_code',\n                                                    y_col='diagnosis',\n                                                    target_size=(224, 224),\n                                                    color_mode='rgb',\n                                                    class_mode='categorical',\n                                                    batch_size=batch_size)\n\ntest_generator = test_datagen.flow_from_dataframe(dataframe=test_df,\n                                                  directory=images_directory,\n                                                  x_col='id_code',\n                                                  y_col='diagnosis',\n                                                  target_size=(224, 224),\n                                                  color_mode='rgb',\n                                                  class_mode='categorical',\n                                                  batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:39.965395Z","iopub.execute_input":"2023-10-24T06:24:39.966195Z","iopub.status.idle":"2023-10-24T06:24:43.091634Z","shell.execute_reply.started":"2023-10-24T06:24:39.966171Z","shell.execute_reply":"2023-10-24T06:24:43.090917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as hub","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:43.092796Z","iopub.execute_input":"2023-10-24T06:24:43.093143Z","iopub.status.idle":"2023-10-24T06:24:43.444239Z","shell.execute_reply.started":"2023-10-24T06:24:43.093118Z","shell.execute_reply":"2023-10-24T06:24:43.442917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the teacher models\ndef create_teacher_model(model_name, num_classes=5):\n    pre_trained_model = keras.applications.__dict__[model_name](weights='imagenet', include_top=False)\n    \n    x = keras.layers.GlobalAveragePooling2D()(pre_trained_model.output)\n    x = keras.layers.Dense(num_classes, activation='softmax')(x)\n\n    teacher_model = keras.models.Model(inputs=pre_trained_model.input, outputs=x)\n    \n    return teacher_model\n\nteacher_models = {\n    'VGG16': create_teacher_model('VGG16', num_classes=5),\n    'VGG19': create_teacher_model('VGG19', num_classes=5),\n    'Xception': create_teacher_model('Xception', num_classes=5),\n    'InceptionV3': create_teacher_model('InceptionV3', num_classes=5),\n    'ResNet50': create_teacher_model('ResNet50', num_classes=5)\n}\n\nimport tensorflow as tf\nimport tensorflow_hub as hub\n\n\n\n# Create the NASNetLarge model with the modified input shape\ndef create_student_model(num_classes=5):\n    base_model = EfficientNetB3(weights='imagenet', include_top=False, input_shape=(331, 331, 3))\n    x = base_model.output\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dense(512, activation='relu')(x)\n    predictions = layers.Dense(num_classes, activation='softmax')(x)\n\n    model = keras.Model(inputs=base_model.input, outputs=predictions)\n    \n    # Freeze the base model layers for fine-tuning\n    for layer in base_model.layers:\n        layer.trainable = False\n\n    return model\n\n# Compile and train the model as before\n\n\nstudent_model = create_student_model(num_classes=5)","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:24:43.447489Z","iopub.execute_input":"2023-10-24T06:24:43.447813Z","iopub.status.idle":"2023-10-24T06:25:03.607254Z","shell.execute_reply.started":"2023-10-24T06:24:43.447788Z","shell.execute_reply":"2023-10-24T06:25:03.605677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the Distiller class\nclass Distiller(keras.Model):\n    def __init__(self, student, teachers):\n        super().__init__()\n        self.teachers = teachers\n        self.student = student\n\n    def call(self, inputs, training=False):\n        # Forward pass through the student model\n        student_logits = self.student(inputs, training=training)\n        # Forward pass through each teacher model\n        teacher_logits = [teacher(inputs, training=training) for teacher in self.teachers]\n        return student_logits, teacher_logits\n\n\n    def compile(self, optimizer, metrics, student_loss_fn, distillation_loss_fn, alpha=0.1, temperature=3):\n        super().compile(optimizer=optimizer, metrics=metrics)\n        self.student_loss_fn = student_loss_fn\n        self.distillation_loss_fn = distillation_loss_fn\n        self.alpha = alpha\n        self.temperature = temperature\n\n    def train_step(self, data):\n        x, y = data\n        teacher_predictions = [teacher(x, training=False) for teacher in self.teachers]\n\n        with tf.GradientTape() as tape:\n            student_predictions = self.student(x, training=True)\n            student_loss = self.student_loss_fn(y, student_predictions)\n            distillation_loss = 0\n\n            for i, teacher_pred in enumerate(teacher_predictions):\n                distillation_loss += self.distillation_loss_fn(\n                    tf.nn.softmax(teacher_pred / self.temperature, axis=1),\n                    tf.nn.softmax(student_predictions / self.temperature, axis=1)\n                )\n\n            distillation_loss /= len(self.teachers)\n            loss = self.alpha * student_loss + (1 - self.alpha) * distillation_loss\n\n        trainable_vars = self.student.trainable_variables\n        gradients = tape.gradient(loss, trainable_vars)\n        self.optimizer.apply_gradients(zip(gradients, trainable_vars))\n\n        self.compiled_metrics.update_state(y, student_predictions)\n        results = {m.name: m.result() for m in self.metrics}\n        results.update({\"student_loss\": student_loss, \"distillation_loss\": distillation_loss})\n        return results\n\n    def test_step(self, data):\n        x, y = data\n        student_predictions = self.student(x, training=False)\n        student_loss = self.student_loss_fn(y, student_predictions)\n        self.compiled_metrics.update_state(y, student_predictions)\n        results = {m.name: m.result() for m in self.metrics}\n        results.update({\"student_loss\": student_loss})\n        return results\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-24T06:25:03.608589Z","iopub.execute_input":"2023-10-24T06:25:03.608992Z","iopub.status.idle":"2023-10-24T06:25:03.623722Z","shell.execute_reply.started":"2023-10-24T06:25:03.608958Z","shell.execute_reply":"2023-10-24T06:25:03.622088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create instances of teacher and student models\nteachers = [teacher_models[name] for name in ['VGG16', 'VGG19', 'Xception', 'InceptionV3', 'ResNet50']]\nstudent = create_student_model()\n\n# Create a distiller\ndistiller = Distiller(student=student, teachers=teachers)\n\n# Compile the distiller\ndistiller.compile(\n    optimizer=keras.optimizers.Adam(),\n    metrics=[keras.metrics.CategoricalAccuracy()],\n    student_loss_fn=keras.losses.CategoricalCrossentropy(),\n    distillation_loss_fn=keras.losses.KLDivergence(),\n    alpha=0.1,\n    temperature=20\n)\n\n# Create an instance of the distiller model","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:25:03.625445Z","iopub.execute_input":"2023-10-24T06:25:03.625746Z","iopub.status.idle":"2023-10-24T06:25:11.218290Z","shell.execute_reply.started":"2023-10-24T06:25:03.625721Z","shell.execute_reply":"2023-10-24T06:25:11.217389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Implement early stopping and checkpoint\nearly_stopping = keras.callbacks.EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)\nmodel_checkpoint = keras.callbacks.ModelCheckpoint('best_student_model.h5', save_best_only=True)\n\nstudent_model.compile(optimizer=keras.optimizers.Adam(), loss='categorical_crossentropy', metrics=['accuracy'])\n\nhistory = student_model.fit(\n    train_generator,\n    validation_data=valid_generator,\n    steps_per_epoch=len(train_generator),\n    validation_steps=len(valid_generator),\n    epochs=15,\n    callbacks=[early_stopping, model_checkpoint]  # Add the callbacks\n)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# student_model.compile(optimizer=keras.optimizers.Adam(), loss='categorical_crossentropy', metrics=['accuracy'])\n\n# history = student_model.fit(\n#     train_generator,\n#     validation_data=valid_generator,\n#     steps_per_epoch=len(train_generator),\n#     validation_steps=len(valid_generator),\n#     epochs=8\n# )","metadata":{"execution":{"iopub.status.busy":"2023-10-24T06:25:11.219718Z","iopub.execute_input":"2023-10-24T06:25:11.221973Z","iopub.status.idle":"2023-10-24T09:51:57.589492Z","shell.execute_reply.started":"2023-10-24T06:25:11.221919Z","shell.execute_reply":"2023-10-24T09:51:57.585010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"teachers = [teacher_models[name] for name in ['VGG16', 'VGG19', 'Xception', 'InceptionV3', 'ResNet50']]\nstudent = create_student_model()\n\n# Create a distiller\ndistiller = Distiller(student=student, teachers=teachers)\n\n# Compile and train the distiller model\ndistiller.compile(\n    optimizer=keras.optimizers.Adam(),\n    metrics=[keras.metrics.CategoricalAccuracy()],\n    student_loss_fn=keras.losses.CategoricalCrossentropy(),\n    distillation_loss_fn=keras.losses.KLDivergence(),\n    alpha=0.1,\n    temperature=20\n)\n\ndistiller_history = distiller.fit(\n    train_generator,\n    validation_data=valid_generator,\n    steps_per_epoch=len(train_generator),\n    validation_steps=len(valid_generator),\n    epochs=8\n)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-24T09:51:57.599788Z","iopub.execute_input":"2023-10-24T09:51:57.600523Z","iopub.status.idle":"2023-10-24T17:01:09.005060Z","shell.execute_reply.started":"2023-10-24T09:51:57.600438Z","shell.execute_reply":"2023-10-24T17:01:08.999073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report, accuracy_score, precision_score, recall_score, f1_score\n\n# Evaluate the student model\nstudent_predictions = student_model.predict(test_generator)\nstudent_predicted_labels = np.argmax(student_predictions, axis=1)\n\n# Get true labels from the test data generator\nstudent_true_labels = test_generator.classes\n\n# Calculate and print a classification report for the student model\nprint('Student Model Classification Report:\\n', classification_report(student_true_labels, student_predicted_labels, target_names=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR']))\n\n# Calculate and print other metrics for the student model\nstudent_accuracy = accuracy_score(student_true_labels, student_predicted_labels)\nstudent_precision = precision_score(student_true_labels, student_predicted_labels, average='weighted', zero_division=1)\nstudent_recall = recall_score(student_true_labels, student_predicted_labels, average='weighted')\nstudent_f1 = f1_score(student_true_labels, student_predicted_labels, average='weighted', zero_division=1)\n\n# Calculate micro-averaged sensitivity and specificity for the student model\nstudent_conf_matrix = confusion_matrix(student_true_labels, student_predicted_labels)\nstudent_sensitivity_micro = recall_score(student_true_labels, student_predicted_labels, average='micro')\nstudent_specificity_micro = (np.sum(student_conf_matrix) - np.diag(student_conf_matrix).sum()) / (np.sum(student_conf_matrix) - np.diag(student_conf_matrix).sum())\n\n# Macro-averaged sensitivity and specificity for the student model\nstudent_sensitivity_macro = recall_score(student_true_labels, student_predicted_labels, average='macro')\nstudent_specificity_macro = specificity_macro = np.mean([(np.sum(student_conf_matrix) - np.sum(student_conf_matrix[i]) - np.sum(student_conf_matrix[:, i]) + student_conf_matrix[i][i]) / (np.sum(student_conf_matrix) - np.sum(student_conf_matrix[i]) - np.sum(student_conf_matrix[:, i]) + 1) for i in range(len(student_conf_matrix))])\n\n# Print metrics for the student model\nprint('Student Model Accuracy:', student_accuracy)\nprint('Student Model Precision:', student_precision)\nprint('Student Model Recall:', student_recall)\nprint('Student Model F1 Score:', student_f1)\nprint('Student Model Micro-averaged Sensitivity:', student_sensitivity_micro)\nprint('Student Model Micro-averaged Specificity:', student_specificity_micro)\nprint('Student Model Macro-averaged Sensitivity:', student_sensitivity_macro)\nprint('Student Model Macro-averaged Specificity:', student_specificity_macro)\n\n# Now, calculate and print the confusion matrix for the student model\nplt.figure(figsize=(8, 6))\nsns.heatmap(student_conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR'], yticklabels=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR'])\nplt.xlabel('Predicted')\nplt.ylabel('True')\nplt.title('Student Model Confusion Matrix')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-10-24T17:01:09.018928Z","iopub.execute_input":"2023-10-24T17:01:09.019525Z","iopub.status.idle":"2023-10-24T17:03:48.088712Z","shell.execute_reply.started":"2023-10-24T17:01:09.019466Z","shell.execute_reply":"2023-10-24T17:03:48.085794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from sklearn.metrics import confusion_matrix\n# import matplotlib.pyplot as plt\n# import seaborn as sns\n\n# # Print confusion matrix for the student model\n# plt.figure(figsize=(8, 6))\n# sns.heatmap(confusion_matrix(student_true_labels, student_predicted_labels), annot=True, fmt='d', cmap='Blues', xticklabels=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR'], yticklabels=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR'])\n# plt.xlabel('Predicted')\n# plt.ylabel('True')\n# plt.title('Student Model Confusion Matrix')\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-24T17:03:48.091011Z","iopub.execute_input":"2023-10-24T17:03:48.091795Z","iopub.status.idle":"2023-10-24T17:03:48.097204Z","shell.execute_reply.started":"2023-10-24T17:03:48.091764Z","shell.execute_reply":"2023-10-24T17:03:48.095585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report, accuracy_score, precision_score, recall_score, f1_score\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Evaluate the distiller model\ndistiller_predictions = distiller.predict(test_generator)\n\n# Check the shape of one of the arrays inside the tuple\nif isinstance(distiller_predictions, tuple) and len(distiller_predictions) > 0:\n    sample_prediction_array = distiller_predictions[0]  # You can choose one of the arrays\n    print('Shape of distiller_predictions:', sample_prediction_array.shape)\n\n    # Ensure the chosen array has the expected shape\n    if sample_prediction_array.shape[1] == 1:\n        distiller_predicted_labels = (sample_prediction_array > 0.5).astype(int).flatten()\n    else:\n        distiller_predicted_labels = np.argmax(sample_prediction_array, axis=1)\n\n    # Get true labels from the test data generator\n    distiller_true_labels = test_generator.classes\n\n    # Calculate and print a classification report for the distiller model\n    print('Distiller Model Classification Report:\\n', classification_report(distiller_true_labels, distiller_predicted_labels, target_names=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR']))\n\n    # Calculate and print other metrics for the distiller model\n    distiller_accuracy = accuracy_score(distiller_true_labels, distiller_predicted_labels)\n    distiller_precision = precision_score(distiller_true_labels, distiller_predicted_labels, average='weighted', zero_division=1)\n    distiller_recall = recall_score(distiller_true_labels, distiller_predicted_labels, average='weighted')\n    distiller_f1 = f1_score(distiller_true_labels, distiller_predicted_labels, average='weighted', zero_division=1)\n\n    # Calculate micro-averaged sensitivity and specificity for the distiller model\n    distiller_conf_matrix = confusion_matrix(distiller_true_labels, distiller_predicted_labels)\n    distiller_sensitivity_micro = recall_score(distiller_true_labels, distiller_predicted_labels, average='micro')\n    distiller_specificity_micro = (np.sum(distiller_conf_matrix) - np.diag(distiller_conf_matrix).sum()) / (np.sum(distiller_conf_matrix) - np.diag(distiller_conf_matrix).sum())\n\n    # Macro-averaged sensitivity and specificity for the distiller model\n    distiller_sensitivity_macro = recall_score(distiller_true_labels, distiller_predicted_labels, average='macro')\n    distiller_specificity_macro = np.mean([(np.sum(distiller_conf_matrix) - np.sum(distiller_conf_matrix[i]) - np.sum(distiller_conf_matrix[:, i]) + distiller_conf_matrix[i][i]) / (np.sum(distiller_conf_matrix) - np.sum(distiller_conf_matrix[i]) - np.sum(distiller_conf_matrix[:, i]) + 1) for i in range(len(distiller_conf_matrix))])\n\n    # Print metrics for the distiller model\n    print('Distiller Model Accuracy:', distiller_accuracy)\n    print('Distiller Model Precision:', distiller_precision)\n    print('Distiller Model Recall:', distiller_recall)\n    print('Distiller Model F1 Score:', distiller_f1)\n    print('Distiller Model Micro-averaged Sensitivity:', distiller_sensitivity_micro)\n    print('Distiller Model Micro-averaged Specificity:', distiller_specificity_micro)\n    print('Distiller Model Macro-averaged Sensitivity:', distiller_sensitivity_macro)\n    print('Distiller Model Macro-averaged Specificity:', distiller_specificity_macro)\n\n    # Now, calculate and print the confusion matrix for the distiller model\n    plt.figure(figsize=(8, 6))\n    sns.heatmap(distiller_conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR'], yticklabels=['No_DR', 'Mild', 'Moderate', 'Severe', 'Proliferative_DR'])\n    plt.xlabel('Predicted')\n    plt.ylabel('True')\n    plt.title('Distiller Model Confusion Matrix')\n    plt.show()\nelse:\n    print('No prediction arrays found in distiller_predictions tuple')\n","metadata":{"execution":{"iopub.status.busy":"2023-10-24T17:03:48.099304Z","iopub.execute_input":"2023-10-24T17:03:48.100515Z","iopub.status.idle":"2023-10-24T17:09:44.632007Z","shell.execute_reply.started":"2023-10-24T17:03:48.100474Z","shell.execute_reply":"2023-10-24T17:09:44.630208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}