지시딥 12. 합성곱 신경망(CNN) 2탄, 딥러닝

곽정은·2021년 2월 1일
2

스터디

목록 보기
6/19

7.5 CNN 구현하기

  • 다음은 단순한 CNN 네트워크 구성임.

  • 위 그림의 CNN 네트워크는 Convolution - ReLU - Pooling - Affine - ReLU - Affine - Softmax 순으로 흐름.

코드로 CNN 구현하기

  • SimpleConvNet이라는 클래스로 구현해보자.
  • SimpleConvNet의 초기화를 살펴보고, 받는 인수들을 알아보자.
    • input_dim: 입력 데이터(채널 수, 높이, 너비)의 차원(입력의 크기)
    • conv_param: 합성곱 계층의 하이퍼파라미터(딕셔너리 형태). 딕셔너리의 키는 다음과 같음.
    1. filter_num: 필터 수
    2. filter_size: 필터 크기
    3. stride: 스트라이드
    4. pad: 패딩
    5. hidden_size: 은닉층(완전연결)의 뉴런 수를 담은 리스트
    6. output_size: 출력층(완전연결)의 뉴런 수(출력의 크기)
    7. weight_init_std: 초기화 때의 가중치 표준편차

첫번째 코드

 def __init__(self, input_dim=(1, 28, 28), 
                 conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},
                 hidden_size=100, output_size=10, weight_init_std=0.01):
        filter_num = conv_param['filter_num']
        filter_size = conv_param['filter_size']
        filter_pad = conv_param['pad']
        filter_stride = conv_param['stride']
        input_size = input_dim[1]
        conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size/2) * (conv_output_size/2))
  • 초기화 인수로 주어진 합성곱 계층의 파라미터를 딕셔너리에서 꺼냄.
  • 그리고 합성곱 계층의 출력 크기를 계산함.

두번째 코드

# 가중치 초기화
        self.params = {}
        self.params['W1'] = weight_init_std * \
                            np.random.randn(filter_num, input_dim[0], filter_size, filter_size)
        self.params['b1'] = np.zeros(filter_num)
        self.params['W2'] = weight_init_std * \
                            np.random.randn(pool_output_size, hidden_size)
        self.params['b2'] = np.zeros(hidden_size)
        self.params['W3'] = weight_init_std * \
                            np.random.randn(hidden_size, output_size)
        self.params['b3'] = np.zeros(output_size)
  • 학습에 필요한 매개변수는 1번째 층의 합성곱 계층과 나머지 두 완전연결 계층의 가중치와 편향.
  • 이 매개변수들을 인스턴스 변수 params 딕셔너리에 저장.

    W1: 1번째 층의 합성곱 계층의 가중치, b1: 1번째 층의 합성곱 계층의 편향
    W2: 2번째 층의 완전연결 계층의 가중치, b2: 2번째 층의 완전연결 계층의 편향
    W3: 3번째 층의 완전연결 계층의 가중치, b3: 3번째 층의 완전연결 계층의 편향

세번째 코드

# CNN 구성 계층 생성
        self.layers = OrderedDict()
        self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],
                                           conv_param['stride'], conv_param['pad'])
        self.layers['Relu1'] = Relu()
        self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)
        self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])
        self.layers['Relu2'] = Relu()
        self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])

        self.last_layer = SoftmaxWithLoss()
  • 순서가 있는 딕셔너리인 layers에 계층들을 차례로 추가.
  • 마지막 SoftmaxWithLoss 계층은 last_layer라는 별도 변수에 저장.

네번째 코드

 def predict(self, x):
        for layer in self.layers.values():
            x = layer.forward(x)
        return x

    def loss(self, x, t):
        y = self.predict(x)
        return self.last_layer.forward(y, t)
  • 인수 x: 입력 데이터, 인수 t: 정답 레이블.
  • 추론을 수행하는 predict 메서드는 초기화 때 layers에 추가한 계층을 맨 앞에서부터 차례로 forward 메서드를 호출하여 그 결과를 다음 계층에 전달함.
  • 손실함수를 구하는 loss 메서드는 predict 메서드의 결과를 인수로 마지막 층의 forward 메서드를 호출.
    = 첫 계층부터 마지막 계층까지 forward를 처리함.

