Deep Learning을 공부하고자 하는 많은 입문자들을 위하여 내가 공부하면서 입문서로 가장 도움이 되었던 Michael Nielsen의 온라인 도서를 여기 장별로 정리하여 두고자 한다.
이 장에서 나오는 내용들은 그의 온라인 도서 5장에 대한 내용을 한국어로 얼기설기 번역한 것이다. 번역이 어색하지만, 개념을 이해하기에는 무리가 없다고 생각한다.
당신이 컴퓨터를 처음부터 설계해야하는 엔지니어라고 상상해 보도록 하겠습니다. 어느날 사무실에서 논리 회로를 설계하고, AND 게이트와 OR 게이트 등을 배치하며 작업에 몰두하고 있을 때, 당신의 상사가 나쁜 소식을 가지고 찾아옵니다. 고객이 방금 놀라운 설계 요구 사항을 추가했다는 것입니다. 바로 컴퓨터 전체 회로가 단 두 층 깊이여야 한다는 것입니다.
당신은 어이가 없어서 상사에게 말합니다. "고객이 미쳤어요!"
상사는 대답합니다. "나도 그렇게 생각해요. 하지만 고객이 원하는 대로 설계할 수 밖에 없어요."
사실, 고객이 완전히 미친 것은 아닙니다. 원하는 만큼 많은 입력을 AND 연산할 수 있는 특별한 논리 게이트를 사용할 수 있다고 가정해 봅시다. 게다가 여러 입력을 AND 연산한 다음 출력을 부정할 수 있는 다중 입력 NAND 게이트도 사용할 수 있습니다. 이러한 특수 게이트를 사용하면 단 두 층 깊이의 회로만으로 어떤 함수든지 계산할 수 있다는 것을 우리는 알고 있습니다.
하지만 어떤 것이 가능하다는 것이 그것이 좋은 아이디어라는 것을 의미하지는 않습니다. 실제로 회로 설계 문제(또는 대부분의 알고리즘 문제)를 해결할 때, 우리는 보통 하위 문제를 어떻게 해결할지 파악하는 것부터 시작하여 점차적으로 해결책을 통합해 나갑니다. 다시 말해, 우리는 여러 계층의 추상화를 통해 해결책을 구축해 나갑니다.
예를 들어, 두 숫자를 곱하는 논리 회로를 설계한다고 가정해 봅시다. 아마도 우리는 두 숫자를 더하는 연산과 같은 작업을 수행하는 하위 회로들로 그것을 만들고 싶어할 것입니다. 두 숫자를 더하는 하위 회로는 차례로 두 비트를 더하는 더 하위 회로들로 만들어 질 것입니다. 매우 대략적으로 말하면 우리 회로는 다음과 같이 보일 것입니다.
즉, 최종 회로는 적어도 세 층의 회로 소자로 구성될 것입니다. 사실, 제가 설명한 것보다 더 작은 단위로 하위 작업을 나누기 때문에 실제로는 세 층보다 더 많은 층으로 구성될 가능성이 큽니다. 하지만, 우리의 논의의 대략적인 개념을 이해했을 것입니다.
따라서 깊은 계층으로 구성된 회로는 설계 과정을 더 쉽게 해줍니다. 그러나 그것이 설계에만 도움이 된다는 것은 아닙니다. 사실, 일부 함수에 대해서는 매우 얕은 계층을 갖는 회로가 깊은 계층을 갖는 회로보다 기하급수적으로 더 많은 회로 소자를 필요로 한다는 것을 보여주는 수학적 증명이 있습니다. 예를 들어 1980년대 초의 유명한 논문들은 비트 집합의 패러티를 얕은 계층의 회로로 계산하려면 기하급수적으로 많은 게이트가 필요하다는 것을 증명했습니다. 반면에 더 깊은 계층의 회로를 사용하면 적은 수의 회로로 패러티를 쉽게 계산할 수 있습니다. 비트 쌍의 패러티를 계산한 다음 그 결과를 사용하여 비트 쌍의 쌍의 패러티를 계산하는 등의 방식으로 전체 패러티를 산출하도록 회로를 구성할 수 있습니다. 따라서 깊은 계층의 회러는 본질적으로 얕은 계층의 회로보다 훨씬 더 강력할 수 있습니다.
지금까지 여기서는 신경망을 미친 고객처럼 접근했습니다. 우리가 작업했던 거의 모든 신경망은 입력 및 출력 계층을 포함하여 하나의 은닉 뉴런 계층만 가지고 있었습니다.
이러한 간단한 신경망은 놀라울 정도로 유익했습니다. 이전 장에서 우리는 이와 같은 신경망을 사용하여 98% 이상의 정확도로 손으로 쓴 숫자를 분류했습니다. 그럼에도 불구하고 직관적으로 우리는 훨씬 더 많은 숨겨진 계층을 가진 신경망이 더 강력할 것이라고 예상할 수 있습니다.
이러한 신경망은 Boolean 회로에서와 마찬가지로 여러 단계의 추상화를 위하여 중간 계층들을 사용할 수 있습니다. 예를 들어, 시각적 패턴 인식에 적용할 경우, 첫 번째 계층의 뉴런은 가장자리를 인식하는 방법을 학습하고, 두 번째 계층의 뉴런은 가장자리에서 구축된 더 복잡한 모양(예: 삼각형 또는 직사각형)을 인식하는 방법을 학습할 수 있습니다. 세 번째 계층은 훨씬 더 복잡한 모양을 인식합니다. 이러한 식의 여러 단계에 걸친 추상화는 깊은 계층의 신경망이 복잡한 패턴 인식 문제를 해결하는 방법을 학습하는데 더 강력한 이점을 제공할 가능성이 높습니다. 게다가 회로의 경우와 마찬가지로 깊은 계층의 신경망이 얕은 계층의 신경망보다 본질적으로 더 강력하다는 것을 시사하는 이론적 결과도 있습니다.
이러한 깊은 계층의 신경망을 어떻게 학습시킬 수 있을까요? 이 장에서는 우리의 주력 학습 알고리즘인 역전파를 통한 확률적 경사 하강법을 사용하여 깊은 계층의 신경망을 학습시켜 볼 것입니다. 하지만 우리는 어려움에 직면하게 될 것이며, 우리의 깊은 계층의 신경망이 얕은 계층의 신경망보다 훨씬 더 나은 성능을 보이지 않을 것입니다.
이러한 실패는 위의 논의에 비추어 볼 때 놀라운 일입니다. 깊은 계층의 신경망을 포기하는 대신 우리는 깊은 계층의 신경망을 학습시키는 것을 어렵게 만드는 요인들에 대해서 논의할 것입니다. 자세히 살펴보면 우리의 깊은 계층의 신경망의 서로 다른 계층들이 엄청나게 다른 속도로 학습하고 있는 것을 발견할 것입니다. 특히, 신경망의 후반 계층들이 잘 학습하고 있을 때, 전반 계층들은 종종 학습 중에 멈춰서 거의 아무것도 학습하지 못합니다. 이러한 학습 저하는 단순히 운이 나빠서가 아닙니다. 오히려 우리는 학습 속도 저하가 발생하는 근본적인 원인으로 경사 기반 학습 기술이 큰 역할을 하고 있다는 것에 대하여 논의할 것입니다.
문제를 더 깊이 파고들수록 우리는 반대 현상도 있다는 것을 알게될 것입니다. 전반 계층은 잘 학습하고 있지만 후반 계층이 학습을 멈출 수도 있습니다. 사실 우리는 여러 계층으로 이루어진 신경망에서 경사 하강법으로 학습하는 것과 관련하여 본질적으로 불안정성이 있다는 것을 발견하게 될 것입니다. 이러한 불안정성은 학습 중에 전반 계층 또는 후반 계층 중 어느 하나가 학습을 멈추는 경향이 있습니다.
이 모든 것이 나쁜 소식처럼 들립니다. 하지만 이러한 어려움을 파고들수록 우리는 깊은 계층의 신경망을 효과적으로 학습시키는데 필요한 것이 무엇인지에 대한 통찰력을 얻을 수 있습니다. 따라서 이러한 논의는 다음 장을 논의하기 전에 필요한 것입니다. 다음 중에서는 딥러닝을 사용하여 이미지 인식 문제에 대하여 논의할 예정입니다.
기울기 소실 문제
자, 우리가 깊은 계층의 신경망을 훈련하려고 할 때, 무엇이 잘못되는 것일까요?
그 질문에 답하기 위하여 먼저 단일 은닉층만 있는 신경망을 다시 살펴보겠습니다. 평소와 마찬가지로 MNIST 숫자 분류 문제를 학습과 실험은 위하여 사용하도록 하겠습니다.
이번 장의 논의는 직접 신경망을 훈련시켜보면서 계속할 수 있습니다. 물론 그냥 읽기만 하셔도 괜찮습니다. 실시간으로 따라하려면 파이선, Numpy, 그리고 신경망 코드가 필요합니다.
git clone https://github.com/mnielsen/neural-networks-and-deep-learning.git
git을 사용하지 않는다면, 여기에서 데이터와 코드를 다운로드할 수 있습니다. src 하위 디렉토리로 이동하여 파이선 쉘에서 MNIST 데이터를 로드해야합니다.
>>> import mnist_loader >>> training_data, validation_data, test_data = \ ... mnist_loader.load_data_wrapper()
신경망은 다음과 같이 구성할 수 있습니다.
>>> import network2 >>> net = network2.Network([784, 30, 10
이 신경망은 입력 이미지의 28×28=784 픽셀에 해당하는 784개의 뉴런을 입력층으로 가지고 있습니다. 우리는 30개의 은닉 뉴런과 10개의 출력 뉴런을 사용하여, 이는 MNIST 숫자에 대한 10가지 가능한 분류('0', '1', '2', ..., '9')에 해당합니다.
학습률 η=0.1, 정규화 파라미터 λ=5.0, 미니 배치 크기 10으로 30번의 전체 에포크 동안 신경망을 학습시켜 보겠습니다. 학습하는 동안 validation_data에 대한 분류 정확도를 모니터링할 것입니다.
>>> net.SGD(training_data, 30, 10, 0.1, lmbda=5.0, ... evaluation_data=validation_data, monitor_evaluation_accuracy=True)
실행할 때마다 약간씩 차이가 나긴 하지만, 분류 정확도 96.48%를 얻을 수 있습니다. 이는 비슷하게 설정한 이전 결과와 비슷합니다.
이제 또 다른 은닉층을 추가해 보겠습니다. 이 은닉층에도 30개의 뉴런을 넣고 동일한 하이퍼파라미터로 학습을 시켜보겠습니다.
>>> net = network2.Network([784, 30, 30, 10]) >>> net.SGD(training_data, 30, 10, 0.1, lmbda=5.0, ... evaluation_data=validation_data, monitor_evaluation_accuracy=True)
이렇게 실행하면 96.90%로 향상된 분류 정확도를 얻을 수 있습니다. 고무적입니다. 신경망에 계층을 추가하니 도움이 됩니다. 30개 뉴런을 가진 은닉층을 하나 더 추가해보겠습니다.
>>> net = network2.Network([784, 30, 30, 30, 10]) >>> net.SGD(training_data, 30, 10, 0.1, lmbda=5.0, ... evaluation_data=validation_data, monitor_evaluation_accuracy=True)
이건 전혀 도움이 되지 않습니다. 사실 결과는 원래의 하나의 은닉층을 가진 신경망과 거의 비슷한 96.57%로 다시 떨어집니다. 그렇지만 하나의 은닉층을 더 추가해보겠습니다.
>>> net = network2.Network([784, 30, 30, 30, 30, 10]) >>> net.SGD(training_data, 30, 10, 0.1, lmbda=5.0, ... evaluation_data=validation_data, monitor_evaluation_accuracy=True)
분류 정확도는 다시 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 근처에서 포화되어 학습 속도가 상당히 느려진다는 증거를 발견했습니다. 그들은 이러한 포화 문제에서 덜 영향을 받는 것으로 보이는 몇 가지 대체 활성화 함수를 제안했습니다.
두 번째 예로, 2013년에 Sutskever, Martens, Dahl과 Hinton은 모멘텀 기반 확률적 경사 하강법에서 무작위 가중치 초기화와 모멘텀 스케줄이 심층 학습에 미치는 영향을 연구했습니다. 무작위 선택보다는 적절한 값을 설정하는 것이 심층 신경망의 학습 능력에 상당한 차이를 만든다는 것을 확인했습니다.
이러한 예들은 "심층 신경망을 학습하기 어렵게 만드는 것은 무엇인가?"라는 질문이 복잡하다는 것을 시사합니다. 이 장에서는 심층 신경망에서의 기울기 기반 학습과 관련된 불안정성에 대하여 다루었습니다. 마지막의 두 단락에서 살펴본 바 들은 활성화 함수의 선택, 가중치 초기화 방법, 심지어 경사 하강법을 통한 학습 구현 방식의 세부 사항도 중요한 역할을 한다는 것을 시사합니다. 물론 신경망의 아키텍처 및 기타 하이퍼파라미터의 선택도 중요합니다. 따라서 많은 요인들이 심층 신경망을 학습하기 어렵게 만드는데 기여할 수 있으며, 이러한 모든 요소들을 이해하는 것은 여전히 진행 중인 연구 주제들입니다. 이 모든 것들이 다소 비관적이고 우울하게 들릴 수 있습니다. 하지만 좋은 소식은 다음 장에서 이러한 장애물들을 어느 정도 극복하거나 우회하는 여러 가지 심층 학습 접근 방식들을 다룰 것이라는 점입니다.
댓글 없음:
댓글 쓰기