[Python] 합성곱 신경망(Convolution Neural Network)

뽕칠이·2024년 1월 11일

시각 피질 구조

시각 피질 안의 많은 뉴런이 작은 국부 수용장을 가진다.
-> 뉴런들이 시야의 일부 범위 안에 있는 시각 자극에만 반응한다.
뉴런의 수용장들은 서로 겹칠 수 있어서, 합치면 전체 시야를 감싸게 된다. 또한, 어떤 뉴런은 수평선의 이미지에만 반응하고 또 다른 뉴런은 다른 각도의 선분에 반응한다는 점을 보였다.
-> 두 뉴런은 동일한 수용장을 가지지만 다른 각도의 선분에 반응한다.

합성곱 신경망(Convolution Neural Network)

합성곱 층(Convolution Layer)

합성곱 층의 뉴런은 입력 이미지의 모든 픽셀에 연결되는 것이 아니라 합성곱 층 뉴런의 수용장 안에 있는 픽셀에만 연결된다.
두 번째 합성곱 층의 뉴런은 첫 번째 합성곱 층의 작은 사각 영역 안에 위치한 뉴런에 연결된다. 이런 구조는 네트워크가 첫 번째 은닉층에서는 작은 저수준 특성에 집중하고, 그 다음 은닉층에서는 더 큰 고수준 특성으로 조합해 나가도록 도와준다.

이미지의 공간적인 구조 정보를 유지하면서 모델을 학습시킬 수 있는 방법이다.

합성곱 연산을 수행하고 활성화 함수를 수행하는 계층이다.

필터(합성곱 커널) : 가중치 세트

합성곱 층l에 있는 k특성 맵의 i행, j열에 위치한 뉴런은 이전 l-1층에 있는 특성 맵의 i x s(h)부터 i x s(h) + f(h) - 1까지의 행i x s(w)부터 ix s(w) + f(w) -1까지의 열에 있는 뉴런의 출력에 연결된다. 특성맵은 커널을 사용한 합성곱 연산을 통해 나온 결과를 말한다.

s : 스트라이드(필터의 이동범위)
f(h) : 필터의 세로 길이
f(w) : 필터의 가로 길이

-> 간단하게 설명하면 크기가 n×mn\times m인 필터로 이미지를 왼쪽 위부터 오른쪽 아래까지 순차적으로 훑는다. 훑으면서 필터의 크기에 해당하는 값들을 곱해서 더한 값을 출력한다. 그렇게 되면 현재 계층의 한 데이터는 이전 계층의 해당하는 위치에 n×mn\times m개의 데이터를 곱하고 더한 값이다.

패딩(Padding)

합성곱 이전에 입력의 가장자리에 지정된 개수의 폭만큼 행과 열을 추가하는 것을 의마한다.

값을 0으로 채우는 제로 패딩(zero padding)을 많이 사용한다.

필터의 크기를 3x3 또는 5x5를 사용하는데 스트라이드가 1일 때, 3x3일 때는 폭이 1인 제로 패딩을 사용하고, 5x5일 때는 폭이 2인 제로 패딩을 사용하면 입력과 출력의 크기를 보존할 수 있다.

풀링 층(Pooling Layer)

풀링 층은 계산량과 메모리 사용량, 파라미터 수를 줄이기 위해 입력 이미지의 부표본(축소본)을 만드는 것이다.
풀링 뉴런은 가중치가 없다. -> 최대나 평균과 같은 합산 함수를 사용해 입력값을 더하는 것 뿐이다.
이외에도 최대 풀링은 작은 변화에도 일정 수준의 불변성을 만들어준다.

최대 풀링과 평균 풀링

최대 풀링은 의미 없는 것은 제거하고 가장 큰 특징만 유지한다.(최대값 추출) 따라서 다음 층이 조금 더 명확한 신호로 작업이 가능하다. 또한, 강력한 불변성을 제공하고 연산 비용이 적게 든다.

평균 풀링은 평균값을 추출하는 것이므로 최대 풀링보다 정보 손실이 적다.

CNN 구조

