# 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/ (較詳細的設定)