이건 convolution을 각 레이어 및 필터 마다 나오는 이미지 혹은 필터값을 특정하기 위해서 찾은 강의를 따라한 것이다.

아래는 그 주소이다
https://machinelearningmastery.com/how-to-visualize-filters-and-feature-maps-in-convolutional-neural-networks/

This tutorial is divided into four parts; they are:

  1. Visualizing Convolutional Layers
  2. Pre-fit VGG Model
  3. How to Visualize Filters
  4. How to Visualize Feature Maps

환경 변수

tensorflow = 2.4.0
kereas = 2.4.3

1. Visualizing Convolutional Layers

신경망 모델은 일반적으로 불투명하다고합니다. 이것은 특정 결정이나 예측을 한 이유를 설명하는 데 부족하다는 것을 의미합니다.

컨볼 루션 신경망은 이미지 데이터와 함께 작동하도록 설계되었으며 그 구조와 기능은 다른 유형의 신경망보다 이해하기 어려운 측면이 있습니다.

특히, 모델은 작은 선형 필터와 활성화 맵 또는보다 일반적으로 기능 맵이라는 필터를 적용한 결과로 구성됩니다.

필터와 기능 맵을 모두 시각화 할 수 있습니다.

예를 들어, 라인 감지기와 같은 작은 필터를 설계하고 이해할 수 있습니다. 학습 된 컨볼 루션 신경망 내에서 필터를 시각화하면 모델 작동 방식에 대한 통찰력을 얻을 수 있습니다.

입력 이미지에 필터를 적용하고 이전 계층에서 출력 한 기능 맵에 생성 된 기능 맵은 모델의 특정 입력 지점에서 모델이 갖는 내부 표현에 대한 통찰력을 제공 할 수 있습니다.

이 튜토리얼에서는 컨볼 루션 신경망을 시각화하는 두 가지 접근 방식을 모두 살펴볼 것입니다.

2. Pre-fit VGG Model

시각화 해볼 모델은 VGG16입니다. keras에서 불러오기도 쉽고 사용하기도 쉬운데 성능이 좋기 때문입니다.

 

# load vgg model
from keras.applications.vgg16 import VGG16
# load the model
model = VGG16()
# summarize the model
model.summary()

# load vgg model
from keras.applications.vgg16 import VGG16
# load the model
model = VGG16()
# summarize the model
model.summary()

 

 

예제를 실행하면 모델 가중치가 메모리에로드되고로드 된 모델구조가 인쇄됩니다.

 

Model: "vgg16"
_________________________________________________________________
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    
_________________________________________________________________
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
_________________________________________________________________

Process finished with exit code 0

3. How to Visualize Filters

수행 할 가장 간단한 시각화는 학습 된 필터를 직접 플로팅하는 것입니다.

신경망 용어에서 학습 된 필터는 단순히 가중치이지만 필터의 특수한 2 차원 구조로 인해 가중치 값은 서로 공간적 관계를 가지며 각 필터를 2 차원 이미지로 플로팅하는 것은 의미가 있습니다

첫 번째 단계는 모델의 필터를 검토하여 작업해야하는 사항을 확인하는 것입니다.

이전 섹션에서 인쇄 된 모델 요약은 각 레이어의 출력 모양 (예 : 결과 피쳐 맵의 모양)을 요약합니다. 네트워크에서 필터 (가중치)의 모양에 대한 아이디어는 제공하지 않으며 레이어 당 총 가중치 수만 제공합니다.

model.layers 속성을 통해 모델의 모든 계층에 액세스 할 수 있습니다 .

 

각 레이어에는 layer.name 속성이 있습니다. 여기서 컨볼 루션 레이어에는 block # _conv # 와 같은 명명 컨볼 루션이 있습니다. 여기서 ' # '는 정수입니다. 따라서 각 레이어의 이름을 확인하고 ' conv ' 문자열이 포함되지 않은 레이어는 건너 뛸 수 있습니다.

 

# summarize filter shapes
for layer in model.layers:
	# check for convolutional layer
	if 'conv' not in layer.name:
		continue

 

 

각 컨벌루션 계층에는 두 세트의 가중치가 있습니다.

하나는 필터 블록이고 다른 하나는 바이어스 값 블록입니다. layer.get_weights () 함수 를 통해 액세스 할 수 있습니다. 이러한 가중치를 검색 한 다음 그 모양을 요약 할 수 있습니다.

 

# get filter weights
filters, biases = layer.get_weights()
print(layer.name, filters.shape)

 

전체 코드 입니다.

 

# summarize filters in each convolutional layer
from keras.applications.vgg16 import VGG16
from matplotlib import pyplot
# load the model
model = VGG16()
# summarize filter shapes
for layer in model.layers:
	# check for convolutional layer
	if 'conv' not in layer.name:
		continue
	# get filter weights
	filters, biases = layer.get_weights()
	print(layer.name, filters.shape)

 

밑에는 그 결과 입니다.

 

     block1_conv1 (3, 3, 3, 64)
     block1_conv2 (3, 3, 64, 64)
     block2_conv1 (3, 3, 64, 128)
     block2_conv2 (3, 3, 128, 128)
     block3_conv1 (3, 3, 128, 256)
     block3_conv2 (3, 3, 256, 256)
     block3_conv3 (3, 3, 256, 256)
     block4_conv1 (3, 3, 256, 512)
     block4_conv2 (3, 3, 512, 512)
     block4_conv3 (3, 3, 512, 512)
     block5_conv1 (3, 3, 512, 512)
     block5_conv2 (3, 3, 512, 512)
     block5_conv3 (3, 3, 512, 512)

 

