본문 바로가기

Study/class note

딥러닝 / 합성곱 신경망(Convolution Neural Network)

1  합성곱 신경망

Convolution층과 pooling층을 포함하는 신경망

Convolution층 : 이미지의 특징을 잡아내는 역할

pooling층 : 이미지를 선명하게 만드는 역할

 

기존 신경망과의 차이?

- 기존방법 : 입력값 -> Affine -> Relu -> Affine -> Relu -> Affine -> softmax (완전연결계층, fully connected)

문제점 : 사진을 사진 그대로 입력하지 않고 1차원으로 flatten시켜서 입력(1,784)

 

- CNN : 입력값 -> convolution -> Relu -> pooling -> 완전연결계층

사진을 그대로 입력함(1,28,28)

 

 

2  CNN을 이용하지 않았을 때 기존층의 문제점 - p229

=>이미지 형상이 무시됨.

 

1. 필기체 이미지 28x28을 1차원으로 flatten시켜서 784개의 데이터로 만들어주고 첫 Affine계층에 입력한게 기존 방법

그래서 생긴 문제점이 형상을 무시하고 모든 입력 데이터를 동등한 뉴런으로 취급하기 때문에 이미지가 갖는 본질적인 패턴을 읽지 못함

 

=> 해결방법 : 원본 이미지를 가지고 여러개의 feature map을 만들어서 데이터를 여러개 생성함.

(원본이미지 한 장을 가지고 비슷한 이미지 수십 또는 수백장을 만듭니다.)

이 작업이 convolution 층에서 일어남.

 

합성곱 연산은 원본 이미지에 필터(filter)를 슬라이딩해서 피처맵(feature map)을 만드는 것을 말함.

그래서 여러개의 필터들을 가지고 다양한 피처맵을 만듬. 이 피처맵들은 원본과 비슷한 이미지.

 

 

CNN(합성곱 신경망)을 사용해야하는 이유?

이미지를 이미지 그대로 받아들여서 학습 시키기 위함.

 

2. 필터를 이용해서 원본이미지와 비슷한 이미지를 여러장 만들어내기 위해서.

원본 이미지 한 장을 filter 100개로 합성곱 연산을 하면 feature map이 100개가 생성됨.

 

 

3  합성곱 연산을 컴퓨터로 구현하는 방법 

합성곱의 역할 : 이미지의 특징을 잡아냄.

 

예제1. 합성곱을 위해서 아래의 입력 데이터와 필터를 생성하시오.

import numpy as np

x = np.array([1,2,3,0,0,1,2,3,3,0,1,2,2,3,0,1]).reshape(4,4)
filter2 = np.array([2,0,1,0,1,2,1,0,2]).reshape(3,3)

print(x)
print(filter2)

# [[1 2 3 0]
#  [0 1 2 3]
#  [3 0 1 2]
#  [2 3 0 1]]
# [[2 0 1]
#  [0 1 2]
#  [1 0 2]]

 

문제143. 위의 입력 이미지 x에서 아래의 3x3영역만 가져오시오.

x[:3,:3]

# array([[1, 2, 3],
#        [0, 1, 2],
#        [3, 0, 1]])

 

문제144. 위에서 가져온 3x3 영역의 원소들과 filter2를 곱하시오.

x[:3,:3]* filter2

# array([[2, 0, 3],
#        [0, 1, 4],
#        [3, 0, 2]])

 

문제145. 위에서 곱셈해서 출력된 원소들의 합을 출력하시오.

np.sum(x[:3,:3]* filter2)  # 15

 

문제146. 이번에는 원본 이미지를 한 칸 옆으로 슬라이딩하고 필터와 합성곱해서 16을 출력하시오.

np.sum(x[0:3, 1:4]*filter2)   #16

 

문제147. 이번에는 원본 이미지를 한 칸 아래로 슬라이딩하고 필터와 합성곱해서 6을 출력하시오.

np.sum(x[1:4, 0:3]*filter2)   #6

 

문제148. 이번에는 원본 이미지를 한칸 아래, 한칸 옆으로 슬라이딩해서 필터와 합성곱하여 15를 출력하시오.

np.sum(x[1:4, 1:4]*filter2)   #15

 

문제149. 지금까지 한 4개의 코드를 다 모아서 수행하시오.

print(np.sum(x[0:3, 0:3]*filter2)) #15
print(np.sum(x[0:3, 1:4]*filter2))  #16
print(np.sum(x[1:4, 0:3]*filter2))  #6
print(np.sum(x[1:4, 1:4]*filter2))  #15

 

문제150. 위의 4개의 계산을 하기 위해서 위와 같이 4번 하드코딩하지 않고 이중 루프문으로 한번에 출력되게 하시오.

for i in range(2):
    for k in range(2):
        print(np.sum(x[i:i+3,k:k+3] * filter2))

 

문제151. 위의 4개의 숫자값을 a라는 빈 리스트에 append시키고 a리스트를 아래와 같이 출력하시오.

a = []
for i in range(2):
    for k in range(2):
        a.append(np.sum(x[i:i+3,k:k+3] * filter2))

print(a)  #[15, 16, 6, 15]

 

문제152. 위에서 출력된 원소 4개를 가지고 2x2 행렬의 넘파이 배열을 생성하시오.

a = []
for i in range(2):
    for k in range(2):
        a.append(np.sum(x[i:i+3,k:k+3] * filter2))

b = np.array(a).reshape(2,2)
b

 

 

4  패딩 - p.232

패딩이란 이미지를 합성곱 하게 되면 피처맵의 크기가 원본 이미지보다 작아지게 됨.

위의 합성곱 과정만으로도 원본이미지 4x4가 2x2로 작아짐

 

그런데 지금 나온 결과를 가지고 또 다시 합성곱을 할 예정

원본이미지 -> 합성곱 -> 풀링 -> 합성곱 -> 풀링 -> 완전연결층 -> 분류결과출력

합성곱 = 이미지의 특징을 추출

풀링 = 추출된 이미지를 선명하게 함

 

패딩이란 합성곱 연산을 수행하기 전에 입력 데이터 주변을 특정값으로 채워 늘리는 것. 패딩을 하지 않을 경우 data 공간의 크기는 합성곱 계층을 지날 때마다 작아지게 되므로 가장자리 정보들이 사라지게 되는 문제가 발생함. 그래서 패딩이 필요함. 패딩은 아래와 같음.

 

 

문제153. 아래의 2x2행렬을 제로 패딩1로 해서 4x4행렬을 만드시오.

x = np.array([18,19,9,18]).reshape(2,2)
x_pad = np.pad(x, pad_width = 1, mode = 'constant', constant_values = 0)
print(x_pad)

# [[ 0  0  0  0]
#  [ 0 18 19  0]
#  [ 0  9 18  0]
#  [ 0  0  0  0]]

 

문제154. 아래의 그림을 구현하시오.

x = np.array([1,2,3,0,0,1,2,3,3,0,1,2,2,3,0,1]).reshape(4,4)
x_pad = np.pad(x, pad_width = 1, mode = 'constant', constant_values = 0)

filter2 = np.array([2,0,1,0,1,2,1,0,2]).reshape(3,3)

lst = []
for i in range(4):
    for k in range(4):
        lst.append(np.sum(x_pad[i:i+3,k:k+3] * filter2 ))

result = np.array(lst).reshape(4,4)
print(result)

# [[ 7 12 10  2]
#  [ 4 15 16 10]
#  [10  6 15  6]
#  [ 8 10  4  3]]
반응형