5장 합성곱 신경망Ⅰ(3) 실습 - 특성맵 시각화

5장 합성곱 신경망Ⅰ(3) 실습 - 특성맵 시각화

1. 새로운 모델 생성

합성곱층, 최대풀링층 쌍을 4개 쌓고, 완전연결층을 순차적으로 쌓음

model = tf.keras.models.Sequential([

tf.keras.layers.Conv2D(input_shape=( 100 , 100 , 3 ), activation=' relu ', kernel_size=( 5, 5 ), filters= 32 ),

tf.keras.layers.MaxPooling2D(),

tf.keras.layers.Conv2D(activation=' relu ', kernel_size=( 5 , 5 ), filters= 64 ),

tf.keras.layers.MaxPooling2D(),

tf.keras.layers.Conv2D(activation=' relu ', kernel_size=( 5, 5 ), filters= 64 ),

tf.keras.layers.MaxPooling2D(),

tf.keras.layers.Conv2D(activation=' relu ', kernel_size=( 5, 5 ), filters= 64 ),

tf.keras.layers.MaxPooling2D(),

tf.keras.layers.Flatten(),

tf.keras.layers.Dense( 128 , activation=' relu '),

tf.keras.layers.Dense( 64 , activation=' relu '),

tf.keras.layers.Dense( 32 , activation=' relu '),

tf.keras.layers.Dense( 2 , activation=' softmax ')

])

ⓐ Conv2D : 합성곱층

- input_shape : (행, 열, 채널 수)

- activation = 'relu' : 은닉층에 주로 쓰이는 활성화 함수

* 활성화 함수 : 각 노드에 가중치를 곱하고 bias를 더한 값이 넘어갈때 특정 조건을 만족하면 활성화 함수에 의해 활성화 되었다는

신호를(활성화 함수를 거친 출력값) 다음 노드로 보내 활성화하고, 조건을 만족하지 못했으면 해당 노드를 비활성화함

- 가중치 : 커널 크기 × 필터 수 (예: (5 × 5) × 64 = 1600개)

ⓑ Dense : 밀집층, 완전연결층

- 첫번째 인자 : 출력 노드(뉴런)의 수

https://dsbook.tistory.com/59

2. 특성맵 정의

특성맵 = 합성곱층을 입력 이미지와 필터를 연산해서 얻은 결과

⇒ 합성곱층의 입력과 출력을 확인하면, 특성 맵에 대한 시각화가 가능할 것

ins = model.inputs #모델 입력으로 (None, 100, 100, 3)의 형태를 가짐(1에서 정의)

outs = model.layers[ 0 ].output # 첫번째 계층 에 대한 출력 형태 : (None, 96, 96, 32)

feature_map = Model(inputs=ins, outputs=outs) #ins, outs를 모델 입력과 출력으로 사용, 특성 맵을 정의

feature_map.summary()

첫번째 계층의 모델

- CNN의 output shape : (batch_size, height, width, depth(channel))

3. 이미지 전처리 및 특성맵 확인

img = plt.imread('../chap5/data/cat.jpg')

img = cv2.resize(img, (100, 100)) #이미지 크기 조정

input_img = np. expand_dims (img, axis=0) #이미지 차원 조정

print(input_img.shape) #입력 이미지 형태 출력

feature = feature_map.predict(input_img) #이미지를 모델에 적용

print(feature.shape) #특성 맵에 대한 형태 출력

fig = plt.figure(figsize=(50, 50))

for i in range(16): #이미지 16개 출력

ax = fig.add_subplot(8, 4, i+1) #subplot(m, n, p)는 , p로 지정된 위치에 좌표축을 만듦

ax.imshow(feature[0, :, :, i])

원본 이미지 첫번째 계층 출력 결과

→ 입력층과 가까운 계층으로 입력 이미지의 형태가 많이 유지되고 있음

ⓐ expand_dims()

nums = np.array([2, 5]) #nums.shape=(2, )

axis_0 = np. expand_dims (nums, axis= 0 )

axis_1 = np. expand_dims (nums, axis= 1 )

expand_dims 예시

4. 여섯 번째 계층에 대한 특성맵

ins = model.inputs //모델 입력으로 (None, 224, 224, 3)의 형태

outs = model.layers[ 6 ].output //여섯 번째 계층에 대한 출력으로 None, 1000)

feature_map = Model(inputs=ins, outputs=outs)

...

여섯번째 계층 출력 결과

원래 입력 이미지의 형태X

=> 출력층에 가까울 수록 원형은 사라지고 이미지 특징만 전달되는 것을 확인 가능

conv2D 참고 : https://tykimos.github.io/2017/01/27/CNN_Layer_Talk/conv

활성화 함수 참고 : https://dsbook.tistory.com/59

Q. 완전연결층(dense)을 여러개 쌓는 것은 출력노드를 점차적으로 줄이기 위한 것인가?(그렇다면 한번에 줄이는건 안되나?)

from http://markme-inur.tistory.com/36 by ccl(A) rewrite - 2021-08-08 21:00:38