모든 컨벌루션 레이어는 작고 해석하기 쉬운 3x3 필터를 사용한다는 것을 알 수 있습니다.

 

컨벌루션 신경망의 구조적 문제는 필터의 깊이가 필터에 대한 입력 깊이 (예 : 채널 수)와 일치해야한다는 것입니다.

 

빨강, 녹색 및 파랑에 대해 3 개의 채널이있는 입력 이미지의 경우 각 필터의 깊이가 3임을 알 수 있습니다 (여기서는 채널-마지막 형식으로 작업 함). 하나의 필터를 각 채널에 대해 하나씩 세 개의 이미지가있는 플롯으로 시각화하거나 세 개를 모두 단일 색상 이미지로 압축하거나 첫 번째 채널을보고 다른 채널이 동일하게 보일 것이라고 가정 할 수도 있습니다. 문제는 시각화하고 싶은 63 개의 다른 필터가 있다는 것입니다.

 

다음과 같이 첫 번째 레이어에서 필터를 검색 할 수 있습니다.

 

# retrieve weights from the second hidden layer
filters, biases = model.layers[1].get_weights()

 

가중치 값은 0.0을 중심으로하는 작은 양수 및 음수 값일 수 있습니다.

 

값을 쉽게 시각화 할 수 있도록 0-1 범위로 정규화 할 수 있습니다.(정규화에 대한 자세한 이야기는 다른 페이지에서 자세히 다루도록 하겠습니다.)

 

# normalize filter values to 0-1 so we can visualize them
f_min, f_max = filters.min(), filters.max()
filters = (filters - f_min) / (f_max - f_min)

 

이제 블록의 64 개 중 처음 6 개 필터를 열거하고 각 필터의 3 개 채널을 각각 플로팅 할 수 있습니다.

 

matplotlib 라이브러리를 사용하고 각 필터를 새로운 서브 플롯 행으로 플로팅하고 각 필터 채널 또는 깊이를 새 열로 플로팅합니다.

 

# plot first few filters
n_filters, ix = 6, 1
for i in range(n_filters):
	# get the filter
	f = filters[:, :, :, i]
	# plot each channel separately
	for j in range(3):
		# specify subplot and turn of axis
		ax = pyplot.subplot(n_filters, 3, ix)
		ax.set_xticks([])
		ax.set_yticks([])
		# plot filter channel in grayscale
		pyplot.imshow(f[:, :, j], cmap='gray')
		ix += 1
# show the figure
pyplot.show()

 

아래는 전체 코드입니다

 

# cannot easily visualize filters lower down
from keras.applications.vgg16 import VGG16
from matplotlib import pyplot
# load the model
model = VGG16()
# retrieve weights from the second hidden layer
filters, biases = model.layers[1].get_weights()
# normalize filter values to 0-1 so we can visualize them
f_min, f_max = filters.min(), filters.max()
filters = (filters - f_min) / (f_max - f_min)
# plot first few filters
n_filters, ix = 6, 1
for i in range(n_filters):
	# get the filter
	f = filters[:, :, :, i]
	# plot each channel separately
	for j in range(3):
		# specify subplot and turn of axis
		ax = pyplot.subplot(n_filters, 3, ix)
		ax.set_xticks([])
		ax.set_yticks([])
		# plot filter channel in grayscale
		pyplot.imshow(f[:, :, j], cmap='gray')
		ix += 1
# show the figure
pyplot.show()

 

예제를 실행하면  각 필터에 대해 한 행, 각 채널에 대해 한 열에 대해 18개의 이미지가 출력된다.

 

어떤 경우에는 필터가 채널(첫 번째 행)에서 동일하고 다른 경우(마지막 행)필터가 다르다는 것을 알 수 있습니다.

어두운 사각형은 weight 부분이 작은 부분이고 밝은 사각형은 큰 weight를 나타내는데 이 직관을 활용하면 첫 번째 행의 필터가 왼쪽 상단의 빛에서 오른쪽 하단의 어두운 곳으로의 그라디언트를 감지하는다는 것을 알 수 있습니다.

시각화가 있지만 첫 번째 컨볼 루션 레이어의 64 개 필터 중 처음 6 개만 볼 수 있습니다. 64 개의 모든 필터를 하나의 이미지로 시각화하는 것이 가능합니다.

 

두 번째 컨벌루션 레이어에서 필터를 살펴 보려면 다시 64 개의 필터가 있지만 각 필터에는 입력 특성 맵과 일치하는 64 개의 채널이 있음을 알 수 있습니다. 64 개 필터 모두에 대해 한 행에있는 모든 64 개 채널을 보려면 (64x64) 4,096 개의 서브 플롯이 필요하므로 세부 정보를 확인하기 어려울 수 있습니다.

 

'vison_study' 카테고리의 다른 글

Chap3. 신경망 (밑바닥부터 딥러닝)  (0) 2021.12.27
2.1 퍼셉트론 (밑바닥부터 딥러닝)  (0) 2021.12.22
Torch tensor to numpy(in use Opencv)  (0) 2021.06.28
Vison Study #2  (0) 2021.06.27

+ Recent posts