Group Study (2023-2024)/Machine Learning 입문

[ML입문] week6 - 합성곱 신경망

임지 Imjee 2023. 12. 23. 15:27

1. 합성곱 신경망

합성곱 신경망은 주로 이미지 분류를 할 때 자주 쓰이는 신경망이다.

이러한 합성곱 신경망은 크게 합성곱층풀링층의 쌍으로 구성된다.

 

2. 합성곱층

2-1 ) 연산 과정

합성곱층에서는 합성곱 연산을 통해 이미지의 특징을 추출한다.

3x3 또는 5x5 크기의 행렬인 필터(커널)를 이미지의 왼쪽 위부터 오른쪽 아래까지 순차적으로 훑는다.
이렇게 훑는 과정을 슬라이딩이라고 한다.

사진 출처 : https://wikidocs.net/62306

위 사진에서는 5x5 크기의 이미지를 3x3 커널을 슬라이딩 시켰다.

총 행 방향 2번, 열 방향 2번의 슬라이딩을 통해 2x2 크기의 행렬을 얻었다.

커널을 사용하여 합성곱 연산을 통해 나온 결과값을 특성 맵이라고 한다.
또한, 이처럼 합성곱 연산을 통해 얻은 특성 맵의 크기는 이미지의 크기보다 작다.

 

2-2 ) 패딩

패딩은 이미지 행렬의 가장자리에 0의 값을 가진 행과 열을 추가하는 행위이다.

위 사진에서 3x3 커널을 슬라이딩 해본다면, 행 방향 5번, 열 방향 5번을 이동함을 확인할 수 있다.
즉, 특성맵의 크기가 5x5로, 기존 이미지 입력 크기와 같은 크기로 출력된다.

패딩은 특성맵의 크기와 이미지의 크기가 같도록 하기 위해 사용한다.
또한, 패딩을 사용하면 각 픽셀이 합성곱 연산에 기여하는 정도의 차이를 줄일 수 있다.

 

2-3) 여러 개의 커널

커널을 한 번에 여러 개 사용할 수도 있다. 이때, 커널들의 픽셀당 가중치값은 모두 다르다.

이렇게 여러 개의 커널을 사용하면, 특성맵의 차원이 하나 더 증가한다.

커널을 여러 개 사용할 경우, 새로 추가된 차원의 값은 커널의 개수이다.
그리고 새로 추가된 이 차원을 채널 차원이라고 한다.

예를 들어, 5x5 특성맵을 얻을 수 있는 필터를 3개 사용한다면, 특성맵의 크기는 (5,5,3)이 된다.

 

2-4) 합성곱층 코드

from tensorflow import keras
keras.layers.Conv2D(10, kernel_size=(3,3), activation='relu', padding='same')
  • Conv2D 함수의 첫 번째 매개변수 : 커널의 개수
  • 두 번째 매개변수 : 커널의 크기. 보통 커널은 정방향으로 설정하기 때문에, 3이라고만 적어도 자동으로 (3,3) 크기의 커널이 생성된다.
  • 세 번째 매개변수 : 활성화 함수 지정. 보통 relu함수를 사용한다.
  • 네 번째 매개변수 : 패딩의 크기. 'same'으로 두면 위 예시처럼 특성맵과 이미지 크기가 같도록 출력된다.

 

 

3. 풀링층

풀링층에서는 합성곱층을 통해 얻은 특성맵의 크기를 줄인다.

3-1) 풀링층의 연산

풀링층 역시 합성곱층처럼 커널을 가진다. 
단, 풀링층의 커널은 특성맵의 정보를 추출해오는 방식으로 사용하기 때문에, 가중치가 없다.

풀링은 최대풀링과 평균풀링이 대표적인데, 여기서는 최대풀링을 이용해 설명해보려한다.

4x4 특성맵에서, 2x2 커널을 슬라이딩 시켰다. 최대 풀링은 2x2 커널 내에서 가장 큰 값을 추출한다.
결과적으로, 4x4 특성맵이 2x2 크기로 줄어들었음을 확인할 수 있다.

단, 합성곱층과 달리 풀링층은 채널차원의 값이 변하지 않는다.