다섯번째 코드

 # 오차역전법으로 기울기 구하기
 def gradient(self, x, t): # x: 입력 데이터, t: 정답 레이블
        # 순전파
        self.loss(x, t)

        # 역전파
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 결과 저장
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
        grads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].db
  • 매개변수의 기울기는 오차역전법으로 구함.
  • 이 과정은 순전파와 역전파를 반복함.
  • grads라는 딕셔너리 변수에 각 가중치 매개변수의 기울기를 저장함.
  • 위 코드는 MNIST 데이터셋을 가지고 손글씨 인식 문제를 풀 때 예시.
  • 작은 데이터셋이지만 시험 데이터 정확도가 거의 99%로 아주 높음.

지금까지 알아본 것

  • 합성곱 계층과 풀링 계층은 이미지 인식에 필수적인 모듈.
  • 이미지라는 공간적인 형상에 담긴 특징을 CNN이 잘 파악하여, 손글씨 숫자 인식에서 높은 정확도를 달성할 수 있었음.

  • 신경망 학습을 통해서 Loss 손실을 줄이는 방향으로 가중치는 변화함.

  • 처음 가중치를 설정할 때는 랜덤으로 값을 정하기 때문에 의미없는 값들로 이루어져 있음.

  • 아무런 규칙이 없는 상태에서 학습을 거치면서 필터는 규칙성이 있는 형태로 변화함.

  • 학습된 필터 몇 개를 선택해서 입력받은 이미지에 합성곱 처리를 하면, 각각의 필터 측징에 맞게 어떤 특징이 부각되어 이미지를 출력함.


7.6 CNN 시각화하기

  • 합성곱 계층은 입력으로 받은 이미지 데이터에서 '무엇을 보고' 있을까?

7.6.1 1번째 층의 가중치 시각화하기

  • 앞에서 MNIST 데이터셋으로 CNN 학습을 했을 때, 1번째 층의 합성곱 계층의 가중치는 그 형상이 (30, 1, 5, 5)였음.
    = (필터 개수, 채널 개수, 높이, 너비)
  • 이는 필터의 크기가 5x5이고, 1채널의 회색조 이미지로 시각화할 수 있다는 뜻.
  • 합성곱 계층(1번째 층) 필터를 이미지로 나타내고 학습 전, 후의 가중치를 비교해보자.

  • 가중치읜 원소는 실수지만, 이미지에서는 가장 작은 값(0)은 검은색으로, 가장 큰 값(255)는 흰색으로 정규화하여 표시.

  • 학습 전 필터는 무작위로 초기화되고 있어 흑백의 정도에 규칙성이 없음.

  • 학습 후 필터는 흰색에서 검은색으로 점차 변화하는 필터, 블롭(blob, 덩어리)을 가진 필터 등규칙성 있는 이미지가 됨.

  • 그렇다면 규칙성이 있는 필터는 '무엇을 보고' 있을까?
  • 규칙성 있는 필터들은 색상이 바뀐 경계선인 '엣지'와 국소적으로 덩어리진 영역인 '블롭'을 보고 있음.

  • 위 그림처럼 왼쪽 절반이 흰색이고, 오른쪽 절반이 검은색인 필터는 세로방향 엣지에 반응하는 필터. 아래 절반이 흰색이고, 위 절반이 검은색은 필터는 가로 방향 엣지에 반응하는 필터.
  • 이처럼 합성곱 계층의 필터는 엣지나 블롭 등의 원시적인 정보를 추출할 수 있음.
  • 우리가 앞서 구현한 CNN에서도 이런 원시적인 정보를 뒷단 계층에 전달하는 것임.