합성곱 층을 몇 개씩 쌓으면서 각각 ReLU층을 그 뒤에 놓고, 풀링 층을 쌓고 위 구조를 반복하는 식이다.
-> 합성곱 층에 너무 큰 커널을 사용하는 것은 좋지 않다.
ex) 5x5 커널의 합성곱 층 대신 3x3 커널 2개를 사용하는 것이 파라미터와 계산량이 적고 일반적으로 더 나은 성능을 낸다.
-> 한 가지 예외는 첫 번째 합성곱 층이다. 이 곳에는 큰 크기의 커널과 2이상의 스트라이드를 사용한다.

CNN 코드

패션 MNIST 데이터셋 문제를 해결하기 위한 간단한 CNN이다.

model = keras.models.Sequential([
    keras.layers.Conv2D(64, 7, activation="relu", padding="SAME", 
    					input_shape=[28, 28, 1]),
    keras.layers.MaxPooling2D(2),
    keras.layers.Conv2D(128, 3, activation="relu", padding="SAME"),
    keras.layers.Conv2D(128, 3, activation="relu", padding="SAME"),
    keras.layers.MaxPooling2D(2),
    keras.layers.Conv2D(256, 3, activation="relu", padding="SAME"),
    keras.layers.Conv2D(256, 3, activation="relu", padding="SAME"),
    keras.layers.MaxPooling2D(2),
    keras.layers.Flatten(),
    keras.layers.Dense(64, activation="relu"),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(64, activation="relu"),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(64, activation="softmax")
])
  1. 첫 번째 층은 64개의 큰 필터(7x7)와 스트라이드 1을 사용한다.

  2. 이미지가 28x28 픽셀 크기이고 하나의 컬러 채널(그레이스케일)이므로 input_shpae = [28, 28, 1]로 작성한다.

  3. 크기가 2인 맥스풀링 층을 사용해서 공간 방향 차원을 절반으로 줄인다.

  4. 이 과정을 반복한다. 맥스풀링 층 다음 합성곱 층이 두 번 등장한다. 이미지가 클 때는 이 구조를 더 많이 반복할 수 있다.

  5. 출력층에 가까울수록 필터 개수가 늘어난다.(64 -> 128 -> 256)
    풀링 층 다음에 필터 개수를 두 배로 늘리는 것이 일반적인 방법이다.

  6. 이 방법이 저수준 특성(동심원, 수평선 등)의 개수는 적지만 이를 연결하여 고수준 특성을 만들 수 있는 방법이 많다.

  7. 풀링 층이 공간 방향 차원을 절반으로 줄이므로 이어지는 층에서 파라미터 개수, 메모리 사용량, 계산 비용을 크게 늘리지 않고 특성 맵 개수를 두 배로 늘릴 수 있다.

  8. 두 개의 은닉층과 하나의 출력층으로 구성된 완전 연결 네트워크이다. 밀집 네트워크는 샘플의 특성을 1D 배열로 입력에 넣어줘야 한다. 또, 밀칩 층 사이에 과대적합을 줄이기 위해 50%의 드롭아웃 비율을 가진 드롭아웃 층을 추가한다.

LeNet-5

CNN구조로 손글씨 숫자 인식(MNIST)에 널리 사용되었다.

LeNet-5 구조

종류특성 맵크기커널 크기스트라이드활성화 함수
입력입력132x32---
C1합성곱628x285x51tanh
S2평균 풀링614x142x22tanh
C3합성곱1610x105x51tanh
S4평균 풀링165x52x22tanh
C5합성곱1201x15x51tanh
F6완전 연결-84--tanh
출력완전 연결-10--RBF
  • MNIST 이미지는 28x28픽셀이지만 제로 패딩되어 32x32가 되고 네트워크에 주입되기 전에 정규화된다. 네트워크의 나머지 부분은 패딩을 사용하지 않는다. 그래서 이미지가 네트워크를 따라 진행하면서 크기가 줄어든다.
    -> 28x28픽셀 제로패딩 -> 32x32, 네트워크를 따라 크기가 줄어든다.
  • 평균 풀링층은 복잡하다. 각 뉴런은 입력의 평균을 계산한 다음, 그 값에 학습되는 계숫값을 곱한다. 그리고 학습되는 값인 편향을 더한다. 마지막으로 활성화 함수를 적용한다.
    -> F((평균x계수값)+편향), F는 활성화 함수
  • C3에 있는 대부분의 뉴런은 S2의 3개 또는 4개 맵에 있는 뉴런에만 연결된다.
  • 출력층은 입력과 가중치 벡터를 행렬 곱셈하는 대신 각 뉴런에서 입력 벡터와 가중치 벡터 사이의 유클리드 거리를 출력한다. 각 출력은 이미지가 얼마나 특정 숫자 클래스에 속하는지 측정한다. 잘못된 예측을 줄여주고 그레이디언트 값이 크고 빠르게 수렴하기 때문에 크로스 엔트로피 비용 함수를 선호한다.
    ->입력x가중치(행렬곱셈) -> 유클리드 거리 출력 = 이미지가 얼마나 특정 숫자 클래스에 속하는지

