import matplotlib.pylab as plt import numpy as np import tensorflow as tf import os import math from tensorflow.keras.models import load_model from data_pretreat import * # src/ function #model = load_model('/home/jhodi/bit/Python/Grapevine_Pathology_Detection/venv/models/2026-03-14_21:21:01.562003/model.keras') model_dir = input("Model dir : ") model = load_model(model_dir+"/model.keras") model.build([None, 224, 224, 3]) model.summary() # img_height = 224 # img_width = 224 # batch_size = 32 # # test_dir = os.getcwd()[:-9]+"/data/datasplit/test" # class_names = ['Black_Rot', 'ESCA', 'Healthy', 'Leaf_Blight'] def read_image(file_name): image = tf.io.read_file(file_name) image = tf.io.decode_jpeg(image, channels=channels) image = tf.image.convert_image_dtype(image, tf.float32) image = tf.image.resize_with_pad(image, target_height=img_height, target_width=img_width) return image def top_k_predictions(img, k=2): image_batch = tf.expand_dims(img, 0) predictions = model(image_batch) probs = tf.nn.softmax(predictions, axis=-1) top_probs, top_idxs = tf.math.top_k(input=probs, k=k) top_labels = [class_names[idx.numpy()] for idx in top_idxs[0]] return top_labels, top_probs[0] # Load img img_name_tensors = {} for images, labels in test_ds: for i, class_name in enumerate(class_names): class_idx = class_names.index(class_name) mask = labels == class_idx if tf.reduce_any(mask): img_name_tensors[class_name] = images[mask][0] / 255.0 # Show img with prediction # plt.figure(figsize=(14, 12)) # num_images = len(img_name_tensors) # cols = 2 # rows = math.ceil(num_images / cols) # # for n, (name, img_tensor) in enumerate(img_name_tensors.items()): # ax = plt.subplot(rows, cols, n+1) # ax.imshow(img_tensor) # # pred_labels, pred_probs = top_k_predictions(img_tensor, k=2) # # pred_text = f"Real classe: {name}\n\nPrédictions:\n" # for label, prob in zip(pred_labels, pred_probs): # pred_text += f"{label}: {prob.numpy():0.1%}\n" # # ax.set_title(pred_text, fontsize=10, fontweight='bold') # ax.axis('off') # # plt.tight_layout() # plt.show() # Calculate Integrated Gradients def f(x): #A simplified model function. return tf.where(x < 0.8, x, 0.8) def interpolated_path(x): #A straight line path. return tf.zeros_like(x) x = tf.linspace(start=0.0, stop=1.0, num=6) y = f(x) # Establish a baseline baseline = tf.zeros(shape=(224,224,3)) # plt.imshow(baseline) # plt.title("Baseline") # plt.axis('off') # plt.show() m_steps=50 alphas = tf.linspace(start=0.0, stop=1.0, num=m_steps+1) # Generate m_steps intervals for integral_approximation() below. def interpolate_images(baseline, image, alphas): alphas_x = alphas[:, tf.newaxis, tf.newaxis, tf.newaxis] baseline_x = tf.expand_dims(baseline, axis=0) input_x = tf.expand_dims(image, axis=0) delta = input_x - baseline_x images = baseline_x + alphas_x * delta return images interpolated_images = interpolate_images( baseline=baseline, image=img_name_tensors['Leaf_Blight'], # class index : 3 alphas=alphas) # fig = plt.figure(figsize=(20, 20)) # # i = 0 # for alpha, image in zip(alphas[0::10], interpolated_images[0::10]): # i += 1 # plt.subplot(1, len(alphas[0::10]), i) # plt.title(f'alpha: {alpha:.1f}') # plt.imshow(image) # plt.axis('off') # # plt.tight_layout(); def compute_gradients(images, target_class_idx): with tf.GradientTape() as tape: tape.watch(images) logits = model(images) probs = tf.nn.softmax(logits, axis=-1)[:, target_class_idx] return tape.gradient(probs, images) path_gradients = compute_gradients( images=interpolated_images, target_class_idx=3) print(path_gradients.shape) pred = model(interpolated_images) pred_proba = tf.nn.softmax(pred, axis=-1)[:, 3] def integral_approximation(gradients): # riemann_trapezoidal grads = (gradients[:-1] + gradients[1:]) / tf.constant(2.0) integrated_gradients = tf.math.reduce_mean(grads, axis=0) return integrated_gradients ig = integral_approximation( gradients=path_gradients) print(ig.shape) # Putting it all together def integrated_gradients(baseline, image, target_class_idx, m_steps=50, batch_size=32): # Generate alphas. alphas = tf.linspace(start=0.0, stop=1.0, num=m_steps+1) # Collect gradients. gradient_batches = [] # Iterate alphas range and batch computation for speed, memory efficiency, and scaling to larger m_steps. for alpha in tf.range(0, len(alphas), batch_size): from_ = alpha to = tf.minimum(from_ + batch_size, len(alphas)) alpha_batch = alphas[from_:to] gradient_batch = one_batch(baseline, image, alpha_batch, target_class_idx) gradient_batches.append(gradient_batch) # Concatenate path gradients together row-wise into single tensor. total_gradients = tf.concat(gradient_batches, axis=0) # Integral approximation through averaging gradients. avg_gradients = integral_approximation(gradients=total_gradients) # Scale integrated gradients with respect to input. integrated_gradients = (image - baseline) * avg_gradients return integrated_gradients @tf.function def one_batch(baseline, image, alpha_batch, target_class_idx): # Generate interpolated inputs between baseline and input. interpolated_path_input_batch = interpolate_images(baseline=baseline, image=image, alphas=alpha_batch) # Compute gradients between model outputs and interpolated inputs. gradient_batch = compute_gradients(images=interpolated_path_input_batch, target_class_idx=target_class_idx) return gradient_batch ig_attributions = integrated_gradients(baseline=baseline, image=img_name_tensors['Leaf_Blight'], target_class_idx=3, m_steps=240) print(ig_attributions.shape) # Visualize attributions def plot_img_attributions(baseline, image, target_class_idx, m_steps=50, cmap=None, overlay_alpha=0.4): attributions = integrated_gradients(baseline=baseline, image=image, target_class_idx=target_class_idx, m_steps=m_steps) # Sum of the attributions across color channels for visualization. # The attribution mask shape is a grayscale image with height and width # equal to the original image. attribution_mask = tf.reduce_sum(tf.math.abs(attributions), axis=-1) fig, axs = plt.subplots(nrows=2, ncols=2, squeeze=False, figsize=(8, 8)) axs[0, 0].set_title('Baseline image') axs[0, 0].imshow(baseline) axs[0, 0].axis('off') axs[0, 1].set_title('Original image') axs[0, 1].imshow(image) axs[0, 1].axis('off') axs[1, 0].set_title('Attribution mask') axs[1, 0].imshow(attribution_mask, cmap=cmap) axs[1, 0].axis('off') axs[1, 1].set_title('Overlay') axs[1, 1].imshow(attribution_mask, cmap=cmap) axs[1, 1].imshow(image, alpha=overlay_alpha) axs[1, 1].axis('off') plt.tight_layout() return fig _ = plot_img_attributions(image=img_name_tensors['Leaf_Blight'], baseline=baseline, target_class_idx=3, m_steps=240, cmap=plt.cm.inferno, overlay_alpha=0.4) plt.show() _ = plot_img_attributions(image=img_name_tensors['ESCA'], baseline=baseline, target_class_idx=1, m_steps=55, cmap=plt.cm.viridis, overlay_alpha=0.5) plt.show() """ @ref : https://www.tensorflow.org/tutorials/interpretability/integrated_gradients?hl=en """