from tensorflow.python.keras.applications.vgg16 import VGG16
model = VGG16(weights = 'imagenet')
- VGG16을 위한 이미지 전처리
from tensorflow.python.keras.preprocessing import image
from tensorflow.python.keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
img_path = './datasets/creative_commons_elephant.jpg'
img = image.load_img(img_path, target_size = (224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis= 0) # (1, 224, 224, 3)
x = preprocess_input(x) # 데이터 전처리 - Imagenet의 전처리는 조금 다르다.
이를 통해,
decode_predictions 함수는 ImageNet 데이터셋에 대한 top 매개변수 만큼의 최상위 항목을 반환해 줍니다.
다음은 이미지에서 가장 아프리카 코끼리 같은 부위를 시각화하기 위해 Grad_CAM 처리 과정을 구현한 것입니다.
import tensorflow as tf
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 예측 벡터의 '아프리카 코끼리' 항목
african_elephant_output = model.output[:, 386]
# VGG16의 마지막 합성곱 층인 block5_conv3 층의 특성 맵
last_conv_layer = model.get_layer('block5_conv3')
# block5_conv3의 특성 맵 출력에 대한 '아프리카 코끼리' 클래스의 그래디언트
grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]
# 특성 맵 채널별 그래디언트 평균 값이 담긴 (512,) 크기의 벡터
pooled_grads = K.mean(grads, axis=(0, 1, 2))
# 샘플 이미지가 주어졌을 때 방금 전 정의한 pooled_grads와 block5_conv3의 특성 맵 출력을 구합니다
iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]])
# 두 마리 코끼리가 있는 샘플 이미지를 주입하고 두 개의 넘파이 배열을 얻습니다
pooled_grads_value, conv_layer_output_value = iterate([x])
# "아프리카 코끼리" 클래스에 대한 "채널의 중요도"를 특성 맵 배열의 채널에 곱합니다
for i in range(512):
conv_layer_output_value[:, :, i] *= pooled_grads_value[i]
# 만들어진 특성 맵에서 채널 축을 따라 평균한 값이 클래스 활성화의 히트맵입니다
heatmap = np.mean(conv_layer_output_value, axis=-1)
heatmap을 얻은 뒤, 정규화를 진행하고
다음과 같은 사진을 얻었습니다.
OpenCv를 활용하여 이미지에 덧붙이면
import cv2
img = cv2.imread(img_path)
# heatmap을 원본 이미지 크기에 맞게 변경
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
# heatmap을 RGB 포맷으로 변환
heatmap = np.uint8(255 * heatmap)
# 히트맵으로 변환
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
# 0.4는 히트맵의 강도
superimposed_img = heatmap * 0.4 + img
cv2.imwrite('./datasets/elephant_cam.jpg', superimposed_img)
다음과 같은 히트맵을 얻을 수 있습니다.
( 결과가 다를 수 있습니다 )
Reference
본 코드의 내용은 '케라스 창시자에게 배우는 딥러닝' 교재의 github를 참조 하였습니다. --
from keras.applications import VGG16
from keras import backend as K
model = VGG16(weights = 'imagenet',
include_top = False)
layer_name = 'block3_conv1'
filter_index = 0
layer_output = model.get_layer(layer_name).output
loss = K.mean(layer_output[:, :, :, filter_index])
# 입력에 대한 손실의 그래디언트 구하기
grads = K.gradients(loss, model.input)[0]
# 그래디언트 정규화 ( 경사 상승법 과정을 부드럽게 하기 위하여 사용 )
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5) # 1e-5는 0 나눗셈 방지, 이를 gradient-clipping 이라고 함.
# 손실값과 그래디언트 값을 얻기 위함.
# 주어진 입력 이미지에 대해 손실 텐서와 그래디언트 텐서를 계산한다.
iterate = K.function([model.input], [loss, grads])
import numpy as np
loss_value, grads_value = iterate([np.zeros((1, 150, 150, 3))])
# 확률적 경사 상승법을 사용한 손실 최대화하기
input_img_data = np.random.random((1, 150, 150, 3)) * 20 + 128.
step = 1.
for i in range(40):
loss_value, grads_value = iterate([input_img_data])
input_img_data += grads_value * step
지금 계속 신경망의 필터에 경사상승법을 적용하여 어떤 패턴에 반응을 하는지 보기위한 작업을 하고 있습니다.
다음은 텐서를 이미지 형태로 변환하기 위한 util function입니다.
def deprocess_image(x):
x -= x.mean()
x /= (x.std() + 1e-5)
x *= 0.1
x += 0.5
x = np.clip(x, 0, 1)
x *= 255
x = np.clip(x, 0, 255).astype('uint8')
return x
다음 함수는 필터 활성화를 최대화하는 패턴을 이미지 텐서로 출력합니다.
또한 위의 모든 함수를 사용하여 패턴을 출력해봅시다.
def generate_pattern(layer_name, filter_index, size = 150):
# 주어진 층과 필터의 활성화를 최대화 하기위한 loss 정의
layer_output = model.get_layer(layer_name).output
loss = K.mean(layer_output[:, :, :, filter_index])
grads = K.gradients(loss, model.input)[0]
# grad clipping
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
# 입력 이미지에 대한 손실과 그래디언트 반환
iterate = K.function([model.input], [loss, grads])
# 회색이미지로 시작
input_img_data = np.random.random((1, size, size, 3)) * 20 + 128.
step = 1.
for i in range(40):
loss_value, grads_value = iterate([input_img_data])
input_img_data += grads_value * step
img = input_img_data[0]
return deprocess_image(img)
위 함수들을 이용하여 다른 층도 살펴봅시다.
layer_name = 'block1_conv1'
size = 64
margin = 5
# 결과를 담은 빈 검은 이미지
results = np.zeros((8 * size + 7 * margin , 8 * size + 7 * margin, 3), dtype='uint8')
for i in range(8):
for j in range(8):
# layer_name에 있는 i + (j*8) 번째 필터에 대한 패턴 생성
filter_img = generate_pattern(layer_name, i + (j * 8), size = size)
horizontal_start = i * size + i * margin
horizontal_end = horizontal_start + size
vertical_start = j * size + j * margin
vertical_end = vertical_start + size
results[horizontal_start:horizontal_end, vertical_start: vertical_end, :] = filter_img
plt.figure(figsize=(20, 20))
plt.imshow(results)
다음과 같은 패턴을 통해 여러분의 모델이 어떤 패턴을 인식하는지 알아 볼 수 있겠네요. (이미지는 일부분만 캡쳐)
Reference
본 코드의 내용은 '케라스 창시자에게 배우는 딥러닝' 교재의 github를 참조 하였습니다. --
We propose a novel semantic segmentation algorithm by learning a deep deconvolution network. We learn the net- work on top of the convolutional layers adopted from VGG 16-layer net. The deconvolution network is composed of deconvolution and unpooling layers, which identify pixel- wise class labels and predict segmentation masks. We ap- ply the trained network to each proposal in an input im- age, and construct the final semantic segmentation map by combining the results from all proposals in a simple man- ner. The proposed algorithm mitigates the limitations of the existing methods based on fully convolutional networks by integrating deep deconvolution network and proposal-wise prediction; our segmentation method typically identifies de- tailed structures and handles objects in multiple scales nat- urally. Our network demonstrates outstanding performance in PASCAL VOC 2012 dataset, and we achieve the best ac- curacy (72.5%) among the methods trained without using Microsoft COCO dataset through ensemble with the fully convolutional network.
우리는 깊은 deconvolution network로 학습이 가능한 semantic segmentation 알고리즘을 제안한다.
VGG16 network를 기반으로 실험하였다.
Deconvolution network는 deconvolution과 unspooling layers로 구성되어 있으며, pixel-wise 클래스들을 식별하고 구분된 마스크를 예측한다.
우리는 각 이미지에 훈련된 네트워크를 사용하며, 각각의 모델로부터 나온 결과를 조합하여 결과를 구성한다.
제안 알고리즘은 FCN의 한계점을 보완한다.
우리의 seg방법은 좀더 디테일하게 구조를 식별하고 다양한 크기의 객체를 자연스럽게 다룰 수 있다.
PASCAL VOC 2012 dataset으로 이미 성능을 증명했으며, COCO 데이터셋을 사용하지 않고 FCN 앙상블 모델을 통해 best acc를 달성하였다.
Reference
Noh, H., Hong, S., & Han, B. (2015). Learning deconvolution network for semantic segmentation. InProceedings of the IEEE international conference on computer vision(pp. 1520-1528).