7.6.2 층 깊이에 따른 추출 정보 변화

  • 우리는 1번째 층의 합성곱 계층에서 엣지나 블롭과 같은 저수준 정보를 추출하는 것을 알게 됨.
  • 그럼 겹겹이 쌓인 CNN의 각 계층에서는 어떤 정보를 추출할까?
    -> 딥러닝 시각화에 대한 연구에 따르면, 계층이 깊어질수록 추출되는 정보는 더 추상화됨.

  • 위 그림은 일반 사물 인식을 수행한 8층 CNN.
  • AlexNet이라는 네트워크 구조.
    (이 구조는 ImageNet 영상 데이터 베이스를 기반으로 한 화상 인식 대회인 "ILSVRC 2012"에서 우승한 CNN 구조라고 함.)
  • 합성곱 계층과 풀링 계층을 여러 겹 쌓고, 마지막으로 완전연결 계층을 거쳐 결과를 출력하는 구조.
  • 위 그림에서 블록으로 나타낸 것은 중간 데이터로, 이 중간 데이터에 합성곱 연산을 연속해서 적용함.
  • 흥미로운 점은 합성곱 계층을 여러 겹 쌓으면, 층이 깊어지면서 더 복잡하고 추상화된 정보가 추출됨.
  • 처음에는 단순한 엣지와 블롭에 반응하고, 3번째에서는 텍스처에 반응하고, 5번째에서는 사물의 일부에 반응함.
  • 즉, 층이 깊어지면서 뉴런이 반응하는 대상이 단순한 모양에서 고급 정보로 변화해감.
    = 사물의 의미를 이해하도록 변화하는 것.

(궁금?) 정보가 추상화되는 과정을 인간이 이해할 수 있을까? 각 계층마다 추상화된 정보를 추출하는데, 우리가 각 레이와 필터에 '해당 요소를 뽑아서 추상화해라'라고 명령한 것이 아닌데 어떻게 추출이 가능한 지 의문임.
(추가) XAI(eXplainable AI, 설명가능 인공지능): 인공지능이 다방면에서 사용되고 있지만 인공지능이 도출한 결과가 왜 그런지 설명하지 못함으로써 나오게 됨. 인공지능의 행위와 판단을 사람이 이해할 수 있는 형태로 설명할 수 있는 기술.


7.7 대표적인 CNN

7.7.1 LeNet

  • LeNet은 손글씨 숫자를 인식하는 네트워크로 1998년에 제안됨.

  • 위 그림과 같이 합성곱 계층과 풀링 계층을 반복하고, 마지막으로 완전연결 계층을 거치면서 결과를 출력.

현재 CNN과 LeNet의 차이점
1. 활성화 함수
LeNet은 시그모이드 함수를 사용하는 반면, 현재는 주로 ReLU 사용.
(Leaky ReLU나 ELU같은 LU 계열이 더 성능이 좋다고 함.)
2. 풀링 계층의 여부
LeNet은 서브샘플링(평균 풀링)하여 중간 데이터의 크기를 줄이지만, 현재는 최대 풀링이 주류.

7.7.2 AlexNet

  • 딥러닝 열풍을 일으키는 데 큰 역할.

  • AlexNet은 합성곱 계층과 풀링 계층을 거듭하여 마지막으로 완전연결 계층을 거쳐 결과를 출력.

    LeNet과의 차이점

    1. 활성화 함수로 ReLU를 사용.
    2. LRN(Local Response Normalization)이라는 국소적 정규화를 실시하는 계층을 이용.
      (측면억제: 실제 뇌 세포 증상으로 강한 뉴런의 활성화가 근처 다른 뉴런의 활동을 억제시키는 현상. NN의 피처에서 한 세포가 유별나게 강한 값을 가지게 된다면, 근처의 값이 약하더라도 컨벌루션 연사을 하면 강한 피처를 가지게 되는 것.)
    3. 드롭아웃을 사용.
  • 두 네트워크는 구성 측면에서는 큰 차이가 없음.

  • 다만 환경과 컴퓨터 기술이 큰 진보를 이룬 것.
    -> 빅데이터, GPU


7.8 정리

