Deep Learning을 공부하고자 하는 많은 입문자들을 위하여 내가 공부하면서 입문서로 가장 도움이 되었던 Michael Nielsen의 온라인 도서를 여기 장별로 정리하여 두고자 한다.
이 장에서 나오는 내용들은 그의 온라인 도서 6장에 대한 내용을 한국어로 얼기설기 번역한 것이다. 번역이 어색하지만, 개념을 이해하기에는 무리가 없다고 생각한다.
지난 장에서 우리는 심층 신경망이 얕은 신경망보다 훨씬 학습시키기 어렵다는 것을 알았습니다. 심층 신경망을 학습시킬 수 있다면 얕은 신경망보다 훨씬 더 강력할 것이라고 믿을 만한 충분한 이유가 있기 때문에 이는 안타까운 일입니다. 하지만 지난 장의 내용이 낙담스럽더라도 우리는 포기하지 않을 것입니다 이번 장에서는 심층 신경망을 학습시키는데 사용할 수 있는 기술을 개발하고 실제로 적용해볼 것입니다. 또한 이미지 인식, 음성 인식 및 기타 애플리케이션을 위한 심층 신경망 사용에 대한 최근 현황을 간략히 살펴보면서 더 넓은 그림을 조망해볼 것입니다. 그리고 신경망과 인공 지능의 미래에 대한 간략한 전망도 해볼 예정입니다.
이 장은 좀 긴 편입니다. 이 장에서 다루게 될 내용들에 대하여 간략하게 먼저 살펴보도록 하겠습니다. 이번 장의 하위 섹션들은 내용적 연관성이 크지 않으므로 신경망에 대한 기본적인 이해가 있다면, 관심있는 섹션으로 바로 이동해도 괜찮습니다.
이 장의 주요 부분은 가장 널리 사용되는 심층 신경망의 유형 중 하나인 심층 합성곱 신경망(deep convolutional network)에 대한 소개입니다. MNIST 학습 데이터에서 손으로 쓴 숫자 분류 문제를 해결하기 위하여 합성곱 신경망을 사용하는 방법에 대한 자세한 사례도 다루도록 하겠습니다.
합성곱 신경망에 대한 설명은 이 책의 앞 부분에서 이 문제를 다루는데 사용한 얕은 신경망부터 시작할 예정입니다. 그리고, 얕은 신경망을 반복적으로 수정해가면서 점점 더 강력한 신경망을 구축해가도록 하겠습니다. 이 장을 진행해가면서 convolution, pooling, 얕은 신경망으로 수행했던 것보다 더 많은 것을 수행하기 위하여 GPU를 사용하는 방법, 과적합을 억제하기 위하여 알고리즘을 이용하여 학습 데이터를 확장하고 드롭아웃 기술을 활용하는 방법, 그리고 신경망 앙상블(ensembles of networks)과 같은 기법들을 활용하는 것에 대해서도 다룰 것입니다. 이런 기법들을 활용하여 신경망을 거의 인간에 버금가는 수준으로 만들어 볼 예정입니다. 학습 중에 보지 못한 10,000개의 MNIST 테스트 이미지 중에서 우리의 신경망 시스템은 9,967개를 정확하게 분류할 수 있을 것입니다. 여기서 잘못 분류된 33개의 이미지를 살짝 미리 보여드리겠습니다. 아래 그림에서 오른쪽 상단에 표시된 숫자는 올바르게 분류했을 때의 답이며, 오른쪽 하단의 숫자는 우리 신경망 시스템이 분류한 결과를 표시합니다.
이러한 이미지 중 상당수는 사람이 분류하기도 어렵습니다. 예를 들어 맨 윗줄의 세 번째 이미지를 보시기 바랍니다. 이 이미지는 숫자 "8"을 쓴 것이지만, "9"로도 보입니다. 우리 신경망도 "9"라고 인식했습니다. 이러한 종류의 오류는 최소한 납득 가능하며, 어쩌면 칭찬할 만할 수도 있습니다. 이미지 인식에 대한 논의는 신경망(특히 합성곱 신경망)을 사용하여 이미지 인식을 수행하는 최근의 놀라운 발전에 대한 개요로 마무리하도록 하겠습니다.
이 장의 나머지 부분에서는 더 넓지만 덜 자세한 관점에서 심층 학습(deep learning)에 대해서 논의할 것입니다. 순환 신경망(recurrent neural nets) 및 장단기 메모리 장치(long short-term memory units)와 같은 다른 신경망 모델과 이러한 모델이 음성 인식, 자연어 처리 및 기타 분야에서 어떻게 응용될 수 있는지 간략하게 살펴볼 것입니다. 그리고 의도 기반 사용자 인터페이스와 같은 아이디어부터 인공 지능에서 심층 학습의 역할에 이르기까지 신경망과 심층 학습의 미래에 대해서도 살펴볼 것입니다.
이 장은 역전파, 정규화, 소프트맥스 함수 등과 같은 아이디어를 활용하고 통합하면서 이 책의 앞 장들에서 살펴본 내용들을 토대로 하고 있습니다. 그러나 이 장을 읽기 위해서 앞 장들을 자세히 공부할 필요는 없습니다.
이 장에서는 최신 신경망 라이브러리들에 대하여는 다루지 않을 예정입니다. 또 최첨단 문제를 해결하기 위해 수십 개의 계층을 가진 심층 신경망을 학습시키지도 않을 것입니다. 오히려 심층 신경망의 핵심 원리를 이해하고 간단하고 이해하기 쉬운 MNIST 문제에 이를 적용해보는 것에 초점을 맞출 것입니다. 다시 말해, 이 장에서는 현재 진행되고 있는 광범위한 심층 신경망과 심층 학습에 대한 내용들을 이해할 수 있도록 기본에 충실할 예정입니다.
합성곱 신경망 개요
이전 장들에서 우리는 신경망을 학습시켜 손으로쓴 숫자를 인식하는데 꽤 좋은 성과를 올렸습니다.
우리는 인접한 신경망 계층이 서로 완전히 연결된 신경망을 사용하여 학습시켰습니다. 신경망 계층이 완전히 연결되었다는 것은 신경망 내의 모든 뉴런이 인접한 계층의 모든 뉴런과 연결되어 있음을 의미합니다.
특히, 입력 이미지의 각 픽셀에 대하여 해당 픽셀의 강도를 입력 계층의 해당 뉴런 값으로 대응되도록 신경망을 설계했습니다. 즉, 28×28 픽셀을 갖는 입력 이미지의 각 픽셀이 784개의 입력 뉴런에 하나씩 대응된다는 의미입니다. 그런 다음 신경망의 가중치와 편향을 학습시켜 신경망의 출력이 입력 이미지를 "1", "2", " ... , "8" 또는 "9"로 정확하게 식별하도록 만들었습니다.
이렇게 학습시킨 신경망은 꽤 잘 작동했습니다. MNIST 손글씨 숫자 데이터 세트의 학습 및 테스트 데이터를 사용하여 98% 이상의 분류정확도를 얻었었습니다. 그러나 다시 생각해보면 완전 연결 계층을 가진 신경망을 사용하여 이미지를 분류하는 것은 다소 이상합니다. 그 이유는 그러한 신경망 아키텍처가 이미지의 공간 구조를 고려하지 않기 때문입니다. 예를 들어 이런 신경망 아키텍처는 멀리 떨어져 있거나 가까이 있는 픽셀을 똑같이 취급합니다. 이러한 공간 구조의 개념은 학습 데이터의 특성을 반영하여야 합니다. 입력 데이터의 공간구조를 전혀 고려하지 않은 신경망 아키텍처를 사용하는 대신, 이를 고려한 신경망 아키텍처를 사용하면 어떻게 될까요? 이 섹션에서는 합성곱 신경망(convolutional neural network)에 대하여 다루도록 하겠습니다. 이러한 신경망은 특히 이미지 분류에 적합한 특별한 아키텍처를 사용합니다. 이 아키텍처를 사용하면 합성곱 신경망을 빠르게 학습시킬 수 있습니다. 이는 결과적으로 이미지 분류에 매우 뛰어난 심층 신경망을 학습시키는데 도움이 됩니다. 오늘날 심층 합성곱 신경망 또는 이를 변형한 신경망들이 대부분의 이미지 인식에 사용됩니다.
합성곱 신경망은 세 가지 기본 아이디어를 사용합니다. 지역 수용장(local receptive fields), 가중치 공유(shared weights)와 폴링(pooling)이 그것들입니다. 이들을 차례로 살펴보도록 하겠습니다.
지역 수용장: 앞서 언급한 완전 연결 계층에서는 입력이 뉴런의 수직적 배열로 표현되어 있습니다. 합성곱 신경망에서는 입력을 28×28 뉴런 정사각형으로 간주할 수 있습니다. 이 뉴런들의 값은 입력으로 사용되는 28×28 픽셀 강도에 해당합니다.
마찬가지로, 입력 픽셀은 은닉층 뉴런에 연결될 것입니다. 하지만 모든 입력 픽셀을 모든 은닉층 뉴런에 연결하지는 않을 것입니다. 대신 입력 이미지의 작고 국소적인 영역에서만 연결을 만들도록 하겠습니다.
더 정확히 말하면, 첫 번째 은닉층의 각 뉴런은 입력 뉴런의 작은 영역, 예를 들어 5×5영역 (25개 입력 픽셀에 해당)에 연결됩니다. 따라서 특정 은닉층 뉴런의 경우 다음과 같이 연결될 수 있습니다.
입력 이미지에서 은닉 뉴런과 연결된 영역을 은닉 뉴런의 지역 수용장이라고 부릅니다. 이것이 입력 픽셀에 대한 작은 창과 같습니다. 각 연결은 가중치를 학습합니다. 그리고 은닉 뉴런은 전체적인 편향 또한 학습합니다. 우리는 그 특정 은닉 뉴런이 자신의 특정 지역 수용장을 분석하는 것을 학습한다고 간주할 수 있습니다.
우리는 전체 입력 이미지에 대하여 지역 수용장을 슬라이딩 합니다.(주: 마치 창문을 옆으로 밀어서 움직이는 것처럼 지역 수용장이라는 작은 영역을 전체 이미지의 왼쪽에서 오른쪽으로, 위에서 아래로 차례로 움직이면서 각 위치에 특증일 추출해 나가는 것을 의미한다.) 각 지역 수용장에 대하여 첫 번째 은닉 계층에 다른 은닉 뉴런이 있습니다. 이것을 구체적으로 설명하기 위하여 왼쪽 상단 모서리에 있는 지역 수용장부터 시작해보겠습니다.
다음, 우리는 지역 수용장을 한 픽셀(다시말 해 한 뉴런) 오른쪽으로 이동(sliding)시켜 두번째 은닉 뉴런과 연결시킵니다.
이와 같은 방법으로 첫 번째 은닉 뉴런을 구성합니다. 만약 28×28 크기의 입력 이미지와 5×5 크기의 지역 수용장이 있다면, 은닉 계층에는 24×24개의 뉴런이 존재할 것이라는 점에 유의하시기 바랍니다. 이는 입력 이미지의 왼쪽 끝에서 시작해서 오른쪽 끝까지 지역 수용장을 23개의 뉴런만큼, 위에서 아래까지도 23개의 뉴런만큼 이동시킬 수 있기 때문입니다.
여기서는 지역 수용장이 한 번에 한 픽셀씩 이동하는 것으로 가정했습니다. 사실, 다른 슬라이드 길이를 사용할 수도 있습니다. 예를 들어 지역 수용장을 오른쪽 (또는 아래)으로 2픽셀씩 이동할 수도 있습니다. 이 경우 슬리이드 길이가 2라고 이야기합니다. 이 장에서는 주로 슬라이드 길이를 1로 사용하지만, 때로는 다른 슬라이드 길이를 사용할 수도 있다는 점도 기억하시면 좋을 것 같습니다.
공유 가중치와 편향: 각 은닉 뉴런은 각각의 지역 수용장에 연결된 편향과 5×5 크기의 가중치를 가지고 있습니다. 아직 언급하지 않았던 것은 24×24개의 은닉 뉴런에 대해 동일한 가중치와 편향을 사용하려 한다는 것입니다. 다시 말해, j,k번째 은닉 뉴런의 출력은 다음과 같습니다.
σ(b+4∑l=04∑m=0wl,maj+l,k+m).
여기서 σ는 신경 활성화 함수이며, 이전 장에서 사용했던 시그모이드 함수를 사용할 수도 있습니다. b는 공유되는 값인 편향입니다. wl,m은 공유 가중치의 5×5 배열입니다. 마지막으로 ax,y는 위치 x, y에서의 입력 활성화를 나타냅니다.
이는 첫 번째 은닉 계층의 모든 뉴런이 입력 이미지의 서로 다른 위치에서 정확히 동일한 특징을 감지한다는 의미입니다. 이것이 왜 합리적인지 이해하기 위해, 가중치와 편향이 숩겨진 뉴런이 특정 지역 수용장에서 예를 들어 수직 모서리를 찾아낼 수 있도록 설정되어 있다고 가정해보겠습니다. 그 능력은 이미지의 다른 위치에서도 유용할 가능성이 높습니다. 따라서 이미지 전체에 동일한 감지기를 적용하는 것이 유용합니다. 좀 더 추상적으로 표현하자면 합성곱 신경망은 이미지의 특성이 위치가 바뀌어도 변하지 않는다는 병진 불변성에 잘 적응합니다. 예를 들어, 고양이 사진을 약간 이동시키더라도 여전히 고양이 사진입니다.
이러한 이유로 이렇게 입력 계층에서 은닉 계층으로 대응시키는 것을 때로는 특징 맵(feature map)이라고 부릅니다. 특징 맵을 정의하는 가중치를 공유 가중치라고 부릅니다. 그리고 이러한 방식으로 특징 맵을 정의하는 편향을 공유 편향이라고 부릅니다. 공유 가중치와 편향은 종종 커널(kernel) 또는 필터(filter)를 정의한다고 합니다. 여러 문헌에서 이러한 용어들이 약간 다른 방식으로 사용되기도 하므로 더 정확하게 정의하지는 않도록 하겠습니다. 대신 잠시 후에 좀 더 구체적인 예를 살펴보도록 하겠습니다.
지금까지 설명한 신경망의 구조는 한 종류의 지역화된 특징만 감지할 수 있습니다. 이미지 인식을 위해서는 하나 이상의 특징 맵이 필요합니다. 따라서 완전한 합성곱 계층은 여러 개의 서로 다른 특징 맵으로 구성되기도 합니다.
위 예에서는 3개의 특징 맵이 있습니다. 각 특징 맵은 5×5 크기의 공유 가중치 세트와 하나의 공유 편향으로 정의됩니다. 그 결과 네트워크는 3가지 다른 종류의 특징을 감지할 수 있으며, 각 특징은 전체 이미지에서 감지될 수 있습니다. 위 다이어그램에서 3개의 특징 맵만 표시하고 있지만, 실제로 합성곱 신경망에서는 더 많은 특징 맵이 사용되기도 합니다. 초기 합성곱 신경만 중 하나인 LeMet-5는 MNIST 숫자를 인식하기 위하여 각각 5×5 크기의 지역 수용장과 관련된 6개의 특징 맵을 사용했습니다. 따라서 위에 설명된 예는 실제로 LeNet-5와 매우 유사합니다. 이 장의 뒷부분에서 개발할 예에서는 20개 및 40개의 특징 맵을 가진 합성곱 계층을 사용할 것입니다. 학습된 특징 중 일부를 간단히 살펴보겠습니다.
위 20개의 이미지는 20개의 서로 다른 특징 맵(필터 또는 커널)을 표시합니다. 각 맵은 지역 수용장의 5×5 가중치에 해당하는 5×5 블록 이미지를 나타냅니다. 흰식 블록은 더 작은 (일반적으로 작은 음수) 가중치를 의미하므로 특징 맵은 해당 입력 픽셀에 덜 반응합니다. 어두운 불록은 더 큰 가중치를 의미하므로 특징 맵은 해당 입력 픽셀에 더 많이 반응합니다. 매우 간단히 말하자면, 위의 이미지는 합성곱 계층에 반응하는 특징의 유형을 보유준다고 볼 수 있습니다.
그렇다면 특징 맵에서 어떤 결론을 얻을 수 있을까요? 여기서는 무작위로 에상할 수 있는 것 이상의 공간 구조가 반영되어 있습니다. 많은 특징들이 밝고 어두운 명확한 하위 영역을 가지고 있습니다. 이는 우리의 신경망이 실제로 공간 구조와 관련된 것들을 학습하고 있다는 것을 나타냅니다. 그러나 그 이상으로 이러한 특징 감지기가 무엇을 학습하고 있는지 확인하기는 어렵습니다. 확실히 우리는 많은 전통적 이미지 인식 접근 방식에 사용되었던 가버 필터(Gabor filter)와 같은 것을 학습하고 있지는 않습니다. 사실, 현재 합성곱 신경망이 학습한 특징을 더 잘 이해하기 위한 많은 연구가 진행 중입니다. 이런 연구에 관심이 있으시면 Matthew Zeiler와 Rob Fergus의 논문, "Visualizing and Understanding Convolutional Networks" (2013)를 읽어보시기 바랍니다.
가중치와 편향을 공유하는 것의 가장 큰 장점은 합성곱 신경망에 관련된 매개변수의 수를 크게 줄여준다는 것입니다. 각 특징 맵에 대해서 25 (5×5)개의 공유 가중치와 하나의 공유 편향이 필요합니다. 따라서 각 특징 맵에는 26개의 매개변수가 필요합니다. 20개의 특징 맵이 있다면 합성곱 계층을 정의하는 총 매개변수는 520 (20×26)개 입니다. 이에 비해 책 앞 부분에서 사용했던 것처럼 784 (28×28)개의 입력 뉴런과 비교적 적은 30개의 은닉 뉴런을 가진 완전히 연결된 첫 번재 계층이 있다고 가정해보겠습니다. 이는 총 784×30개의 가중치에 30개의 편향이 추가되어 총 23,550개의 매개변수가 필요합니다. 즉, 완전히 연결된 계층은 합성곱 계층보다 40배 이상 많은 매개변수가 필요합니다.
물론 두 모델을 근본적으로 다르기 때문에 매개변수의 수를 직접적으로 비교할 수는 없습니다. 그러나 직관적으로 볼 때 합성곱 계층에서 병진 불변성을 활용하는 것이 완전히 연결된 모델을 가지고 동일한 성능을 얻는 데 필요한 매개변수 수 보다 훨씬 적은 매개변수 수가 필요할 가능성이 높습니다. 이는 결과적으로 합성곱 모델의 훈련 속도를 높이고 궁극적으로 합성곱 계층을 사용하여 심층 신경망을 구축하는데 도움이 될 것입니다.
덧붙여서 합성곱이라는 이름은 식 (125)의 연산이 때때로 합성곱(convolution)이라고 알려져 있기 때문에 유래했습니다. 좀 더 정확히 말하자면, 식 (125)는 때로 a1=σ(b+w∗a0)와 같이 표시되기도 합니다. 여기서 a1은 하나의 특징 맵에서 나오는 출력 활성화의 집합을 나타내고 a0은 입력 활성화의 집합이며, *는 합성곱 연산을 의미합니다. 여기서 합성곱 연산을 수학적으로 깊이있게 다루지 않을 것이므로 이 것에 대해서 너무 걱정할 필요는 없습니다. 하지만 이름의 유래에 대해서는 알아두는 것이 좋습니다.
폴링 계층: 방금 설명한 합성곱 계층 외에도 합성곱 신경망에서는 폴링 계층도 사용됩니다. 폴링 계층은 일반적으로 합성곱 계층 바로 뒤에 사용됩니다. 폴링 계층의 역할은 합성곱 계층의 출력에서 정보를 단순화하는 것입니다.
좀 더 상세히 말하자면, 폴링 계층은 합성곱 계층에서 출력된 각 특징 맵을 가져와 축약된 특징 맵을 만듭니다. 예를 들어 폴링 계층의 각 뉴런(unit)은 이전 계층에서 2×2개의 뉴런 영역에 대한 요약 작업을 할 수 있습니다. 구체적인 예로 폴링의 일반적인 절차 중 하나는 최대 폴링(max-pooling)이라고 하는 것입니다. 최대 폴링에서 폴링 뉴런은 단순히 다음 그림에서 설명하고 있는 것처럼 2×2 입력 영역에서 최대 활성화를 출력합니다.
합성곱 계층에서 24×24개의 뉴런이 출력되므로, 폴링 후에는 12×12개의 뉴런이 된다는 점에 유의하시기 바랍니다.
위에서 언급했듯이 합성곱 계층은 보통 하나 이상의 특징 맵을 포함합니다. 우리는 각 특징 맵에서 개별적으로 최대 폴링을 적용할 수 있습니다. 이러한 경우 아래 그림과 같은 형태가 될 것입니다.
최대 폴링은 신경망이 이미지 영역 내에 특정 특징이 있는지 여부를 묻는 방법으로 간주할 수 있습니다. 그런 다음 정확한 위치정보는 버립니다. 이에 대한 직관적 설명은 일단 특징이 발견되면 다른 특징과 비교했을 때 정확한 위치 보다는 대락적인 위치만 알면된다는 것입니다. 이러한 방식의 큰 장점은 폴링된 특징의 수가 훨씬 적다는 것입니다. 따라서 이후 계층에서 필요한 매개 변수 수를 줄일 수 있습니다.
최대 폴링만이 폴링에서 사용되는 유일한 기법이 아닙니다. 일반적으로 사용되는 또 다른 폴링으로는 L2 폴링이라는 것이 있습니다. 이 폴링 기법은 2×2 뉴런 영역의 최대 활성화 값을 추출하는 대신 2×2 영역 내에 있는 제곱합의 제곱근을 추출합니다. 세부 사항은 다르지만 직관적인 작동 방식은 최대 폴링과 유사합니다. L2 폴링은 합성곱 계층의 정보를 압축하는 방법입니다. 실제로 두 기술 모두 널리 사용되었습니다. 그리고 때로는 다른 유형의 폴링 연산을 하고도 합니다. 성능을 최대화하려는 경우 검증 데이터를 사용하여 여러 가지 다른 폴링 방식을 비교하고 가장 잘 작동하는 방식을 채택할 수 있습니다. 하지만 우리는 그런 세부적인 최적화에 대해서는 다루지 않을 예정입니다.
전체 구성: 지금까지 논의한 모든 아이디어들을 바탕으로 완전한 합성곱 신경망을 구성할 수 있습니다. 이는 우리가 방금 살펴본 아키텍처에 MNIST 숫자에 대한 10가지 가능한 값('0', '1', '2' 등)에 해당하는 10개의 출력 뉴런 계층을 추가한 것입니다.
위 신경망은 MNIST 이미지의 픽셀 강도를 나타내는데 사용되는 28×28 입력 뉴런으로 시작합니다. 그 다음에는 5×5 지역 수용장과 2개의 특징 맵을 사용하는 합성곱 계층이 이어집니다. 그 결과 3×24×24 크기의 은닉 특징 뉴런 계층이 생성됩니다.
신경망의 마지막 연결 계층은 완전 연결 계층입니다. 즉, 이 계층은 최대 폴링 계층의 모든 뉴런을 10개의 출력 뉴런으로 연결합니다. 이 완전 연결 아키텍처는 이전 장에서와 같습니다. 그러나 위 다이어그램에서 모든 연결을 보여 주는 대신 단순화를 위하여 하나의 화살표만 표시했습니다.
이 합성곱 아키텍처는 이전 장의 아키텍처와 상당히 다릅니다. 그러나 전체적인 그림은 유사합니다. 즉, 가중치와 편향에 의해 동작이 결정되는 많은 간단한 뉴런으로 구성된 신경망입니다. 그리고 전체적인 목표는 여전히 동일합니다. 즉, 학습 데이터를 사용하여 신경망의 가중치와 편향을 학습시켜 입력된 숫자를 잘 분류하도록 하는 것입니다.
특히, 이 책의 앞 부분과 마찬가지로 확률적 경사 하강법과 역전파를 사용하여 신경망을 훈련시킬 것입니다. 이는 이전 장과 거의 동일한 방식으로 진행됩니다. 그러나, 역전파 절차에 몇 가지 수정이 필요합니다. 그 이유는 이전의 역전파 유도가 완전 연결 계층을 가진 신경망을 위한 것이기 때문입니다. 다행히 합성곱 및 최대 폴링 계층에 맞도록 이를 수정하는 것은 그리 어렵지 않습니다. (이것은 숙제로 남기도록 하겠습니다.)
합성곱 신경망 실습
합성곱 신경망의 핵심 아이디어에 대해서 살펴 보았습니다. 몇 가지 합성곱 신경망을 구현해 보고 MNIST 숫자 분류 문제에 적용하여 실제 어떻게 작동하는지 살펴보도록 하겠습니다. 이를 위해 사용할 프로그램은 network3.py 이며, 이전 장에서 살펴변 network.py 나 network2.py 프로그램의 개선된 버전입니다. 직접 실행시켜 보고 싶다면 코드를 Github에서 받을 수 있습니다. 다음 섹션에서 network3.py 에 대하여 자세히 살펴보도록 하겠습니다. 이 섹션에서는 network3.py에서 라이브러리를 사용하여 합성곱 신경망을 구축해보도록 하겠습니다.
network.py 와 network2.py는 Python과 행렬 라이브러리인 Numpy를 사용하여 구현되어있습니다. 이 프로그램들은 기본 원리부터 시작하여 역전파, 확률적 경사 하강법 등 세부 사항까지 직접 구현하고 있습니다. 하지만 이제 이러한 세부 사항을 이해했으므로, network3.py 에서는 Theano 라는 기계학습 라이브러리를 사용하도록 하겠습니다. Theano를 사용하면 관련된 모든 매핑을 자동으로 계산하므로 합성곱 신경망에 대한 역전파를 쉽게 구현할 수 있습니다. 또한 Theano는 이해하기 쉽도록 개발되어 있으며, 속도가 빠르지 않았던 이전 코드들 보다 훨씬 빠르게 구동됩니다. 이 라이브러리를 사용하면 복잡한 신경망을 훨씬 쉽게 학습시킬 수 있습니다. 특히 Theano의 큰 특징 중 하나는 CPU 또는 사용 가능한 경우 GPU에서 코드를 쉽게 실행할 수 있다는 것입니다. GPU에서 실행하면 속도가 상당히 향상되며 더 복잡한 신경망을 더 용이하게 학습시킬 수 있습니다.
이번 장에서 다루는 프로그램을 실행시켜 보고 싶다면, Theano를 설치해야합니다. 프로젝트 홈페이지의 지침에 따라 Theano를 설치할 수 있습니다. 예제들은 Theano 0.6을 활용하여 개발되어 있습니다. 이 장의 실행 결과 중 일부는 GPU 없이 Mac OS X Yosemite, 일부는 NVIDIA GPU가 있는 Ubuntu 14.04에서 실행된 것입니다. 그리고 일부 실행 결과는 두 플랫폼 모두에서 실행된 것입니다. network3.py 를 실행하려면 소스에서 GPU 플래그를 True 또는 False로 적절히 설정해야합니다. 그 외에도 GPU에서 Theano를 설정하기 실행하기 위해서 일련의 작업이 필요할 수도 있습니다. 필요한 지침이나 튜토리얼들을 구글에서 검색해볼 수 있습니다. 로컬 컴퓨터로 GPU를 사용할 수 없다면 Amazon Webservice EC2 G2 Spot Instance를 사용하는 것도 대안이 될 수 있습니다. GPU를 사용하더라도 코드가 실행되는데는 시간이 어느 정도 걸립니다. CPU 환경에서 이 장에서 다루는 가장 복잡한 프로그램을 실행시키면 며칠이 걸리기도 합니다. 이 경우 epoch를 줄이거나 실행을 생략하시기 바랍니다.
* 주석: PyTensor 라이브러리로 구현한 network3.py와 run6.py는 이 링크에서 받을 수 있다. (python 3.13 환경에서 구동 가능 / PyTensor 라이브러리 설치 필요)
위와 같이 실행한 결과 97.80%의 분류 정확도를 얻을 수 있습니다. 이는 검증 데이터를 가지고 최고 분류 정확도를 얻은 학습 에포트에서 평가된 테스트 데이터에 대한 분류 정확도입니다. 테스트 정확도를 평가할 시점을 결정하는 데 검증 데이터를 사용하는 것은 테스트 데이터에 대한 과적합을 피하는데 도움이 됩니다. (이전 장에서 논의한 바 있습니다.) 이후로도 이와 같은 관행을 따라 분류 정확도를 평가하도록 하겠습니다. 신경망의 가중치와 편향이 무작위로 초기화되기 때문에 결과는 약간씩 차이가 날 수 있습니다.
97.80%라는 정확도는 3장에서 비슷한 신경망 아키텍처와 학습 파라미터를 사용하여 얻었던 98.04% 정확도와 유사합니다. 특히 두 예 모두 100개의 은닉 뉴런을 포함하는 단일 은닉 계층이 있는 얕은 신경망을 사용한 것입니다. 뿐만 아니라 두 경우 모두 60 epoch 동안 학습을 진행했고, 미니 배치 크기도 10, 학습률 η=0.1을 사용했습니다.
Deep Learning을 공부하고자 하는 많은 입문자들을 위하여 내가 공부하면서 입문서로 가장 도움이 되었던 Michael Nielsen의 온라인 도서를 여기 장별로 정리하여 두고자 한다.
이 장에서 나오는 내용들은 그의 온라인 도서 5장에 대한 내용을 한국어로 얼기설기 번역한 것이다. 번역이 어색하지만, 개념을 이해하기에는 무리가 없다고 생각한다.
당신이 컴퓨터를 처음부터 설계해야하는 엔지니어라고 상상해 보도록 하겠습니다. 어느날 사무실에서 논리 회로를 설계하고, AND 게이트와 OR 게이트 등을 배치하며 작업에 몰두하고 있을 때, 당신의 상사가 나쁜 소식을 가지고 찾아옵니다. 고객이 방금 놀라운 설계 요구 사항을 추가했다는 것입니다. 바로 컴퓨터 전체 회로가 단 두 층 깊이여야 한다는 것입니다.
당신은 어이가 없어서 상사에게 말합니다. "고객이 미쳤어요!"
상사는 대답합니다. "나도 그렇게 생각해요. 하지만 고객이 원하는 대로 설계할 수 밖에 없어요."
사실, 고객이 완전히 미친 것은 아닙니다. 원하는 만큼 많은 입력을 AND 연산할 수 있는 특별한 논리 게이트를 사용할 수 있다고 가정해 봅시다. 게다가 여러 입력을 AND 연산한 다음 출력을 부정할 수 있는 다중 입력 NAND 게이트도 사용할 수 있습니다. 이러한 특수 게이트를 사용하면 단 두 층 깊이의 회로만으로 어떤 함수든지 계산할 수 있다는 것을 우리는 알고 있습니다.
하지만 어떤 것이 가능하다는 것이 그것이 좋은 아이디어라는 것을 의미하지는 않습니다. 실제로 회로 설계 문제(또는 대부분의 알고리즘 문제)를 해결할 때, 우리는 보통 하위 문제를 어떻게 해결할지 파악하는 것부터 시작하여 점차적으로 해결책을 통합해 나갑니다. 다시 말해, 우리는 여러 계층의 추상화를 통해 해결책을 구축해 나갑니다.
예를 들어, 두 숫자를 곱하는 논리 회로를 설계한다고 가정해 봅시다. 아마도 우리는 두 숫자를 더하는 연산과 같은 작업을 수행하는 하위 회로들로 그것을 만들고 싶어할 것입니다. 두 숫자를 더하는 하위 회로는 차례로 두 비트를 더하는 더 하위 회로들로 만들어 질 것입니다. 매우 대략적으로 말하면 우리 회로는 다음과 같이 보일 것입니다.
즉, 최종 회로는 적어도 세 층의 회로 소자로 구성될 것입니다. 사실, 제가 설명한 것보다 더 작은 단위로 하위 작업을 나누기 때문에 실제로는 세 층보다 더 많은 층으로 구성될 가능성이 큽니다. 하지만, 우리의 논의의 대략적인 개념을 이해했을 것입니다.
따라서 깊은 계층으로 구성된 회로는 설계 과정을 더 쉽게 해줍니다. 그러나 그것이 설계에만 도움이 된다는 것은 아닙니다. 사실, 일부 함수에 대해서는 매우 얕은 계층을 갖는 회로가 깊은 계층을 갖는 회로보다 기하급수적으로 더 많은 회로 소자를 필요로 한다는 것을 보여주는 수학적 증명이 있습니다. 예를 들어 1980년대 초의 유명한 논문들은 비트 집합의 패러티를 얕은 계층의 회로로 계산하려면 기하급수적으로 많은 게이트가 필요하다는 것을 증명했습니다. 반면에 더 깊은 계층의 회로를 사용하면 적은 수의 회로로 패러티를 쉽게 계산할 수 있습니다. 비트 쌍의 패러티를 계산한 다음 그 결과를 사용하여 비트 쌍의 쌍의 패러티를 계산하는 등의 방식으로 전체 패러티를 산출하도록 회로를 구성할 수 있습니다. 따라서 깊은 계층의 회러는 본질적으로 얕은 계층의 회로보다 훨씬 더 강력할 수 있습니다.
지금까지 여기서는 신경망을 미친 고객처럼 접근했습니다. 우리가 작업했던 거의 모든 신경망은 입력 및 출력 계층을 포함하여 하나의 은닉 뉴런 계층만 가지고 있었습니다.
이러한 간단한 신경망은 놀라울 정도로 유익했습니다. 이전 장에서 우리는 이와 같은 신경망을 사용하여 98% 이상의 정확도로 손으로 쓴 숫자를 분류했습니다. 그럼에도 불구하고 직관적으로 우리는 훨씬 더 많은 숨겨진 계층을 가진 신경망이 더 강력할 것이라고 예상할 수 있습니다.
이러한 신경망은 Boolean 회로에서와 마찬가지로 여러 단계의 추상화를 위하여 중간 계층들을 사용할 수 있습니다. 예를 들어, 시각적 패턴 인식에 적용할 경우, 첫 번째 계층의 뉴런은 가장자리를 인식하는 방법을 학습하고, 두 번째 계층의 뉴런은 가장자리에서 구축된 더 복잡한 모양(예: 삼각형 또는 직사각형)을 인식하는 방법을 학습할 수 있습니다. 세 번째 계층은 훨씬 더 복잡한 모양을 인식합니다. 이러한 식의 여러 단계에 걸친 추상화는 깊은 계층의 신경망이 복잡한 패턴 인식 문제를 해결하는 방법을 학습하는데 더 강력한 이점을 제공할 가능성이 높습니다. 게다가 회로의 경우와 마찬가지로 깊은 계층의 신경망이 얕은 계층의 신경망보다 본질적으로 더 강력하다는 것을 시사하는 이론적 결과도 있습니다.
이러한 깊은 계층의 신경망을 어떻게 학습시킬 수 있을까요? 이 장에서는 우리의 주력 학습 알고리즘인 역전파를 통한 확률적 경사 하강법을 사용하여 깊은 계층의 신경망을 학습시켜 볼 것입니다. 하지만 우리는 어려움에 직면하게 될 것이며, 우리의 깊은 계층의 신경망이 얕은 계층의 신경망보다 훨씬 더 나은 성능을 보이지 않을 것입니다.
이러한 실패는 위의 논의에 비추어 볼 때 놀라운 일입니다. 깊은 계층의 신경망을 포기하는 대신 우리는 깊은 계층의 신경망을 학습시키는 것을 어렵게 만드는 요인들에 대해서 논의할 것입니다. 자세히 살펴보면 우리의 깊은 계층의 신경망의 서로 다른 계층들이 엄청나게 다른 속도로 학습하고 있는 것을 발견할 것입니다. 특히, 신경망의 후반 계층들이 잘 학습하고 있을 때, 전반 계층들은 종종 학습 중에 멈춰서 거의 아무것도 학습하지 못합니다. 이러한 학습 저하는 단순히 운이 나빠서가 아닙니다. 오히려 우리는 학습 속도 저하가 발생하는 근본적인 원인으로 경사 기반 학습 기술이 큰 역할을 하고 있다는 것에 대하여 논의할 것입니다.
문제를 더 깊이 파고들수록 우리는 반대 현상도 있다는 것을 알게될 것입니다. 전반 계층은 잘 학습하고 있지만 후반 계층이 학습을 멈출 수도 있습니다. 사실 우리는 여러 계층으로 이루어진 신경망에서 경사 하강법으로 학습하는 것과 관련하여 본질적으로 불안정성이 있다는 것을 발견하게 될 것입니다. 이러한 불안정성은 학습 중에 전반 계층 또는 후반 계층 중 어느 하나가 학습을 멈추는 경향이 있습니다.
이 모든 것이 나쁜 소식처럼 들립니다. 하지만 이러한 어려움을 파고들수록 우리는 깊은 계층의 신경망을 효과적으로 학습시키는데 필요한 것이 무엇인지에 대한 통찰력을 얻을 수 있습니다. 따라서 이러한 논의는 다음 장을 논의하기 전에 필요한 것입니다. 다음 중에서는 딥러닝을 사용하여 이미지 인식 문제에 대하여 논의할 예정입니다.
기울기 소실 문제
자, 우리가 깊은 계층의 신경망을 훈련하려고 할 때, 무엇이 잘못되는 것일까요?
그 질문에 답하기 위하여 먼저 단일 은닉층만 있는 신경망을 다시 살펴보겠습니다. 평소와 마찬가지로 MNIST 숫자 분류 문제를 학습과 실험은 위하여 사용하도록 하겠습니다.
이번 장의 논의는 직접 신경망을 훈련시켜보면서 계속할 수 있습니다. 물론 그냥 읽기만 하셔도 괜찮습니다. 실시간으로 따라하려면 파이선, Numpy, 그리고 신경망 코드가 필요합니다.
이 신경망은 입력 이미지의 28×28=784 픽셀에 해당하는 784개의 뉴런을 입력층으로 가지고 있습니다. 우리는 30개의 은닉 뉴런과 10개의 출력 뉴런을 사용하여, 이는 MNIST 숫자에 대한 10가지 가능한 분류('0', '1', '2', ..., '9')에 해당합니다.
학습률 η=0.1, 정규화 파라미터 λ=5.0, 미니 배치 크기 10으로 30번의 전체 에포크 동안 신경망을 학습시켜 보겠습니다. 학습하는 동안 validation_data에 대한 분류 정확도를 모니터링할 것입니다.
분류 정확도는 다시 96.53%로 떨어집니다. 통계적으로 유의미한 하락이라고 볼 수는 없지만, 고무적인 것도 아닙니다.
이러한 결과는 이상하다고 밖에 할 수 없습니다. 직관적으로 추가되는 은닉층들은 신경망이 더 복잡한 분류 함수를 학습할 수 있도록 하여 분류 작업을 더 잘 수행하도록 해야 합니다. 분명히 최악의 경우 추가된 은닉층은 아무것도 하지 않을 수 있으므로 상황이 악화되지는 않아야 합니다. 그러나 실제로는 악화되기도 합니다.
그렇다면 무슨 일이 일어나고 있는 것일까요? 추가 은닉층이 원칙적으로는 실제로 도움이 될 수 있다고 가정하면, 문제는 우리의 학습 알고리즘이 올바른 가중치와 편향을 찾고 있지 못하다는 것이 됩니다. 우리는 우리의 학습 알고리즘에 무엇이 잘못되었는지, 그리고 어떻게 하면 더 잘 할 수 있는지를 알아내고 싶습니다.
무슨 일이 잘못되고 있는지에 대한 통찰력을 얻기 위해 신경망이 어떻게 학습하는지 시각화해보겠습니다. 아래는 2개의 은닉층을 가지고 각 은닉층에 30개의 은닉 뉴런을 포함하는 [784, 30, 30, 10] 신경망의 일부를 그림으로 나타낸 것입니다. 다이어그램의 각 뉴런에는 신경망이 학습하면서 해당 뉴런이 얼마나 빠르게 변화하는지 나타내는 작은 막대가 있습니다. 막대가 크면 뉴런의 가중치와 편향이 빠르게 변하고 막대가 작으면 가중치와 편향이 천천히 변한다는 뜻입니다. 더 정확하게 말하면 막대는 각 뉴런에 대한 기울기 ∂C/∂b를 나타냅니다. 즉, 뉴런의 편향에 대한 비용 함수의 변화율입니다. 2장에서 우리는 이 기울기 값이 학습 중에 편향이 얼마나 빠르게 변하는지 뿐만 아니라 뉴런에 입력되는 가중치도 얼마나 빠르게 변하는지에 영향을 미친다는 것에 대하여 논의했습니다. 세부 사항이 기억나지 않더라도 걱정하지 마세요. 기억해야할 것은 단순히 이 막대가 신경망이 학습하면서 각 뉴런의 가중치와 편향이 얼마나 빠르게 변하는지를 보여준다는 것입니다.
다어이그램을 단순하게 유지하기 위해 두 개의 은닉층에 있는 상위 6개의 뉴런만 표시했습니다. 입력 뉴런은 학습할 가중치나 편향을 갖지 않으므로 생략했습니다. 여기서는 계층별로 비교를 하는 것이 목적이므로 동일한 수의 뉴런을 가진 계층을 비교하는 것이 가장 의미있으므로 출력 뉴런도 생략했습니다. 다이어그램은 훈련이 시작될 때, 즉 신경망이 초기화된 직후를 표시한 것입니다.
신경망은 무작위로 초기화되었으므로 각 뉴런의 학습 속도의 차이가 크다는 것은 놀라운 것은 아닙니다. 하지만 눈에 띄는 점 중 하나는 두 번째 은닉층의 막대가 대부분 첫 번째 은닉층의 막대보다 훨씬 크다는 것입니다. 결과적으로 두번째 은닉층의 뉴런은 첫 번째 은닉층의 뉴런보다 훨씬 빠르게 학습할 것입니다. 이것은 단순한 우연일까요? 아니면 일반적으로 두 번째 은닉층의 뉴런이 첫 번째 은닉층의 뉴런보다 빠르게 학습할 가능성이 높은 것일까요?
이를 확인하기 위해서는 첫 번째와 두 번째 은닉층의 학습 속도를 전반적으로 비교할 수 있는 방법이 필요합니다. 이를 위해서 l번째 계층의 j번째 뉴런에 대한 기울기를 δlj=∂C/∂blj라고 표시하겠습니다. 기울기 δ1을 첫 번째 은닉층이 얼마나 빠르게 학습할지를 결정하는 항목을 가진 벡터로, δ2는 두 번째 은닉층이 얼마나 빠르게 학습하는지를 결정하는 벡터로 각각 간주할 수 있습니다. 그런 다음 이러한 벡터의 길이를 계층이 학습하는 속도에 대한 대략적인 전체적은 측정값으로 사용하겠습니다. 예를 들어, 길이 $$|| \delta^1 ||$은 첫 번째 은닉층이 학습하는 속도의 측정값이며, 길이 $|| \delta^2 ||$는 두 번째 은닉층이 학습하는 속도에 대한 측정값입니다.
이러한 정의를 사용하면 위에 그림으로 표시된 것과 동일한 구성에서 ||δ1||=0.07... 그리고 ||δ2||=0.31 ..이라는 것을 알 수 있습니다. 따라서 이는 우리가 초기에 품었던 의심을 확인해주고 있습니다. 두 번째 은닉층의 뉴런은 실제로 첫 번째 은닉층의 뉴런보다 훨씬 빠르게 학습하고 있습니다.
세 개의 은닉층을 가진 신경망 [784, 30, 30, 30, 10]에서 은닉층을 추가하면 각각의 학습 속도는 0.012, 0.060, 0.283으로 나타납니다. 여기서도 전반의 은닉층들이 후반의 은닉층보다 훨씬 느리게 학습하는 것을 볼 수 있습니다. 만약 30개의 은닉 뉴런을 가진 또다른 층을 추가하면 학습 속도는 0.003, 0.017, 0.070, 0.285가 됩니다. 전반의 은닉층이 후반의 은닉증 보다 느리게 학습하는 경향은 바뀌지 않습니다.
우리는 신경망이 초기화된 직후인 학습 시작 시점의 학습속도를 살펴보았습니다. 신경망이 학습을 하면서 학습 속도는 어떻게 변할까요? 이제 두 개의 은닉층만 가진 신경망을 다시 살펴보겠습니다. 학습 속도는 다음과 같이 변합니다.
위의 결과는 1,000개의 학습 이미지로 500 에포크 동안 학습한 배치 경사 하강법을 사용하여 얻었습니다. 이는 우리가 보통 학습하는 방식과는 약간 다릅니다. 미니 배치 없이 전체 50,000개 이미지 학습 세트가 아닌 1,000개의 학습 이미지 만을 사용했습니다. 눈 가림하려는 것은 아니지만 미니 배치 확률적 경사 하강법을 사용하면 훨씬 더 노이즈가 많은 결과를 얻게 되기 때문입니다. 여기서 선택한 파라미터를 사용하는 것이 결과를 훨씬 부드럽게 만들어 상황을 쉽게 파악할 수 있게 해줍니다.
어쨌든 보시다시피 두 층은 매우 다른 속도로 학습을 시작합니다. 그런 다음 두 층의 학습 속도는 급격하게 떨어졌다가 다시 반등합니다. 하지만 그 모든 과정에서 첫 번째 은닉층은 두 번째 은닉층보다 훨씬 느리게 학습합니다.
더 복잡한 신경망은 어떨까요? 다음은 비슷한 실험 결과지만, 이번에는 세 개의 은닉층(Network[784, 30, 30, 30, 10])을 구성했습니다.
다시 확인할 수 있지만, 전방의 은닉층이 후방의 은닉층보다 훨씬 느리게 학습합니다. 마지막으로 네 번째 은닉층(Network[784, 30, 30, 30, 30, 10])을 추가하고 학습했을 때 어떤 일이 일어나는지도 살펴보겠습니다.
이 경우에도 전방의 은닉층은 후방의 은닉층보다 느리게 학습합니다. 첫 번째 은닉층은 마지막 은닉층보다 약 100배 느리게 학습하고 있습니다. 이전에는 이러한 신경망을 학습시키는데 어려움을 겪었던 것이 당연합니다.
여기서 중요한 관찰을 할 수 있습니다. 최소한 일부 심층 신경망에서는 역전파를 통해 전방 은닉층으로 이동할수록 기울기가 작아지는 경향이 있습니다. 이는 앞쪽 층의 뉴런이 뒤쪽 층의 뉴런보다 훨씬 느리게 학습한다는 것을 의미합니다. 그리고 우리는 하나의 신경망에서만 이 사실을 살펴보았지만, 많은 신경망에서 이러한 현상이 발생하는 근본적인 이유가 있습니다. 이러한 현상을 기울기 소실 문제(vanishing gradident problem)라고 합니다.
기울기 소실 문제는 왜 발생하는 걸까요? 이를 피할 수 있는 방법은 무엇일까요? 그리고 심층 신경망을 학습시킬 때 어떻게 대처해야할까요? 사실, 곧 알게 되겠지만 이것이 불가피한 것은 아닙니다. 하지만 대안 역시 그다지 매력적이지 않습니다. 때로는 앞쪽 층에서 기울기가 훨씬 더 커지기도 합니다. 이를 기울기 폭주 문제(exploding gradient problem)라고 하며, 기울기 소실 문제보다 나은 소식은 아닙니다. 일반적으로 심층 신경망의 기울기는 불안정하며 앞쪽 층에서 폭주하거나 소실되는 경향이 있습니다. 이러한 불안정성은 심층 신경망에서 기울기 기반의 학습의 근본적인 문제입니다. 우리는 이것을 이해하고, 가능하다면 이를 해결하기 위한 조치를 취해야 합니다.
소실되는(또는 불안정한) 기울기에 대한 한 가지 반응은 그것이 정말 큰 문제인지 궁금해하는 것입니다. 잠시 신경망에서 벗어나 단일 변수 함수 f(x)를 수치적으로 최소화하려고 한다고 가정해봅시다. 도함시 f′(x)가 작다면 좋은 소식이 아닐까요? 이는 우리가 이미 극값에 가까워졌다는 것을 의미하지 않을까요? 마찬가지로 심층 신경망의 앞쪽 층에서 작은 기울기가 가중치와 편향을 많이 조정할 필요가 없다는 것을 의미할 수도 있지 않을까요?
물론 그렇지 않습니다. 신경망에서 가중치와 편향을 무작위로 초기화했다는 것을 상기하시기 바랍니다. 이러한 방식으로 가중치와 편향을 초기화하여, 신경망이 해야할 일을 잘 수행할 가능성은 극히 낮습니다. 구체적으로 MNIST 문제에 대한 Network[784, 30, 30, 30, 10]의 첫 번째 가중치 층에 대하여 생각해봅시다. 무작위 초기화는 첫 번째 층이 입력 이미지에 대한 대부분의 정보를 버린다는 것을 의미합니다. 이후 층이 광범위하게 훈련되었다 하더라도 단순히 정보가 충분하지 않았기 때문에 입력 이미지를 식별하는 데 매우 어려움을 겪을 것입니다. 따라서 첫 번째 층에서 많은 학습이 필요하지 않다는 것은 받아들이기 어렵습니다. 심층 신경망을 학습시키려면 기울기 소실 문제에 대한 해결방법을 알아내야 합니다.
기울기 소실이 일어나는 이유: 심층 신경망에서 기울기 불안정성
기울기가 소실되는 문제의 원인에 대한 통찰력을 얻기 위하여 각 계층마다 하나의 뉴런만 있는 가장 간단한 심층 신경망을 바탕으로 생각해보도록 하겠습니다. 다음은 세 개의 은닉층이 있는 신경망입니다.
위 그림에서 w1,w2,...는 가중치이며, b1,b2,...는 편향, 그리고 C는 비용 함수입니다. 이 신경망이 어떻게 작동하는지 다시 한번 상기해보도록 하겠습니다. j번째 뉴런의 출력 aj는 σ(zj)입니다. 여기서 σ는 일반적인 시그모이드 활성화 함수이고 zj=wjaj−1+bj인 zj는 뉴런에 대한 가중 입력입니다. 비용 C가 신경망의 출력 a4의 함수임을 강조하기 위하여 이를 맨 끝에 표시했습니다. 신경망의 실제 출력이 원하는 출력에 가까우면 비용은 낮아지고 멀리 떨어져 있으면 비용은 높아집니다.
우리는 첫 번째 은닉 뉴런과 관련된 경사도 ∂C/∂b1에 대하여 자세히 살펴볼 것입니다. 우리는 ∂C/∂b1를 구하기 위한 식에 대해서 살펴보고 이를 바탕으로 기울기 소실 문제가 발생하는 원인에 대해서 알아보도록 하겠습니다.
자 먼저, ∂C/∂b1을 구하기 위한 식부터 살펴보겠습니다. 그 식은 무시무시하게 보일 수 있습니다만, 실제로는 간단한 구조를 가지고 있습니다. 아래에 그 식이 있습니다. (잠시 신경망에 대해서는 잊도록 하겠습니다. σ′는 σ 함수의 도함수입니다.)
위 식의 구조를 살펴보면 이렇습니다. 신경망의 각 뉴런마다 곱셈 항에 σ′(zj)항과 가중치 wj항이 각각 하나씩 있고, 마지막에 비용 함수에 해당하는 ∂C/∂a4항이 있습니다. 위의 식에서 각 항을 신경망의 해당 부분 위에 배치하였습니다. 신경망 자체를 보고 표현식을 기억할 수 있도록 하기 위함입니다.
이 식에 대한 설명은 앞서 역전파에 대한 부분에서 다루었던 내용입니다.
편향 b1에 작은 변화 Δb1을 주었다고 상상해보도록 하겠습니다. 이 변화는 신경망의 나머지 부분으로 일련의 연쇄적인 변화를 일으킵니다. 먼저, 첫 번째 은닉 뉴런의 출력에 변화 Δa1을 일으킵니다. 이는 다시 두 번째 은닉 뉴런에 대한 가중 입력에 대한 변화 Δz2를 일으킵니다. 그런 다음 두 번째 은닉 뉴런의 출력의 변화 Δa2가 발생합니다. 그리고 이것이 출력의 비용 C에 변화, ΔC가 생길 때까지 계속됩니다. 즉,
∂C∂b1≈ΔCΔb1.
이는 연쇄적인 효과의 각 단계들을 주의 깊게 추적함으로써 경사도 ∂C/partialb1에 대한 식을 도출할 수 있음을 시사합니다.
이를 위해서 Δb1이 첫 번째 은닉 뉴런의 출력 a1에 어떻게 변화를 일으키는지 알아보도록 하겠습니다. a1=σ(z1)=σ(w1a0+b1)이므로, 다음이 성립합니다.
Δa1≈∂σ(w1a0+b1)∂b1Δb1=σ′(z1)Δb1.
σ′(z1)항은 이제 친숙하게 보일 것입니다. 이것이 앞서 살펴보았던 경사도 ∂C/∂b1를 구하는 식의 첫 번째 항입니다. 직관적으로 이 항은 편향 Δb1의 변화를 출력 활성화 Δa1의 변화로 변환합니다. 이 Δa1의 변화는 다시 두 번째 은닉 뉴런에 대한 가중 입력 z2=w2a1+b2에 변화를 일으킵니다. 즉,
Δz2≈∂z2∂a1Δa1=w2Δa1.
Δz2와 Δa1에 대한 표현식을 결합하여 편향 b1의 변화가 신경망을 따라 전파되어 z2에 영향을 미치는 방식을 알 수 있습니다.
Δz2≈σ′(z1)w2Δb1.
조금 더 친숙해지셨길 바랍니다. 이제 우리는 경사도를 나타내는 식, ∂C/∂b1의 처음 두 개의 항을 얻었습니다.
이러한 방식으로 계속하면 신경망의 나머지 부분을 통해 변화가 전파되는 방식을 추적할 수 있습니다. 각 뉴런에서 σ′(zj)항을 구하고, 각 가중치를 통과할 때마다 wj을 구할 수 있습니다. 최종 결과는 편향의 초기 변화 Δb1와 비용의 최종 변화 ΔC 사이의 관계를 나타내는 표현식입니다. 즉,
ΔC≈σ′(z1)w2σ′(z2)…σ′(z4)∂C∂a4Δb1.
이 식을 Δb1으로 나눔으로써, 기울기를 위한 우리가 바라는 식을 구할 수 있습니다.
∂C∂b1=σ′(z1)w2σ′(z2)…σ′(z4)∂C∂a4.
기울기 소실 문제가 발생하는 이유: 기울기 소실 문제가 발생하는 이유를 이해하기 위하여 경사도에 대한 전체 표현식을 명시적으로 다시 기술하도록 하겠습니다.
∂C∂b1=σ′(z1)w2σ′(z2)w3σ′(z3)w4σ′(z4)∂∂a4.
마지막 항을 제외하고, 위 식은 wjσ′(zj) 형태의 항의 곱입니다. 각 항의 동작 방식을 이해하기 위하여 σ′ 함수의 그래프를 살펴보겠습니다.
도함수, σ′은 σ′(0)=1/4에서 최대값을 갖습니다. 신경망에서 가중치를 초기화하기 위한 표준 방식을 사용한다면, 평균이 0이고 표준 편차가 1인 가우시안 분포를 사용하여 가중치를 설정할 것입니다. 따라서 가중치는 일반적으로 |wj|<1을 만족합니다. 이러한 관찰을 종합해보면 항 wjσ′(zj)는 일반적으로 |wjσ′(zj)|<1/4을 만족한다는 것을 알 수 있습니다. 그리고 많은 이러한 항들의 곱을 취하면, 그 곱은 기하급수적으로 감소하는 경향이 있습니다. 즉, 항이 많을 수록 곱은 작아집니다. 이것은 기울기 소실 문제에 대한 실마리가 조금씩 드러나기 시작하는 것 같습니다.
조금 더 명확하게 하기 위하여, ∂C/∂b1을 위한 식을 나중에 나오는 편향에 대한 기울기, 예를 들어 ∂C/∂b3와 비교해보도록 하겠습니다. 물론 ∂C/∂b3을 구하기 위한 식을 명시적으로 계산해보진 않았지만, ∂C/∂b1에 대해서 위에서 설명한 것과 유사합니다. 다음은 이 두 식에 대한 비교입니다.
두 식은 많은 공통된 항들을 가지고 있습니다. 그러나 기울기 ∂C/∂b1은 wjσ′(zj) 형태의 항을 두 개 더 가지고 있습니다. 앞에서 살펴 보았듯이 이러한 항은 일반적으로 크기가 1/4보다 작습니다. 따라서 기울기 ∂C/∂b1는 ∂C/∂b3보다 16배(혹은 그 이상) 작을 것입니다. 이것이 기울기 소실 문제의 근본적 원인입니다. 물론 이 설명은 기울기 소실 문제에 대한 엄밀한 증명이 아니라 비공식적인 논증입니다. 여기에는 몇 가지 문제를 피해갈 수 있는 가능성이 있습니다. 특히, 학습 중에 가중치 wj가 증가할 수 있는지 궁금해할 수 있습니다. 만약 그렇다면 곱셈 항에 있는 wjσ′(zj)가 더 이상 |wjσ′(zj)|<1/4를 만족하지 않을 수도 있습니다. 실제로 항이 충분히 커지면 (1보다 커지면) 더 이상 기울기 소실 문제가 발생하지 않을 것입니다. 대신, 계층을 역방향으로 이동할수록 기울기가 기하급수적으로 증가할 것입니다. 기울기 소실 문제 대신에 기울기 폭증 문제가 발생할 것입니다.
기울기 폭증 문제: 기울기 폭증이 발생하는 명시적인 예를 살펴보겠습니다. 이 사례는 다소 인위적입니다. 기울기 폭증이 일어나도록 신경망의 매개변수를 면밀히 조정할 것이기 때문입니다. 이 예가 인위적이긴 하지만 기울기 폭증이 단순히 가상적인 상황에서 뿐만 아니라 실제로도 일어날 수 있다는 것을 보여줄 것입니다.
기울기 폭증이 발생하기 위해서 두 단계가 필요합니다. 첫째, 신경망의 모든 가중치를 크게 설정합니다. 예를 들어 w1=w2=w3=w4=100으로 설정합니다. 둘째, σ′(zj) 항이 너무 작지 않도록 편향을 설정합니다. 이는 실제로 매우 쉽습니다. 각 뉴런에 대한 가중 입력이 zj=0 (따라서, σ′(zj)=1/4)이 되도록 편향을 설정하기만 하면 됩니다. 예를 들어 z1=w1a0+b1=0와 같이 설정합니다. b1=−100∗a0로 설정하면 됩니다. 이와 같이 다른 편향도 설정할 수 있습니다. 이렇게 하면 모든 항 wjσ′(zj이 100∗14=25와 같아지는 것을 알 수 있습니다. 이렇게 설정하면 기울기 폭증 현상을 일으킬 수 있습니다.
기울기 불안정성 문제: 여기서 근본적인 문제는 기울기 소실 문제나 기울기 폭증 문제가 아닙니다. 전방 계층의 기울기는 후반 계층의 모든 항의 곱이라는 점입니다. 계층이 많으면 본질적으로 불안정한 상황이 됩니다. 모든 계층이 거의 동일한 속도로 학습할 수 있는 유일한 방법은 해당 항의 모든 곱이 거의 균헝을 이루는 경우입니다. 이러한 균형을 유지할 수 있는 어떤 메커니즘이 없다면, 균형이 우연히 유지될 가능성은 거의 없습니다. 그리고 결과적으로 신경망이 기울기 불안정성 문제를 겪는다는 것입니다. 궁극적으로 표준 기울기 기반 학습 기술을 사용하면 신경망의 여러 계층이 매우 다른 속도로 학습하는 경향이 있습니다.
기울기 소실 문제의 만연성: 다층 신경망의 전방 계층에서 기울기가 소실되거나 폭증할 수 있다는 사실을 확인했습니다. 실제로 시그모이드 뉴런을 사용할 때 기울기는 보통 소실됩니다. 그 이유를 알아보기 위해 |wσ′(z)| 식을 다시 살펴보겠습니다. 기울기 소실 문제를 피하려면 |wσ′(z)|≥1이어야 합니다. w가 매우 크다면 이를 달성할 수 있다고 생각할 수도 있습니다. 그러나 생각보다 이는 어렵습니다. 그 이유는 σ′(z)) 항도 w에 의존하고 있기 때문입니다. 즉, σ′(z)=σ′(wa+b)이며, a는 입력 활성화 입니다. 따라서, w를 크게 만들면서 동시에 σ′(wa+b)가 작아지지 않도록 주의해야합니다. 이는 상당한 제약조건입니다. 그 이유는 w를 크게 만들면 wa+b도 매우 커지는 경향이 있기 때문입니다. 이는 σ′의 그래프에서 σ′ 함수의 '날개' 영역에 해당되어 σ′(wa+b)가 매우 작아지게 됩니다.이를 피할 수 있는 유일한 방법은 입력 활성화가 상당히 좁은 값 범위 내에 유지되는 경우 뿐입니다. 운이 좋다면 우연히 입력 활성화가 그 좁은 값 범위 내에 유지되겠지만, 대부분의 경우 그렇지 않습니다. 따라서 일반적으로 기울기 소실은 발생합니다.
심층 신경망에서의 기울기 불안정성
우리는 각 은닉 계층에 뉴런이 하나씩 있는 간단한 신경망에 대해서 살펴보았습니다. 각 은닉 계층에 많은 뉴런이 있는 더 복잡한 심층 신경망은 어떨까요?
사실, 심층 신경망에서도 거의 동일한 현상이 발생합니다. 역전파에 대한 이전 장에서 우리는 L개의 계층으로 이루어진 신경망의 l번째 계층에서의 기울기가 다음과 같다는 것을 살펴보았습니다.
δl=Σ′(zl)(wl+1)TΣ′(zl+1)(wl+2)T…Σ′(zL)∇aC
여기서 Σ′(zl)는 대각선 항목이 l번째 계층의 가중 입력값인 σ′(z)인 대각 행렬입니다. wl은 각기 다른 계층의 가중치 행렬입니다. 그리고, ∇aC는 출력 활성화에 대한 C의 편도함수 벡터입니다.
이는 단일 뉴런의 경우보다 훨씬 더 복잡한 식입니다. 하지만 자세히 살펴보면, (wj)TΣ′(zj) 형태의 쌍이 많이 있다는 점에서 본질적인 형태는 매우 유사합니다. 더욱이, 행렬 Σ′(zj)는 대각선에 작은 항목을 가지고 있으며, 1/4보다 큰 항목은 없습니다. 가중치 행렬 wj가 너무 크지 않다면, 각 추가항 ((wj)TΣ′(zl)은 기울기 벡터를 더 작게 만들어 기울기 소실을 유발하는 경향이 있습니다. 실제 경험적으로도 시그모이드 신경망에서는 전방 계층에서 기울기가 기하급수적으로 빠르게 소실되는 것이 일반적으로 나타납니다. 결과적으로 이러한 계층에서의 학습 속도가 느려집니다. 이 느려짐은 단순한 우연이나 불편함이 아니라 우리가 채택한 학습 방식에 내재된 문제입니다.
심층 학습의 다른 장애물들
이 장에서는 심층 학습의 장애물로써 기울기 소실, 그리고 더 일반적으로 기울기 불안정성에 초점을 맞췄습니다. 사실, 기울기 불안정성은 심층 학습의 여러 장애물들 중 하나일 뿐이지만 중요하고 근본적인 장애물입니다. 현재 진행 중인 많은 연구들이 심층 신경망을 학습할 때 발생할 수 있는 어려움을 더 잘 이해하는 것을 목표로 하고 있습니다. 여기서는 그 연구들을 포괄적으로 요약하기 보다는 몇 가지 질문에 감을 잡을 수 있도록 몇 편의 논문을 간략히 소개하고자 합니다.
첫 번재 예로, 2010년에 Glorot과 Bengio는 시그모이드 활성화 함수의 사용이 심층 신경망 학습에 문제를 일으킬 수 있다는 증거를 발견했습니다. 특히, 그들은 시그모이드를 사용하면 학습 초기에 마지막 은닉 계층의 활성화 값이 0 근처에서 포화되어 학습 속도가 상당히 느려진다는 증거를 발견했습니다. 그들은 이러한 포화 문제에서 덜 영향을 받는 것으로 보이는 몇 가지 대체 활성화 함수를 제안했습니다.
이러한 예들은 "심층 신경망을 학습하기 어렵게 만드는 것은 무엇인가?"라는 질문이 복잡하다는 것을 시사합니다. 이 장에서는 심층 신경망에서의 기울기 기반 학습과 관련된 불안정성에 대하여 다루었습니다. 마지막의 두 단락에서 살펴본 바 들은 활성화 함수의 선택, 가중치 초기화 방법, 심지어 경사 하강법을 통한 학습 구현 방식의 세부 사항도 중요한 역할을 한다는 것을 시사합니다. 물론 신경망의 아키텍처 및 기타 하이퍼파라미터의 선택도 중요합니다. 따라서 많은 요인들이 심층 신경망을 학습하기 어렵게 만드는데 기여할 수 있으며, 이러한 모든 요소들을 이해하는 것은 여전히 진행 중인 연구 주제들입니다. 이 모든 것들이 다소 비관적이고 우울하게 들릴 수 있습니다. 하지만 좋은 소식은 다음 장에서 이러한 장애물들을 어느 정도 극복하거나 우회하는 여러 가지 심층 학습 접근 방식들을 다룰 것이라는 점입니다.
Biography: Bachelor: Computer Science in Korea Univ. Master: Computer Science in KAIST Carrier: 1. Junior Researcher at Korea Telecom (2006 ~ 2010) 2. Researcher at Korea Institute of Nuclear Nonproliferation and Control (2010~)