DEEP.I - Lab

오프라인 공간의 지능화를 꿈꾸는 딥아이 연구실입니다.

Python/Tensorflow

[Tensorflow] 사전 학습된 VGG16 모델에서 특징맵 추출하기

Jongwon Kim 2020. 10. 23. 01:26
반응형

신경망 학습 모델의 특징맵은 (Feature Map) 단순 분류문제 이외에도 그림 1과 같이 RNN, LSTM, Tracking과 같은 다양한 알고리즘에서 매우 높은 빈도로 활용되고 있습니다. 특히 제가 요즘 주목하고 있는 RE-ID(Re-identification) 알고리즘에서 영상의 특징맵이 객체의 유사도를 비교하는데 활용되고 있는것이 상당히 흥미로웠습니다. 오늘 포스팅에서는 텐서플로우에서 사전 학습된 VGG16 모델을 이용한 특징맵 추출 방법을 간단히 알아보도록 하겠습니다.

 

 

그림1. Visual Tracking with fully Convolutional Networks. ICCV 2015

 

기본 시스템 환경은 다음과 같습니다. 윈도우에서 아나콘다 가상환경으로 구축하였으며 Spyder 내에서 코드를 구현하였습니다. 이전 포스팅을 참고하시면 빠르게 기본 환경을 구축하실 수 있습니다.

 

OS : Windows 10

Python : 3.8

Tensorflow : 2.2

CUDA : 10.1

cuDNN : 7.6.5

 

https://deep-eye.tistory.com/9

 

[Tensorflow] 텐서플로우에서 사전 학습된 VGG16 모델 불러오기

텐서플로우 설치 포스팅에 이어 사전 학습된 VGG 모델을 활용하는 방법을 살펴보겠습니다. VGG Network는 2014년 이미지넷 인식 학술대회에서 2등을 한 신경망 구조입니다. 본격적으로 층이 깊어지기

deep-eye.tistory.com

 

0. 소스코드 다운로드 (깃허브) : github.com/DEEPI-LAB/python-TensorFlow-Tutorials.git

 

DEEPI-LAB/python-TensorFlow-Tutorials

Contribute to DEEPI-LAB/python-TensorFlow-Tutorials development by creating an account on GitHub.

github.com

 

git clone 0 github.com/DEEPI-LAB/python-TensorFlow-Tutorials.git

 

1.사전 학습된 VGG16 모델 불러오기 (import)

 

import cv2
from matplotlib import pyplot
from tensorflow.keras.models import Model
from tensorflow.python.keras.applications.vgg16 import VGG16, preprocess_input
from tensorflow.python.keras.preprocessing.image import img_to_array

# 모델 불러오기
base_model = VGG16(weights='imagenet')
# 모델 확인하기
base_model.summary()

 

추출된 특징맵 전처리와 plot으로 확인하기 위해 opencvmatlotlib를 import 해줍니다. 모듈이 없다면, pip를 통해 설치해주시면 됩니다. 오늘은 사전 학습된 모델에서 입력된 영상이 어떻게 임베딩되는지 보기위한 방법이기에 Imagenet 기반으로 사전 학습된 VGG16 모델을 불러온 뒤, summary 함수를 통해 네트워크 구조를 확인합니다.

 

2.VGG16 모델 구조 (base_model.summary())

 

Model: "vgg16"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
predictions (Dense)          (None, 1000)              4097000   
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

 

 

 

3. VGG16 모델 자르기

 

# Feature Map 추출 모델 생성
model = Model(inputs = base_model.input,outputs = base_model.get_layer('block3_conv3').output)
model.summary()

 

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
=================================================================
Total params: 1,735,488
Trainable params: 1,735,488
Non-trainable params: 0
_________________________________________________________________

 

일반적으로는 사전 학습된 모델에서 새로운 데이터 학습이나 응용을 위한 미세 학습 (find-tuning)에는 마지막 컨볼루션 레이어에서 가까운 층을 선택하게됩니다. get_layer('추출을 원하는 레이어 이름').output 으로 새로운 모델을 지정해줍니다. 저는 입력과 가까운 층 'block3_conv3'을 선택했습니다.

 

 

4. 테스트 영상 입력으로 특징맵 확인하기

 

# 입력 영상 전처리
image = cv2.imread("1.jpg")
# 학습 모델에 맞게 영상 크기 수정
image = cv2.resize(image,dsize=(224,224))
image = img_to_array(image)
image = image.reshape((1, image.shape[0],image.shape[1],image.shape[2]))
image = preprocess_input(image)
# Feature Map 추출
feature_map = model.predict(image)

 

vgg16 모델 입력을 위해 영상을 224 x 224 크기로 수정한 뒤, 전처리하여 새롭게 생성된 모델에 입력해주시면 됩니다. Spyder를 이용한다면 다음과 같이 추출된 특징맵 데이터를 확인할 수 있습니다. 56x56 크기의 특징맵이 256개의 채널로 구성되어있음을 확인할 수 있습니다.

 

그림2. 영상 입력으로 추출된 특징맵

 

 

5. Plot으로 특징맵 확인하기

 

# plot 크기 square x square
square = 8
ix = 1
for i in range(square):
    for j in range(square):
        ax = pyplot.subplot(square,square,ix)
        ax.set_xticks([])
        ax.set_yticks([])
        # Feature Map
        pyplot.imshow(feature_map[0,:,:,ix-1])
        ix = ix + 1
pyplot.show()

 

square 크기는 한번에 확인하고 싶은 특징맵 채널 개수에 따라 설정하시면 됩니다. 정방행렬로 plot하기위해 2중 for문으로 구현하였습니다. 특징맵은 그림 3-4와 같이 추출됩니다.

 

그림 3. block3_conv3

 

그림 4. block5_conv3

 

 

6. 최종 코드

 

# -*- coding: utf-8 -*-
"""
Created on Fri Oct 23 00:32:45 2020

@author: Deep.i inc.

"""
import cv2
from matplotlib import pyplot
from tensorflow.keras.models import Model
from tensorflow.python.keras.applications.vgg16 import VGG16, preprocess_input
from tensorflow.python.keras.preprocessing.image import img_to_array

# 모델 불러오기
base_model = VGG16(weights='imagenet')
base_model.summary()
# Feature Map 추출 모델 생성
model = Model(inputs = base_model.input,outputs = base_model.get_layer('block5_conv3').output)
model.summary()

# IMAGE PREPOSSESSING
image = cv2.imread("1.jpg")
image = cv2.resize(image,dsize=(224,224))
image = img_to_array(image)
image = image.reshape((1, image.shape[0],image.shape[1],image.shape[2]))
image = preprocess_input(image)
# Feature Map 추출
feature_map = model.predict(image)


# plot 크기 square x square
square = 8
ix = 1
for i in range(square):
    for j in range(square):
        ax = pyplot.subplot(square,square,ix)
        ax.set_xticks([])
        ax.set_yticks([])
        # Feature Map
        pyplot.imshow(feature_map[0,:,:,ix-1])
        ix = ix + 1
pyplot.show()

 

FeatureMap_Extraction.zip
0.36MB

 

 

 

# 머신러닝 프로젝트 제작, 상담 및 컨설팅  / 머신러닝 접목 졸업작품 컨설팅

# 데이터 가공, 수집, 라벨링 작업 / C, 파이썬 프로그램 제작

# email : deepi.contact.us@gmail.com

# site : www.deep-i.net

반응형