입력층이나 출력층과 달리 은닉층의 뉴런은 사람 눈에는 보이지 않는다.

위의 그림 속 신경망은 3층으로 구성되어있지만 가중치를 갖는 층이 2개이기 때문에 2층 신경망 이라고 한다.

 

y=0 (b+w1x1+w2x2<=0)
y=1 (b+w1x1+w2x2>0)
 

편향(bias)은 하나의 뉴런으로 입력된 모든 값을 다 더한 다음에(가중합이라고 합니다) 이 값에 더 해주는 상수입니다. 이 값은 하나의 뉴런에서 활성화 함수를 거쳐 최종적으로 출력되는 값을 조절하는 역할을 함

 

활성화 함수(activateion function) : 입력 신호의 총합을 출력 신호로 변환하는 함수. 변환된 신호를 다음 뉴런에 전달한다. 입력 신호의 총합이 활성화를 일으키는지를 정하는 역할을 한다.

 

 
a = b+w1x1+w2x2 #가중치가 달린 입력 신호와 편향의 총합
y=h(a) #a를 함수 h()에 넣어 y를 출력

 

3-2 활성화함수


시그모이드 함수 (sigmoid function)

 

신경망에서는 활성화 함수로 시그모이드 함수를 이용하여 신호를 변환하고 그 변환된 신호를 다음 뉴런에 전달한다.

  • 시그모이드 함수 구현하기
    브로드캐스트 기능: 넘파이 배열과 스칼라값의 연산을 넘파이 배열의 원소 각각과 스칼라값의 연산으로 바꿔 수행한다.
import numpy as np
import matplotlib.pylab as plt

def sigmoid(x):
  return 1/(1+np.exp(-x))

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
#브로드캐스트
#넘파이 배열과 스칼라값의 연산을 넘파이 배열의 원소 각각과 스칼라값의 연산으로 바꿔 수행

plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()
 
 

계단함수 (step function)

 

def step_function(x):
  return np.array(x>0, dtype=np.int)
  ##numpy 배열을 인수로 넣을 수 있게 하는 방법
    #x = np.array([-1.0, 1.0, 2.0])
    #y = x>0
    #y를 출력하면 0보다 큰 x값은 True로, 0보다 작거나 같은 값은 False로 나온다.
    #booleaan값을 int형으로 변환시키면 True는 0, False는 1이다.
        
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) 
plt.show()
 
 

ReLU함수 (rectified linear unit)

 
그림 7. ReLU 수식

def relu(x):
  return np.maximum(0, x)

x = np.arange(-5.0, 5.0, 0.1)
y= relu(x)
plt.plot(x, y)
plt.show()
 
 
그림 8. ReLU 함수

 

3-3 다차원 배열의 계산


np.ndim(): 배열의 차원 수 확인
배열.shape: 배열의 형상 확인

import numpy as np

#1차원 배열
A = np.array([1,2,3,4])
np.ndim(A)
A.shape #튜플로 반환

#2차원 배열
B = np.array([[1,2], [3,4], [5,6]])
np.ndim(B)
B.shape
'''
[[1 2]
 [3 4]
 [5 6]]
2
(3, 2)
'''
 
 

행렬의 곱

 
 
#위 그림을 파이썬으로 구현
A = np.array([[1,2], [3,4]]) #2*2행렬
B = np.array([[5,6], [7,8]]) #2*2행렬
np.dot(A, B)
'''
(2, 2)
(2, 2)
array([[19, 22],
       [43, 50]])
'''​

 

신경망에서의 행렬 곱

X = np.array([1,2])
X.shape #(2,)

W = np.array([[1,3,5], [2,4,6]])
print(W)
'''
[[1 3 5]
 [2 4 6]]
'''
W.shape #(2,3)

Y = np.dot(X, W)
print(Y)
print(Y.shape)
'''
[ 5 11 17]
(3,)
'''
 

 

3층 신경망 구현하기

 
 

은닉층에서의 가중치 합(가중 신호와 편향의 총합)을 a로 표기하고 활성화 함수 h( )로 변환된 신호를 z로 표현한다.

 

 

1층의 '가중치 부분'을 행렬식으로 간소화하면

 
 