풀링층의 커널을 통해 특성맵의 크기를 줄일 수 있다.
풀링층의 커널은 가중치가 없으며, 연산을 마쳐도 채널차원의 값이 변하지 않는다.

 

3-2) 풀링층 코드

keras.layers.MaxPooling2D(2) #풀링의 크기
keras.layers.MaxPooling2D(2, strides = 2, padding='valid')
  • MaxPooling2D의 첫 번째 매개 변수 : 풀링 커널의 크기. 2x2 크기로 설정되며, 채널 차원의 크기는 입력값과 같게 설정된다.
  • 두 번째 매개변수 : 스트라이드(슬라이딩 시 몇 칸씩 슬라이딩 할 것인지). 풀링의 크기에 따라 자동으로 설정된다.
  • 세 번째 매개변수 : 패딩의 여부. 풀링층에서는 특성맵의 크기를 줄이는 것이 목적이기 때문에 패딩을 설정하지 않는다.('valid')

 

 

4. 합성곱 신경망 실습 - 데이터 준비

(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
# 패션 MNIST에서 데이터 로드

가중치 시각화와 특성맵 시각화를 위해 사용할 데이터는 패션 MNIST 데이터이다.
우선  load_data() 함수를 통해 데이터를 로드한다.

 

5. 합성곱 신경망 실습 - 가중치 시각화

from tensorflow import keras

conv = model.layers[0] #첫 번째 층 참조
print(conv.weights[0].shape, conv.weights[1].shape)
#wegiths[0] : 가중치 텐서, weights[1] : 편향 텐서
# (3, 3, 1, 32) (32,)

conv_weights = conv.weights[0].numpy()
#시각화를 위해 넘파이 배열로 만든다.

matplotlib을 통해 위 코드를 통해 넘파이 배열로 만든 가중치를 시각화 할 수 있다.

fig, axs = plt.subplots(2, 16, figsize=(15,2))

for i in range(2):
    for j in range(16):
        axs[i, j].imshow(conv_weights[:,:,0,i*16 + j], vmin=-0.5, vmax=0.5)
        axs[i, j].axis('off')

plt.show()

  • vmin = -0.5 , vmax = 0.5 : 픽셀값의 범위를 제어한다. 즉, 모든 가중치가 같은 기준을 가지도록 한다.
  • axis('off') : 깔끔한 이미지 출력을 위해 서브플롯의 축을 비활성화한다.

짙은 어두운 색은 음수 가중치를 의미한다.
이미지 픽셀 내에서 음수영역과, 음수 가중치를 곱해 높은 양수가 나오도록 하기 위함이다.
반대로 밝은 색은 양수 가중치를 의미한다고 볼 수 있겠다.

matplotlib의 imshow 함수를 통해 가중치를 시각화 할 수 있다.
어두운 색은 음수 가중치를, 밝은 색은 양수 가중치를 의미한다.

 

6. 합성곱 신경망 실습 - 함수형 API

conv_acti = keras.Model(model.input, model.layers[0].output)

함수형 API를 사용해 conv_acti를 설정하였다.

여기서는 기존 모델의 입력과 (model.input), 기존 모델의 첫 번째 층(layers[0])의 출력을 가져옴을 확인할 수 있다.

함수형 API를 사용하면, 층의 출력과 입력을 자연스럽게 조합해 복잡한 형태의 모델을 만들 수 있다.

 

7. 합성곱 신경망 실습 - 특성맵 시각화

inputs = train_input[0:1].reshape(-1, 28, 28, 1)/255.0
# 패션 MNIST 데이터 전처리
feature_maps = conv_acti.predict(inputs)

print(feature_maps.shape)
#(1, 28, 28, 32)
  • feature_maps : conv_acti 모델에 input을 넣어 예측값을 받아온다.
fig, axs = plt.subplots(4, 8, figsize=(15,8))

for i in range(4):
    for j in range(8):
        axs[i, j].imshow(feature_maps[0,:,:,i*8 + j])
        axs[i, j].axis('off')

plt.show()

이처럼 시각화를 통해, 입력 이미지에서 모델이 다양한 시각적 패턴이나 특징을 어떻게 인식하는지에 대한 정보를 얻을 수 있다.