이번 장에서 배운 내용
1. CNN은 지금까지 완전연결 계층 네트워크에 합성곱 계층과 풀링 계층을 새로 추가한다.
2. 합성곱 계층과 풀링 계층은 im2col(이미지를 행렬로 전개하는 함수)를 이용하면 간단하고 효율적으로 구현할 수 있다.
3. CNN을 시각화해보면 계층이 깊어질수록 고급정보가 추출되는 모습을 확인할 수 있다.
4. 대표적인 CNN에는 LeNet과 AlexNet이 있다.
5. 딥러닝 발전에는 빅데이터와 GPU가 크게 기여했다.

딥러닝

  • 딥러닝은 층을 깊게한 신경망.

8.1 더 깊게

8.1.1 더 깊은 신경망으로

  • 위 그림은 손글씨 숫자를 인식하는 심층 CNN.

    • 이 깊은 신경망의 특징
    1. 합성곱 계층은 모두 3x3 크기의 작은 필터
    2. 층이 깊어지면서 채널 수가 늘어남.(합성곱 계층 채널 수는 16, 16, 32, 32, 64, 64로 늘어남.)
    3. 활성화 함수는 ReLU.
    4. 완전연결 계층에서는 드롭아웃 계층을 사용.
    5. Adam을 사용해 최적화(가중치 매개변수 갱신).
    6. 가중치 초깃값은 'He의 초깃값'.
  • 이 심층 신경망은 학습시키는 데에 거의 반나절이 걸린다고 함.

  • 대신 정확도는 99.38%(책 기준)임.

  • 이 신경망이 잘못 인식할 확률은 고작 0.62%인데, 그 범위에 드는 어떤 이미지를 잘못 인식했을까?

  • 각 사진의 왼쪽 상단에는 정답 레이블, 오른쪽 하단에는 신경망 추론결과가 있음.

  • 이번의 심층 CNN은 정확도가 높고, 인간과 비슷한 인식 오류를 가짐.
    = 심층 CNN의 잠재력이 크다!

8.1.2 정확도를 높이려면

  • What is the class of this image? 웹 사이트는 다양한 데이터셋을 대상으로 그동안 논문 등에서 발표한 기법들의 정확도를 순위로 정리해 둠.

  • 위 사진은 책에서 인용한 2016년 12월 시점의 순위인데, 현재 2021년 2월의 순위도 위와 같음.
  • MNIST 데이터셋에서의 정확도 1위는 CNN을 기초로 한 것으로, 합성곱 계층 2개에 완전연결 계층 2개 정도의 깊지 않은 신경망을 사용.
  • 데이터 확장은 손쉬운 정확도 개선 방법 중 하나.
  • 입력 이미지(훈련 이미지)를 알고리즘을 동원해 회전이나 이동과 같은 미세한 변화를 주어 인위적으로 이미지의 개수를 늘리는 것.
  • 데이터가 몇 개 없을 때, 매우 효과적임.
  • 이외에도 데이터 확장 방법에는 이미지 일부를 잘라내는 크롭, 좌우를 뒤집는 플립, 밝기 등의 외형변화, 확대나 축소 같은 스케일 변화 등이 있음.

8.1.3 깊게 하는 이유

  • 층을 왜 깊게 하는가?
  • 아직 근거는 부족하지만 다음과 같은 설명을 할 수 있음.

1. 주류의 경향

  • ILSVRC로 대표되는 대규모 이미지 인식 대회에서 좋은 성적을 거둔 기법 대부분이 딥러닝 기법이며, 그 경향은 신경망을 더 깊게 만드는 방향으로 가고 있음.