def init_network():
  network = {}
  network['w1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
  network['b1'] = np.array([0.1, 0.2, 0.3])

  network['w2'] = np.array([[0.1, 0.4], [0.2, 0.5],[0.3, 0.6]])
  network['b2'] = np.array([0.1, 0.2])

  network['w3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
  network['b3'] = np.array([0.1, 0.2])
  return network

def forward(network, x):
  w1, w2, w3 = network['w1'], network['w2'], network['w3']
  b1, b2, b3 = network['b1'], network['b2'], network['b3']

  a1 = np.dot(x,w1) + b1
  z1 = sigmoid(a1)
  a2 = np.dot(z1, w2) + b2
  z2 = sigmoid(a2)
  a3 = np.dot(z2, w3) + b3
  z3 = sigmoid(a3)
  return z3
  
network = init_network()

x = np.array([1.0, 0.5])
y = forward(network, x)
print(y) # [0.57855079 0.66736228]

 

3-4. 출력층 설계하기

기계학습 문제는 분류(classification)와 회귀(regression)로 나뉜다.
일반적으로 회귀에는 항등함수를 분류에는 소프트맥스 함수를 출력층의 활성화 함수로 사용한다.

 

항등 함수와 소프트맥스 함수 구현하기

  • 항등함수(identity function): 입력을 그대로 출력
  • 소프트맥스 함수(softmax function):

def softmax(a):
  exp_a = np.exp(a)
  sum_exp_a = np.sum(exp_a)
  y = exp_a / sum_exp_a
  
  return y

a = np.array([0.3, 2.9, 4.0])
print(softmax(a)) # [0.01821127 0.24519181 0.73659691]

 

소프트맥스 함수 구현 시 주의점

지수함수를 사용하는 소프트맥스 함수는 '오버플로'의 문제가 발생해 수치가 '불안정'해질 수 있는 문제점이 있다.

  • 오버플로(overflow) : 표현할 수 있는 수의 범위가 한정되어 너무 큰값은 표현할 수 없다.
  • 소프트맥스 함수 구현 개선

-> 소프트맥스의 지수 함수를 계산할 때 어떤 정수를 더해도(혹은 빼도) 결과는 바뀌지 않는다.
-> C '에 어떤 값을 대입해도 상관없지만 오버플로를 막기 위해 입력 신호 중 최댓값을 이용하는 것이 일반적이다.

 

 
def softmax(a):
  c = np.max(a)
  exp_a = np.exp(a-c) # 오버플로우 대책
  sum_exp_a = np.sum(exp_a)
  y = exp_a / sum_exp_a
  
  return y​

 

소프트맥스 함수의 특징

  • 출력값은 0에서 1.0 사이의 실수이다.
  • 출력의 총합은 1이다. -> 확률로 해석가능 (엄밀히 말하자면 확률은 아님, score라고 말하기도 한다.)
  • 지수함수가 단조 증가 함수 이기 때문에 소프트맥스 함수를 적용해도 각 원소의 대소 관계는 변하지 않는다. 결과적으로 신경망으로 분류할 때는 출력층의 소프트맥스 함수를 생략해도 된다.
                                  •  

'vison_study' 카테고리의 다른 글

2.1 퍼셉트론 (밑바닥부터 딥러닝)  (0) 2021.12.22
Torch tensor to numpy(in use Opencv)  (0) 2021.06.28
Vison Study #2  (0) 2021.06.27
Vison_study #1  (0) 2021.06.27

2-1. 퍼셉트론(Perceptron)


퍼셉트론(perceptron)은 프랑크 로젠블라트(Fank Rosenblatt)가 1957년에 고안안 알고리즘이다. 이 퍼셉트론

퍼셉트론(perceptron)은 프랑크 로젠블라트(Fank Rosenblatt)가 1957년에 고안한 알고리즘이다. 이 퍼셉트론이 바로 신경망(딥러닝)의 기원이 되는 알고리즘이다.

퍼셉트론은 다수의 신호(흐름이 있는)를 입력으로 받아 하나의 신호를 출력한다. 퍼셉트론은 이 신호를 입력으로 받아 '흐른다/안 흐른다'(1 또는 0)이라는 정보를 앞으로 전달한다.

 
그림 1. 입력이 2개인 퍼셉트론
 

위의 그림에서,

  • x_1​과 x_2 ​는 입력 신호, y​는 출력 신호, w_1​과 w_2​는 가중치(weight)를 의미한다.
  • 원을 뉴런 또는 노드라고 부른다.
  • 입력 신호가 뉴런에 보내질 때는 각각 고유한 가중치가 곱해진다(w_1x_1,w_2,x_2​).
  • 뉴런에서 전달 받은 신호의 총합이 임계값 θ를 넘을 때만 1을 출력

 

2-2. 단순한 논리 회로


A. AND 게이트

 

그림 2. AND게이트 진리표
그림 3. AND 단층 퍼셉트론 시각화

위의 표는 AND게이트의 진리표이며 이 AND게이트를 퍼셉트론으로 표현해보자. 이를 위해서는 ​ w_1, w_2, θ 의 값을 적절하게 정해야 한다.

예를 들어 , (w_1, w_2, θ) = (0.5, 0.5, 0.7) 일 때, AND 게이트의 조건을 만족한다.

 

B. NAND 게이트와 OR 게이트

NAND 게이트는 Not AND를 의미하며 AND 게이트의 출력을 반대로한 것과 같다.

(w_1, w_2, θ) = (-0.5, -0.5, -0.7)

그림 4. NAND게이트 진리표
그림 5. OR게이트 NAND게이트 퍼셉트론 시각화

 

OR 게이트는 입력 신호 중 하나 이상이 1이면 출력이 1이 되는 논리 회로다.

그림 6. OR게이트 진리표

 

C. XOR 게이트

XOR 게이트는 베타적 논리합 이라는 논리 회로다.

 
그림 7. XOR게이트 진리표

그림 8. XOR게이트 퍼셉트론 시각화
그림 9. XOR게이트 논리 회로도
그림 10. 논리 회로도의 진리표

그림 8에서 보이는 것과 같이 기존의 게이트에서 보이지 않던 비선형적인 성질이 보인다. 따라서 하나의 게이트로 구현할 수 없어서 기존의 게이트를 조합하는 형식으로 구현하였다.

 

'vison_study' 카테고리의 다른 글

Chap3. 신경망 (밑바닥부터 딥러닝)  (0) 2021.12.27
Torch tensor to numpy(in use Opencv)  (0) 2021.06.28
Vison Study #2  (0) 2021.06.27
Vison_study #1  (0) 2021.06.27

딥러닝에서 어떤 모델을 사용하든 모델을 분석하는 과정을 train code를 사용하거나 test code를 사용하는 와중에 값을 확인할 때, 일부 vison 모델에서는 결과값을 opencv로 확인하고 싶을 때의 과정을 정리했다.

 

여기서 사용한 모델은 Yolact모델이다. (Yolact 모델 정리는 추후 backbone정리가 마무리가 되면 진행할 예정.. fpn과정의 연산이 모듈형태로 foward연산이 자동으로 실행돼서 연산과정을 확인할 수 없어서 시간이 조금 걸릴것으로 예상됨)

 

여기서는 mask가 씌워지는 결과는 각각 확인하고 싶었다.

 

 

뭔가 마스크라는 변수에 15개(object)의 텐서가 들어가 있다 현재 이 연산은 Tensor형태로 gpu에서 연산중이니 opencv에서 확인하기 위해서는 변환하는 과정이 있어야 한다.
gpu -> cpu(메모리에 값을 복사) -> byte() float형태의 값을 integer값으로 변환해줘야 opencv에서 사용가능 -> numpy (tensor값을 numpy로 변환해야 opencv에서 확인가능)

 

# 실제 코드
(masks[0]* 255).byte().cpu().numpy()
cv2.imshow("test1",(masks[0]* 255).byte().cpu().numpy())
cv2.waitKey(0)

 

  • 변환결과
  •  
  • 변과결과 확인
  •  

마스킹 형태가 잘 나온걸 확인할 수 있다.

 

p.s
train이나 test중간의 값을 확인하기 하다가 보면 tensor값의 경우 torch.Size([4, 3, 32, 32])
이런식으로 channel값이 바뀌어 있는 경우가 있는데 이 경우에는 opencv 형식으로 변환해줘야 한다.

# torch.Size([4, 3, 32, 32]) 일 때 train_t = np.transpose(train, (0, 2, 3, 1)) train_t.shape

 

출력
torch.Size([4, 32, 32, 3])
​

'vison_study' 카테고리의 다른 글

Chap3. 신경망 (밑바닥부터 딥러닝)  (0) 2021.12.27
2.1 퍼셉트론 (밑바닥부터 딥러닝)  (0) 2021.12.22
Vison Study #2  (0) 2021.06.27
Vison_study #1  (0) 2021.06.27

기능 맵을 시각화하는 방법

기능 맵이라고하는 활성화 맵은 입력 이미지 또는 다른 기능 맵과 같은 입력에 필터를 적용한 결과를 캡처합니다.

특정 입력 이미지에 대한 특성 맵을 시각화하는 아이디어는 특성 맵에서 감지되거나 보존되는 입력 특성을 이해하는 것입니다. 입력에 가까운 기능 맵은 작거나 세분화 된 세부 사항을 감지하는 반면 모델 출력에 가까운 기능 맵은보다 일반적인 기능을 캡처합니다.
(1pixel이 의미하는 바가 layer를 거치기 전에는 부리의 일부분 깃털의 일부분이라면 layer가 진행되면 진행될수록 부리, 깃털, 날개, 몸톰, 새, 이미지천체 한 픽셀에 담기는 데이터 정보가 점점 커져간다. 이것 때문에 피라미드 구조가 나오게 됨)

기능 맵의 시각화를 탐색하려면 활성화를 만드는 데 사용할 수있는 VGG16 모델에 대한 입력이 필요합니다. 간단한 새 사진을 사용합니다. 특히, Chris Heald가 촬영 한 Robin 은 허용 라이센스에 따라 릴리스되었습니다.

사진을 다운로드하고 파일 이름이 ' bird.jpg '인 현재 작업 디렉토리에 배치합니다

STEP1. - 먼저 이미지를 VGG16에서 사용하는 input size로 가져옵니다

데이터 불러오기 -> 데이터 전처리 -> 모델 train&val -> 모델 test -> inference(service)
[학습에서는 데이터의 dependency가 강력하기 때문에 데이터의 일관성이 굉장이 중요함. 본 이미지 데이터 분석은 나중에 이미지 프로젝트 진행시 이미지 데이터를 분석을 하기 위한 초석으로 보면 될 듯 싶다.

 

import cv2
from tensorflow.keras.models import Model
import numpy as np
from keras.applications.vgg16 import VGG16
from matplotlib import pyplot

#load the image with the required shape
img = cv2.imread('bird.jpg',cv2.COLOR_BGR2RGB)
img = cv2.resize(img,(224,224))
print(img.__class__)
print(img.shape)

 

STEP2. - 데이터 차원 확장 및 전처리

데이터 차원확장은 이번에 사용하는 데이터가 하나이기 때문에 따로 차원확장을 진행해줬다. [ N, H, W, C], [ N, C, H, W] C,H,W의 순서는 opencv냐 아니냐에 달라질 수는 있으나 (tensorflow, pytorch의 차이도 존재) 기본적으로 4차원으로 들어가야한다.

 

img = np.expand_dims(img, axis=0) # 차원확대

img = img/255.0 # 이미지 scaling

 

STEP3. - 모델을 불러오기

# load the model
model = VGG16()
# summarize featu

model = Model(inputs=model.inputs, outputs=model.layers[1].output)

STEP4. - 예측하기

feature_maps = model.predict(img)

STEP5. - 결과확인

# plot all 64 maps in an 8x8 squares
square = 8
ix = 1
for _ in range(square):
	for _ in range(square):
		# specify subplot and turn of axis
		ax = pyplot.subplot(square, square, ix)
		ax.set_xticks([])
		ax.set_yticks([])
		# plot filter channel in grayscale
		pyplot.imshow(feature_maps[0, :, :, ix-1], cmap='gray')
		ix += 1
# show the figure
pyplot.show()

 

각 레이어에 대한 이미지 feature값들도 확인해보자

input에서 output으로 나오는 각각의 layer의 이미지들을 출력값으로 뽑은 이미지들이다.

# visualize feature maps output from each block in the vgg model
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import Model
from matplotlib import pyplot
from numpy import expand_dims
# load the model
model = VGG16()
# redefine model to output right after the first hidden layer
ixs = [2, 5, 9, 13, 17]
outputs = [model.layers[i].output for i in ixs]
model = Model(inputs=model.inputs, outputs=outputs)
# load the image with the required shape
img = load_img('bird.jpg', target_size=(224, 224))
# convert the image to an array
img = img_to_array(img)
# expand dimensions so that it represents a single 'sample'
img = expand_dims(img, axis=0)
# prepare the image (e.g. scale pixel values for the vgg)
img = preprocess_input(img)
# get feature map for first hidden layer
feature_maps = model.predict(img)
# plot the output from each block
square = 8
for fmap in feature_maps:
	# plot all 64 maps in an 8x8 squares
	ix = 1
	for _ in range(square):
		for _ in range(square):
			# specify subplot and turn of axis
			ax = pyplot.subplot(square, square, ix)
			ax.set_xticks([])
			ax.set_yticks([])
			# plot filter channel in grayscale
			pyplot.imshow(fmap[0, :, :, ix-1], cmap='gray')
			ix += 1
	# show the figure
	pyplot.show()

 

 

 

 

'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 #1  (0) 2021.06.27

이건 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