AlexNet

LeNet-5와 구조는 비슷하나, 더 크고 깊다. 처음으로 합성곱 층 위에 풀링 층을 쌓지 않고 합성곱 층끼리 쌓았다.

AlexNet 구조

종류특성 맵크기커널 크기스트라이드패딩활성화 함수
입력입력3(RGB)227x227----
C1합성곱9655x5511x114validReLU
S2최대 풀링9627x273x32valid-
C3합성곱25627x275x51sameReLU
S4최대 풀링25613x133x32valid-
C5합성곱38413x133x31sameReLU
C6합성곱38413x133x31sameReLU
C7합성곱25613x133x31sameReLU
F8합성곱2566x63x32valid-
F9완전 연결-4,096---ReLU
F10완전 연결-4,096---ReLU
출력완전 연결-1,000---Softmax

활성화 함수 Tanh와 ReLU

  • tanh함수는 [-1, 1] 범위에서 존재하지만, ReLU 함수는 [0, ∞] 범위에서 존재한다.
  • tanh함수는 saturating function이기 때문에 non saturating한 ReLU함수보다 훨씬 느리다.
  • saturating function이란 유한한 영역을 가지는 함수이다. 반대로 non saturating function은 -∞ 혹은 +∞로 발산한다.
  • saturating function의 완만한 기울기는 gradient의 update를 더디게 만든다.

과대적합을 줄이기 위해 두 가지 규제 기법을 사용했다.
1. 훈련하는 동안 F9와 F10의 출력에 드롭아웃 50% 비율로 적용
2. 훈련 이미지를 랜덤하게 여러 간격으로 이동하거나 수평으로 뒤집고 조명을 바꾸는 식으로 데이터 증식을 수행

데이터 증식

데이터 증식은 진짜 같은 훈련 샘플을 인공적으로 생성하여 훈련 세트의 크기를 늘립니다. 데이터 증식은 과대적합을 줄이므로 규제 기법으로 사용할 수 있습니다. 생성된 샘플은 가능한 진짜에 가까워야 합니다. 이상적으로는 증식된 훈련 세트에서 이미지를 뽑았을 때 증식된 것인지 아닌지를 구분할 수 없어야 합니다. 단순한 백색 잡읍을 추가하는 것은 도움이 되지 않습니다. 증식 방식은 학습이 가능해야 합니다.(백색 잡은은 학습이 불가능합니다.)
예를 들어, 각기 다른 양으로 훈련 세트에 있는 모든 이미지의 크기를 조금 변경하거나 이동, 회전합니다. 이렇게 만든 이미지를 훈련 세트에 추가합니다. 이렇게 하면 모델이 그림에 있는 물체의 위치, 방향, 크기 변화에 덜 민감해집니다. 조명 조건에 민감하지 않은 모델을 만들기 위해 비슷하게 여러 가지 명암을 가진 이미지를 생성할 수 있습니다. 일반적으로 이미지는 수평으로 뒤집을 수 있습니다. 이런 변환을 연결하여 훈련 세트의 크기를 많이 늘릴 수 있습니다.

AlexNet은 C1과 C3 층의 ReLU 단계 후에 바로 LRN(Local Response Normalization)이라 부르는 경쟁적인 정규화 단계를 적용했다. 가장 강하게 활성화된 뉴런이 다른 특성 맵에 있는 같은 위치의 뉴런을 억제한다. 이는 특정 맵을 각기 특별하게 다른 것과 구분되게 하고, 더 넓은 시각에서 특징을 탐색하도록 만들어 결국 일반화 성능을 향상한다.