2. 심층 사용 시 매개변수 감소

  • 신경망의 매개변수 수가 줄어듦. 이는 깊지 않은 신경망보가 적은 매개변수로 같거나 그보다 위인 수준의 표현력을 달성 가능한 것.
  • 5x5 필터로 구성된 합성곱 계층이 있다고 하자.
  • 여기서 주목할 점은 출력 데이터의 각 노드가 입력 데이터의 어느 영역으로부터 계산되었냐는 것.
  • 여기서는 각각의 출력노드는 5x5 크기 영역에서 계산됨.
  • 3x3의 합성곱 연산을 2회 반복하는 경우를 생각해보자.
  • 5x5 크기의 영역에서 3x3의 중간데이터가 계산되고, 3x3의 중간데이터에서 출력노드 하나가 나옴.
  • 이 결과는 5x5의 합성곱 연산 1회가 3x3의 합성곱 연산 2회 수행으로 대체될 수 있음을 보여줌.
  • 또한 전자는 매개변수가 25개(1회x5x5)라하면, 후자는 총 18개(2회x3x3)임.
    = 매개변수 수는 층을 반복할수록 작아짐.
    = 이를 넓은 수용영역을 소화한다고 말함.
  • 반대로 말하면 층이 얕을수록 필요한 매개변수가 많아짐.
  • 3x3의 합성곱 연산을 3회하면 매개변수는 27개지만, 같은 크기 영역을 1회 합성곱 연산으로 면 7x7 크기의 필터, 즉 매개변수 49개 필요한 것임.
    (거꾸로 올라가기: 1 -> 9 -> 25 -> 49)

3. 학습 효율성이 좋아짐.

  • 층을 깊게하면 학습 데이터의 양을 줄여 학습을 고속으로 수행할 수 있음.
  • 앞 장에서 우린 CNN이 층마다 엣지, 블룸, 텍스처, 사물의 부분과 같은 정보를 계층적으로 추출하고 있음을 봤음.
  • 만약 '개'를 인식한다고 했을 때, 얕은 신경망에서 해결하려면 합성곱 계층은 개의 특징 대부분을 한번에 이해해야 함.
  • 그런데 견종도 많고 각도에 따라 사진도 달리보일 수 있으니, 개의 특징을 이해하려면 변화가 풍부하고 많은 학습 데이터를 필요로 하게 되며 따라서 학습 시간이 오래 걸리게 됨.
  • 신경망을 깊게 하면 학습해야할 문제를 계층마다 분업해서 도맡을 수 있으니, 각 층에서는 보다 단순한 문제만 해결하면 됨.

4. 정보를 계층적으로 전달 가능.

  • 예를 들어 엣지를 추출한 층의 다음 층은 엣지 정보를 가져다 쓸 수 있고, 이를 바탕으로 고도의 패턴을 효과적으로 학습하리라 기대할 수 있음.
  • 지금 심층 신경망이 제대로 학습할 수 있는 이유는 새로운 기술과 빅데이터, 컴퓨터 연산 기술 향상이 뒷받침된 결과.

8.2 딥러닝 초기 역사

  • 딥러닝이 뜨게 된 계기는 이미지 인식 기술을 겨루는 ILSVRC(ImageNet Large Scale Visual Recognition Challenge)의 2012년 대회에서 였음.
  • 압도적인 성적으로 Alexnet이 우승하면서 그동안 이미지 인식에 대한 접근법을 바꿔놓음.

8.2.1 이미지넷

  • 이미지넷은 100만 장이 넘는 이미지를 담고 있는 데이터셋.

  • 위 사진처럼 다양한 이미지를 포함하며, 각 이미지에는 레이블이 붙어있음.

  • ILSVRC에서는 이 데이터셋을 가지고 이미지 인식 기술 대회를 여는 것.

  • 대회 시험 항목 중에는 분류가 있는데, 분류 부문에서는 1,000개의 클래스를 제대로 분류하는지 겨룸.

  • 위 그래프는 2010년부터 최근까지 ILSVRC의 분류 부문 우승팀의 성적 기록으로, 예측이 틀린 비율을 나타냄.

  • 2012년에 AlexNet이 등장함으로 인해 오류 비율이 크게 낮아졌으며, 그 이후 2015년에는 150층이 넘는 심층 신경망인 ResNet이 오류 비율을 3.5%까지 낮춤.

  • 이 결과는 일반적인 인간의 인식능력을 넘어 선 것이라고 함.

  • 최근 뛰어난 성적을 거두고 있는 딥러닝 중에서는 VGG, GoogLeNet, ResNet이 특히 유명함.

profile
인공지능 냉각시스템 개발기업 전략기획

0개의 댓글