---
# System prepended metadata

title: Image Classification - Evaluate tool

---

# Image Classification - Evaluate tool
## Plot Function
### 定義類別
```python=
class_names = ['normal', 'abnormal']
```
### 載入圖片轉np格式
```python=
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.xception import preprocess_input

def load_image(path, img_shape):
    img = image.load_img(path, target_size=img_shape)
    x = image.img_to_array(img)
    imgg =x.astype('uint8')
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    return x, imgg
```
### 畫測試圖
```python=
def plot_image(i, predictions_array, true_label, img, img_id):
  #true_label, img = true_label[i], img[i]
    true_label = true_label
    img = img
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img, cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({}) \nid: ({})".format(class_names[predicted_label],
                                  100*np.max(predictions_array),
                                  class_names[true_label],
                                  img_id),
                                  color=color)
```
### 畫機率值
```python=
def plot_value_array(i, predictions_array, true_label):
    true_label = true_label
    plt.grid(False)
    plt.xticks(range(2))
    plt.yticks([])
    thisplot = plt.bar(range(2), predictions_array, width=0.3, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_label].set_color('blue')
```
### 畫grad cam或者grad cam ++
* grad_cam
* grad_cam_plus

詳細請參考:https://hackmd.io/@JackyYen/BkOvDp8PY
```python=
def plot_gram(i, img_path, img_shape, input_model, layer_name):
    
    preprocessed_input, img = load_image(img_path, img_shape)

    predictions = input_model.predict(preprocessed_input)
    predicted_class = np.argmax(predictions)

    #cam, heatmap = grad_cam(input_model, img, img_shape, predicted_class, layer_name)   
    cam = grad_cam_plus(input_model, img, img_shape, predicted_class, layer_name)   
    overcam = cv2.addWeighted(img, 0.8, cam, 0.3, 0)

    #cv2.imwrite(os.path.join(cam_path, each), overcam)

    #plt.figure(figsize=(5, 5))
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(overcam[:,:,[ 2, 1, 0]])
    #plt.axis("off")
```
### 畫lime
詳細請參考:https://hackmd.io/@JackyYen/BkOvDp8PY
```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

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))
```
### plot_gram subfunction
#### 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
```
## 畫 測試圖+gradcam/lime+機率圖
```python=
num_rows = 10
num_cols = 3
num_images = num_rows*num_cols
n = 3
plt.figure(figsize=(n*n*num_cols, n*num_rows))
class_names = ['normal', 'abnormal']
#j = 0
start = (y_test_cat.shape[0]//num_images)
for j in range(0, start+1):
    print('批次: ', j)
    print('range: ', num_images*j,' ~ ', num_images*(j+1))
    plt.figure(figsize=(n*n*num_cols, n*num_rows))
    for i in range(num_images*j, num_images*(j+1), 1):
        print('processing: ', i+1, '/', num_images)
        #print('----',n*i+1,'----',n*(i- (num_images*j)) + 1,'----',n*(i- (num_images*j)) + 2, '----',n*(i- (num_images*j)) + 3)
        if i == (y_test_cat.shape[0]):
            print('-----Stop-----')
            print('i: ',i)
            print('---Complete---')
            break
        plt.subplot(num_rows, n*num_cols, n*(i- (num_images*j)) + 1)
        plot_image(i, y_predict[i], y_test[i], test_view[0][0][i], x_test[i])
        plt.subplot(num_rows, n*num_cols, n*(i- (num_images*j)) + 2)
        plot_lime(i, x_test[i], test_generator[0][0][i].shape[0:2], model)
        #plot_gram(i, x_test[i], test_generator[0][0][i].shape[0:2], model, layer_name)
        plt.subplot(num_rows, n*num_cols, n*(i- (num_images*j)) + 3)
        plot_value_array(i, y_predict[i],  y_test[i])
    plt.tight_layout()
    plt.savefig('./results_lime/xception/all/xception'+str(j+1)+'.png')
    plt.show()
```
## 畫判斷錯誤圖
記下有錯的位址
```python=
import numpy as np 
import matplotlib.pyplot as plt
index = 0
misclassifiedIndexes = []
for label, predict in zip(y_test, y_predict_argmax):
    
    if label != predict: 
        misclassifiedIndexes.append(index)
    index +=1
```
### 錯誤樣本+機率圖(可修改)
```python=
# Plot the first X test images, their predicted labels, and the true labels.
# Color correct predictions in blue and incorrect predictions in red.
num_rows = 10
num_cols = 4
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
class_names = ['normal', 'abnormal']
#j = 0
start = (len(misclassifiedIndexes)//num_images)
for j in range(0, start+1):
    print('批次: ', j)
    print('range: ', num_images*j,' ~ ', num_images*(j+1))
    plt.figure(figsize=(2*2*num_cols, 2*num_rows))
    for i in range(num_images*j, num_images*(j+1), 1):
        print('processing: ', i+1, '/', num_images)
        if i == (len(misclassifiedIndexes)):
            print('-----Stop-----')
            print('*'*15,'\n')
            print('*'*15,'\n')
            print('---Complete---')
            break
        print('*'*15)
        print('misclassifiedIndexes: ',misclassifiedIndexes[i])
        print('*'*15,'\n')
        idx = misclassifiedIndexes[i]
        plt.subplot(num_rows, 2*num_cols, 2*(i- (num_images*j)) + 1)
        plot_image(i, y_predict[idx], y_test[idx], test_generator[0][0][idx], x_test[idx].split('\\')[1])
        plt.subplot(num_rows, 2*num_cols, 2*(i- (num_images*j)) + 2)
        plot_value_array(i, y_predict[idx],  y_test[idx])
    plt.tight_layout()
    plt.savefig('./results/xception/wrong/xception_錯的_'+str(j+1)+'.png')
    plt.show()
```
## 指標分析
### Confusion matrix
```python=
import seaborn as sns
import pandas as pd

target_names = ['normal', 'abnormal']
conf_m = pd.DataFrame(cm,
            index = target_names,
            columns = target_names)
fig, ax = plt.subplots(figsize = (8, 6))

sns.heatmap(conf_m, annot=True, annot_kws={"size": 20},
            cmap='Blues_r', fmt='g', linewidth=0.5, square=True)
plt.ylabel('True label', fontsize=18)
plt.xlabel('Pred label', fontsize=18)
plt.yticks(fontsize=18)
plt.xticks(fontsize=18)
plt.savefig('./results/xception/xception_cm.png', bbox_inches='tight')
plt.show()
```
### metrics report
```python=
from sklearn.metrics import classification_report

report = classification_report(np.argmax(test_generator[0][1], axis=1), y_predict_argmax, target_names=target_names)
print(report)
```