bi는 i 특성 맵, 특정 행열에 위치한 뉴런의 정규화된 출력
ai는 ReLU 단계를 지나고 정규화 단계는 거치기 전인 뉴런의 활성화 값
k, α, β, r는 하이퍼파라미터이다. k는 편향, r은 깊이 반경을 의미한다.
fn은 특성 맵의 수이다.

AlexNet에서 하이퍼파라미터는 r=2, k=1, α=0.00002, β=0.75로 설정되어 있다.
tf.nn.local_response_normalization()을 사용하여 구현할 수 있다.

GoogLeNet

인셉션 모듈이라는 서브 네트워크를 가지고 있어서 이전의 구조보다 훨씬 효과적으로 파라미터를 사용한다. 실제로 GoogLeNet은 AlexNet보다 10배나 적은 파라미터를 가진다.

3x3+1(S) 표현은 3x3커널, 스트라이드1, SAME 패딩을 사용한다는 뜻이다.
모든 합성곱 층은 ReLU 함수를 사용한다.
두 번째 합성곱 층은 각기 다른 커널 크기를 사용하여 다른 크기의 패턴을 잡는다.
모든 층은 스트라이드 1과 SAME 패딩을 사용하므로 출력의 높이와 너비가 모두 입력과 같습니다. 이렇게 하면 모든 출력을 깊이 연결 층에서 깊이방향으로 연결할 수 있다. 이 연결 층은 tf.concat() 연산을 사용하여 구현할 수 있다.

  • 공간상의 패턴을 잡을 수는 없지만 깊이 차원을 따라 놓인 패턴을 잡을 수 있다.
  • 입력보다 더 적은 특성 맵을 출력하므로 차원을 줄인다는 의미인 병목 층의 역할을 담당합니다. 연산 비용과 파라미터 개수를 줄여 훈련 속도를 높이고 일반화 성능을 향상시킨다.
  • 합성곱 층의 쌍([1x1, 3x3]과 [1x1, 5x5])이 더 복잡한 패턴을 감지할 수 있는 한 개의 강력한 합성곱 층처럼 동작합니다. 실제로 합성곱 층 쌍은 하나의 합성곱 층이 하는 것처럼 단순한 선형 분류기 하나로 이미지를 서치하는 것이 아니라 두 개의 층을 가진 신경망으로 이미지를 서치하는 것이다.

실제로는 하나로 길게 쌓은 구조이며, 9개의 인셉션 모듈을 포함한다. 인셉션 모듈에 있는 6개의 숫자는 모듈 안에 있는 합성곱 층에서 출력하는 특성 맵의 수이다. 모든 합성곱 층은 ReLU 함수를 사용한다.

  1. 처음 두 층은 계산의 양을 줄이기 위해 이미지의 높이와 너비를 4배로 줄인다.(그러므로 면적은 16배 줄어든다.) 많은 정보를 유지하기 위해 첫 번째 층은 큰 크기의 커널을 사용한다.
  2. LRN 층은 이전 층이 다양한 특성을 학습하도록 한다. 이어지는 두 개의 합성곱 층 중에서 첫 번째 층이 병목 층처럼 작동한다. 합성곱층 쌍을 하나의 고수준 합성곱 층으로 생각할 수 있다.
  3. LRN 층이 이전 층이 학습하도록 한다.
  4. 최대 풀링 층이 계산수를 줄이기 위해 파라미터를 줄인다.
  5. 9개의 인셉션 모듈이 존재하는데 차언 감소와 속도 향상을 위해 몇 개의 최대 풀링 층을 넣었다.
  6. 전역 평균 풀링 층이 각 특성 맵의 평균을 출력한다. 여기서 공간 방향 정보를 모두 잃는다. -> 이 지점에서는 공간 정보가 거의 남아 있지 않기 때문에 괜찮다.
    실제 GoogLeNet은 224x224 크기의 입력 이미지를 기대한다. 5번의 최대 풀링 층에서 매번 높이와 너비가 절반으로 줄어든다면 특성 맵 크기는 7x7이 된다. 또한 위치 추정이 아니라 분류 작업이므로 물체가 어디 있는지 중요하지 않다. 이 층에서 수행된 차원 축소 덕분에 CNN 위에 몇 개의 완전 연결 층을 둘 필요가 없다. 파라미터의 수를 크게 감소시키고 과대적합의 위험도 줄여준다.

0개의 댓글