클래스 활성화의 히트맵 시각화
클래스 활성화 맵(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 |