본문 바로가기
  • 🦄 창민이 개발일지
딥러닝

클래스 활성화의 히트맵 시각화

by 창민이 개발일지 2022. 6. 23.

클래스 활성화의 히트맵 시각화

클래스 활성화 맵(CAM)

  • Claa Activation Map
  • 해당 기법을 사용하면 이미지의 어느 부분이 컨브넷의 최종 분류 결정에 기여하는지 이해할 수 있다.
  • 클래스 활성화 히트맵은 특정 출력 ㅍ클래스에 대해 입력 이미지의 모든 위치를 계산한 2D 그리드로, 클래스에 대해 각 위치가 얼마나 중요한지 알려줌.
  • 이미지에 특정 물체가 있는 위치를 파악하는 데 사용. -> Object Detection 응용 가능.

Grad-CAM

  • 입력이미지가 주어지면 합성곱 층에 있는 특성 맵의 출력 추출하고 그다음 특성 맵의 모든 채널 출력에 대한 클래스의 그래디언트 평균을 곱한다.
  • 입력 이미지가 각  채널을 활성화하는 정도에 대한 공간적인 맵을 클래스에 대한 각 채널의 중요도로 가중치를 부여.
  • 컨브넷 필터 시각화에 사용된 경사상승법 기법 사용. 
from tensorflow import keras
from tensorflow.keras.applications.vgg16 import preprocess_input,decode_predictions
from tensorflow.keras import layers, models
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import cv2
In [9]:
model = keras.applications.VGG16()
In [11]:
file_path = "/jupyterNotebook/images/test_images/ferrari_roma.jpeg"
img = cv2.imread(file_path)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
In [12]:
plt.imshow(img)
plt.show()

이미지 축소

In [13]:
img_shape = model.input.shape

while True:
    shape = img.shape
    row = int(shape[0]*(9/10))
    column = int(shape[1]*(9/10))
    temp_img = cv2.resize(img,(row,column))
    if(np.min( [temp_img.shape[0],temp_img.shape[1]] ) <= img_shape[1]):
        img = cv2.resize(img,(img_shape[1],img_shape[1]))
        break
    else:
        img = cv2.resize(img,(row,column))

img = np.expand_dims(img,[0])

데이터 전처리

In [14]:
plt.imshow(img[0])
plt.show()
In [15]:
img = preprocess_input(img) # standardization
In [16]:
img = tf.Variable(img)
In [17]:
plt.imshow(img[0].numpy().astype('uint8')[:,:,0])
plt.show()
In [19]:
preds = model.predict(img.numpy())
1/1 [==============================] - 2s 2s/step
In [21]:
print('Predicted:',decode_predictions(preds, top=3)[0])
Predicted: [('n04285008', 'sports_car', 0.3499788), ('n03100240', 'convertible', 0.2894608), ('n02814533', 'beach_wagon', 0.068147704)]

Sports Car에 대한 Grad-CAM 구하기

temp1_conv_layer = model.get_layer('block5_conv2')
temp2_conv_layer = model.get_layer('block5_conv3')
In [25]:
block5_temp1_model = models.Model(model.input,temp1_conv_layer.output)
block5_temp2_model = models.Model(temp2_conv_layer.input,model.output)
In [26]:
with tf.GradientTape() as tape:
    temp1_model_ouput = block5_temp1_model(img)
    temp1_model_ouput = tf.Variable(temp1_model_ouput)
    temp2_model_output = block5_temp2_model(temp1_model_ouput)[0,np.argmax(preds)]
In [27]:
grads = tape.gradient(temp2_model_output,temp1_model_ouput)

pooled_grads = tf.reduce_mean(grads,axis=(0,1,2))

pooled_grads_value = pooled_grads.numpy()
In [28]:
conv_layer_output_value = temp1_model_ouput[0].numpy()
In [29]:
for i in range(512):
    conv_layer_output_value[:,:,i] *= pooled_grads[i]
In [30]:
heatmap = np.mean(conv_layer_output_value,axis=-1)

Grad-CAM 그래프로 출력

 
plt.imshow(np.maximum(heatmap,0))
plt.colorbar()
plt.show()
스포츠 자동차 부분에 값이 활성화 된 것을 확인 할 수 있다.

 

원본 이미지와 겹치기 위한 원본 이미지와 같은 이미지로 변경

In [32]:
img = cv2.imread(file_path)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
In [33]:
heatmap = cv2.resize(heatmap, (img.shape[1],img.shape[0]))
In [34]:
plt.imshow(heatmap)
plt.colorbar()
plt.show()

heatmap RGB 포맷(0~255)으로 변경

In [39]:
heatmap_rgb = np.maximum(0,heatmap) # 0보다 작은 값들은 0으로 바꾼다. 
heatmap_rgb = (heatmap_rgb - np.min(heatmap_rgb))/(np.max(heatmap_rgb) - np.min(heatmap_rgb))
# minmax 정규화 -> 0~1로 정규화
heatmap_rgb = np.uint8(heatmap_rgb*255) # RGB포맷(0~255)으로 변경
In [51]:
heatmap = cv2.applyColorMap(heatmap_rgb, cv2.COLORMAP_JET)
In [53]:
plt.imshow(heatmap)
plt.colorbar()
plt.show()

이미지에 히트맵 적용

In [54]:
superimposed_img = heatmap*0.4 + img
superimposed_img = np.minimum(255,superimposed_img).astype('uint8')
In [55]:
plt.imshow(np.minimum(255,superimposed_img).astype('uint8'))
plt.colorbar()
plt.show()

'딥러닝' 카테고리의 다른 글

GAN개념과 DCGAN 구현  (0) 2022.07.12
stanford dogs 분석 및 학습하기  (1) 2022.06.23
컨브넷 필터 시각화  (0) 2022.06.23
Cat vs Dog 분류 모델 만들기  (0) 2022.06.18
Keras.1 Modeling  (0) 2022.06.18