# Image Classification - XAI grad cam/grad cam plus plus: 反向傳播看熱圖變化 lime: 模型遮住猜猜樂 ## Grad Cam ```python= def grad_cam(input_model, image, img_shape, category_index, layer_name): grad_model = Model(input_model.inputs, [input_model.get_layer(layer_name).output, model.output]) with tf.GradientTape() as tape: conv_outputs, predictions = grad_model(np.array([image])) loss = predictions[:, category_index] output = conv_outputs[0] grads = tape.gradient(loss, conv_outputs)[0] grads_val = grads.numpy() weights = np.mean(grads_val, axis = (0, 1)) cam = np.dot(output.numpy(), weights) cam = cv2.resize(cam, img_shape) #relu max_cam = np.maximum(cam, 0) if np.max(max_cam) == 0: max_cam[max_cam==0] = 1e-10 #normalize cam = cam/np.max(max_cam) cam = cv2.applyColorMap(np.uint8(255 * cam), cv2.COLORMAP_JET) return cam #, heatmap ``` ## Grad Cam++ ```python= def grad_cam_plus(input_model, image, img_shape, category_index, layer_name): grad_model = Model(input_model.inputs, [input_model.get_layer(layer_name).output, model.output]) with tf.GradientTape() as gtape1: with tf.GradientTape() as gtape2: with tf.GradientTape() as gtape3: conv_output, predictions = grad_model(np.array([image])) output = predictions[:, category_index] conv_first_grad = gtape3.gradient(output, conv_output) conv_second_grad = gtape2.gradient(conv_first_grad, conv_output) conv_third_grad = gtape1.gradient(conv_second_grad, conv_output) global_sum = np.sum(conv_output, axis=(0, 1, 2)) alpha_num = conv_second_grad[0] alpha_denom = conv_second_grad[0]*2.0 + conv_third_grad[0]*global_sum alpha_denom = np.where(alpha_denom != 0.0, alpha_denom, 1e-10) alphas = alpha_num/alpha_denom alpha_normalization_constant = np.sum(alphas, axis=(0,1)) alphas /= alpha_normalization_constant weights = np.maximum(conv_first_grad[0], 0.0) deep_linearization_weights = np.sum(weights*alphas, axis=(0,1)) grad_CAM_map = np.sum(deep_linearization_weights*conv_output[0], axis=2) heatmap = np.maximum(grad_CAM_map, 0) max_heat = np.max(heatmap) if max_heat == 0: max_heat = 1e-10 heatmap /= max_heat heatmap = cv2.resize(heatmap, (image.shape[1], image.shape[0])) heatmap = (heatmap*255).astype("uint8") heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET) return heatmap ``` --- ## Lime 安裝lime套件 ``` pip install lime ``` import ```python= import lime from lime import lime_image import skimage.io as io from skimage import transform from skimage import img_as_float from skimage.segmentation import mark_boundaries from tensorflow.keras.preprocessing import image ``` 程式打包 ```python= def plot_lime(i, img_path, img_shape, input_model): preprocessed_input, img = load_image(img_path, img_shape) explainer = lime_image.LimeImageExplainer() x = preprocessed_input[0].astype(np.double) explanation = explainer.explain_instance( x, input_model.predict, top_labels=5, hide_color=0, num_samples=1000 ) #print(explanation) temp, mask = explanation.get_image_and_mask( explanation.top_labels[0], positive_only=True, negative_only=False, num_features=5, hide_rest=False ) img = io.imread(img_path) img = transform.resize(img, img_shape) image = img_as_float(img) plt.grid(False) plt.xticks([]) plt.yticks([]) #plt.axis("off") plt.imshow(mark_boundaries(image,mask)) #plt.imsave("out.jpg",mark_boundaries(image,mask)) ``` [Ref] 理論 https://medium.com/@kstseng/lime-local-interpretable-model-agnostic-explanation-%E6%8A%80%E8%A1%93%E4%BB%8B%E7%B4%B9-a67b6c34c3f8 code https://www.twblogs.net/a/5edfaf8078636330da9b2fe5 (下半段程式碼) https://www.pythonheidong.com/blog/article/401003/9a55d5466c41ee9b8c64/ (較詳細的設定)