케라스 창시자에게 배우는 딥러닝/ 신경망 시작하기

신경망의 구조

  • 신경망 훈련에는 다음 요소들이 관련되어 있다.
    • 네트워크(또는 모델)를 구성하는 층
    • 입력 데이터와 그에 상응하는 타깃
    • 학습에 사용할 피드백 신호를 정의하는 손실 함수
    • 학습 진행 방식을 결정하는 옵티마이저
  • 이들 간의 상호 작용은 아래 그림에 나타냈다.
    • 연속된 층으로 구성된 네트워크가 입력 데이터를 예측으로 매핑한다.
    • 손실 함수는 예측과 타깃을 비교하여 네트워크의 예측이 기댓값에 얼마나 잘 맞는지를 측정하는 손실 값을 만든다.
    • 옵티마이저는 손실 값을 사용하여 네트워크 가중치를 업데이트 한다.

층: 딥러닝의 구성 단위

  • 신경망의 핵심적인 데이터 구조는 층이다. 층은 하나 이상의 텐서를 입력으로 받아 하나 이상의 텐서를 출력하는 데이터 처리 모듈이다.
    • 어떤 종류의 층은 상태가 없지만 대부분의 경우 가중치라는 층의 상태를 가진다.
    • 가중치는 확률적 경사 하강법에 의해 학습되는 하나 이상의 텐서이며 여기에 네트워크가 학습한 지식이 담겨 있다.
  • 층마다 적절한 텐서 포맷과 데이터 처리 방식이 다르다.
    • 예컨대 (samples, features) 크기의 2D 텐서가 저장된 간단한 벡터 데이터는 완전 연결 층(fully connected layer)이나 밀집 층(dense layer)라고도 불리는 밀집 연결 층(densely connected layer)에 의해 처리되는 경우가 많다. (케라스에서는 Dense 클래스이다)
    • (samples, timesteps, features) 크기의 3D 텐서로 저장된 시퀀스 데이터는 보통 LSTM 같은 순환 층(recurrent layer)에 의해 처리된다.
    • 4D 텐서로 저장되어 있는 이미지 데이터는 일반적으로 2D 합성곱 층(convolution layer)에 의해 처리 된다. (Conv2D 클래스)
  • 층을 딥러닝의 레고 블록처럼 생각할 수 있다. 이런 비유는 케라스 같은 프레임워크 때문에 생겼는데, 케라스에서는 호환 가능한 층들을 엮어 데이터 변환 파이프라인(pipeline)을 구성함으로써 딥러닝 모델을 만든다.
    • 여기에서 층 호환성(layer compatibility)은 각 층이 특정 크기의 입력 텐서만 받고 특정 크기의 출력 텐서를 반환한다는 사실을 말한다.
  • 다음 예를 살펴 보자.
from keras import layers
layer = layers.Dense(32, input_shape=(784,)) --32개의 유닛으로 밀집된 층
  • 첫 번째 차원이 784인 2D 텐서만 입력으로 받는 층을 만들었다. (배치 차원인 0번째 축은 지정하지 않기 때문에 어떤 배치 크기도 입력으로 받을 수 있다.)
    • 이 층은 첫 번째 차원 크기가 32로 변환된 텐서를 출력할 것이다.
    • 따라서 이 층에는 32차원의 벡터를 입력으로 받는 하위 층이 연결되어야 한다. 케라스에서는 모델에 추가된 층을 자동으로 상위 층의 크기에 맞추어주기 때문에 호환성을 걱정하지 않아도 된다.
  • 예컨대 다음과 같이 작성 했다고 가정하자.
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(32, input_shape=(784,)))
model.add(layers.Dense(10))
  • 두 번째 층에는 input_shape 매개변수를 지정하지 않았는데, 이러면 앞선 층의 출력 크기를 입력 크기로 자동으로 채택한다.

모델: 층의 네트워크

  • 딥러닝 모델은 층으로 만든 비순환 유향 그래프(Directed Acyclic Graph, DAG)이다.
    • 가장 일반적인 예가 하나의 입력을 하나의 출력으로 매핑하는 층을 순서대로 쌓는 것이다.
  • 앞으로 공부하다 보면 아주 다양한 네트워크 구조를 보게 될 것이다. 자주 등장하는 것들은 다음과 같다.
    • 가지(branch)가 2개인 네트워크
    • 출력이 여러 개인 네트워크
    • 인셉션(Inception) 블록
  • 네트워크 구조는 가설 공간(hypothesis space)을 정의한다.
    • 1장에서 머신 러닝을 ‘가능성 있는 공간을 사전에 정의하고 피드백 신호의 도움을 받아 입력 데이터에 대한 유용한 변환을 찾는 것’으로 정의했는데, 네트워크 구조를 선택함으로써 가능성 있는 공간(가설 공간)을 입력 데이터에서 출력 데이터로 매핑하는 일련의 특정 텐서 연산으로 제한하게 된다.
    • 우리가 찾아야 할 것은 이런 텐서 연산에 포함도니 가중치 텐서의 좋은 값이다.
  • 딱 맞는 네트워크 구조를 찾아내는 것은 과학보다 예술에 가깝다. 신뢰할 만한 모범적인 사례와 원칙이 있지만 연습을 해야만 적절한 신경망을 설계할 수 있는 기술을 갖추게 될 것이다.
    • (여기서 과학은 이론적으로 구성 가능한 것을 의미하고, 예술은 훈련을 통해 향상 시키는 기예의 의미에 가깝다. 실제 Art에는 그런 의미가 포함 되어 있음. 예술 작품이 아니라)

손실 함수와 옵티마이저: 학습 과정을 조절하는 열쇠

  • 네트워크 구조를 정의하고 나면 두 가지를 더 선택해야 한다.
    • 손실 함수(loss function) (목적 함수(objective function)): 훈련하는 동안 최소화 될 값이다. 주어진 문제에 대한 성공 지표가 된다.
    • 옵티마이저(optimizer): 손실 함수를 기반으로 네트워크가 어떻게 업데이트될지 결정한다. 특정 종류의 확률적 경사 하강법(SGD)를 구현한다.
  • 여러 개의 출력을 내는 신경망은 여러 개의 손실 함수를 가질 수 있다. (출력당 하나씩).
    • 하지만 경사 하강법 과정은 하나의 스칼라 손실 값을 기준으로 한다. 따라서 손실이 여러 개인 네트워크에서는 모든 손실이 (평균을 내서) 하나의 스칼라 양으로 합쳐진다.
  • 문제에 맞는 올바른 목적 함수를 선택하는 것이 아주 중요하다. 네트워크가 손실을 최소화하기 위해 편법을 사용할 수 있기 때문이다.
    • 목적 함수가 주어진 문제의 성공과 전혀 관련이 없다면 원하지 않은 일을 수행하는 모델이 만들어질 것이다.
    • “모든 인류의 평균 행복 지수를 최대화하기” 같은 잘못된 목적 함수에서 SGD로 훈련된 멍청하지만 전지전능한 AI가 있다고 가정하자. 이 문제를 쉽게 해결하기 위해 이 AI는 몇 사람을 남기고 모든 인류를 죽여서 남은 사람들의 행복에 초점을 맞출 수 있다.
    • 우리가 만든 모든 신경망은 단지 손실 함수를 최소화하기만 한다는 것을 기억하라. 목적 함수를 현명하게 선택하지 않으면 원하지 않는 부수 효과가 발생할 것이다.
  • 다행히 분류, 회귀와 시퀀스 예측 같은 일반적인 문제에서는 올바른 손실 함수를 선택하는 간단한 지침이 있다.
    • 예컨대 2개의 클래스가 있는 분류 문제에는 이진 크로스엔트로피(binary crossentropy), 여러 개의 클래스가 있는 분류 문제에는 범주형 크로스엔트로피(categorical croessentropy), 회귀 문제에는 평균 제곱 오차, 시퀀스 학습 문제에는 CTC(Connection Temporal Classification) 등을 사용한다.
    • 완전히 새로운 연구를 할 때만 독자적인 목적 함수를 만들게 된다.

케라스 소개

  • 이 책에서는 코드 예제를 위해 케라스(https://keras.io)를 사용한다.
    • 케라스는 거의 모든 종류의 딥러닝 모델을 간편하게 만들고 훈련시킬 수 있는 파이썬을 위한 딥러닝 프레임워크이다.
    • 케라스는 MIT 라이선스를 따르고 있으므로 상업적인 프로젝트에도 자유롭게 사용할 수 있다.

케라스, 텐서플로, 씨아노, CNTK

  • 케라스는 딥러닝 모델을 만들기 위한 고수준의 구성 요소를 제공하는 모델 수준의 라이브러리이다. 텐서 조작이나 미분 같은 저수준의 연산을 다루지 않는다. 
    • 대신 케라스의 백엔드 엔진에서 제공하는 최적화되고 특화된 텐서 라이브러리를 사용한다.
    • 케라스는 하나의 텐서 라이브러리에 국한하여 구현되어 있지 않고 모듈 구조로 구성되어 있다.
    • 여러 가지 백엔드 엔진이 케라스와 매끄럽게 연동된다. 현재는 텐서플로, 씨아노, 마이크로소프트 코그니티브 툴킷(Microsoft Cognitive Toolkit, CNTK) 3개를 백엔드 엔진으로 사용할 수 있다.

  • 텐서플로, CNTK, 씨아노는 딥러닝을 위한 주요 플랫폼 중 하나이다.
    • 씨아노는 몬트리올 대학 MILA 연구소에서 개발했고, 텐서플로는 구글에서 개발했으며, CNTK는 마이크로소프트에서 개발했다.
    • 케라스로 작성한 모든 코드는 아무런 변경 없이 이런 백엔드 중 하나를 선택해서 실행시킬 수 있다.
    • 개발하는 중간에 하나의 백엔드가 특정 작업에 더 빠르다고 판단되면 언제든 백엔드를 바꿀 수 있다.
    • 가장 널리 사용되고 확장성이 뛰어나며 상용 제품에 쓸 수 있기 때문에 딥러닝 작업에 텐서플로 백엔드가 기본으로 권장된다.
  • 텐서플로(또는 씨아노, CNTK)를 사용하기 때문에 케라스는 CPU와 GPU에서 모두 작동될 수 있다.
    • CPU에서 실행될 때 텐서플로는 Eigen이라고 불리는 저수준 텐서 연산 라이브러리를 사용하고, GPU에서는 NVIDIA CUDA 심층 신경망 라이브러리(cuDNN)라고 불리는 고도로 최적화된 딥러닝 연산 라이브러리를 이용한다.

케라스를 사용한 개발: 빠르게 둘러보기

  • 이미 케라스 모델의 예로 MNIST 예제를 살펴보았다. 전형적인 케라스 작업 흐름은 이 예제와 비슷하다.
    1. 입력 텐서와 타깃 텐서로 이루어진 훈련 데이터를 정의한다.
    2. 입력과 타깃을 매핑하는 층으로 이루어진 네트워크(또는 모델)를 정의한다.
    3. 손실 함수, 옵티마이저, 모니터링하기 위한 측정 지표를 선택하여 학습 과정을 설정한다.
    4. 훈련 데이터에 대해 모델의 fit() 메서드를 반복적으로 호출한다.
  • 모델을 정의하는 방법은 두 가지인데, Sequential 클래스(가장 자주 사용하는 구조인 층을 순서대로 쌓아 올린 네트워크) 또는 함수형 API(완전히 임의의 구조를 만들 수 있는 비순환 유향 그래프)를 사용한다.
  • Sequential 클래스를 사용하여 정의한 2개의 층으로 된 모델을 다시 살펴보자.
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(784,)))
model.add(layers.Dense(10, activation='softmax'))
  • 같은 모델을 함수형 API를 사용해서 만들면 다음과 같다.
input_tensor = layers.Input(shape=(784,))
x = layers.Dense(32, activation='relu')(input_tensor)
output_tensor = layers.Dense(10, activation='softmax')(x)

model = models.Model(inputs=input_tensor, outputs=output_tensor)
  • 함수형 API를 사용하면 모델이 처리할 데이터 텐서를 만들고 마치 함수처럼 이 텐서에 층을 적용한다.
  • 모델 구조가 정의된 후에는 Sequential 모델을 사용했는지 함수형 API를 사용했는지 상관없이 이후 단계가 동일하다.
  • 컴파일 단계에서 학습 과정이 설정된다. 여기에서 모델이 사용할 옵티마이저와 손실 함수, 훈련 하는 동안 모니터링하기 위해 필요한 측정 지표를 지정한다.
  • 다음이 하나의 손실 함수를 사용하는 가장 흔한 경우의 예이다.
from keras import optimizers

model.compile(optimizer=optimizers.RMSprop(lr=0.001), loss='mse', metrics=['accuracy'])
  • 마지막으로 입력 데이터의 넘파이 배열을 모델의 fit() 메서드에 전달함으로써 학습 과정이 이루어진다.
    • 이는 사이킷런(Scikit-Learn)이나 몇몇 다른 머신 러닝 라이브러리에서 하는 방식과 비슷하다.
model.fit(input_tensor, target_tensor, batch_size=128, epochs=10)

딥러닝 컴퓨터 셋팅

  • 딥러닝 애플리케이션을 실행할 때는 NVIDIA GPU에서 실행하는 것을 권장한다.
  • 운영체제는 유닉스(Unix) 운영체제를 사용하는 것이 좋다.
    • 기술적으로 윈도우에서 케라스를 사용할 수 있지만 권장하지는 않는다.
    • 번거로울 수 있지만 우분투를 사용하면 장기적으로 시간이 절약되고 문제가 발생할 가능성이 적다.

주피터 노트북: 딥러닝 실험을 위한 최적의 방법

  • 주피터 노트북(Jupyter Notebook)은 데이터 과학과 머신 러닝 커뮤니티에서 폭넓게 사용된다.
    • 노트북은 주피터 노트북 애플리케이션(https://jupyter.org)으로 만든 파일이며 웹 브라우저에서 작성할 수 있다.
    • 작업 내용을 기술하기 위해 서식 있는 텍스트 포맷을 지원하며 파이썬 코드를 실행할 수 있는 기능도 있다.
    • 필수적이지는 않지만, 케라스를 배울 때 주피터 노트북을 사용할 것을 권장한다. 하지만 파이참(PyCharm) 같은 IDE에서 코드를 실행하거나 독립된 파이썬 스크립트를 실행할 수도 있다.

케라스 시작하기: 두 가지 방법

  • 케라스를 실행하려면 다음 두 방법 중 하나를 권장한다.
    • 공식 EC2 딥러닝 AMI(https://aws.amazon.com/amazon-ai/amis)를 사용해서 EC2에서 주피터 노트북으로 케라스 예제를 실행한다. 로컬 컴퓨터에 GPU가 없을 때 이 방법을 사용한다.
  • 로컬 유닉스 컴퓨터에 처음부터 모든 것을 설치한다. 그 다음 로컬 컴퓨터에서 주피터 노트북을 실행하든지 일반 파이썬 스크립트를 실행한다.
    • 이미 고사양 GPU 카드가 있을 때 이 방법을 사용한다.

클라우드에서 딥러닝 작업을 수행했을 때 장단점

  • (생략)

어떤 GPU 카드가 딥러닝에 최적일까?

  • (생략)

영화 리뷰 분류: 이진 분류 예제

IMDB 데이터셋

  • 인터넷 영화 데이터베이스(Internet Movie Database)로부터 가져온 양극단의 리뷰 5만 개로 이루어진 IMDB 데이터셋을 사용하겠다.
    • 이 데이터셋은 훈련 데이터 25,000개와 테스트 데이터 25,000개로 나뉘어 있고 각각 50/50으로 긍정/부정 리뷰가 구성되어 있다.
  • MNIST 데이터셋처럼 IMDB 데이터셋도 케라스에 포함되어 있다. 이 데이터는 전처리되어 있어 각 리뷰(단어 시퀀스)가 숫자 시퀀스로 변환되어 있다.
    • 여기서 각 숫자는 사전에 있는 고유한 단어를 나타낸다.
  • 다음 코드는 데이터셋을 로드한다.
from keras.datasets import imdb

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
  • (이하 데이터 설명 생략)

데이터 준비

  • 신경망에 숫자 리스트를 주입할 수는 없다. 리스트를 텐서로 바꾸는 두 가지 방법이 있다.
    • 같은 길이가 되도록 리스트에 패딩(padding)을 추가하고 (samples, sequence_length) 크기의 정수 텐서로 변환한다. 그 다음 이 정수 텐서를 다룰 수 있는 층을 신경망의 첫 번째 층으로 사용한다(Embedding 층)
    • 리스트를 원-핫 인코딩(one-hot encoding)하여 0과 1의 벡터로 변환한다. 예컨대 시퀀스 [3, 5]를 인덱스 3과 5의 위치는 1이고 그 외는 모두 0인 10,000차원의 벡터로 각각 변환한다. 그 다음 부동 소수 벡터 데이터를 다룰 수 있는 Dense 층을 신경망의 첫 번째 층으로 사용한다.
  • 여기서는 두 번째 방식을 사용하고 이해를 돕기 위해 직접 데이터를 원-핫 벡터로 만들겠다.
import numpy as np

def vectorize_sequences(sequences, dimension=10000):
results = np.zeros((len(sequences), dimension)) #크기가 (len(sequences), dimension)이고 모든 원소가 0인 행렬을 만든다.
for i, sequence in enumerate(sequences):
results[i, sequence] = 1. #results[i]에서 특정 인덱스의 위치를 1로 만든다.
return results

x_train = vectorize_sequences(train_data) #훈련데이터를 벡터로 변환한다
x_test = vectorize_sequences(test_data) #테스트 데이터를 벡터로 변환한다.

x_train[0]
#array([0., 1., 1., ..., 0., 0., 0.])

y_train = np.asarray(train_labels).astype('float32')
y_test = np.asarray(test_labels).astype('float32')

신경망 모델 만들기

  • 입력 데이터가 벡터이고 레이블은 스칼라(1 또는 0)이다. 이런 문제에 잘 작동하는 네트워크 종류는 relu 활성화 함수를 사용한 완전 연결 층(즉 Dense(16, activation=’relu’))을 그냥 쌓은 것이다.
  • Dense 층에 전달한 매개변수(16)은 은닉 유닛(hidden unit)의 개수이다.
    • 하나의 은닉 유닛은 층이 나타내는 표현 공간에서 하나의 차원이 된다.
    • 2장에서 relu 활성화 함수를 사용한 Dense 층을 다음 텐서 연산을 연결하여 구현했었다.
output = relu(dot(W, input) + b)
  • 16개의 은닉 유닛이 있다는 것은 가중치 행렬 W의 크기가 (input_dimension, 16)이라는 뜻이다.
    • 입력 데이터와 W를 내적하면 입력 데이터가 16차원으로 표현된 공간으로 투영된다(그리고 편향 벡터 b를 더하고 relu 연산을 적용한다)
    • 표현 공간의 차원을 ‘신경망이 내재된 표현을 학습할 때 가질 수 있는 자유도’로 이해할 수 있다.
    • 은닉 유닛을 늘리면(표현 공간을 더 고차원으로 만들면) 신경망이 더욱 복잡한 표현을 학습할 수 있지만 계산 비용이 커지고 원하지 않는 패턴을 학습할 수도 있다. (훈련 데이터에서는 성능이 향상되지만 테스트 데이터에서는 그렇지 않은 패턴)
  • Dense 층을 쌓을 때 두 가지 중요한 구조상의 결정이 필요하다.
    • 얼마나 많은 층을 사용할 것인가?
    • 각 층에 얼마나 많은 은닉 유닛을 둘 것인가?
  • 중간에 있는 은닉 층은 활성화 함수로 relu를 사용하고 마지막 층은 확률을 출력하기 위해 시그모이드 활성화 함수를 사용한다.
    • relu는 음수를 0으로 만드는 함수이다.
    • 시그모이드는 임의의 값을 [0, 1] 사이로 압축하므로 출력 값을 확률처럼 해석할 수 있다.

  • 아래 그림은 이 신경망을 보여준다.

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
  • Note)
    • relu와 같은 활성화 함수(또는 비선형성(non-linearity)라고도 한다)가 없다면 Dense 층은 선형적인 연산인 내적과 덧셈 2개로 구성된다.
      • output = dot(W, input) + b
    • 그러므로 이 층은 입력에 대한 선형 변환(아핀 변환)만을 학습할 수 있다. 이 층의 가설 공간은 입력 데이터를 16차원의 공간으로 바꾸는 가능한 모든 선형 변환의 집합이다.
    • 이런 가설 공간은 매우 제약이 많으며, 선형 층을 깊게 쌓아도 여전히 하나의 선형 연산이기 때문에 층을 여러 개로 구성하는 장점이 없다. 즉 층을 추가해도 가설 공간이 확장되지 않는다.
    • 가설 공간을 풍부하게 만들어 층을 깊게 만드는 장점을 살리기 위해서는 비선형성 또는 활성화 함수를 추가해야 한다. relu는 딥러닝에서 가장 인기 있는 활성화 함수이다.
    • prelu, elu등 비슷한 다른 함수들도 많다.
  • 마지막으로 손실 함수와 옵티마이저를 선택해야 한다.
    • 이진 분류 문제고 신경망의 출력이 확률이기 때문에 binary_crossentropy 손실이 적합하다. 이 함수가 유일한 선택은 아니고 mean_squared_error도 사용할 수 있다. 확률을 출력하는 모델을 사용할 때는 크로스엔트로피가 최선의 선택이다.
    • 크로스엔트로피(Crossentropy)는 정보 이론(Information Theory) 분야에서 온 개념으로 확률 분포 간의 차이를 측정한다. 여기서는 원본 분포와 예측 분포 사이를 측정한다.
  • 다음은 rmsprop 옵티마이저와 binary_crossentropy 손실 함수로 모델을 설정하는 단계이다. 훈련하는 동안 정확도를 사용하여 모니터링 하겠다.
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
  • 케라스에 rmsprop, binary_crossentropy, accuracy가 포함되어 있기 때문에 옵티마이저, 손실 함수, 측정 지표를 문자열로 지정하는 것이 가능하다.
  • 이따금 옵티마이저의 매개변수를 바꾸거나 자신만의 손실 함수, 측정 함수를 전달해야 할 경우가 있다.
  • 전자의 경우에는 아래와 같이 간이 옵티마이저 파이썬 클래스를 사용해 객체를 직접 만들어 optimizer 매개변수에 전달하면 된다.
from keras import optimizers

model.compile(optimizer=optimizers.RMSprop(lr=0.001), loss='binary_crossentropy', metrics=['accuracy'])
  • 후자의 경우는 아래와 같이 loss와 metrics 매개변수에 함수 객체를 전달하면 된다.
from keras import losses
from keras import metrics

model.compile(optimizer=optimizers.RMSprop(lr=0.001), loss=losses.binary_crossentropy, metrics=[metrics.binary_accuracy])

훈련 검증

  • 훈련하는 동안 처음 본 데이터에 대한 모델의 정확도를 측정하기 위해 원본 훈련 데이터에서 10,000의 샘플을 떼어 검증 세트를 만들어야 한다.
x_val = x_train[:10000]
y_val = y_train[:10000]
partial_x_train = x_train[10000:]
partial_y_train = y_train[10000:]
  • 이제 모델을 512개의 샘플씩 미니 배치를 만들어 20번의 에포크 동안 훈련시킨다. 동시에 따로 떼어 놓은 1만 개의 샘플에서 손실과 정확도를 측정할 것이다.
    • 이렇게 하려면 validation_data 매개변수에 검증 데이터를 전달해야 한다.
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, validation_data=(x_val, y_val))
  • model.fit() 메서드는 History 객체를 반환한다. 이 객체는 훈련하는 동안 발생한 모든 정보를 담고 있는 딕셔너리인 history 속성을 갖고 있다.
history_dict = history.history
history_dict.keys()
#dict_keys(['val_loss', 'val_acc', 'loss', 'acc'])
  • 이 딕셔너리는 훈련과 검증하는 동안 모니터링할 측정 지표당 하나씩 모두 4개의 항목을 담고 있다.
    • 이어지는 두 목록에서 맷플롯립을 사용하여 훈련과 검증 데이터에 대한 손실과 정확도를 그려보자.
import matplotlib.pyplot as plt

history_dict = history.history
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(loss) + 1)

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

plt.clf()
acc = history_dict['acc']
val_acc = history_dict['val_acc']

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Trainging and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

  • 여기에서 볼 수 있듯이 훈련 손실이 에포크마다 감소하고 훈련 정확도는 에포크마다 증가한다.
    • 경사 하강법 최적화를 사용했을 때 반복마다 최소화되는 것이 손실이므로 기대했던대로이다.
    • 검증 손실과 정확도는 이와 같지 않은데, 네 번째 에포크에서 그래프가 역전되는 것을 볼 수 있다.
    • 이것이 훈련 세트에서 잘 작동하는 모델이 처음 보는 데이터에서 잘 작동하지 않을 수 있다고 한 과대적합(overfitting)이다.

훈련된 모델로 새로운 데이터에 대해 예측하기

  • 모델을 훈련 시킨 후에 이를 실전 환경에서 사용하고 싶을 것이다. predict 메서드를 사용해서 어떤 리뷰가 긍정일 확률을 예측할 수 있다.
model.predict(x_test)

추가 실험

  • (생략)

정리

  • 원본 데이터를 신경망에 텐서로 주입하기 위해서는 꽤 많은 전처리가 필요하다. 단어 시퀀스는 이진 벡터로 인코딩될 수 있고 다른 인코딩 방식도 있다.
  • relu 활성화 함수와 함께 Dense 층을 쌓은 네트워크는 여러 종류의 문제에 적용할 수 있어 앞으로 자주 사용하게 될 것이다.
  • 출력 클래스가 2개인 이진 분류 문제에서 네트워크는 하나의 유닛과 sigmoid 활성화 함수를 가진 Dense 층으로 끝나야 한다. 이 신경망의 출력은 확률을 나타내는 0과 1사이의 스칼라 값이다.
  • 이진 분류 문제에서 이런 스칼라 시그모이드 출력에 대해 사용할 손실 함수는 binary_crossentropy이다.
  • rmsprop 옵티마이저는 문제에 상관없이 일반적으로 충분히 좋은 선택이다.
  • 훈련 데이터에 대해 성능이 향상됨에 따라 신경망은 과대적합되기 시작하고 이전에 본적 없는 데이터에서는 결과가 점점 나빠진다. 항상 훈련 세트 이외의 데이터에서 성능을 모니터링 해야 한다.

뉴스 기사 분류: 다중 분류 문제

  • 여기서는 로이터 뉴스를 46개의 상호 배타적인 토픽으로 분류하는 신경망을 만들어 보겠다. 
    • 클래스가 많기 때문에 이 문제는 다중 분류(multiclass classification)의 예이다.
    • 각 데이터 포인트가 정확히 하나의 범주로 분류되기 때문에 좀 더 정확히 말하면 단일 레이블 다중 분류 문제이다.
    • 각 데이터 포인트가 여러 개의 범주에 속할 수 있다면 이것은 다중 레이블 다중 분류 문제가 된다.

로이터 데이터셋

  • IMDB, MINIST와 마찬가지로 로이터 데이터셋도 케라스에 포함되어 있다.
    • IMDB와 마찬가지로 각 샘플은 정수 리스트이다.
from keras.datasets import reuters

(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)

데이터 준비

  • 이전 예제와 동일한 코드를 사용해서 단어를 벡터로 변환한다.
    • (코드 생략)
  • 레이블을 벡터로 바꾸는 방법은 두 가지이다. 레이블의 리스트를 정수 텐서로 변환하는 것과 원-핫 인코딩을 사용하는 것이다.
    • 원-핫 인코딩이 범주형 데이터에 널리 사용되기 때문에 범주형 인코딩(categorical encoding)이라고도 부른다.
def to_one_hot(labels, dimension=46):
results = np.zeros((len(labels), dimension))
for i, label in enumerate(labels):
results[i, label] = 1.
return results

one_hot_train_labels = to_one_hot(train_labels)
one_hot_test_labels = to_one_hot(test_labels)

  • MINIST 예제에서 보았듯이 케라스에는 이를 위한 내장 함수가 이미 있다.
from keras.utils.np_utils import to_categorical

one_hot_train_labels = to_categorical(train_labels)
one_hot_test_labels = to_categorical(test_labels)

모델 구성

  • 이 토픽 분류 문제는 영화 리뷰 분류 문제와 비슷해 보인다. 두 경우 모두 짧은 텍스트를 분류하는 것이기 때문이다.
    • 여기서는 새로운 제약 사항이 추가되었는데, 출력 클래스의 개수가 2에서 46개로 늘어났다는 점이다. 출력 공간의 차원이 훨씬 커졌다.
  • 이전에 사용했던 것처럼 Dense 층을 쌓으면 각 층은 이전 층의 출력에서 제공한 정보만 사용할 수 있다.
    • 한 층이 분류 문제에 필요한 일부 정보를 누락하면 그 다음 층에서 이를 복원할 방법이 없다.
    • 각 층은 잠재적으로 정보의 병목(information bottleneck)이 될 수 있다.
    • 이전 예제에서 16차원을 가진 중간층을 사용했지만 16차원 공간은 46개의 클래스를 구분하기에 너무 제약이 많을 것 같다. 이렇게 규모가 작은 층은 유용한 정보를 완전히 잃게 되는 정보의 병목 지점처럼 동작할 수 있다.
  • 이런 이유로 좀 더 규모가 큰 층을 사용해 보겠다. 64개의 유닛을 사용해 보자.
from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(46, activation='softmax'))
  • 이 구조에서 주목해야 할 점이 두 가지 있다.
    • 마지막 Dense 층의 크기가 46이다. 각 입력 샘플에 대해 46차원의 벡터를 출력한다는 뜻이다. 이 벡터의 각 원소(각 차원)는 각기 다른 출력 클래스가 인코딩 된 것이다.
    • 마지막 층에 softmax 활성화 함수가 사용되었다.
  • 이런 문제에 사용할 최선의 손실 함수는 categorical_crossentropy이다.
    • 이 함수는 두 확률 분포 사이의 거리를 추정한다. 여기서는 네트워크가 출력한 확률 분포와 진짜 레이블의 분포 사이의 거리이다.
    • 두 분포 사이의 거리를 최소화하면 진짜 레이블에 가능한 가까운 출력을 내도록 모델을 훈련하게 된다.
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

훈련 검증

  • 훈련 데이터에서 1,000개의 샘플을 떼어 검증 세트로 사용하자.
x_val = x_train[:1000]
partial_x_train = x_train[1000:]

y_val = one_hot_train_labels[:1000]
partial_y_train = one_hot_train_labels[1000:]
  • 20번의 에포크로 모델을 훈련시킨다.
import numpy as np

history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, validation_data=(x_val, y_val))
  • 손실과 정확도 곡선을 그려보자.
    • (코드 생략)

새로운 데이터에 대해 예측하기

  • 모델 객체의 predict 메서드는 46개의 토픽에 대한 확률 분포를 반환한다.
model.predict(x_test)

레이블과 손실을 다루는 다른 방법

  • 레이블을 인코딩 하는 다른 방법은 다음과 같이 정수 텐서로 변환하는 것이다.
y_train = np.array(train_labels)
y_test = np.array(test_labels)
  • 이 방식을 사용하려면 손실 함수 하나만 바꾸면 된다. categorical_crossentropy는 레이블이 범주형 인코딩되어 있을 것이라고 기대한다.
    • 정수 레이블을 사용할 때는 sparse_categorical_crossentropy를 사용해야 한다.
model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['acc'])
  • 이 손실 함수는 인터페이스만 다를 뿐이고 수학적으로는 categorical_crossentropy와 동일하다.

충분히 큰 중간층을 두어야 하는 이유

  • 마지막 출력이 46차원이기 때문에 중간의 히든 유닛이 46개보다 많이 적어져서는 안된다.
  • 46차원보다 훨씬 작은 중간층을 두면 정보의 병목이 어떻게 나타나는지 확인해 보겠다.
    • (생략 – 정확도가 매우 떨어짐)

추가 실험

  • (생략)

정리

  • N개의 클래스로 데이터 포인트를 분류하려면 네트워크의 마지막 Dense 층의 크기는 N이어야 한다.
  • 단일 레이블, 다중 분류 문제에서는 N개의 클래스에 대한 확률 분포를 출력하기 위해 softmax 활성화 함수를 사용해야 한다.
  • 이런 문제에는 항상 범주형 크로스엔트로피를 사용해야 한다. 이 함수는 모델이 출력한 확률 분포와 타깃 분포 사이의 거리를 최소화 한다.
  • 다중 분류에서 레이블을 다루는 두 가지 방법이 있다.
    • 레이블을 범주형 인코딩(또는 원-핫 인코딩)으로 인코딩하고 categorical_crossentropy 손실 함수를 사용한다.
    • 레이블을 정수로 인코딩하고 sparse_categorical_crossentropy 손실 함수를 사용한다.
  • 만은 수의 범주를 분류할 때 중간층의 크기가 너무 작아 네트워크에 정보의 병목이 생기지 않도록 주의해야 한다.

주택 가격 예측: 회귀 문제

  • 앞선 두 예제는 분류 문제로 입력 데이터 포인트의 개별적인 레이블 하나를 예측하는 것이 목적이었다.
  • 또 다른 종류의 머신 러닝 문제는 개별적인 레이블 대신 연속적인 값을 예측하는 회귀(regression)가 있다.

보스턴 주택 가격 데이터셋

  • 1980년 중반 보스턴 외곽 지역에 대한 데이터셋은 이전 2개의 예제와 다른데, 데이터 포인트가 506개로 비교적 적다. 404개는 훈련 샘플, 102개는 테스트 샘플로 나뉘어 있다.
    • 입력 데이터에 있는 특성(feature)은 스케일이 서로 다르다. 어떤 값은 0-1 사이의 비율이고, 어떤 것은 1-12, 1-100 사이의 값을 갖는 것도 있다.
from keras.datasets import boston_housing

(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()

데이터 준비

  • 상이한 스케일을 가진 값을 신경망에 주입하면 문제가 된다. 
    • 네트워크가 이런 다양한 데이터에 자동으로 맞추려고 할 수 있지만, 이는 확실히 학습을 더 어렵게 만든다. 이런 데이터를 다룰 때 대표적인 방법은 특성별로 정규화를 하는 것이다.
    • 입력 데이터에 있는 각 특성에 대해 특성의 평균을 내고 표준편차로 나눈다. 특성의 중앙이 0 근처에 맞추어지고 표준 편차가 1이 된다. 
    • 넘파이를 사용하면 간단하게 할 수 있다.
mean = train_data.mean(axis=0)
std = train_data.std(axis=0)

train_data -= mean
train_data /= std

test_data -= mean
test_data /= std

모델 구성

  • 샘플 개수가 적기 때문에 64개의 유닛을 가진 2개의 은닉 층으로 작은 네트워크를 구성하여 사용하겠다.
    • 일반적으로 훈련 데이터의 개수가 적을수록 과대적합이 더 쉽게 일어나므로 작은 모델을 사용하는 것이 과대적합을 피하는 방법이다.
from keras import models
from keras import layers

def build_model():
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(train_data.shape[1],)))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
return model
  • 이 네트워크의 마지막 층은 하나의 유닛을 가지고 있고 활성화 함수가 없다 (선형 층이라고 부른다). 이것이 전형적인 스칼라 회귀(하나의 연속적인 값을 예측하는 회귀)를 위한 구성이다.
    • 활성화 함수를 적용하면 출력 값의 범위를 제한하게 된다. 예컨대 마지막 층에 sigmoid 활성화 함수를 적용하면 네트워크가 0-1 사이의 값을 예측하도록 학습될 것이다.
    • 여기서는 마지막 층이 순수한 선형이므로 네트워크가 어떤 범위의 값이라도 예측하도록 자유롭게 학습된다.
  • 이 모델은 mse 손실 함수를 사용하여 컴파일한다.
    • 이 함수는 평균 제곱 오차(mean squared error)의 약어로 예측과 타깃 사이 거리의 제곱이다. 회귀 문제에서 널리 사용되는 손실함수이다.
  • 훈련하는 동안 모니터링을 위해 새로운 지표인 평균 절대 오차(Mean Absolute Error, MAE)를 측정한다.
    • 이는 예측과 타깃 사이 거리의 절댓값이다. 예컨대 이 예제에서 MAE가 0.5면 예측이 평균적으로 500달러 정도 차이가 난다는 뜻이다.

K-겹 검증을 사용한 훈련 검증

  • 매개변수들을 조정하면서 모델을 평가하기 위해 이전 예제에서 했던 것처럼 데이터를 훈련 세트와 검증 세트로 나눈다.
    • 데이터 포인트가 많지 않기 때문에 검증 세트도 매우 작아진다(약 100개)
    • 결국 검증 세트와 훈련 세트로 어떤 데이터 포인트가 선택되었는지에 따라 검증 점수가 크게 달라진다. 검증 세트의 분할에 대한 검증 점수의 분산이 높다. 이렇게 되면 신뢰 있는 모델 평가를 할 수 없다.
  • 이런 상황에서 가장 좋은 방법은 K-겹 교차 검증(K-fold cross-validation)을 사용하는 것이다.
    • 데이터를 K개의 분할(즉 폴드(fold))로 나누고 (일반적으로 K = 4 또는 5), K개의 모델을 각각 만들어 K-1개의 분할에서 훈련하고 나머지 분할에서 평가하는 방법이다.
    • 모델의 검증 점수는 K개의 검증 점수 평균이 된다.

import numpy as np

k = 4

num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []

for i in range(k):
print('처리 중인 폴드 #', i)
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]

partial_train_data = np.concatenate([train_data[:i*num_val_samples], train_data[(i+1)*num_val_samples:]], axis=0)
partial_train_targets = np.concatenate([train_targets[:i*num_val_samples], train_targets[(i+1)*num_val_samples:]], axis=0)

model = build_model()
model.fit(partial_train_data, partial_train_targets, epochs=num_epochs, batch_size=1, verbose=0)

val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
all_scores.append(val_mae)
  • num_epochs = 100으로 실행하면 다음 결과를 얻을 수 있다.
all_scores
# [2.0956787838794217, 2.220593797098292, 2.859968412040484, 2.40535704039111]

np.mean(all_scores)
# 2.3953995083523267
  • 검증 세트가 다르므로 검증 점수의 변화가 크다. 평균값이 각각의 점수보다 훨씬 신뢰할만 하다. 이것이 K-겹 교차 검증의 핵심이다.
num_epochs = 500
all_nae_histories = []

for i in range(k):
print('처리 중인 폴드 #', i)
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]

partial_train_data = np.concatenate([train_data[:i*num_val_samples], train_data[(i+1)*num_val_samples:]], axis=0)
partial_train_targets = np.concatenate([train_targets[:i*num_val_samples], train_targets[(i+1)*num_val_samples:]], axis=0)

model = build_model()
history = model.fit(partial_train_data, partial_train_targets, epochs=num_epochs, batch_size=1, verbose=0)

mae_history = history.history['val_mean_absolute_error']
all_mae_histories.append(mae_history)
  • 그 다음 모든 폴드에 대해 에포크의 MAE 점수 평균을 계산한다.
average_mae_history = [np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
  • 그래프로 나타내면 다음과 같다.

  • 이 그래프는 범위가 크고 변동이 심하기 때문에 보기가 어렵다. 다음과 같이 해보자.
    • 곡선의 다른 부분과 스케일이 많이 달느 첫 10개의 데이터 포인트를 제외한다.
    • 부드러운 곡선을 얻기 위해 각 포인트를 이전 포인트의 지수 이동 평균(exponential moving average)으로 대체한다.
def smooth_curve(points, factor=0.9):
smoothed_points = []
for point in points:
if smoothed_points:
previous = smoothed_points[-1]
smoothed_points.append(previous * factor + point * (1-factor))
else:
smoothed_points.append(point)
return smoothed_points

smooth_mae_history = smooth_curve(average_mae_history[10:])

  • 이 그래프를 보면 검증 MAE가 80번째 에포크 이후에 줄어드는 것이 멈추었다. 이 지점 이후로는 과대적합이 시작된다.
  • 모델의 여러 변수에 대한 튜닝이 끝나면 모든 훈련 데이터를 사용하고 최상의 매개변수로 최종 실전에 투입될 모델을 훈련시킨다. 그 다음 테스트 데이터로 성능을 확인한다.
model = build_model()
model.fit(train_data, train_targets, epochs=80, batch_size=16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)

정리

  • 회귀는 분류에서 사용했던 것과는 다른 손실 함수를 사용한다. 평균 제곱 오차(MSE)는 회귀에서 자주 사용되는 손실 함수이다.
  • 비슷하게 회귀에서 사용되는 평가 지표는 분류와 다르다. 당연히 정확도 개념은 회귀에 적용되지 않는다. 일반적인 회귀 지표는 평균 절대 오차(MAE)이다.
  • 입력 데이터의 특성이 서로 다른 범위를 가지면 전처리 단계에서 각 특성을 개별적으로 스케일 조정해야 한다.
  • 가용한 데이터가 적다면 K-겹 검증을 사용하는 것이 신뢰할 수 있는 모델 평가 방법이다.
  • 가용한 훈련 데이터가 적다면 과대적합을 피하기 위해 은닉 층의 수를 줄인 모델이 좋다. (일반적으로 1개 또는 2개)

요약

  • 이제 벡터 데이터를 사용하여 가장 일반적인 머신 러닝인 이진 분류, 다중 분류, 스칼라 회귀 작업을 다룰 수 있다.
  • 보통 원본 데이터를 신경망에 주입하기 전에 전처리해야 한다.
  • 데이터에 범위가 다른 특성이 있다면 전처리 단계에서 각 특성을 독립적으로 스케일 조정해야 한다.
  • 훈련이 진행됨에 따라 신경망의 과대적합이 시작되고 새로운 데이터에 대해 나쁜 결과를 얻게 된다.
  • 훈련 데이터가 많지 않으면 과대적합을 피하기 위해 1개 또는 2개의 은닉 층을 가진 신경망을 사용한다.
  • 데이터가 많은 범주로 나뉘어 있을 때 중간층이 너무 작으면 정보의 병목이 생길 수 있다.
  • 회귀는 분류와 다른 손실 함수와 평가 지표를 사용한다.
  • 적은 데이터를 사용할 때는 K-겹 검증이 신뢰할 수 있는 모델 평가를 도와준다.

케라스 창시자에게 배우는 딥러닝/ 시작하기 전에: 신경망의 수학적 구성 요소

신경망과의 첫 만남

  • 딥러닝의 “hello world”인 MNIST 데이터셋을 이용해서  신경망 예제를 살펴보겠다.
    • 실제 실습은 3장에서 할 것이고, 여기서는 개념만 살펴본다.
  • 머신 러닝에서 분류 문제의 범주(category)를 클래스(class)라고 한다. 데이터 포인트는 샘플(sample)이라고 한다. 특정 샘플의 클래스는 레이블(label)이라고 한다.

  • MNIST 데이터셋은 넘파이(NumPy) 배열 형태로 케라스에 이미 포함되어 있다.
from keras.datasets import mnist

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
  • train_images와 train_labels가 모델이 학습해야 할 훈련 세트(training set)를 구성한다. 모델은 test_images와 test_labels로 구성된 테스트 세트(test set)에서 테스트될 것이다.
  • 이미지는 넘파이 배열로 인코딩 되어 있고 레이블은 0-9까지의 숫자배열이다. 이미지와 레이블은 일대일 관계이다.
  • 훈련 데이터와 테스트 데이터를 살펴 보자.
train_images.shape
# (60000, 28, 28)

len(train_labels)
# 60000

train_labels
# array([5, 0, 4, ... , 5, 6, 8], dtype=unit8)

test_images.shape
# (10000, 28, 28)

len(test_labels)
# 10000

test_labels
# array([7, 2, 1, ... , 4, 5, 6], dtype=unit8)
  • 작업 순서는 다음과 같다.
    • 먼저 훈련 데이터 train_images와 train_labels를 네트워크에 주입한다.
    • 그러면 네트워크는 이미지와 레이블을 연관시킬 수 있도록 학습된다.
    • 마지막으로 test_images에 대한 예측을 네트워크에 요청한다.
    • 그리고 이 예측이 test_labels와 맞는지 확인할 것이다.
  • 신경망을 만들어 보자
from keras import models
from keras import layers

network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
  • 신경망의 핵심 고숭요소는 일종의 데이터 처리 필터라고 생각할 수 있는 층(layer)이다. 어떤 데이터가 들어가면 더 유용한 형태로 출력된다.
    • 좀 더 구체적으로 층은 주어진 문제에 더 의미 있는 표현(representation)을 입력된 데이터로부터 추출한다.
    • 대부분의 딥러닝은 간단한 층을 연결하여 구성되어 있고, 점진적으로 데이터를 정제하는 형태를 띠고 있다.
    • 딥러닝 모델은 데이터 정제 필터(층)가 연속되어 있는 데이터 프로세싱을 위한 여과기와 같다.
  • 이 예에서는 조밀하게 연결된 (또는 완전 연결(fully connected)된) 신경망 층인 Dense 층 2개가 연속되어 있다.
    • 두 번째 (즉 마지막) 층은 10개의 확률 점수가 들어 있는 배열(모두 더하면 1)을 반환하는 소프트맥스(softmax) 층이다.
    • 각 점수는 현재 숫자 이미지가 10개의 숫자 클래스 중 하나에 속할 확률이 된다.
  • 신경망이 훈련 준비를 마치기 위해 컴파일 단계에 포함될 세 가지가 더 필요하다.
    • 손실 함수(loss function): 훈련 데이터에서 신경망의 성능을 측정하는 방법으로 네트워크가 옳은 방향으로 학습될 수 있도록 도와준다.
    • 옵티마이저(optimizer): 입력된 데이터와 손실 함수를 기반으로 네트워크를 업데이트하는 메커니즘
    • 훈련과 테스트 과정을 모니터링할 지표: 여기서는 정확도(정확히 분류된 이미지의 비율)만 고려하겠다.
  • 손실 함수와 옵티마이저의 정확한 목적은 이어지는 장에서 자세히 설명하겠다.
network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
  • 훈련을 시작하기 전에 데이터를 네트워크에 맞는 크기로 바꾸고 모든 값을 0과 1사이로 스케일 조정한다.
    • 예컨대 우리의 훈련 이미지는 [0, 255] 사이의 값인 uint8 타입의 (60000, 28 * 28) 크기를 가진 배열로 저장되어 있는데, 이 데이터를 0과 1사이의 값을 가지는 float32 타입의 (60000, 28 * 28) 크기인 배열로 바꾼다.
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
  • 또 레이블을 범주형으로 인코딩해야 하는데, 이 단계는 다음 장에서 설명하겠다.
from keras.utils import to_categorical

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
  • 이제 신경망을 훈련시킬 준비가 되었다. 케라스에서는 fit 메서드를 호출하여 데이터에 모델을 학습 시킨다.
network.fit(train_images, train_labels, epochs=5, batch_size=128)

# Epoch 1/5
# 60000/60000 [===========================================] - 1s 22us/step - loss: 0.2571 - acc: 0.9257
# Epoch 2/5
# 60000/60000 [===========================================] - 1s 12us/step - loss: 0.1027 - acc: 0.9695
# Epoch 3/5
# 60000/60000 [===========================================] - 1s 12us/step - loss: 0.0686 - acc: 0.9797
# Epoch 4/5
# 60000/60000 [===========================================] - 1s 12us/step - loss: 0.0494 - acc: 0.9856
# Epoch 5/5
# 60000/60000 [===========================================] - 1s 12us/step - loss: 0.0368 - acc: 0.9894
  • 훈련 하는 동안 2개의 정보가 출력되는데, 훈련 데이터에 대한 네트워크의 손실과 정확도이다.
  • 훈련 데이터에 대해 0.989(98.9%)의 정확도를 금방 달성했다. 테스트 세트에서도 모델이 잘 작동하는지 확인해 보자.
test_loss, test_acc = network.evaluate(test_images, test_labels)
# 10000/10000 [===========================================] - 0s 16us/step

print('test_acc:', test_acc)
# test_acc: 0.9789
  • 테스트 세트의 정확도는 97.8%로 나왔다.
    • 훈련 세트 정확도 보다 약간 낮은데, 훈련 정확도와 테스트 정확도 사이의 차이는 과대적합(overfitting) 때문이다. 이는 머신 러닝 모델이 훈련 데이터보다 새로운 데이터에서 성능이 낮아지는 경향을 말한다.
    • 과대적합에 대해서는 3장에서 자세히 논의하겠다.

신경망을 위한 데이터 표현

  • 최근의 모든 머신 러닝 시스템은 일반적으로 텐서를 기본 데이터 구조로 사용한다. 텐서는 머신 러닝의 기본 구성 요소이다.
  • 텐서는 데이터를 위한 컨테이너(container)이다.
    • 거의 항상 수치형 데이터를 다루므로 숫자를 위한 컨테이너이다.
    • 텐서는 임의의 차원 개수를 가지는 행렬의 일반화된 모습이다. (텐서에서는 차원(dimension)을 종종 축(axis)라고 부른다.)

스칼라(0D 텐서)

  • 하나의 숫자만 담고 있는 텐서를 스칼라(scalar) (또는 스칼라 텐서, 0차원 텐서, 0D 텐서)라고 부른다.
    • 넘파이에서는 float32, float64 타입의 숫자가 스칼라 텐서(또는 배열 스칼라(array scalar)) 이다.
    • ndim 속성을 사용하면 넘파이 배열의 축 개수를 확인할 수 있다.
    • 스칼라 텐서의 축 개수는 0이다(ndim==0)
    • 텐서의 축 개수를 랭크(rank)라고 부른다.

벡터(1D 텐서)

  • 숫자의 배열을 벡터(vector) 또는 1D 텐서라고 부른다.
    • 1D 텐서는 딱 하나의 축을 가진다.
    • 5개의 원소를 가진 배열을 5차원 벡터라고 부르는데, 5D 벡터와 5D 텐서를 혼동하지 말 것

행렬(2D 텐서)

  • 벡터의 배열이 행렬(matrix) 또는 2D 텐서이다.
    • 행렬에는 2개의 축이 있다. (보통 행(row)과 열(column)이라 부른다)
    • 행렬은 숫자가 채워진 사각 격자라고 생각할 수 있다.
    • 첫 번째 축에 놓여 있는 원소를 행이라 부르고, 두 번째 축에 놓여 있는 원소를 열이라 부른다.

3D 텐서와 고차원 텐서

  • 이런 행렬들을 하나의 새로운 배열로 합치면 숫자가 채워진 직육면체 형태로 해석할 수 있는 3D 텐서가 만들어진다.
  • 3D 텐서들을 하나의 배열로 합치면 4D 텐서가 만들어진다.
  • 딥러닝에서는 보통 0D에서 4D까지 텐서를 다루는데, 동영상 데이터를 다룰 때에는 5D 텐서까지 가기도 한다.

핵심 속성

  • 텐서는 4개의 핵심 속성으로 정의된다.
    • 축의 개수(rank): 예컨대 3D 텐서에는 3개의 축이 있고, 행렬에는 2개의 축이 있다. 넘파이 라이브러리에서는 ndim 속성에 저장되어 있다.
    • 크기(shape): 텐서의 각 축을 따라 얼마나 많은 차원이 있는지를 나타낸 파이썬의 튜플(tuple)이다.
      • 예컨대 행렬의 크기는 (3, 5), 3D 텐서의 크기는 (3, 3, 5)와 같이 표현된다. 벡터의 크기는 (5,)처럼 1개의 원소로 이루어진 튜플이고 배열 스칼라는 ()처럼 크기가 없다.
    • 데이터 타입(넘파이에서는 dtype에 저장된다): 텐서에 포함된 데이터의 타입이다. 예컨대 텐서의 타입은 float32, uint8, float64 등이 될 수 있다.
  • (크기 살펴보는 예시 코드 생략)

넘파이로 텐서 조작하기

  • train_images[i] 같은 형식으로 첫 번째 축을 따라 특정 숫자를 선택했는데, 배열에 있는 특정 원소들을 선택하는 것을 슬라이싱(slicing)이라고 한다. 넘파이 배열에서 할 수 있는 슬라이싱 연산을 살펴보자.
  • 다음 예는 11번째에서 101번째까지 숫자를 선택하여 (90, 28, 28) 크기의 배열을 만든다.
my_slice = train_images[10:100]
print(my_slice.shape)
# (90, 28, 28)
  • 동일하지만 조금 더 자세한 표기법은 각 배열의 축을 따라 슬라이싱의 시작 인덱스와 마지막 인덱스를 지정하는 것이다. :(콜론)은 전체 인덱스를 선택한다.
my_slice = train_images[10:100, :, :]
print(my_slice.shape)
# (90, 28, 28)

my_slice = train_images[10:100, 0:28, 0:28]
print(my_slice.shape)
# (90, 28, 28)
  • 일반적으로 각 배열의 축을 따라 어떤 인덱스 사이도 선택할 수 있다. 예컨대 이미지의 오른쪽 아래 14×14 픽셀을 선택하려면 다음과 같이 한다.
my_slice = train_images[:, 14:, 14:]
  • 음수 인덱스도 사용할 수 있다. 파이썬 리스트의 음수 인덱스와 마찬가지로 현재 축의 끝에서 상대적인 위치를 나타낸다.
    • 정중앙에 위치한 14×14 픽셀 조각을 이미지에서 잘라 내려면 다음과 같이 하면 된다.
my_slice = train_images[:, 7:-7, 7:-7]

배치 데이터

  • 일반적으로 딥러닝에서 사용하는 모든 데이터의 텐서의 첫 번째 축(인덱스가 0부터 시작하므로 0번째 축)은 샘플 축(sample axis)이다. (이따금 샘플 차원이라고도 부른다)
    • MNIST 예제에서는 숫자 이미지가 샘플이다.
  • 딥러닝 모델은 한 번에 전체 데이터셋을 처리하지 않는다. 대신 데이터를 작은 배치(batch)로 나눈다. 구체적으로 말하면 MNIST 숫자 데이터에서 크기가 128인 배치 하나는 다음과 같다.
batch = train_images[:128]
  • 그 다음 배치는 다음과 같다.
batch = train_images[128:256]
  • n번째 배치는 다음과 같다.
batch = train_images[128 * n:128 * (n + 1)]
  • 이런 배치 데이터를 다룰 때는 첫 번째 축(0번 축)을 배치 축(batch axis) 또는 배치 차원(batch dimension)이라고 부른다.

텐서의 실제 사례

  • 우리가 사용할 데이터는 대부분 다음 중 하나에 속할 것이다.
    • 벡터 데이터: (samples, features) 크기의 2D 텐서
    • 시계열 데이터 또는 시퀀스(sequence) 데이터: (samples, timesteps, features) 크기의 3D 텐서
    • 이미지: (samples, height, width, channels) 크기의 4D 텐서
    • 동영상: (samples, frames, height, width, height, channels) 크기의 5D 텐서

벡터 데이터

  • 대부분의 경우에 해당한다. 이런 데이터셋에서는 하나의 데이터 포인트가 벡터로 인코딩될 수 있으므로 배치 데이터는 2D 텐서로 인코딩될 것이다.
    • 여기서 첫 번째 축은 샘플 축이고, 두 번째 축은 특성 축(feature axis)이다.

시계열 데이터 또는 시퀀스 데이터

  • 데이터에서 시간이 (또는 연속된 순서가) 중요할 떄는 시간 축을 포함하여 3D 텐서로 저장된다.
    • 각 샘플은 벡터(2D 텐서)의 시퀀스로 인코딩 되므로 배치 데이터는 3D 텐서로 인코딩 될 것이다.
    • 관례적으로 시간 축은 항상 두 번째 축(인덱스가 1인 축)이다.

이미지 데이터

  • 이미지는 전형적으로 높이, 너비, 컬러의 3차원으로 이루어진다.
    • 흑백 이미지는 컬러 채널만 갖고 있어 2D 텐서로 저장할 수 있지만 관례상 항상 3D로 저장한다. 흑백 이미지의 경우 컬러 채널 차원의 크기는 1이다.
  • 이미지 텐서의 크기를 지정하는 방식은 두 가지인데, 텐서플로에서 사용하는 채널 마지막(channel-last) 방식과 씨아노에서 사용하는 채널 우선(channel-first) 방식이다.
    • 케라스 프레임워크는 두 형식을 모두 지원한다.

비디오 데이터

  • 비디오 데이터는 5D 텐서가 필요한 몇 안되는 데이터 중 하나로 하나의 미비도는 프레임의 연속이고 각 프레임은 하나의 컬러 이미지이다.

신경망의 톱니바퀴: 텐서 연산

  • 심층 신경망이 학습한 모든 변환을 수치 데이터 텐서에 적용하는 몇 종류의 텐서 연산(tensor operation)으로 나타낼 수 있다.
  • 첫 번째 예제에서는 Dense 층을 쌓아서 신경망을 만들었다. 케라스의 층은 다음과 같이 생성한다.
keras.layers.Dense(512, activation='relu')
  • 이 층은 2D 텐서를 입력으로 받고 입력 텐서의 새로운 표현인 또 다른 2D 텐서를 반환하는 함수처럼 해석할 수 있다.
    • 구체적으로 보면 이 함수는 다음과 같다. (W는 2D 텐서고, b는 벡터이다. 둘 모두 층의 속성이다)
output= = relu(dot(W, input) + b)
  • 좀 더 자세히 알아보자. 여기에는 3개의 텐서 연산이 있다.
    • 입력 텐서와 텐서 W 사이의 점곱(dot), 점곱의 결과인 2D 텐서와 벡터 b 사이의 덧셈, 마지막으로 relu(렐루) 연산이다.
    • relu(x)는 max(x, 0)이다.

원소별 연산

  • relu 함수와 덧셈은 원소별 연산(element-wise operation)이다. 이 연산은 텐서에 있는 각 원소에 독립적으로 적용된다.
    • 이 말은 고도의 병렬 구현(1970-1990년대 슈퍼컴퓨터의 구조인 벡터 프로세서(vector processor)에서 온 용어인 벡터화된 구현을 말한다)이 가능한 연산이라는 의미이다.
    • 파이썬에서 단순한 원소별 연산을 구현한다면 for 반복문을 사용해야 할 것이다.
    • (예시 코드 생략)
  • 사실 넘파이 배열을 다룰 때는 최적화된 넘파이 내장 함수로 이런 연산들을 처리할 수 있다.
    • 넘파이는 시스템에 설치된 BLAS(Basic Linear Algebra Subprogram) 구현에 복잡한 일들을 위임한다.
    • BLAS는 고도로 병렬화되고 효율적인 저수준의 텐서 조작 루틴이며, 전형적으로 포트란(Fortran)이나 C 언어로 구현되어 있다.
    • 넘파이는 원소별 연산을 엄청난 속도로 처리한다.

브로드캐스팅

  • Dense 층에서는 2D 텐서와 벡터를 더했는데, 크기가 다른 두 텐서가 더해질 때 무슨 일이 일어날까?
  • 모호하지 않고 실행 가능하다면 작은 텐서가 큰 텐서의 크기에 맞추어 브로드캐스팅(broadcasting) 된다. 브로드캐스팅은 두 단계로 이루어진다.
    • 큰 텐서의 ndim에 맞도록 작은 텐서에 (브로드캐스팅 축이라고 부르는) 축이 추가된다.
    • 작은 텐서가 새 축을 따라서 큰 텐서의 크기에 맞도록 반복된다.
  • 구현 입장에서 새로운 텐서가 만들어지면 매우 비효율적이므로 어떤 2D 텐서도 만들어지지 않는다. 반복된 연산은 완전히 가상적이다. 이 과정은 메모리 수준이 아니라 알고리즘 수준에서 일어난다.
    • 하지만 새로운 축을 따라 벡터가 반복된다고 생각하는 것이 이해하기 쉽다.

텐서 점곱

  • 텐서 곱셈(tensor product)이라고도 부르는 점곱 연산(dot operation)은 가장 널리 사용되고 유용한 텐서 연산이다. 원소별 연산과 반대로 입력 텐서의 원소들을 결합시킨다.
    • 넘파이, 케라스, 씨아노, 텐서플로에서 원소별 곱셈은 * 연산자를 사용한다.
    • 텐서플로에서는 dot 연산자가 다르지만 넘파이와 케라스는 점곱 연산에 보편적인 dot 연산자를 사용한다.
  • (예시 코드 생략)
  • 두 벡터의 점곱은 스칼라가 되므로 원소 개수가 같은 벡터끼리 점곱이 가능하다.
    • 행렬 x와 벡터 y 사이에서도 점곱이 가능하다. y와 x의 행 사이에서 점곱이 일어나므로 벡터가 반환된다.
    • (사실 행렬의 곱셈은 행렬의 각 벡터간 점곱(내적)의 결과이다)
  • 점곱은 임의의 축 개수를 가진 텐서에 일반화 된다. 가장 일반적인 용도는 두 행렬 간의 점곱일 것이다.

  • x, y, z는 직사각형 모양으로 그려져 있다. x의 행 벡터와 y의 열 벡터가 같은 크기여야 하므로 자동으로 x의 너비는 y의 높이와 동일해야 한다.
  • 더 일반적으로 크기를 맞추는 동일한 규칙을 따르면 다음과 같이 고차원 텐서 간의 점곱을 할 수 있다.

(a, b, c, d) \cdot (d, ) \to (a, b, c)

(a, b, c, d) \cdot (d, e) \to (a, b, c, e)

텐서 크기 변환

  • 꼭 알아두어야 할 세 번째 텐서 연산은 텐서 크기 변환(tensor reshaping)이다.
  • 텐서의 크기를 변환한다는 것은 특정 크기에 맞게 열과 행을 재배열한다는 뜻이다. 당연히 크기가 변환된 텐서는 원래 텐서와 원소 개수가 동일하다.
    • (예시 코드 생략)
  • 자주 사용하는 특별한 크기 변환은 전치(transposition)이다. 전치는 행과 열을 바꾸는 것을 의미한다.
    • 즉 x[i, :]이 x[:, i]가 된다.

텐서 연산의 기하학적 해석

  • 텐서 연산이 조작하는 텐서의 내용은 어떤 기하학적 공간에 있는 좌표 포인트로 해석될 수 있기 때문에 모든 텐서 연산은 기하학적 해석이 가능하다.
  • 다음 벡터를 보자.
A = [0.5, 1]
  • 이 포인트는 2-6 이미지와 같은 2D 공간에 있다. 일반적으로 2-7이미지와 같이 원점에서 포인트를 연결하는 화살표로 벡터를 나타낸다.

  • 새로운 포인트 B = [1, 0.25]를 이전 벡터에 더해 보자. 기하학적으로는 벡터 화살표를 연결하여 계산할 수 있다. 최종 위치는 두 벡터의 덧셈을 나타내는 벡터가 된다.

  • 일반적으로 아핀 변환(affine transformation), 회전, 스케일링(scaling) 등처럼 기본적인 기하학적 연ㅅ나은 텐서 연산으로 표현될 수 있다.
    • 예컨대 \theta 각도로 2D 벡터를 회전하는 것은 2 x 2 행렬 R = [u, v] 를 접곱하여 구할 수 있다.
    • 여기에서 u, v 는 동일 평면상의 벡터이며, u = [cos(\theta), sin(\theta)], v = [-sin(\theta), cos(\theta)] 이다.

딥러닝의 기하학적 해석

  • 신경망은 전체적으로 텐서 연산의 연결로 구성된 것이고, 모든 텐서 연산은 입력 데이터의 기하학적 변환임을 배웠다.
    • 단순한 단계들이 길게 이어져 구현된 신경망을 고차원 공간에서 매우 복잡한 기하학적 변환을 하는 것으로 해석할 수 있다.
  • 3D라면 다음 비유가 이해하는데 도움이 될 것이다.
    • 하나는 빨간색이고 다른 하나는 파란색인 2개의 색종이가 있다고 가정하자.
    • 두 장을 겹친 다음 뭉쳐서 작은 공으로 만든다.
    • 이 종이 공이 입력 데이터이고 색종이는 분류 문제의 데이터 클래스이다.
    • 신경망(또는 다른 머신 러닝 알고리즘)이 해야 할 일은 종이 공을 펼쳐서 두 클래스가 다시 깔끔하게 분리되는 변환을 찾는 것이다.
    • 손가락으로 종이 공을 조금씩 펼치는 것처럼 딥러닝을 사용하여 3D 공간에서 간단한 변환들을 연결해서 이를 구현한다.

  • 종이 공을 펼치는 것이 머신 러닝이 하는 일이다. 복잡하고 심하게 꼬여 있는 데이터의 매니폴드에 대한 깔끔한 표현을 찾는 일이다.
    • 이쯤되면 딥러닝이 왜 이런 작업에 뛰어난지 알았을 것이다.
    • 기초적인 연산을 길게 연결하여 복잡한 기하학적 변환을 조금씩 분해하는 방식이 마치 사람이 종이 공을 펼치기 위한 전략과 매우 흡사하기 때문이다.
  • 심층 네트워크의 각 층은 데이터를 조금씩 풀어 주는 변환을 적용하므로, 이런 층을 깊게 쌓으면 아주 복잡한 분해 과정을 처리할 수 있다.

신경망의 엔진: 그래디언트 기반 최적화

  • 이전 절에서 보았듯이 첫 번째 신경망 예제에 있는 각 층은 입력 데이터를 다음과 같이 변환한다.
output = relu(dot(W, intput) + b)
  • 이 식에서 텐서 W와 b는 층의 속성처럼 볼 수 있다.
    • 가중치(weight) 또는 훈련되는 파라미터(trainable parameter)라고 부른다. (각각 커널(kernel)과 편향(bias)라고 부르기도 한다) 이런 가중치에는 훈련 데이터를 신경망에 노출시켜서 학습된 정보가 담겨 있다.
  • 초기에는 가중치 행렬이 작은 난수로 채워져 있다. (무작위 초기화(random initialization) 단계라고 부른다)
    • 물론 W와 b가 난수일 때 relu(dot(W, input) + b)가 유용한 어떤 표현을 만들 것이라고 기대할 수는 없다.
    • 즉 의미없는 표현이 만들어진다. 하지만 이는 시작 단계일 뿐이다.
    • 그 다음에는 피드백 신호에 기초하여 가중치가 점진적으로 조정될 것이다.
    • 이런 점진적인 조정 또는 훈련(training)이 머신 러닝 학습의 핵심이다.
  • 훈련은 다음과 같은 훈련 반복 루프(training loop) 안에서 일어난다. 필요한 만큼 반복 루프 안에서 이런 단계가 반복된다.
    1. 훈련 샘플 x와 이에 상응하는 타깃 y의 배치를 추출한다.
    2. x를 사용하여 네트워크를 실행하고(정방향 패스(forward pass) 단계), 예측 y_pred를 구한다.
    3. y_pred와 y의 차이를 측정하여 이 배치에 대한 네트워크의 손실을 계산한다.
    4. 배치에 대한 손실이 조금 감소되도록 네트워크의 모든 가중치를 업데이트한다.
  • 결국 훈련 데이터에서 네트워크의 손실, 즉 예측 y_pred와 타깃 y의 오차가 매우 작아질 것이다.
    • 이 네트워크는 입력에 정확한 타깃을 매핑하는 것을 학습했다.
    • 전체적으로 보면 마술처럼 보이지만 개별적인 단계로 쪼개어보면 단순하다.
  • 1단계는 입출력 코드이므로 매우 쉽다. 2-3단계는 몇 개의 텐서 연산을 적용할 뿐이므로 이전 절에 배웠던 연산을 사용하여 이 단계를 구현할 수 있다.
    • 어려운 부분은 네트워크의 가중치를 업데이트하는 4단계이다. 개별적인 가중치 값이 있을 때 값이 증가해야 할지 감소해야 할지 또 얼마만큼 업데이트해야 할지 어떻게 알 수 있을까?
  • 한 가지 간단한 방법은 네트워크 가중치 행렬의 원소를 모두 고정하고 관심 있는 하나만 다른 값을 적용해 보는 것이다.
    • 이 가중치의 초깃값이 0.3이고 배치 데이터를 정방향 패스에 통과시킨 후 네트워크 손실이 0.5가 나왔다고 하자.
    • 이 가중치를 0.35로 변경하고 다시 정방향 패스를 실행했더니 손실이 0.6으로 증가했다.
    • 반대로 0.25로 줄이면 손실이 0.4로 감소했다. 이 경우에 가중치를 -0.05만틈 업데이트한 것이 손실을 줄이는데 기여한 것으로 보인다.
    • 이런 식으로 네트워크의 모든 가중치에 반복한다.
  • 이런 접근 방식은 모든 가중치 행렬의 원소마다 두 번의 (비용이 큰) 정방향 패스를 계산해야 하므로 엄청나게 비효율적이다. (보통 수천에서 경우에 따라 수백만 개의 많은 가중치가 있다.)
    • 신경망에 사용된 모든 연산이 미분가능(differentiable) 하다는 장점을 사용하여 네트워크 가중치에 대한 손실의 그래디언트(gradient)를 계산하는 것이 훨씬 더 좋은 방법이다.
    • 그래디언트의 반대 방향으로 가중치를 이동하면 손실이 감소된다.

변화율이란?

  • 실수 x를 새로운 실수 y로 매핑하는 연속적이고 매끄러운 함수 f(x) = y를 생각해 보자.
    • 이 함수가 연속적이므로 x를 조금 바꾸면 y가 조금 변경될 것이다. 이것이 연속성의 개념이다.
    • x를 작은 값 epsilon_x 만큼 증가시켰을 때 y가 epsilon_y 만큼 바뀐다고 말할 수 있다.
f(x + eplsion_x) = y + epsion_y
  • 또 이 함수가 매끈하므로(곡선의 각도가 갑자기 바뀌지 않는다) epsilon_x가 충분히 작다면 어떤 포인트 p에서 기울기 a의 선형 함수로 f를 근사할 수 있다.
    • 따라서 epsilon_y는 a * epsilon_x 가 된다.
f(x + eplsion_x) = y + a * epsion_x
  • 이 선형적인 근사는 x가 p에 충분히 가까울 때 유효하다.
  • 이 기울기를 p에서 f의 변화율(derivative)라고 한다.
    • 이는 a가 음수일 때 p에서 양수 x만큼 조금 이동하면 f(x)가 감소한다는 것을 의미한다.
    • a가 양수일 때는 음수 x만큼 조금 이동하면 f(x)가 감소된다.
    • a의 절댓값(변화율의 크기)은 이런 증가나 감소가 얼마나 빠르게 일어날지 알려준다.

  • 모든 미분 가능한(미분 가능하다는 것은 변화율을 유도할 수 있다는 의미로, 예컨대 매끄럽고 연속적인 함수이다) 함수 f(x)에 대해 x의 값을 f의 국부적인 선형 근사인 그 지점의 기울기로 매핑하는 변화율 함수 f'(x)가 존재한다.
    • 예컨대 cos(x)의 변화율은 -sin(x)이고, f(x) = a * x의 변화율은 f'(x) = a이다.
  • f(x)를 최소화하기 위해 epsilon_x 만큼 x를 업데이트하고 싶을 때 f의 변화율을 알고 있으면 해결된다.
    • 변화율 함수는 x가 바뀜에 따라 f(x)가 어떻게 바뀔지 설명해 준다.
    • f(x)의 값을 감소 시키고 싶다면 x를 변화율의 방향과 반대로 조금 이동해야 한다.

텐서 연산의 변화율: 그래디언트

  • 그래디언트는 텐서 연산의 변화율이다. 이는 다차원 입력, 즉 텐서를 입력으로 받는 함수에 변화율 개념을 확장시킨 것이다.
  • 입력 벡터 x, 행렬 W, 타깃 y와 손실 함수 loss가 있다고 가정하자.
    • W를 사용하여 타깃의 예측 y_pred를 계산하고 손실, 즉 타깃 예측 y_pred와 타깃 y사이의 오차를 계산할 수 있다.
y_pred = dot(W, x)
loss_value = loss(y_pred, y)
  • 입력 데이터 x와 y가 고정되어 있다면 이 함수는 W를 손실 값에 매핑하는 함수로 볼 수 있다.
loss_value = f(W)
  • W의 현재 값을 W0라고 하자.
    • 포인트 W0에서 f의 변화율은 W와 같은 크기의 텐서인 gradient(f)(W0)이다.
    • 이 텐서의 각 원소 gradient(f)(W0)[i, j]는 W0[i, j]를 변경했을 때 loss_value가 바뀌는 방향과 크기를 나타낸다.
    • 다시 말해 gradient(f)(W0)가 W0)에서 함수 f(W) = loss_value의 그래디언트이다.
  • 앞서 함수 f(x)의 변화율 하나는 곡선 f의 기울기로 해석할 수 있다는 것을 보았다. 비슷하게 gradient(f)(W0)는 W0에서 f(W)의 기울기를 타나내는 텐서로 해석할 수 있다.
    • 그렇기 때문에 함수 f(x)에 대해서는 변화율의 반대 방향으로 x를 조금 움직이면 f(x)의 값을 감소시킬 수 있다.
    • 동일한 방식을 적용하면 함수 f(W)의 입장에서는 그래디언트의 반대 방향으로 W를 움직이면 f(W)의 값을 줄일 수 있다.
    • 예컨대 W1 = W0 – step * gradient(f)(W0)이다. (step은 스케일을 조정하기 위한 작은 값이다)
    • 이 말은 기울기가 작아지는 곡면의 낮은 위치로 이동된다는 의미이다.
    • gradient(f)(W0)는 W0)에 아주 가까이 있을 때 기울기를 근사한 것이므로 W0에서 너무 크게 벗어나지 않기 위해 스케일링 비율 step이 필요하다.

확률적 경사 하강법

  • 미분 가능한 함수가 주어지면 이론적으로 이 함수의 최솟값을 해석적으로 구할 수 있다.
    • 함수의 최솟값은 변화율이 0인 지점이다. 따라서 우리가 할 일은 변화율이 0이 되는 지점을 모두 찾고 이 중에서 어떤 포인트의 함수 값이 가장 작은지 확인하는 것이다.
  • 신경망에 적용하면 가장 작은 손실 함수의 값을 만드는 가중치의 조합을 해석적으로 찾는 것을 의미한다.
    • 이는 식 gradient(f)(W) = 0을 풀면 해결된다. 이 식은 N개의 변수로 이루어진 다항식이다.
    • 여기서 N은 네트워크 가중치 개수이다. N=2, N=3인 식을 푸는 것은 가능하지만 실제 신경망에서는 파라미터의 개수가 수천 개보다 적은 경우가 거의 없고 종종 수천만 개가 되기 때문에 해석적으로 해결하는 것이 어렵다.
  • 그 대신 앞서 설명한 알고리즘 네 단계를 사용할 수 있다. 랜덤한 배치 데이터에서 현재 손실 값을 토대로 하여 조금씩 파라미터를 수정하는 것이다.
    • 미분 가능한 함수를 가지고 있으므로 그래디언트를 계산하여 단계 4를 효율적으로 구현할 수 있다. 그래디언트 방향으로 가중치를 업데이트 하면 손실이 매번 조금씩 감소할 것이다.
  • 그래디언트 계산을 반영하여 업데이트
    1. 훈련 샘플 x와 이에 상응하는 타깃 y의 배치를 추출한다.
    2. x를 사용하여 네트워크를 실행하고 예측 y_pred를 구한다.
    3. y_pred와 y의 차이를 측정하여 이 배치에 대한 네트워크의 손실을 계산한다.
    4. 네트워크의 파라미터에 대한 손실 함수의 그래디언트를 계산한다(역방향 패스(backward pass))
    5. 그래디언트의 반대 방향으로 파라미터를 조금 이동시킨다. 예컨대 W -= step * gradient 처럼 하면 배치에 댛나 손실이 조금 감소할 것이다.
  • 이것이 바로 미니 배치 확률적 경사 하강법(mini-batch stochastic gradient descent)(미니 배치 SGD)이다.
    • 확률적(stochastic)이란 단어는 각 배치 데이터가 무작위로 선택된다는 의미이다. (확률적이란 것은 무작위(random) 하다는 것의 과학적 표현이다.)
    • 네트워크의 파라미터와 훈련 샘플이 하나일 때 이 과정을 아래 그림에 나타냈다.

  • 그림에서 볼 수 있듯이 step 값을 적절히 고르는 것이 중요하다.
    • 이 값이 너무 작으면 곡선을 따라 내려가는데 너무 많은 반복이 필요하고 지역 최솟값(local minimum)에 갇힐 수 있다.
    • step이 너무 크면 손실 함수 곡선에서 완전히 임의의 위치로 이동시킬 수 있다.
  • 미니 배치 SGD 알고리즘의 한 가지 변종은 반복마다 하나의 샘플과 하나의 타깃을 뽑는 것이다.
    • 이것이 (미니 배치 SGD와 반대로) 진정한(true) SGD이다.
    • 다른 한편으로 극단적인 반대의 경우를 생각해 보면 가용한 모든 데이터를 사용하여 반복을 실행할 수 있다.
    • 이를 배치 SGD (batch SGD)라고 한다. 더 정확하게 업데이트 되지만 더 많은 비용이 든다.
    • 극단적인 두 가지 방법의 효율적인 절충안은 적절한 크기의 미니 배치를 사용하는 것이다.
  • 그림 2-11은 1D 파라미터 공간에서 경사 하강법을 설명하고 있지만 실제로는 매우 고차원 공간에서 경사 하강법을 사용하게 된다.
    • 신경망에 있는 각각의 가중치 값은 이 공간에서 하나의 독립된 차원이고 수만 또는 수백만 개가 될 수도 있다.
    • 손실 함수의 표면을 좀 더 쉽게 이해하기 위해 아래 그림 2-12와 같이 2D 손실 함수의 표면을 따라 진행하는 경사 하강법을 시각화해 볼 수 있다.

  • 하지만 신경망이 훈련되는 실제 과정을 시각화하기는 어렵다. 4차원 이상의 공간을 사람이 이해할 수 있도록 표현하는 것이 불가능하기 때문이다.
    • 때문에 저차원 표현으로 얻은 직관이 실전과 항상 맞지 않는다는 것을 유념해야 한다. 이는 딥러닝 연구 분야에서 오랫동안 여러 이슈를 일으키는 근원이었다.
  • 또 업데이트할 다음 가중치를 계산할 때 현재 그래디언트 값만 보지 않고 이전에 업데이트도니 가중치를 여러 다른 방식으로 고려하는 SGD 변종이 많이 있다.
    • 예컨대 모멘텀을 사용한 SGD, Adagrad, RMSProp 등이 그것이다.
    • 이런 변종들은 모두 최적화 방법(optimization method) 또는 옵티마이저라고 부른다.
  • 특히 여러 변종들에서 사용하는 모멘텀(momentum) 개념은 아주 중요하다. 모멘텀은 SGD에 이는 2개의 문제점인 수렴 속도와 지역 최솟값을 해결한다.
    • 아래 그림 2-13은 네트워크의 파라미터 하나에 대한 손실 값의 곡선을 보여준다.

  • 어떤 파라미터 값에서는 지역 최솟값에 도달한다. 그 지점 근처에서는 왼쪽으로 이동해도 손실이 증가하고 오른쪽으로 이동해도 손실이 증가하기 때문이다.
    • 대상 파라미터가 작은 학습률을 가진 SGD로 최적화되었다면 최적화 과정이 전역 최솟값으로 향하지 못하고 이 지역 최솟값에서 갇히게 될 것이다.
  • 물리학에서 영감을 얻은 모멘텀을 사용하여 이 문제를 피할 수 있다. 여기에서 최적화 과정을 손실 곡선 위로 작은 공을 굴리는 것으로 생각하면 쉽게 이해할 수 있다.
    • 모멘텀이 충분함녀 공이 골짜기에 갇히지 않고 전역 최솟값에 도달할 것이다.
    • 모멘텀은 현재 기울기 값(현재 가속도) 뿐만 아니라 (과거의 가속도로 인한) 현재 속도를 함께 고려하여 각 단계에서 공을 움직인다.
    • 실전에 적용할 때는 현재 그래디언트 값 뿐만 아니라 이전에 업데이트한 파라미터에 기초하여 파라미터 w를 업데이트 한다.
  • 다음은 단순한 구현 예이다.
past_velocity = 0
momentum = 0.1 --모멘텀 상수
while loss > 0.01: --최적화 반복 루프
w, loss, gradient = get_current_parameters()
velocity = momentum * past_velocity - learning_rate * gradient
w = w + momentum * velocity - learning_rate * gradient
past_velocity = velocity
update_parameter(w)

변화율 연결: 역전파 알고리즘

  • 앞의 알고리즘에서 함수가 미분 가능하기 때문에 변화율을 직접 계산할 수 있다고 가정했다.
    • 실제로 신경망은 많은 텐서 연산으로 구성되어 있고 이 연산들의 변화율은 간단하며 이미 잘 알려져 있다.
    • 3개의 텐서 연산 a, b, c와 가중치 행렬 W1, W2, W3으로 구성된 네트워크 f를 예로 들어보자.
f(W1, W2, W3) = a(W1, b(W2, c(W3)))
  • 이벅분에서 이렇게 연결된 함수는 연쇄 법칙(chain rule)이라 부르는 다음 항등식 f(g(x))’ = f'(g(x)) * g'(x)를 사용하여 유도될 수 있다.
    • 연쇄 법칙을 신경망의 그래디언트를 계산에 적용하여 역전파(Backpropagation) 알고리즘(후진 모드 자동 미분(reverse-mode automatic differentiation)이라고도 부른다)이 탄생되었다.
    • 역전파는 최종 손실 값에서부터 시작한다.
    • 손실 값에 각 파라미터가 기여한 정도를 계산하기 위해 연쇄 법칙을 적용하여 최상위 층에서 하위층까지 거꾸로 진행된다.
  • 요즘에는 그리고 향후 몇 년 동안은 텐서플로처럼 기호 미분(symbolic differentiation)이 가능한 최신 프레임워크를 사용하여 신경망을 구현할 것이다.
    • 이 말은 변화율이 알려진 연산들로 연결되어 있으면 (연쇄 법칙을 적용하여) 네트워크 파라미터와 그래디언트 값을 매핑하는 그래디언트 함수를 계산할 수 있다는 의미이다.
    • 이런 함수를 사용하면 역방향 패스는 그래디언트 함수를 호출하는 것으로 단순화될 수 있다.
    • 기호 미분 덕택에 역전파 알고리즘을 직접 구현할 필요가 전혀 없고 정확한 역전파 공식을 유도하느라 시간과 노력을 소모하지 않아도 된다. 그래디언트 기반의 최적화가 어떻게 작동하는지 잘 이해하는 것만으로 충분하다.

첫 번째 예제 다시 살펴보기

  • 신경망의 이면에 어떤 원리가 있는지 기초적인 내용을 이해했으므로 첫 번째 예제로 돌아가서 이전 절에서 배웠던 내용을 이용하여 코드를 리뷰해 보자.
  • 먼저 입력 데이터이다.
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255
  • 입력 이미지의 데이터 타입은 float32, 훈련 데이터는 (60000, 784) 크기, 테스트 데이터는 (10000, 784) 크기의 넘파이 배열로 저장된다.
  • 우리가 사용할 신경망이다.
network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
  • 이 네트워크는 2개의 Dense 층이 연결되어 있고 각 층은 가중치 텐서를 포함하여 입력 데이터에 대한 몇 개의 간단한 텐서 연산을 적용한다.
    • 층의 속성인 가중치 텐서는 네트워크가 정보를 저장하는 곳이다.
  • 이제 네트워크를 컴파일 하는 단계이다.
network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
  • categorical_crossentropy는 손실 함수이다. 가중치 텐서를 학습하기 위한 피드백 신호로 사용되며 훈련하는 동안 최소화 된다.
    • 미니 배치 확률적 경사 하강법을 통해 손실이 감소된다.
    • 경사 하강법을 적용하는 구체적인 방식은 첫 번째 매개변수로 전달된 rmsprop 옵티마이저에 의해 결정된다.
  • 마지막으로 훈련 반복이다.
network.fit(train_images, train_labels, epochs=5, batch_size=128)
  • fit 메서드를 호출했을 때 다음과 같은 일이 일어난다.
    • 네크워크가 128개 샘플씩 미니 배치로 훈련 데이터를 다섯 번 반복한다(전체 훈련 데이터에 수행되는 각 반복을 에포크(epoch)라고 한다.)
    • 각 반복마다 네트워크가 배치에서 손실에 대한 가중치의 그래디언트를 계산하고 그에 맞추어 가중치를 업데이트 한다.
    • 다섯 번의 에포크 동안 네트워크는 2,345번의 그래디언트 업데이트를 수행할 것이다 (에포크마다 469번)

요약

  • 학습(Learning)은 훈련 데이터 샘플과 그에 상응하는 타깃이 주어졌을 때 손실 함수를 최소화 하는 모델 파라미터의 조합을 찾는 것을 의미한다.
  • 데이터 샘플과 타깃의 배치를 랜덤하게 뽑고 이 배치에서 손실에 대한 파라미터의 그래디언트를 계산함으로써 학습이 진행된다. 네트워크의 파라미터는 그래디언트의 반대 방향으로 조금씩(학습률에 의해 정의된 크기만큼) 움직인다.
  • 전체 학습 과정은 신경망이 미분 가능한 텐서 연산으로 연결되어 있기 때문에 간으하다. 현재 파라미터와 배치 데이터를 그래디언트 값에 매핑해주는 그래디언트 함수를 구성하기 위해 미분의 연쇄 법칙을 사용한다.
  • 이어지는 장에서 자주 보게 될 두 가지 핵심 개념은 손실과 옵티마이저이다. 이 두 가지는 네트워크에 데이터를 주입하기 전에 정의 되어야 한다.
  • 손실은 훈련하는 동안 최소화해야 할 양이므로 해결하는 문제의 성공을 측정하는데 사용한다.
  • 옵티마이저는 손실에 대한 그래디언트가 파라미터를 업데이트하는 정확한 방식을 정의한다. 예컨대 RMSProp 옵티마이저, 모멘텀을 사용한 SGD 등이다.

케라스 창시자에게 배우는 딥러닝/ 딥러닝이란 무엇인가?

인공 지능과 머신 러닝, 딥러닝

인공 지능

  • 인공 지능은 1950년대 초기 컴퓨터 과학 선각자들이 ‘컴퓨터가 생각할 수 있는가?’라는 질문을 하면서 시작되었음
  • 이 분야에 대한 간결한 정의는 ‘보통의 사람이 수행하는 지능적인 작업을 자동화하기 위한 연구활동’이다.
    • AI는 머신 러닝과 딥러닝을 포괄하는 종합적인 분야로 학습 과정이 전혀 없는 다른 방법도 많이 포함된다.
  • 오랜 기간 많은 전문가들이 프로그래머들이 명시적인 규칙을 충분히 많이 만들어 지식을 다루면 인간 수준의 인공 지능을 만들 수 있다고 믿었는데, 이런 접근 방법을 심볼릭 AI(Symbolic AI)라고 하며, 1950-1980년대까지 AI 분야의 지배적인 패러다임이었다.
    • 1980년대 전문가 시스템(expert system)의 호황으로 그 인기가 절정에 달했다.
  • 심볼릭 AI가 체스 처럼 잘 정의된 논리적인 문제를 푸는데는 적합하다는 것이 증명되었지만, 이미지 분류, 음성 인식, 언어 번역 같은 더 복잡하고 불분명한 문제를 해결하기 위한 명확한 규칙을 찾는 것은 아주 어려운 일이었다. 이런 심볼릭 AI를 대체하기 위한 새로운 방법이 바로 머신 러닝이다.

머신 러닝

  • 최초의 기계적 범용 컴퓨터인 해석기관(Analytical Engine)을 발명한 사람은 찰스 배비지(Charles Babbage)였다.
    • 범용 컴퓨터란 개념이 정의되지 않은 때였기 때문에 해석 기관은 해석학(mathematical analysis) 분야의 계산을 자동화 하기 위해 기계적인 연산을 사용하는 방법이었을 뿐이었다. 그래서 이름이 해석 기관이다.
  • 찰스 배비지의 친구자이 동료였던 –더불어 최초의 프로그래머로 인정받는– 에이다 러브레이스(Ada Lovelace)는 이 발명에 대해 다음과 같이 언급했다.
    • “해석 기관이 무언가를 새롭게 고안해 내는 것은 아니다. 우리가 어떤 것을 작동시키기 위해 어떻게 명령할지 알고 있다면 이 장치는 무엇이든 할 수 있다. … 이런 능력은 우리가 이미 알고 있는 것을 유용하게 사용할 수 있도록 도와줄 것이다”
  • AI의 선구자인 앨런 튜링(Alan Turing)은 그의 기념비적인 논문 “Computing Machinery and Intelligence”에서 ‘러브레이스의 반론(Lady Lovelace’s objection)’으로 이 논평을 인용했다.
    • 튜링은 에이다 러브레이스의 말을 인용했지만 범용 컴퓨터가 학습과 창의력을 가질 수 있는지에 대해 가능한 일이라고 결론을 냈다.
  • 머신 러닝은 이런 질문에서 시작된다.
    • 우리가 어떤 것을 작동시키기 위해 ‘어떻게 명령할지 알고 있는 것’ 이상을 컴퓨터가 처리하는 것이 가능한가?
    • 특정 작업을 수행하는 법을 스스로 학습할 수 있는가?
    • 컴퓨터가 우리를 놀라게 할 수 있을까?
    • 프로그래머가 직접 만든 데이터 처리 규칙 대신 컴퓨터가 데이터를 보고 자동으로 이런 규칙을 학습할 수 있을까?
  • 이 질문은 새로운 프로그래밍 패러다임의 장을 열었다. 전통적인 프로그래밍인 심볼릭 AI의 패러다임에서는 규칙과 이 규칙에 따라 처리될 데이터를 입력하면 해답이 출력된다.
    • 머신 러닝에서는 데이터와 이 데이터로부터 기대되는 해답을 입력하면 규칙이 출력된다. 이 규칙을 새로운 데이터에 적용하여 창의적인 답을 만들 수 있다.

  • 머신 러닝 시스템은 명시적으로 프로그램 되는 것이 아니라 훈련(training) 된다.
    • 작업과 관련 있는 많은 샘플을 제공하면 이 데이터에서 통계적 구조를 찾아 그 작업을 자동화하기 위한 규칙을 만들어낸다.
  • 머신 러닝은 1990년대 들어서야 각광을 받기 시작했지만, 고성능 하드웨어와 대량의 데이터셋이 가능해지면서 AI에서 가장 인기 있고 성공적인 분야가 되었다.
  • 머신 러닝은 수리 통계와 밀접하게 관련되어 있지만 통계와 다른 점이 몇 가지 있다.
    • 먼저 머신 러닝은 통계와 달리 보통 대량의 복잡한 데이터셋을 다루기 때문에 베이지안 분석(Bayesian analysis) 같은 전통적인 통계 분석 방법은 현실적으로 적용하기 어렵다.
    • 이런 이유로 머신 러닝, 특히 딥러닝은 수학적 이론이 비교적 부족하고 엔지니어링 지향적이다.
    • 이런 실천적인 접근 방식 때문에 이론보다 경험을 바탕으로 아이디어가 증명되는 경우가 많다.

데이터에서 표현을 학습하기

  • 머신 러닝은 샘플과 기댓값이 주어졌을 때 데이터 처리 작업을 위한 실행 규칙을 찾는 것이다. 머신 러닝을 하기 위해서는 세 가지가 필요하다.
    • 입력 데이터 포인트 –음성 파일, 이미지 파일 등
    • 기대 출력 –강아지, 고양이 등
    • 알고리즘의 성능을 측정하는 방법 –알고리즘의 현재 출력과 기대 출력 간의 차이를 결정하기 위해 필요. 측정 값은 알고리즘의 작동 방식을 교정하기 위한 신호로 다시 피드백되는데, 이런 수정 단계를 학습(learning)이라고 한다.
  • 머신 러닝 모델은 입력 데이터를 의미 있는 출력으로 변환한다. 이것이 알고 있는 입력과 출력의 샘플로부터 학습하는 과정이다. 그렇기 때문에 머신 러닝과 딥러닝의 핵심 문제는 의미있는 데이터로의 변환이다.
    • 다시 말해 입력 데이터를 기반으로 기대 출력에 가깝게 만드는 유용한 표현(representation)을 학습하는 것이다.
    • 여기서 표현이란 데이터를 인코딩(encoding)하거나 묘사하기 위해 데이터를 바라보는 다른 방법이다. 예컨대 컬러 이미지는 RGB, HSV 포맷으로 인코딩될 수 있는데, 이들은 같은 데이터의 다른 표현이다.
    • 어떤 표현으로는 해결하기 힘든 문제가 다른 표현으로는 쉽게 해결될 수 있다. 예컨대 이미지에서 빨간색 픽셀을 선택하는 것은 RGB 포맷이 쉽고, 이미지의 채도를 낮추는 것은 HSV 포맷이 더 쉽다.
    • 머신 러닝 모델은 입력 데이터에서 적절한 표현을 찾는 것이다. 이런 데이터 변환은 분류 작업 같은 문제를 더 쉽게 해결할 수 있도록 만들어 준다.
  • 예들 들어보자. x, y축이 있고 이 x, y 좌표 시스템으로 표현된 데이터 포인트가 아래 그림과 같다고 하자.

  • 위 그림에는 흰색점과 빨간색점이 존재하는데, 포인트의 좌표 (x, y)를 입력으로 받고 그 포인트가 빨간색인지 흰색인지를 출력하는 알고리즘을 개발한다고 하자. 이 경우는 다음과 같이 요약할 수 있다.
    • 입력은 점의 좌표이다.
    • 기대 출력은 점의 색깔이다.
    • 알고리즘의 성능을 측정하는 방법은 정확히 분류한 포인트의 비율을 사용하여 알고리즘의 성능을 측정한다.
  • 여기서 우리가 원하는 것은 흰색점과 빨간색점을 완벽하게 구분하는 새로운 데이터표현이다. 사용할 수 있는 변환 방법 중 하나는 아래 그림과 같은 좌표 변환이다.

  • 포인트에 대한 새로운 좌표는 새로운 데이터 표현이라고 할 수 있다. 그리고 좋은 표현을 찾았다.
    • 이 표현을 사용하면 색깔 분류 문제를 “x > 0 인 것은 빨간색 점이다”와 같은 간단한 규칙으로 나타낼 수 있다.
    • 기본적으로 이 분류 문제를 해결한 것은 새로운 표현이다.
  • 이 경우 우리가 직접 좌표 변환을 정했는데, 만약 시스템적으로 가능한 여러 좌표 변환을 찾아서 포인트 중 몇 퍼센트가 정확히 분류되었는지를 피드백으로 사용한다면, 바로 머신 러닝을 하고 있는 것이다.
    • 이처럼 머신 러닝에서의 학습(Learning)이란 더 나은 표현을 찾는 자동화된 과정이다.
  • 모든 머신 러닝 알고리즘은 주어진 작업을 위해 데이터를 더 유용한 표현으로 바꾸는 이런 변환을 자동으로 찾는다.
    • 이 연산은 앞서 본 좌표 변환일 수도 있고 또는 선형 투영(linear projection), 이동(translation), 비선형 연산 등이 될 수 있다.
    • 머신 러닝 알고리즘은 일반적으로 이런 변환을 찾기 위한 창의력은 없다. 가설 공간(hypothesis space)이라 부르는 미리 정의된 연산의 모음들을 자세히 조사하는 것 뿐이다.
  • 기술적으로 말하면 머신 러닝은 가능성 있는 공간을 사전에 정의하고 피드백 신호의 도움을 받아 입력 데이터에 대한 유용한 변환을 찾는 것이다.
    • 이 간단한 아이디어가 음성 인식에서부터 자율 주행 자동차까지 아주 다양한 분야에서 지능에 관한 문제를 해결한다.

딥러닝에서 ‘딥’이란 무엇일까?

  • 딥러닝은 머신 러닝의 특정한 한 분야로서 연속된 층(layer)에서 점진적으로 의미 있는 표현을 배우는데 강점이 있으며, 데이터로부터 표현을 학습하는 새로운 방식이다.
    • 딥러닝의 딥(deep)이란 단어는 연속된 층으로 표현을 학습한다는 개념을 나타낸다.
    • 데이터로부터 모델을 만드는데 얼마나 많은 층을 사용했는지가 그 모델의 깊이가 된다.
    • 이 분야에 대한 적절한 다른 이름은 층 기반 표현 학습(layered representations learning) 또는 계층적 표현 학습(hierarchical representations learning)이 될 수 있다.
    • 최근 딥러닝 모델은 표현 학습을 위해 수십 개, 수백 개의 연속된 층을 갖고 있다. 이 층들을 모두 훈련 데이터에 노출해서 자동으로 학습시킨다.
    • 한편 다른 머신 러닝 접근 방법은 1-2개의 데이터 표현 층을 학습하는 경향이 있다. 그래서 이런 방식을 얕은 학습(shallow learning)이라 부르기도 한다.
  • 딥러닝에서는 기본 층을 겹겹이 쌓아 올려 구성한 신경망(neural network)이라는 모델을 사용하여 표현 층을 학습한다.
    • 신경망이란 단어는 신경 생물학의 용어로 딥러닝의 일부 핵심 개념이 뇌 구조를 이해하는 것에서 영감을 얻어 개발된 부분이 있지만, 딥러닝 모델이 뇌를 모델링한 것은 아니다.
    • 최근의 딥러닝 모델이 사용하는 학습 메커니즘과 유사한 것을 뇌가 가지고 있다는 근거는 없다. 대중 과학 저널에서 딥러닝이 뇌처럼 작동한다거나 뇌를 모방하여 만들었다고 주장하는 그은 사실이 아니다.
    • 딥러닝은 그냥 데이터로부터 표현을 학습하는 수학 모델일 뿐이다.
  • 딥러닝 알고리즘으로 학습된 표현은 어떻게 나타나는지 예를 들어보자. 몇 개의 층으로 이루어진 네트워크가 이미지 안의 숫자를 인식하기 위해 이미지를 어떻게 변환하는지 살펴보자.

  • 아래 그림에서 볼 수 있듯 최종 출력에 대해 점점 더 많은 정보를 가지지만 원본 이미지와는 점점 더 다른 표현으로 숫자 이미지가 변환된다.
    • 심층 신경망을 정보가 연속된 필터(filter)를 통과하면서 순도 높게 정제되는 다단계 정보 추출 작업으로 생각할 수 있다.

  • 바로 이것이 딥러닝이다. 기술적으로는 데이터 표현을 학습하기 위한 다단계 처리 방식을 말한다.

그림 3개로 딥러닝의 작동 원리 이해하기

  • 머신 러닝이 많은 입력과 타깃(target)의 샘플을 관찰하면서 입력을 타깃에 매핑(mapping) 하는 것임을 알았다.
    • 심층 신경망은 이런 입력-타깃 매핑을 간단한 데이터 변환기(층)를 많이 연결하여 수행한다는 것도 배웠다. 이런 데이터 변환은 샘플에 노출됨으로써 학습이 이루어진다.
  • 층에서 입력 데이터가 처리되는 상세 내용은 일련의 숫자로 이루어진 층의 가중치(weight)에 저장되어 있다.
    • 기술적으로 말하면 어떤 층에서 일어나는 변환은 그 층의 가중치를 파라미터(parameter)로 가지는 함수로 표현된다. (이따금 가중치를 그 층의 파라미터라고도 부른다)
    • 이런 맥락으로 보면 학습은 주어진 입력을 정확한 타깃에 매핑하기 위해 신경마으이 모든 층에 있는 가중치 값을 찾는 것을 의미한다.
    • 하지만 어떤 심층 신경망은 수천만 개의 파라미터를 가지기도 한다.
    • 이런 경우 모든 파라미터의 정확한 값을 찾는 것은 어려운 일로 보인다. 파라미터 하나의 값을 바꾸면 다른 모든 파라미터에 영향을 끼치기 때문이다.

  • 어떤 것을 조정하려면 먼저 관찰해야 한다. 신경망의 출력을 제어하려면 출력이 기대하는 것보다 얼마나 벗어났는지를 측정해야 한다.
    • 이는 신경망의 손실 함수(loss function) 또는 목적 함수(objective function)가 담당하는 일이다.
    • 신경망이 한 샘플에 대해 얼마나 잘 예측했는지 측정하기 위해 손실 함수가 신경망의 예측과 진짜 타깃의 차이를 점수로 계산한다. (아래 그림 참고)

  • 기본적인 딥러닝 방식은 이 점수를 피드백 신호로 사용하여 현재 샘플의 손실 점수가 감소되는 방향으로 가중치 값을 조금씩 수정하는 것이다.
    • 이런 수렴 과정은 딥러닝의 핵심 알고리즘인 역전파(Backpropagation) 알고리즘을 구현한 옵티마이저(optimizer)가 담당한다.

  • 초기에는 네트워크의 가중치가 랜덤한 값으로 할당되므로 랜덤한 변환을 연속적으로 수행한다.
    • 자연스럽게 출력은 기대한 것과 멀어지고 손실 점수가 높을 것이지만 네트워크가 모든 샘플을 처리하면서 가중치가 조금씩 올바른 방향으로 조정되고 손실 점수가 감소한다.
    • 이를 훈련 반복(training loop)이라고 하며, 충분한 횟수만큼 반복하면 손실 함수를 최소화하는 가중치 값을 산출한다.
    • 최소한의 손실을 내는 네트워크가 타깃에 가능한 가장 가까운 출력을 만든느 모델이 된다.

지금까지 딥러닝의 성과

  • 딥러닝은 머신 러닝의 오래된 하위 분야지만 2010년 초가 되서야 유명해졌다. 이때부터 몇 년 동안 이 분야에서 일어난 혁신은 결코 작지 않다.
    • 기계가 오랫동안 해결하기 어려웠던 시각과 청각 같은 지각의 문제에서 괄목할만한 성과를 냈기 때문이다.
    • (이하 성과 사례 생략)

단기간의 과대 선전을 믿지 말자

  • 딥러닝이 최근 몇 년간 놀라운 성과를 냈지만, 사람들이 향후 10년 안에 기대하는 성과는 가능한 것보다 훨씬 높다.
    • 자율 주행 같은 몇 가지 애플리케이션은 이미 가까이 다가왔지만, 신뢰할 만한 대화 시스템이나 사람 수준의 기계 번역 그리고 사람 수준의 자연어 이해처럼 더 많은 것이 오랫동안 어려운 문제로 남아 있을 것 같다.
    • 특히 사람 수준의 일반 지능(general intelligence)에 관한 이야기는 너무 심각하게 다루지 않는 것이 좋다.
  • 과거에 AI는 장미빛 전망 뒤에 이어진 실망과 회의의 사이클을 두 번이나 경험했다.
  • 첫번째는 1960년대 심볼릭 AI였는데, 심볼릭 AI 방법에 관한 가장 유명한 개척자이지 지지자 중 한 명인 마빈 민스키(Marvin Minsky)는 1967년에 “이번 세대 안에 … ‘인공 지능’을 만드는 문제는 거의 해결될 것이다”라고 주장했다.
    • 몇 년 후 이런 높은 기대가 구체화되지 못하자 연구자들과 정부 자금은 투자를 줄였고 첫 번째 AI 겨울이 시작되었다. (이는 냉전이 절정에 다다른 후에 나타난 핵 겨울(nuclear winter)에 대한 비유이다)
  • 1980년대 심볼릭 AI의 새로운 버전인 전문가 시스템(expert system)이 큰 기업들 사이에 인기를 끌기 시작해서 전 세계 회사들이 전문가 시스템을 구축하기 위해 내부에 AI 부서를 꾸리기도 했다.
    • 1990년대 초기 이 시스템은 유지 비용이 비싸고 확장하기 어려우며 제한된 범위를 가진다는 것이 증명되고 관심은 사그라들었다. 이로 인해 두 번째 AI겨울이 시작되었다.

AI에 대한 전망

  • AI에 대한 단기간의 기대는 비현실적일지 모르지만 장기간의 전망은 매우 밝다.
    • (이하 설명 생략)

딥러닝 이전: 머신 러닝의 간략한 역사

확률적 모델링

  • 확률적 모델링(probabilistic modeling)은 통계학 이론을 데이터 분석에 응요한 것으로 초기 머신 러닝 형태 중 하나고 요즘도 널리 사용된다. 가장 잘 알려진 알고리즘 중 하나는 나이브 베이즈(Naive Bayes) 알고리즘이다.
  • 나이브 베이즈는 입력 데이터의 특성이 모두 독립적이라고 가정하고 베이즈 정리를 적용하는 머신 러닝 분류 알고리즘이다.
    • 이런 형태의 데이터 분석은 컴퓨터 보다 먼저 있었기 때문에 컴퓨터가 등장하기 전에는 수작업으로 적용했다. (거의 1950년대로 거슬러 올라간다)
    • 베이즈 정리와 통계의 토대는 18세기까지 올라간다.
  • 이와 밀접하게 연관된 모델이 로지스틱 회귀(logistic regression)인데, 이 모델은 현대 머신 러닝의 “hello world”로 여겨진다.
    • 이름 때문에 헷갈리지만 로지스틱 회귀는 회귀(regression) 알고리즘이 아니라 분류(classification) 알고리즘이다.
    • 나이브 베이즈와 비슷하게 로지스틱 회귀도 컴퓨터 보다 훨씬 오래 전에 있었다.
    • 하지만 간단하고 다목적으로 활용할 수 있어서 오늘날에도 유용하다.
    • 데이터 과학자가 분류 작업에 대한 감을 빠르게 얻기 위해 데이터셋에 적용할 첫 번째 알고리즘으로 선택하는 경우가 많다.

초창기 신경망

  • 초창기 버전의 신경망은 이 책에서 다루는 최신 구조로 완전히 대체되었다.
    • 신경망의 핵심 아이디어는 1950년대 연구 되었으나 본격적으로 시작되기까지는 수십 년이 걸렸다.
    • 대규모 신경망을 훈련시킬 수 있는 효과적인 방법을 오랜 기간 동안 찾지 못했기 때문이다.
  • 1980년대 중반에 여러 사람들이 제각기 역전파 알고리즘을 재발견하고 신경망에 적용하기 시작하면서 상황이 바뀌었다.
    • 이 알고리즘은 경사 하강법 최적화를 사용하여 연쇄적으로 변수가 연결된 연산을 훈련하는 방법이다.
  • 성공적인 첫 번째 신경망 애플리케이션은 1989년 벨 연구소에서 나왔다.
    • 얀 르쿤(Yann LeCun)은 초창기 합성곱 신경망(convolution nerual network)과 역전파를 연결하여 손글씨 숫자 이미지를 분류하는 문제에 적용했다.
    • LaNet 이라 부르는 이 신경망은 우편 봉투의 우편 번호 코드를 자동으로 읽기 위해 1990년대 미국 우편 서비스에 사용 되었다.

커널 방법

  • 초기 성공에 힘입어 1990년대 신경망은 연구자들 사이에 관심을 얻기 시작했지만 머신 러닝의 새로운 접근 방법인 커널 방법이 인기를 얻자 신경망은 빠르게 잊혀졌다.
  • 커널 방법(Kernel method)는 분류 알고리즘의 한 종류이며, 그중 서포트 벡터 머신(Support Vector Machine, SVM)이 가장 유명하다.
    • 현대적인 SVM의 공식은 1990년대 초 벨 연구소의 블라드미르 바프닉(Vladmir Vapnik)과 코리나 코르테스(Corinna Cortes)에 의해 개발되었고 1995년에 공개되었다.
    • 바프닉과 알렉세이 체르보넨키스(Alexey Chervonenkis)가 만든 오래된 선형 공식은 1963년에 공개되었다.
  • SVM은 분류 문제를 해결하기 위해 2개의 다른 범주에 속한 데이터 포인트 그룹 사이에 좋은 결정 경계(decision boundary)를 찾는다.
    • 결정 경계는 훈련 데이터를 2개의 범주에 대응하는 영역으로 나누는 직선이나 표면으로 생각할 수 있다.
    • 새로운 데이터 포인트를 분류하려면 결정 경계 어느 쪽에 속하는지를 확인하기만 하면 된다.

  • SVM이 결정 경계를 찾는 과정은 두 단계이다.
    1. 결정 경계가 하나의 초평면(hyperplane)으로 표현될 수 있는 새로운 고차원 표현으로 데이터를 매핑한다. (위 그림과 같은 2차원 데이터라면 초평면은 직선이 된다)
    2. 초평면과 각 클래스의 가장 가까운 데이터 포인트 사이의 거리가 최대가 되는 최선의 결정 경계(하나의 분할 초평면)를 찾는다. 이 단계를 마진 최대화(maximizing the margin)라고 부른다. 이렇게 함으로써 결정 경계가 훈련 데이터셋 이외의 새로운 샘플에 잘 일반화 되도록 도와준다.
  • 분류 문제를 간단하게 만들어 주기 위해 데이터를 고차원 표현으로 매핑하는 기법이 이론상으로는 좋아보이지만 실제로는 컴퓨터로 구현하기 어려운 경우가 많다. 그래서 커널 기법(kernel trick)이 등장했다.
    • 요지는 다음과 같다. 새롭게 표현된 공간에서 좋은 결정 초평면을 찾기 위해 새로운 공간에 대응하는 데이터 포인트의 좌표를 실제로 구할 필요가 없다.
    • 새로운 공간에서의 두 데이터 포인트 사이의 거리를 계산할 수만 있으면 된다. 커널 함수(kernel function)를 사용하면 이를 효율적으로 계산할 수 있다.
    • 커널 함수는 원본 공간에 있는 두 데이터 포인트를 명시적으로 새로운 표현으로 변환하지 않고 타깃 표현 공간에 위치했을 떄의 거리를 매핑해 주는 계산 가능한 연산이다.
    • 커널 함수는 일반적으로 데이터로부터 학습되지 않고 직접 만들어야 한다. SVM에서 학습되는 것은 분할 초평면뿐이다.
  • SVM이 개발되었을 때 간단한 분류 문제에 대해 최고 수준의 성능을 달성했고 광범위한 이론으로 무장된 몇 안되는 머신 러닝 방법 중 하나가 되었다.
    • 또 수학적으로 깊게 분석하기 용이하여 이론을 이해하고 설명하기 쉽다.
    • 이런 유용한 특징 때문에 SVM이 오랫동안 머신 러닝 분야에서 매우 큰 인기를 끌었다.
  • 하지만 SVM은 대용량의 데이터셋에 확자오디기 어렵고 이미지 분류 같은 지각에 관련된 문제에서 좋은 성능을 내지 못했다.
    • SVM은 얕은 학습 방법이기 때문에 지각에 관련된 문제에 SVM을 적용하려면 먼저 수동으로 유용한 표현을 추출해야 하는데 (이런 단계를 특성 공학(feature engineering)이라고 한다) 이는 매우 어렵고 불안정하다.

결정 트리, 랜덤 포레스트, 그래디언트 부스팅 머신

  • 결정 트리 (decision tree)는 플로차트(flowchart) 같은 구조를 가지며 입력 데이터 포인트를 분류하거나 주어진 입력에 대해 출력 값을 예측한다.
    • 결정 트리는 시가고하하고 이해하기 쉽다.
    • 데이터에서 학습되는 결정 트리는 2000년대부터 연구자들에게 크기 관심을 받기 시작했고 2010년까지는 커널 방법보다 선호하곤 했다.

  • 특히 랜덤 포레스트(Random Forest) 알고리즘은 결정 트리 학습에 기초한 것으로 안정적이고 실전에서 유용하다.
    • 서로 다른 결정 트리를 많이 만들고 그 출력을 앙상블 하는 방법을 사용한다.
    • 랜덤 포레스트는 다양한 문제에 적용할 수 있다. 얕은 학습에 해당하는 어떤 작업에서도 거의 항상 두 번째로 가장 좋은 알고리즘이다.
    • 머신 러닝 경연 웹 사이트인 캐글(Kaggle)이 2010년에 시작되었을 때부터 랜덤 포레스트가 가장 선호하는 알고리즘이 되었다.
  • 2014년에 그래디언트 부스팅 머신(gradient boosting machine)이 그 뒤를 이어 받았다.
    • 랜덤 포레스트와 아주 비슷하게 그래디언트 부스팅 머신은 약한 예측 모델인 결정 트리를 앙상블 하는 것을 기반으로 하는 머신 러닝 기법이다.
    • 이 알고리즘은 이전 모델에서 놓친 데이터 포인트를 보완하는 새로운 모델을 반복적으로 훈련함으로써 머신 러닝 모델을 향상하는 방법인 그래디언트 부스팅(gradient boosting)을 사용한다.
  • 결정 트리에 그래디언트 부스팅 기법을 적용하면 비슷한 성질을 가지면서도 대부분의 경우에 랜덤 포레스트의 성능을 능가하는 모델을 만든다.
    • 이 알고리즘이 오늘날 지각에 관련되지 않은 데이터를 다루기 위한 알고리즘 중 최고는 아니지만 가장 뛰어나다.
    • 딥러닝을 제외하고 캐글 경연 대회에서 가장 많이 사용되는 기법이다.

다시 신경망으로

  • 2010년경 신경망은 관심을 받지 못했지만, 여전히 신경망에 대해 연구하고 있던 일부 사람들이 중요한 성과를 내기 시작했다.
    • 토론토 대학의 제프리 힌튼(Geoffrey Hinton), 몬트리올 대학의 요슈아 벤지오(Yoshua Bengio), 뉴욕 대학의 얀 르쿤, 스위스의 IDSIA이다.
  • 2011년에 IDSIA의 댄 크리슨(Dan Ciresan)이 GPU로 훈련된 심층 신경망(depp neural network)으로 학술 이미지 분류 대회에서 우승한 것이 시작이었다. 이것이 현대적인 딥러닝의 첫 번째 성공이다.
    • 이어서 2012년 대규모 이미지 분류 대회인 ImageNet에서 힌튼 팀이 등장하면서 분수령이 되었다.
    • ImageNet 대회는 당시 아주 어려운 문제로 전통적인 컴퓨터 비전 방식을 사용한 우승 모델의 상위 5개 예측이 타깃 클래스를 맞출 정확도는 74.3%였는데, 제프리 힌튼이 조언자로 참여하고 알렉스 크리체브스키(Alex Krizhevsky)가 이끄는 팀이 상위 5개 예측에 대한 정확도 83.6%의 놀라운 성과를 달성했다.
  • 이때부터 매년 이 대회는 심층 합성곱 신경망(deep convolutional nerual networ, ConvNet)이 우승을 차지했다.
    • 2015년 우승자는 96.4%의 정확도를 달성했고 ImageNet의 분류 문제는 완전히 해결된 것으로 간주되었다.
  • 2012년부터 심층 합성곱 신경망이 모든 컴퓨터 비전 작업의 주력 알고리즘이 되었다. 이 알고리즘은 조금 더 일반적이며, 지각에 관한 모든 문제에 적용할 수 있다.
    • 2015년과 2016년에 열린 주요 컴퓨터 비전 컨퍼런스에서 어떤 형태로든 컨브넷(ConvNet)을 포함하지 않은 발표를 찾는 것은 거의 불가능할 정도이다.
    • 동시에 딥러닝은 자연어 처리(natural language processing) 같은 다른 종류의 문제에도 적용되었다.
  • 다양한 애플리케이션에서 SVM과 결정 트리를 완전히 대체하고 있다.
    • 예컨대 지난 몇 년간 유럽 입자 물리 연구소(European Organization for Nuclear Research, CERN)는 대형 강입자 충돌기(Large Hadron Collider, LHC)에 있는 ATALS 감지기에서 얻은 입자 데이터를 분석하기 위해 결정 트리 기반의 알고리즘을 사용했으나 최근 연구는 케라스(Keras) 기반의 심층 신경망을 적용하기 시작했다.

딥러닝의 특징

  • 딥러닝이 이렇게 빠르게 확산된 주된 이유는 많은 문제에서 더 좋은 성능을 내고 있기 때문이다.
    • 하지만 그것뿐만이 아닌데, 딥러닝은 머신 러닝에서 가장 중요한 단계인 특성 공학을 완전히 자동화 하기 때문에 문제를 더 해결하기 쉽게 만들어준다.
  • 얕은 학습인 이전의 머신 러닝 기법은 입력 데이터를 고차원 비선형 투영(SVM)이나 결정 트리 같은 간단한 변환을 통해 하나 또는 2개의 연속된 표현 공간으로만 변환한다. 하지만 복잡한 문제에 필요한 잘 정제된 표현은 일반적으로 이런 방식으로 얻지 못한다.
    • 이런 머신 러닝 방법들로 처리하기 용이하게 사람이 초기 입력 데이터를 여러 방식으로 변환해야 한다. 즉 데이터의 좋은 표현을 수동으로 만들어야 하는데, 이를 특성 공학(feature engineering)이라고 한다.
  • 이에 반해 딥러닝은 이 단계를 완전히 자동화 한다. 딥러닝을 사용하면 특성을 직접 찾는 대신 한 번에 모든 특성을 학습할 수 있다.
    • 머신 러닝 작업 흐름을 매우 단순화시켜 주므로 고도의 다단계 작업 과정을 하나의 간단한 end-to-end 딥러닝 모델로 대체할 수 있다.
  • 이슈의 핵심이 여러 개의 연속된 표현 층을 가지는 것이라면, 얕은 학습 방법도 딥러닝의 효과를 모사하기 위해 반복적으로 적용할 수 있지 않을까 하는 의문이 들 수 있다.
    • 실제로 얕은 학습 방법을 연속적으로 적용하면 각 츠으이 효과는 빠르게 줄어든다. 3개의 층을 가진 모델에서 최정의 첫 번째 표현 층은 하나의 층이나 2개의 층을 가진 모델에서 최정의 첫 번째 층과는 달라야 한다.
  • 딥러닝의 변환 능력은 모델이 모든 표현 층을 순차적이 아니라(탐욕적(greedily) 방법이 아니라) 동시에 공동으로 학습하게 만든다.
    • 이런 공동 특성 학습 능력 덕택에 모델이 내부 특성 하나에 맞춰질 때마다 이에 의존하는 다른 모든 특성이 사람이 개입하지 않아도 자동으로 변화에 적응하게 된다.
    • 모든 학습은 하나의 피드백 신호에 의해 시작된다. 즉 모델의 모든 변화는 최종 목표를 따라가게 된다.
    • 이 방식은 모델을 많은 중간 영역(층)으로 나누어 복잡하고 추상화된 표현을 학습시킬 수 있기 때문에 얕은 학습 모델을 탐욕적으로 쌓은 것보다 훨씬 강력하다. 여기에 각 층은 이전 층의 의존하지 않는 단순한 변환을 수행한다.
  • 딥러닝이 데이터로부터 학습하는 방법에는 두 가지 중요한 특징이 있다.
    • 층을 거치면서 점진적으로 더 복잡한 표현이 만들어진다는 것과 이런 점진적인 중간 표현이 공동으로 학습된다는 사실이다.
    • 각 층은 상위 층과 하위 층의 표현이 변함에 따라 함께 바뀐다. 이 2개의 특징이 이전의 머신 러닝 접근 방법보다 딥러닝이 훨씬 성공하게 된 이유이다.

머신 러닝의 최근 동향

  • (앞선 내용 생략)
  • 오늘날 머신 러닝을 성공적으로 적용하기 위해 알아야 할 두 가지 기술은 얕은 학습 문제를 위한 그래디언트 부스팅 머신과 지각에 관한 문제를 위한 딥러닝이다.

왜 딥러닝일까? 왜 지금일까?

  • 컴퓨터 비전에 대한 딥러닝의 두 가지 핵심 아이디어인 합성곱 신경망과 역전파는 이미 1989년에 소개되었다.
    • 시계열을 위한 딥러닝의 기본인 LSTM(Long Short-Term Memory) 알고리즘은 1997년에 개발되었고 그 이후로 변화가 거의 없다.
  • 왜 2012년 이후 딥러닝이 부상하게 되었을까? 일반적으로 세 가지 기술적인 힘이 머신 러닝의 진보를 이끌었다.
    • 하드웨어
    • 데이터셋과 벤치마크
    • 알고리즘 향상
  • 이 분야는 이론보다 실험을 통해서 성장해 왔기 때문에 새로운 아이디어를 실험할 적절한 데이터와 하드웨어가 준비되어 있어야만 알고리즘이 발전할 수 있다.
    • 머신 러닝은 수학이나 물리학이 아니라 하나의 공학이다.

하드웨어

  • (GPU가 등장했다는 설명 생략)

데이터

  • (데이터가 많아졌다는 설명 생략)

알고리즘

  • 2000년대 후반까지는 매우 깊은 심층 신경망을 훈련시킬 수 있는 안정적인 방법을 찾지 못했는데, 이런 이유로 하나 또는 2개의 층만 사용하는 매우 얕은 신경망만 가능했고 SVM과 랜덤 포레스트처럼 잘 훈련된 얕은 학습 방법에 비해 크게 빛을 보지 못했다.
  • 깊게 쌓은 층을 통과해서 그래디언트(gradient)를 전파하는 것이 가장 문제였는데, 신경망을 훈련하기 위한 피드백 신호가 층이 늘어남에 따라 희미해지기 때문이다.
  • 2009-2010년경 몇 가지 간단하지만 중요한 알고리즘이 개선되면서 그래디언트를 더 잘 전파되게 만들어 주었고 상황이 바뀌었다.
    • 신경망의 층에 더 잘 맞는 활성화 함수(activation function)
    • 층별 사전 훈련(pretraining)을 불필요하게 만든 가중치 초기화(weight initialization) 방법
    • RMSProp과 Adam 같은 더 좋은 최적화 방법
  • 이런 기술의 향상으로 10개 이상의 층을 가진 모델을 훈련시킬 수 있게 되었을 때 비로소 딥러닝이 빛을 발하기 시작했다.
  • 2014-2016년 사이에 그래디언트를 더욱 잘 전파할 수 있는 배치 정규화(batch normalization), 잔차 연결(residual connection), 깊이별 분리 합성곱(depthwise separable convolution) 같은 고급 기술들이 개발된 덕에 요즘에는 층의 깊이가 수천 개인 모델을 처음부터 훈련시킬 수 있다.

새로운 투자의 바람

  • (생략)

딥러닝의 대중화

  • (생략)

지속될까?

  • (생략)

물성의 원리

물성의 원리

개인적으로 신뢰하는 최낙언씨의 물성에 관한 책. 단순히 식품 자체에 대한 것보다 식품을 구성하는 원리를 탐구한다는 컨셉으로 식품을 구성하는 핵심적인 분자인 물, 단백질, 탄수화물, 지방에 대한 특성을 담고 있다.

생각보다 우리가 분자 차원에서 알고 있는 지식이 대단히 단편적인게 많은데, 실제로 분자 차원에서는 운동성도 굉장히 높고 –그 유명한 브라운 운동도 물 분자의 운동성 때문이다–, 그 크기의 차이나 모양(구조)의 차이가 대단히 중요한데, 우리가 그런 지식을 배울 때는 그런 내용을 잘 배우지 않기 때문. 원리를 알면 영양에 대한 이상한 소리는 꽤 많이 걸러낼 수 있는데 그걸 몰라서 사람들은 잘못된 영양 정보에 현혹되는게 아닐까 싶다.

원리를 담고 있기 때문에 어쩌면 나와 같은 대중들이 이해하기는 조금 어려운 책일 수 있는데, –실제로 나도 따라가지 못한 내용이 많음– 관심 있다면 꼭 한 번 읽어볼 만한 책이라 생각함. 

개인적으로 기회가 되면 다시 읽으면서 공부를 해두고 싶을 정도로 유용한 내용이 대단히 많았는데, 내 전문 분야가 아닌 분야에 공부 시간을 쓰기가 점점 더 어려워져서 한참 나중의 일이 되지 않을까 싶다.

추가로 식품이나 영양 관련해서 정보가 필요하면 찾아보는 http://www.seehint.com 를 참조하는데, 관심 있다면 둘러 보는 것을 추천. 사이트의 내용이 책의 내용과 동일한 것을 보면, 아무래도 최낙언 씨는 본인이 궁금한 내용을 공부해서 자료로 정리하고, 그 자료들을 하나의 주제로 엮어서 책을 내시는게 아닐까 싶은데, 덕분에 저술도 엄청 많이 하셨음. 나도 나중에 이런 식으로 공부한 자료를 모으고 책을 내면 좋겠다는 생각을 했음.

21세기 자본/ 공공부채의 문제

  • 정부가 재정을 마련하는 주된 방식은 세금과 부채다.
    • 일반적으로 공정성과 효율성 측면에서 부채보다 과세가 훨씬 더 바람직하다.
    • 부채는 상환을 해야 하기 때문에, 채권을 통한 조달은 정부에 빌려줄 자산이 있는 사람들에게만 이익이 된다는 문제가 있다.
    • 공익적 관점에서는 부자들에게 자금을 빌리는 것보다 부자들에게 과세를 하는 것이 더 바람직하다.
  • 부유한 국가들은 아직 1년치 국민소득에 해당하는 공공부채를 떠안고 있는데, 이것은 1945년 이래 전례가 없는 일이다.
    • 신흥국들은 빈곤하지만 공공보채는 훨씬 더 적다 (평균적으로 GDP의 30%)
  • 이는 공공부채가 부의 분배, 특히 공공부분과 민간부문 사이의 문제이지 절대적인 부의 문제는 아님을 보여준다.
    • 부유한 국가는 부유하지만 그 국가의 정부는 가난하다. 유럽이 가장 극단적인 사례다.

공공부채의 감축: 자본세, 인플레이션, 긴축

  • 대규모 공공부채를 감소시키는데는 3가지 방법이 있는데, 자본에 대한 세금, 인플레이션, 긴축재정이 그것이다.
    • 민간자본에 파격적인 세금을 부과하는 것이 가장 공정하고 효율적이지만 그것이 실패한다면 인플레이션이 유용한 방법이다.
    • 역사적으로 인플레이션은 대규모 공공부채를 처리하는 주된 방법이었다.
    • 공정성과 효율성 측면에서 최악의 해결책은 지속적인 긴축재정이다.
  • (유럽의 재정 상황 설명 생략)
  • 이런 상황에서 어떻게 공공부채를 감소시킬 것인가? 한 가지 방법은 공공자산을 민영화하는 것이다.
    • (설명 생략)
    • 그러나 내 생각에 이러한 해결 방안은 고려할 필요도 없이 제외되어야 한다.
  • 공공부채를 줄이는 더 만족스러운 방법은 민간자본에 파격적인 세금을 부과하는 것이다.
    • 민간자본에 일률적으로 15%를 과세하면 1년치 국민소득과 맞먹는 수입을 올릴 수 있고 이로 인해 모든 공공부채를 즉시 상환할 수 있다.
    • 이런 해결책은 두 가지 차이를 제외하면 공공부채 갚기를 거부하는 것과 동일하다.
    • (채무 불이행 설명 생략)
  • 좀 더 현실적인 사례가 누진적 자본세이다.
    • 이 세금은 유로존 내 GDP의 2%에 해당하는 세수를 확보할 수 있다.
    • (이하 설명 생략)

인플레이션은 부를 재분배하는가?

  • 자본에 세금을 부과하는 것 외에 인플레이션이 또 다른 선택지가 될 수 있다.
    • 인플레이션이 소폭 상승하는 것으로 공공부채의 실질 가치를 상당히 낮출 수 있다.
    • 다른 조건이 동일할 때 인플레이션이 연 2%가 아니라 5%라면 공공부채의 실질 가치는 GDP에 대한 비율로 나타냈을 때 15% 이상 감소할 것이다.
    • 20세기 유럽에서는 인플레이션이 대부분의 거대한 공공부채를 감소시킨 방법이었다.
    • (이하 설명 생략)
  • 지속적인 긴축재정을 통한 해결책의 사례는 19세기 영국이 있다.
    • 영국은 나폴레옹 전쟁을 거친 뒤 엄청난 공공부채를 없애는데, 한 세기 동안의 기초재저웃지 흑자가 필요 했다.
    • 이러한 선택은 국채 소유자들의 이익에 부합했지만 영국인들의 일반적인 공익에 기여하지는 못했다.
    • (이하 설명 생략)
  • 인플레이션은 누진세에 비해 불완전한 대체 수단에 지나지 않으며, 바람직하지 못한 2차적인 효과를 불러올 수 있다.
    • 첫 번째 문제는 인플레이션을 통제하기 어렵다는 것이고, 두 번째 문제는 인플레이션이 고착화되고 예측 가능해지면 대부분의 수많은 바람직한 효과는 사라진다는 것이다. 예컨대 정부에 돈을 빌려주는 사람들은 더 높은 이자율을 요구할 것이다.
  • (이하 설명 생략)

중앙은행은 어떤 일을 하는가?

  • 1차대전 이전 전 세계가 금본위제를 기반으로 하던 시기에 중앙은행은 오늘날보다 훨씬 더 작은 역할을 수행했다.
    • 특히 화폐를 만들어내는 능력은 금과 은의 보유고에 크게 제한되었다.
  • 통화가 귀금속으로 교환되는 것이 중단되면 화폐를 찍어내는 중앙은행의 권력이 잠재적으로 무한해지기 때문에 반드시 엄격하게 규제되어야 한다.
    • 이는 중앙은행의 독립성에 대한 논쟁의 핵심이자 수많은 오해의 원인이다.
  • (이하 설명 생략)

통화 창조와 국민총자본

  • 중앙은행이 부 자체를 창출하지는 않는다는 사실을 인식하는 것이 중요하다. 즉, 중앙은행은 부를 재분배할 뿐이다.
  • (이하 설명 생략)
  • 중앙은행은 강력한 힘을 가지고 있다. 그들은 신속하게, 그리고 이론상으로 그들이 원하는대로 광범위하게 부를 재분배할 수 있다.
    • (이하 설명 생략)
  • 중앙은행의 약점은 분명히 통화정책의 결과로 나타난 금융 포트폴리오의 관리가 어려울 뿐 아니라 누가, 얼마나, 어느 정도의 만기로 대출 받을 것인지 결정할 수 있는 능력이 제한되어 있다는 것이다.
  • (이하 설명 생략)

키프로스의 금융위기: 자본세와 은행 규제가 결합되었을 때

  • 중앙은행의 기본적, 필수적 역할은 금융시스템의 안정성을 보장하는 것이다.
    • 중앙은행은 유일하게 시스템을 구성하는 다양한 은행의 상태를 평가할 준비가 되어 있고, 지불 시스템의 정상적인 작동을 보장하기 위해 필요하다면 이 은행들에 재융자를 해줄 수 있다.
    • 또한 중앙은행은 때로는 은행 규제라는 특정 책임을 맡은 다른 정부 기관들의 도움을 받기도 한다.
  • (이하 설명 생략)
  • 키프로스 사태는 중앙은행과 금융당국의 한계를 흥미롭게 보여준다. 중앙은행과 금융당국은 사태에 재빨리 대응할 수 있다는 강점을 지닌 반면, 그들이 야기할 자산 재분배의 표적을 정확하게 조준하는데는 제한적이라는 약점이 있다.
    • 결론적으로 누진적 자본세는 지속적인 세제로서 유용할 뿐만 아니라 주요한 금융위기가 일어날 때 예외적으로 부과되어 위기 해결 기능을 담당할 수도 있다.

유로화: 21세기를 위한 국경 없는 통화인가?

  • 유로화의 탄생은 통합 유럽을 향한 긴 과정 가운데 한 단계에 지나지 않는다.
  • (이하 설명 생략)
  • 2002년 유로화가 도입되고 2007-2008년 금융위기가 발생하기 전까지 유럽 전역의 이자율은 대체로 동일했다. 그 누구도 특정 국가의 유로존 탈퇴 가능성을 예상하지 않았고 모든 것이 순조로워보였다.
    • 하지만 금융위기가 발생하자 국가별로 금리 차가 급속히 커지기 시작했고, 이는 정부 예산에 심각한 영향을 미쳤다.
    • 이와 같은 불확실성에 직면한 상황에서는 채무 조정의 분담이라든지 필수적인 사회적 국가의 개혁에 관해 차분한 자세로 민주적 토론을 하기 불가능하다.
  • (이하 설명 생략)

유럽 통합의 문제

  • 이런 모순들을 극복할 유일한 방법은 유로존 국가들이 공공부채를 한데 모으는 것이다.
  • (이하 유로존 통합에 대한 내용 생략)

21세기의 정부와 자본축적

  • 이상적인 사회의 바람직한 공공부채 수준은 어느 정도일까? 이에 대한 확실한 정답은 없아. 이는 각 국가가 마주한 상황과 각 사회가 설정한 목표에 따라 민주적인 논의를 거쳐서만 결정할 수 있다.
  • 자본이 너무 많이 축적되어 이론상 자본의 한계생산성과 동일한 자본수익률 r이 성장률 g와 똑같아질 때 자본은 최대 수준에 도달한다.
    • 1961년 에드먼드 펠프스(Edmund Phelps)는 자본수익률과 성장률이 동일한 r=g 등식을 자본축적의 황금률이라고 명명했다.
    • 만약 그의 주장을 그대로 받아들인다면 이 황금률은 역사적으로 관찰된 것보다 훨씬 더 높은 자본/소득 비율을 의미한다. 왜냐하면 자본수익률이 언제나 성장률보다 상당히 높았기 때문이다.
  • 어떤 사회에서도 그렇게 많은 자본을 축적하지는 못할 것이기 때문에 황금률이 제시한 대답은 현실적으로 유용하지 않지만 황금률에 내재된 논리는 흥미를 끈다.
    • 만약 황금률이 충족되어 r=g가 된다면 당연히 장기적으로 국민소득에서 자본이 차지하는 몫은 정확히 저축률과 일치한다.
    • 반대로 r>g 상황이지속되는 한 국민소득에서 자본의 몫은 저축률보다 크다.
    • 다시 말해 황금률이 충족되려면 자본이 더 이상 아무것도 생산해낼 수 없을 정도로 엄청나게 축적되어야 한다는 의미다.
    • 더 정확하게는 자본이 너무 많이 축적되어 오로지 동일한 수준의 자본 총량을 유지하기 위해 해마다 모든 자본수익을 자본에 재투자해야 한다.
  • 황금률은 ‘자본 포화(capital saturation)’ 전력과 관련이 있다.
    • 이는 너무 많은 자본을 축적해 자본소득자들에게 소비할 돈이 전혀 남지 않은 상태다. 그들이 높은 사회적 지위를 계속 유지하기 위해 경제성장률과 동일하게 그들의 자본을 증가시키기를 원한다면 모든 자본을 재투자해야 하기 때문이다.
    • 반대로 r>g라면 자본수익률 중 성장률과 동일한 부분만 자본에 재투자하고 나머지는 소비할 수 있다. r>g는 자본소득자 사회의 기반이 된다.
  • (이하 설명 생략)

법과 정치

  • (설명 생략)
  • 정부 예산에 관한 제한을 헌법이나 법률에 명시하는 것은 여러 이유로 현명한 처사가 아니다.
  • 국부에 영향을 미치는 수많은 다른 요인은 고려하지 않은 채 부채와 적자의 적정 수준을 판단하는 것은 불가능하다.
  • (이하 설명 생략)

기후변화와 공공자본

  • 2006년 발표된 스턴 보고서는 금세기가 끝날 무렵이면 환경오염 때문에 발생하는 잠재적 손실액이 최악의 경우 연간 전 세계 GDP의 수십 %에 이를 것이라는 시나리오를 제시했다.
  • (이하 설명 생략)

경제적 투명성과 자본의 민주적 통제

  • 좀더 일반적으로 나는 새로운 형태의 소유권의 발전과 자본에 대한 민주적 통제가 향후 가장 중요한 문제 가운데 하나라는 주장이 중요하다고 생각한다.
  • 핵심은 다양한 형태의 민주적 자본통제는 각각의 관련 당사자에 대한 경제 정보를 이용할 수 있는 가능성에 크게 좌우된다는 것이다.
  • (이하 투명성이 중요하다는 내용 생략)

21세기 자본/ 글로벌 자본세

  • 민주주의가 현 세기의 세계화된 금융자본주의를 통제하려면 새로운 수단을 개발해야 한다. 여기서 이상적인 수단은 매우 높은 수준의 국제적 금융 투명성과 결부된 누진적인 글로벌 자본세가 될 것이다.
    • 이와 같은 세금은 끝없는 불평등의 악순환을 피하고 세계적인 자본 집중의 우려스러운 동학을 통제하는 방법이 될 수 있다.

글로벌 자본세: 유용한 유토피아

  • 글로벌 자본세는 유토피아적인 이상이고 가까운 시일 내에 그와 같은 세금에 합의하는 나라들이 있을거라고 생각하기는 어렵다.
    • 이 목적을 이루려면 세계의 모든 자산에 적용할 수 있는 세율표를 만들고 세수를 어떻게 배분할지를 결정해야 한다.
  • 확실히 글로벌 자본세는 매우 높은 수준의 비현실적인 수준의 국제 협력을 필요로 한다. 그러나 이 방향으로 나아가려는 나라들은 지역적인 차원에서 점진적으로 이를 실현할 수 있다.
    • 보호주의와 자본통제는 글로벌 자본세의 만족스러운 대안이 아니다.
  • 글로벌 자본세의 이상적인 해법은 대륙이나 지역수 준에서 그 다음에는 지역 간의 긴밀한 협력을 통해 충분히 실현 가능하다.
  • 금융 투명성과 정보 공유 문제는 이상적인 자본세와 밀접하게 관련되어 있다.
    • 내 생각에는 개인 자산에 매년 부과하는 누진세가 목표가 되어야 한다.
    • 그래서 지구상에서 가장 부유한 사람들에 대한 세금은 개인의 순자산을 바탕으로 해야 할 것이다.
  • (이하 설명 생략)

민주적 투명성과 금융의 투명성

  • 글로벌 자본세는 결코 기존의 모든 세금을 대체하는 것이 아니다. 현대의 사회적 국가가 의존하는 다른 세원을 적당히 보충해주는 정도 이상은  아닐 것이다. 그 세수는 고작해야 국민소득의 3-4%이다.
  • 자본세의 주된 목적은 사회적 국가의 재원을 조달하는게 아니라 자본주의를 규제하는 것이다.
    • 첫 번째 목적은 부의 불평등이 끝없이 증가하는 것을 막는 것이고,
    • 두 번째 목적은 금융 및 은행 제도의 위기를 피하기 위해 금융과 은행 시스템에 효과적인 규제를 가하는 것이다.
  • 이 두 가지 목적을 달성하기 위해 자본세는 민주적 투명성과 금융 투명성을 확보해야 한다.
  • (이하 설명 생략)

간단한 해법: 은행 정보의 자동 전송

  • 글로벌 자본세 과세를 위한 첫 걸음은 사전에 계산되어 개별 납세자에게 통지되는 자산 내역서에 해외 은행에 유치된 자산에 관한 정보를 포함하기 위해 이러한 방식의 은행 데이터의 자동 전송을 국제적 차원으로까지 확대하는 것이다. 이를 위한 기술적 장애는 없다.
  • (이하 설명 생략)

자본세의 목적은 무엇인가?

  • 누진적 소득세와 상속세가 존재하는데, 누진적 자본세의 목적은 무엇인가?
    • 사실 이 세 가지 누진제는 서로 다르면서 상호 보완적인 역할을 한다. 각각은 이상적인 조세 체계에서 필수적인 주축이다.
  • 자본세를 정당화하는 논리는 담세 능력과 유인 두 가치 측면으로 구분할 수 있다.
  • (이하 설명 생략)
  • 최상위 부유층의 자산이 매우 높은 수익을 낸다는 관점에서 담세 능력에 따라 과세를 하자는 주장은 누진적 자본세를 정당화하는 가장 중요한 논리다.
  • 기본적인 아이디어는 자본세가 한 사람의 자본총량으로 최고의 수익을 추구하게 하는 유인이 된다는 것이다.
    • 자산을 기껏해야 2-3% 수익율에 내는 투자 수단에 맡겨두는 사람에게는 자본세가 무겁기 때문에 자신의 재산을 비효율적으로 활용하는 사람들이 세금을 내기 위해 자산을 팔도록 하고 그리하여 그 자산이 확실히 더 역동적인 투자자들의 손에 가도록 하는 것이다.
    • (이거는 말이 안되는 듯)
  • (이하 설명 생략)

유럽 부유세를 위한 청사진

  • 나는 영구적인 연간 자본세를 말하는 것이므로 세율은 상당히 낮아야 한다.
  • 오늘날 유럽에서 민간의 부가 매우 높은 수준임을 감안하면 연간 누진세로도 상당한 세수를 창출할 수 있다.
    • 예컨대 100만 유로 이하에는 0%, 100-500만 유로에는 1%, 500만 유로 이상에는 2%의 부유세를 매긴다면, 인구의 2.5%에 영향을 미칠 것이고 유럽 GDP의 2%에 맞먹는 세수를 가져올 것이다.
    • 이는 민간의 부가 GDP의 5배에 달하고 있기 때문이다.
  • (이하 설명 생략)

역사적 관점에서 본 자본세

  • 모든 문명에서 자본소유자들이 노동을 하지 않고도 연 4-5%의 수익을 거둔 사실은 다양한 정치적 대응과 격렬하고 분개에 찬 반응을 일으켜왔다.
    • 정치적 대응 중 가장 일반적인 형태는 고리대금업을 금지하는 것이었는데, 이는 기독교, 이슬람교를 포함한 대부분의 종교 전통에서 다양한 형태로 발견된다.
    • 그러나 이자놀이를 금지하려는 시도는 흔히 비논리적이었다.
    • 마르크스와 19세기 많은 사회주의자가 제시하고 20세기 소련과 다른 곳에서 실행된 자본 문제에 대한 해결책은 훨씬 급진적이며 논리적으로는 더 일관성 있었다.
  • (이하 설명 생략)
  • 누진세 혁명은 20세기와 두 차례 세계대전 사이의 기간을 기다려야 했다.
    • 혁명은 혼돈의 와중에 일어났으며, 주로 소득 및 상속에 대한 누진세의 형태로 나타났다.
  • (이하 설명 생략)

규제의 다른 형태: 보호무역주의와 자본통제

  • 세습자본주의를 규제하는 다른 방법들이 있으며, 이들 중 일부는 이미 세계적으로 다양한 지역에서 시도되고 있지만, 그럼에도 불구하고 이런 규제 형태들은 자본세보다 만족스럽지 않으며, 때때로 문제를 해결하기보다 더 많은 문제를 낳기도 한다.
  • 가장 단순한 방법은 보호무역주의와 자본통제에 의한 것이다.
    • (이하 각 방법의 문제점 생략)

중국의 자본 규제 미스터리

  • 중국은 자국으로 유입되는 자본과 국외로 나가는 자본을 엄격히 통제해왔다.
  • (이하 설명 생략)
  • 나는 중국의 자본 규제 체계를 옹호할 생각은 없지만 그럼에도 불구하고 자본통제는 부의 불평등의 동학을 규제하고 제한할 수 있는 하나의 방법이다.
    • 게다가 중국의 소득세는 충분히 누진적이라고 할 수는 없지만, 러시아보다는 더 누진적이다.
    • 이 세수는 다른 신흥국들에서보다 훨씬 더 큰 규모로 교육, 의료, 사회기반시설에 투자되는데, 이런 면에서 중국은 이들보다 훨씬 앞서나가고 있다.
  • (이하 설명 생략)

석유 지대의 재분배

  • 만약 지구촌이 하나의 민주적 글로벌 공동체라면 이상적인 자본세는 석유 지대를 공평한 방식으로 재분배할 것이다.
    • 그러나 현실은 아니기 때문에 천연자원의 재분배는 평화롭지 못한 방식으로 결정된다.
  • (이하 설명 생략)
  • 석유 지대의 더 공정한 분배를 위한 다른 방법들을 찾아내야 한다. 석유가 없는 나라들에게 발전할 기회를 주기 위해 각종 제재와 조세, 대외원조와 같은 방법들을 쓸 수 있을 것이다.

이민을 통한 재분배

  • 미인은 평화로운 방식으로 글로벌 부의 불평등에 대한 규제와 재분배를 할 수 있는 수단으로 보인다.
    • 미국이 독립전쟁 당시 300만명이었던 인구가 오늘날 3억 명 이상으로 성장한 것은 지속적인 이민 행렬 덕분이었다.
    • 이민을 통한 재분배의 메커니즘, 즉 가난한 국가에서 태어난 이들이 부유한 국가로 이주함으로써 자신의 운명을 개척할 수 있도록 하는 것은 미국뿐만 아니라 유럽에서도 중요한 요소가 되고 있다.
  • 그러나 이민을 통한 재분배는 바람직하기는 하지만, 불평등 문제를 부분적으로만 해결한다는 점을 강조할 필요가 있다.
  • (이하 설명 생략)
  • 거듭 강조하지만 금융 투명성과 누진적인 글로벌 자본세가 올바른 해답이다.
    • (자본통제, 보호무역주의, 석유 지대 분배, 이민 같은 방법보다 자본세가 낫다는 이야기)

21세기 자본/ 누진적 소득세를 다시 생각한다

현대적 재분배: 누진세의 문제

  • 과세는 기술적인 문제가 아니라 상당히 정치적이며 철학적인 문제이고, 모든 정치 문제 가운데 가장 중요하다.
  • 보통 세금은 소득세, 자본세, 소비세로 구분된다. 각각의 세금은 거의 모든 시기에 다양한 비율로 나타난다.
  • 20세기에 네 번째 범주의 세금이 등장했는데 그것은 정부가 후원하는 사회보장제도에 대한 기여금이었다. 이는 특별한 유형의 소득세인데, 보통 노동소득에만 과세된다.
  • ‘비례세’는 세율이 모두에게 똑같이 적용되는 세금이고 ‘누진세’는 소득이나 소유한 자산 또는 소비가 더 많은 사람에게 더 높은 세율이 적용되는 세금이다.
    • ‘역진세’는 더 부유한 사람에게 적용되는 세율이 낮은 경우인데, 세금부담을 최적화하거나 회피하거나 법률이 역진적인 세율을 부과했기 때문에 발생한다.
    • 1990년 마거릿 대처를 실각시킨 ‘인두세(poll tax)’가 역진적인 세율을 부과한 대표적인 경우이다.

누진세: 제한적이지만 중요한 역할

  • 누진세가 현대적 재분배에서 제한된 역할만 한다는 결론은 잘못된 것이다.
  • 첫 번째 이유는 전반적인 과세가 대다수 인구의 소득과 상당 수준 비례한다고 해도, 가장 높은 소득과 가장 많은 재산에 더 높은 세율로 과세하는 것은 불평등 구조에 큰 영향을 줄 수 있기 때문이다.
    • 특히 매우 높은 소득과 상속재산에 대한 누진세는 1914-1945년 충격 이후 부의 집중이 벨 에포크 시대만큼 돌아가지 않았는가를 부분적으로 설명해준다.
    • 반면 2차대전 이후 누진세의 선도국가들이었던 영국과 미국에서 나타난 매우 높은 노동소득의 증가는 아마도 소득세의 누진성이 극적으로 감소한 것으로 상당 부분 설명이 가능할 것이다.
  • (세율 관련 내용 생략)
  • 사회적 계층 구조의 상류층에 대한 과세가 미래에 더욱 역진적으로 바뀌면 그것이 부의 불평등의 역학에 미치는 영향은 더 커질 것이고 그 결과 매우 심한 자본의 집중이 나타날 것이다.
  • (이하 설명 생략)
  • 이 모든 이유로 인해 누진세는 사회적 국가의 핵심적인 요소다. 누진세는 20세기 불평등 구조의 발전과 변화에서 중요한 역할을 했으며, 미래의 사회적 국가의 지속가능성을 확보하기 위해서도 중요하다.

20세기의 누진세: 단명한 혼돈의 산물

  • 누진세는 민주주의뿐만 아니라 두 차례에 걸친 세계대전의 산물임을 깨닫는 것이 중요하다.
    • 1900-1910년 사이 모든 선진국이 누진세를 도입한 것은 아니지만 누진성의 원칙과 총소득에 대한 누진세 적용에 관한 국제적인 합의가 등장하고 있었다.
  • (전쟁으로 인한 비용 증가 때문에 누진세가 빠르게 도입 될 수 있었다는 내용 생략)

제3공화정의 누진세

  • 누진세와 함께 20세기 초 두 번째로 중요한 조세제도 혁신이었던 누진적 상속세도 낮은 세율부터 시작했다.
    • 상속세의 세율은 1914까지 꽤 낮았다.
  • (이하 상속세 도입과 관련한 프랑스 내용 생략)

  • 다른 국가들에서도 상속세는 1차대전 이후 근본적인 변화를 겪었다.
  • (이하 설명 생략)

과다소득에 대한 몰수적 과세: 미국의 발명

  • 두 차례의 세계대전 사이에 모든 선진국은 매우 높은 최고세율의 적용을 실험하기 시작했다. 그러나 1919년부터 1922년 사이 70% 이상의 세율을 시도한 최초의 국가는 바로 미국이었다.
    • 1919-1922년에 먼저 소득에 적용했고, 이후 1937-1939년에 상속재산에 적용했는데, 정부가 이처럼 소득이나 상속에 대해 70-80% 세율을 부과한 주된 목표는 세수 확보가 아니라 지나치게 많은 소득과 대규모의 상속을 억제하려는데 있었다.
    • 이런 높은 소득 구간에서 얻을 수 있는 세수가 많지 않았기 때문이다.
  • (이하 누진세에 대한 당시 논의 생략)
  • 웨지우드는 “경제민주화 없는 정치적 민주주의는 본질적으로 불안정하다”고 확신했다. 그의 관점에서는 매우 누진적인 상속세가 그가 필수적이라고 생각했던 경제민주화를 달성하기 위한 주요한 도구였다.

최고위 경영진 급여의 폭발적 증가: 조세의 역할

  • 1930-1970년대까지 열정적으로 평등을 추가했던 영국과 미국은 최근 10년간 정반대 방향으로 진로를 바꾸었다.
    • 그 결과 과거 30년 동안 프랑스와 독일보다 훨씬 더 높았던 영국과 미국의 소득세 최고 한계세율은 프랑스와 독일 수준보다 훨씬 낮게 떨어졌다.
  • 1980년대부터 현재까지 나타난 소득세 최고한계세율의 감소 규모가 같은 기간에 국민소득에서 상위 1%의 소득이 차지하는 비율이 증가한 규모와 긴밀한 관련이 있다는 사실을 발견할 수 있다.
    • 구쳊거으로 보면 이 두가지 현상은 서로 완벽하게 관련되어 있다. 즉, 최고세율이 가장 크게 인하된 국가는 국민소득에서 최고소득자가 차지하는 비율, 특히 대기업 최고위 경영진의 급여가 가장 크게 증가한 국가다.
    • 반면 최고세율이 그리 많이 인하되지 않은 나라에서는 국민소득에서 최고소득자가 차지하는 비율이 훨씬 더 완만하게 증가했다.
  • (이하 설명 생략)
  • ‘협상력(bargaining power)’에 기초한 설명은 1970년대 이후 선진국들에서 최고한계세율의 하락과 생산성 상승률 사이에 통계적으로 유의미한 관련성이 없다는 사실과 일치한다.
    • 구체적으로 말해 1970-1980년 이후 모든 부유한 국가에서 1인당 GDP 성장률은 비슷했다는 사실이 중요하다.
    • 달리 말하면 소득세 최고한계세율의 인하와 최상위 소득의 증가는 생산성을 촉진하지 못했으며, 어쨌든 통계적으로 거시적인 수준에서 유의미할 정도로 생산서을 촉진하지는 못했던 것으로 보인다.
  • (이하 설명 생략)

국가의 정체성과 경제적 성과

  • (설명 생략)
  • 우리의 연구는 급증하는 최고위 경영진의 보수가 협상력 이론으로 잘 설명되며, 한계생산성 상승 가설과는 그다지 관련이 없다는 사실을 보여준다.
    • 우리는 ‘재능’ 보다는 ‘행운’과 관련된 최고위 경영진 보수의 탄력성이 더 높았다는 사실을 다시 한번 확인했다.
    • 이러한 결과는 최고위 경영진의 높은 급여가 좋은 성과에 따른 보상이라는 견해에 심각한 문제를 제기한다.
    • 게다가 우리는 행운과 관련된 탄력성이 최고한계세율이 더 낮은 나라에서 더 높다는 사실을 발견했다.
  • 우리의 연구는 1980년 이전에 미국과 영국에서 적용되었던 고율의 과세와 같은 수단만이 효과적일 수 있음을 시사한다.

다시 생각하는 최고한계세율

  • 조사 결과에 따르면 사실상 최고소득에 매우 높은 세율을 부과하는 것은 매우 높은 급여의 증가를 억제하는 유일한 방법이다.
    • 우리의 추정에 따르면 선진국의 최적최고세율은 아마도 80%를 넘을 것이다.
  • 연 50만 달러 내지 100만 달러 이상의 소득에 80% 세율을 적용한다고 해도 정부의 세수 변화는 그리 크지 않을 것이다. 미국 경제의 생산성을 떨어뜨리지 않으면서 이 최고 수준의 보수를 급격히 줄이는 목적이 달성될 것이고, 따라서 낮은 수준의 급여는 상승할 것이기 때문이다.
    • 미국의 빈약한 사회적 국가를 발전시키고 의료와 교육에 더 많은 투자를 하기 위해 절실히 필요한 재원을 확보하기 위해서는 더 낮은 수준의 소득에 대한 세금도 역시 인상되어야 할 것이다.
  • (이하 설명 생략)

21세기 자본/ 21세기를 위한 사회적 국가

  • 이미 언급한 바와 같이 끝없는 불평등의 악순환을 피하고 자본축적의 동학에 대한 통제권을 되찾기 위한 이상적인 정채은 자본에 대한 글로벌 누진세다.
    • 이러한 세금은 또 다른 장점도 갖고 있는데, 부를 노출시켜 민주적인 감시가 이뤄지도록 하는 것이다.
    • 이 자본세는 경제의 투명성과 경쟁의 힘을 유지시키는 한편 사적 이익에 앞서 공공의 이익을 증진할 것이다.

2008년 금융위기와 국가의 귀환

  • 2008년 금융위기는 1929년 대공황 이후 자본주의의 가장 심각한 위기로 묘사된다.
    • 그러나 금융위기는 대공황만큼 파괴적일 정도의 불황을 야기하지는 않았다.
    • 1929년과 1935년 사이 선진국의 생산량은 1/4이나 감소했고, 실업률도 같은 비율로 증가했으며 2차대전이 발발할 때까지도 세계 경제는 대공황으로부터 완전히 회복되지 못했다.
    • 그래서 지금의 위기는 위험이 덜한 ‘대침체(Great Recession)’라는 이름이 붙여졌다.
    • 하지만 분명한 사실은 2013년 세계 경제를 주도하는 경제 선진국들의 총생산은 2007년 수준을 전혀 회복하지 못했고, 정부 재정 상태는 심각한 수준이며, 가까운 장래의 성장 전망도 밝지 않다는 것이다.
    • 끝없는 국가 채무 위기에 휩싸여 있는 유럽은 특히 더 심각하다.
    • 2008년 세계 경제 위기는 21세기의 세계화된 세습자본주의 최초의 위기다. 그리고 마지막 위기도 아닐 것이다.
  • 많은 전문가들은 경제를 관리하는데 진정한 의미의 ‘국가의 귀환’이 부재함을 한탄하고 있다.
    • 그들은 대공황이 실로 끔찍했지만 적어도 조세정책과 예산정책에 있어서 급진적인 변화를 가져온 공은 인정받을 만하다고 지적한다.
    • 루스벨트 대통령은 취임 후 몇 년 내 후버 대통령 시절 25%에 불과했던 초고소득층에 대한 연방소득세의 최고한계세율을 80% 이상으로 끌어 올렸다.
  • 훌륭한 경제 및 사회 정책은 단순히 최고소득자에게 높은 한계세율을 부과하는 것 이상을 요구한다.
    • 이러한 과세는 본질적으로 거의 득이 되지 않는다. 20세기를 위해 고안된 누진적 소득세보다 자본에 대한 누진세가 21세기의 진정한 도전 과제를 해결하는데 좀 더 적절한 조치일 것이다.
  • (이하 정치적인 내용 설명 생략)

20세기 사회적 국가의 성장

  • 사회와 경제에 관한 정부의 역할 변화를 측정할 수 있는 가장 간단한 방법은 국민소득과 비교하여 세금과 과징금의 총액을 살펴보는 것이다.
    • 다음 도표는 부유한 4개 국가들 –미국, 영국, 프랑스, 스위스– 에서 어떤 일이 일어 났는지를 보여주는데, 놀랄만한 유사점과 중요한 차이점이 나타난다.

  • 첫 번째 유사점은 19세기부터 1차대전까지 이들 4개국 모두 세금 부담이 국민소득의 10% 미만이었다는 사실이다.
    • 이것은 당시 국가가 경제 및 사회생활 전반에 거의 개입하지 않았다는 사실을 말해준다. 국민소득의 7-8% 만으로는 정부가 ‘기본적’ 기능만 수행할 수 있을 뿐이다. 치안 유지, 재산권 집행 및 군대 유지를 위한 비용을 지불하고 나면 정부 금고에는 남는 것이 거의 없었다.
    • 당시에도 국가는 학교, 대학, 병원 및 도로와 사회기반시설을 건설하는데 비용을 댔지만, 대부분의 사람은 매우 기초적인 수준의 교육 및 의료 서비스만 받을 수 있었다.
  • 1920-1980년 사이 부유한 국가들이 국민소득 중 사회적 지출에 투입하기로 한 금액의 비중은 상당히 증가했다.
    • 불과 반세기 만에 국민소득에서 세금이 차지하는 비중은 적어도 3-4배 정도 늘어났다.
    • 또한 국민소득에서 세금이 차지하는 비중은 9180년부터 2010년대인 오늘날까지 모든 국가에서 거의 완벽한 안정성을 유지하고 있다.
    • 사실 국가간 차이는 상당하지만 장기간의 전체적 변화가 유사하다는 점은, 특히 지난 30년간 모든 국가에서 관찰된 거의 완벽한 안정화는 놀랄 만한 일이다.
  • (국가의 역할이 커졌다는 내용 생략)

사회적 국가의 형태

  • 19세기를 거쳐 1914년에 이르기까지 정부는 기본적 기능을 수행하는데만 만족했다. 오늘날 이 기능을 담당하는데 드는 지출은 국민소득의 1/10 미만이다.
    • 지금은 증대된 세수 덕분에 정부가 더 폭넓은 사회적 기능을 수행할 수 있으며 나라에 따라 국민소득의 1/4-1/3 정도가 여기에 쓰이고 있다.
    • 이러한 지출은 대략 두 분야로 동일하게 나누어지는데, 절반은 의료와 교육에 쓰이고 나머지는 대체소득과 이전지출을 위해 쓰인다.
  • 교육과 의료 관련 지출은 오늘날 모든 선진국에서 국민소득의 10-15%를 차지한다.
    • 대체소득과 이전지출은 오늘날 대부분의 선진국에서 10-15%를 차지한다. 정부는 세금과 사회보장 기여금으로 많은 돈을 거두어 이를 다시 대체소득의 형태로 가계에 분배한다.
    • 연금은 대체소득과 이전지출 전체에서 가장 큰 부분을 차지한다.
    • 실업보험급여는 연금 지출에 비해 더 적은 비중을 차지하는데 이는 실업 기간이 은퇴 기간보다 짧기 때문이다.
  • (이하 설명 생략)

현대적 재분배: 기본권의 논리

  • 현대적 재분배는 부자로부터 빈자에게 소득이 이전되는 것이 아니라 의료, 교육, 연금을 비롯해 대체로 모두에게 동등한 혜택이 돌아가는 공공서비스와 대체소득을 위한 재원을 조달하는 방식으로 이뤄진다.
  • 비교적 추상적인 관점에서 보자면 이런 기본권에 근거한 접근 방식은 다양한 국가의 정치 및 철학적 전통에서 그 정당성을 찾아볼 수 있다.
  • (이하 관련 논의 설명 생략)

사회적 국가: 해체가 아닌 현대화

  • 정부가 국민소득의 2/3 또는 3/4을 세금으로 걷겠다고 결정하지 못할 이유는 없다. 세금 자체는 좋은 것도 나쁜거솓 아니고 세금을 어떤 방식으로 걷느냐와 어디에, 무엇을 위해 쓰느냐가 중요하기 때문이다.
  • 그럼에도 사회적 국가의 규모를 급격히 키우는 것이 현실적이지도 바람직하지도 않다고 생각할 수 밖에 없는 이유는 다음과 같다.
  • 첫째, 2차대전 이후 30년간 정부의 역할이 급격히 확대된 것은 적어도 유럽 대륙에서는 당시 예외적으로 빠른 경제성장이 이를 대대적으로 촉진하고 가속화 시켰기 때문에 가능한 일이었다.
    • 국민소득이 연간 5%씩 성장할 때 국민에게 성장으로 인해 늘어난 소득 가운데 많은 부분을 사회적 지출에 사용하는데 동의하도록 설득하는 것이 그렇게 어려운 일이 아니었다.
    • (이하 설명 생략)
  • 세다가 성장의 과실이 다양한 필요들 사이에 어떻게 배분되는지와 상관없이, 공공부문이 일단 일정 규모 이상으로 성장하면 심각한 조직 문제와 씨름해야 한다.
    • (이하 설명 생략)

교육 기관들은 사회적 이동성을 촉진시키고 있는가?

  • 모든 나라에서 교육에 공공지출을 하는 주요한 목적은 ‘사회적 이동성’ 즉 계층 이동을 촉진하는데 있다. 공언된 목표는 사회적 신분에 상관없이 모두에게 균등한 교육 기회를 주는 것이다.
    • 3부에서 20세기를 거치면서 교육의 평균 수준이 상당히 높아졌음에도 불구하고 노동소득의 불평등이 감소하지 않았다는 것을 살펴보았다.
    • (이하 설명 생략)
  • 이런 결과들은 한때 미국 사회학계를 지배했던 ‘미국 예외주의’ 신념과 극명하게 대비된다.
    • 개척자 사회였던 19세기 초반 미국에서의 계층 이동은 좀더 활발했다는데에 의심의 여지가 없다. 더구나 미국에서 상속된 부는 유럽보다 그 역할이 미미했다.
    • 그러나 20세기 전체를 놓고 보면, 이용 가능한 데이터는 미국의 사회적 계층 이동성이 유럽보다 낮았고 오늘날에도 여전히 낮다는 것을 보여준다.
    • 이에 대한 한 가지 설명은 미국 최고 엘리트 대학들이 극히 높은 수업료를 요구하고 있다는 사실이다.
    • (이하 설명 생략)
  • 그러나 이런 고등교육 기회의 불평등이 미국만의 문제라 생각한다면 오산이다. 이는 21세기에 세계 도처의 사회적 국가가 직면한 가장 중요한 문제 중 하나다. 이 문제에 대해 지금까지 정말로 만족할 만한 해답을 내놓은 국가는 없다.
    • (이하 설명 생략)
  • 고등교육의 실질적인 기회균등을 달성할 수 있는 쉬운 방법은 없다. 이는 21세기 사회적 국가에서 핵심 사안이 될 것이며, 이상적인 제도는 아직 고안되지 않았다.
  • (이하 설명 생략)

퇴직연금의 미래: 부과식 연금 제도와 저성장

  • 적립식 연금제도와 대조적으로 부과식 연금 시스템에서 투자되는 것은 아무것도 없고 들어오는 기금은 즉시 현재의 은퇴자에게 지출된다.
    • 부과식 연금 시스템은 세대 간 연대의 원리를 기반으로 하는데, 여기서 연금 수익률은 기본적으로 경제성장률과 같은 개념이다.
    • 미래의 은퇴자들에게 지급할 수 있는 기금은 평균 임금이 상승하는만큼 늘어날 것이다.
  • 20세기 중반 부과식 연금 시스템이 도입되었을 때는 사실 선순환적인 일련의 사건이 일어나기 적합한 상황이었다.
    • 인구증가율은 높았고 생산성 상승률은 더 높았다. 유럽 대륙 국가들의 성장률은 5%에 가까웠고, 이 성장률이 곧 부과식 연금 시스템의 수익률이었다.
  • (이하 연금 관련 문제 설명 생략)

빈곤국과 신흥국에서의 사회적 국가

  • 서유럽 국가들의 국민소득 대비 세수는 약 45-50%에서 안정된 것으로 보이는데 비해 미국과 일본의 경우 30-35% 수준에 고정된 것으로 보인다.
    • 1970-1980년까지 전 세계에서 가장 빈곤한 국가들을 보면 세수가 보통 국민소득의 10-15%에 불과하다는 것을 알 수 있다.
  • (이하 설명 생략)
  • 이러한 변화는 염려스럽다. 오늘날 전 세계 모든 선진국에서 재정 확보와 사회적 국가 건설은 현대화와 경제발전 과정의 핵심적인 부분이었기 때문이다.
    • 역사적 증거를 보면 국민소득의 10-15%에 불과한 세수로는 국가가 전통적으로 수행했던 기본적인 책임 이상을 수행하는 것이 불가능함을 알 수 있다.
  • (이하 설명 생략)
  • 오늘날 빈곤국과 신흥국에서는 매우 다른 여러 경향이 나타나고 있다. 중국과 같은 나라들은 조세 체계의 현대화에서 상당히 앞서 있다.
    • 예컨대 중국은 많은 인구를 대상으로 소득세를 징수해 상당한 세수를 거두고 유럽, 미국, 아시아에서 찾아볼 수 있는 것과 비슷한 사회적 국가를 발전시키는 과정에 있다.
    • 인도와 같은 다른 나라들은 낮은 수준의 세수에 기반을 둔 균형 상태에서 벗어나는데 더 많은 어려움을 겪어 왔다.
  • (이하 설명 생략)

21세기 자본/ 21세기 글로벌 부의 불평등

자본수익률의 불평등

  • 많은 경제 모형이 재산의 많고 적음에 상관없이 자본수익률을 동일한 것으로 가정하지만, 이것은 결코 확실하지 않다. 부유한 사람의 평균 수익률이 그렇지 않은 사람의 평균 수익률보다 높은 것은 가능한 일이다.
    • 부유한 사람은 자산관리자와 금융 자문을 고용할 수 있고, 예비 자금을 갖고 있기 때문에 위험을 감수하고 인내하기가 더 쉽기 때문이다.
  • 이런 메커니즘이 자본의 분배에 자동적으로 근본적인 격차를 만들어낸다는 것을 알 수 있다.
    • 글로벌 부의 계층 구조에서 최상위 십분위 혹은 백분위의 재산이 더 낮은 십분위의 재산보다 구조적으로 더 빠르게 성장한다면, 부의 불평등은 무한히 증가하게 될 것이다.
  • 엄밀한 논리를 적용하면 유일하게 ‘자연적’ 대항력은 역시 성장이다.
    • 세계의 경제성장률이 높으면, 대규모 자산의 상대적 성장률은 그리 높지 않게 유지될 것이다.
  • (이하 설명 생략)

세계적인 부자들의 순위 변화

  • (포브스지의 자산 순위 설명 생략)
  • 포브스에 따르면 지구촌의 억만장자는 1987년 140명을 넘겼지만, 2013년에는 1400명 이상으로 10배 증가했다.

  • 1980년대부터 세계의 부는 평균적으로 소득보다 약간 빠르게 증가했고, 거액의 자산들은 평균치 자산보다 훨씬 더 급속하게 증가했다.

억만장자 순위부터 ‘글로벌 자산보고서’까지

  • (국제 금융기관이 발간하는 ‘글로벌 자산보고서’ 설명 생략)
  • 지구상에서 가장 부유한 사람들에 속하는 0.1%는 평균 1000만 유로의 자산을 소유하는데, 이는 1인당 6만 유로인 세계 평균 자산의 200배이며, 전 세계 부의 20%를 차지한다.
    • 가장 부유한 1%는 평균 300만 유로를 소유하며 이는 세계 평균 자산의 약 50배이고, 전 세계 부의 50%를 차지한다.
  • (이하 자료의 불완전성 설명 생략)

부자 순위에 오른 상속자와 기업가

  • 포브스 순위에서 가장 교훈적인 것 중 하나는 특정 한도를 넘으면 거액의 재산은 그것이 무엇이든 모두 극단적으로 높은 성장률을 보여준다는 것이다.
  • (이하 빌게이츠, 스티브잡스나 포브스에 대한 내용 생략)

부의 도덕적 위계

  • 누구도 사회에서 기업가, 발명, 혁신이 중요하다는 것을 부인하지 않는다. 벨 에포크 시대에도 오늘날과 마찬가지로 자동차, 영화, 전기 같은 혁신이 많이 등장했다.
    • 문제는 단순하다. 부의 불평등이 기업가적인 노력 때문이라는 주장은 부의 모든 불평등을 그것이 얼마나 극단적인지와 상관없이 정당화할 수는 없다는 사실이다.
    • r>g는 초기의 부에 따라 달라지는 자본수익률의 불평등과 결합되어 과도하고 지속적인 자본의 집중을 낳을 수 있다.
    • 처음에 부의 불평등이 어떻게 정당화되었건 재산은 모든 이성적인 한계를 넘어 스스로 성장하고 영속할 수 있다.
  • 기업가는 세대를 거치면서 자신의 일생 동안 자본소득자로 변모해가는 경향이 있다. 특히 인간의 기대수명이 늘어나면서 이런 현상은 더 심해진다.
    • 40세애 좋은 아디이어를 가졌던 사람이라도 90세까지 그럴 수는 없을 것이고, 자녀가 좋은 아이디어를 가질 수도 없다.
    • 그러나 재산은 항상 그대로 남아 있으며, 빌 게이츠와 릴리앙 베탕쿠르처럼 20년 만에 재산이 10배가 넘게 늘어나는 경우도 있다.
  • 이것이 세계적으로 대규모 재산에 대해 매년 부과하는 누진세가 필요한 중요하고 타당한 이유다.
    • 그런 세금은 이와 같이 자산이 잠재적으로 폭발적으로 성장하는 과정을 기업의 역동성과 국제적인 개방경제를 보호하면서 민주적으로 통제하는 유일한 방법이다.
  • 조세적 접근은 부의 도덕적 위계에 대한 헛된 논쟁에서 벗어나는 방법이다. 모든 재산은 부분적으로는 정당하지만, 잠재적으로는 과도하다.
    • 자본에 대한 누진제의 이점은 다양한 상황에 유연하고 일관되며 예측 가능한 방식으로 대처하는 방법인 동시에 대규모 재산을 민주적으로 규제할 수 있는 방법이라는 점이다.
  • (부에 대한 도덕적인 논쟁 내용 생략)
  • 대체로 중요한 사실은 자본의 수익에는 흔히 진정한 기업가적 활동, 순수한 행운, 노골적인 도둑질 등의 요소가 복잡하게 결합되어 있다는 것이다.
    • 재산 축적에서의 임의성은 상속재산에서의 임의성보다 훨씬 더 광범위한 현상이다.
    • 자본의 수익은 원래 변동성이 크고 예측 불가능하며 수십 년간 벌어들인 소득에 달하는 자본이득을 쉽게 만들어낼 수 있다.
    • 부의 최상위 계층에서 이런 현상은 더 극단적이다.

대학 기금의 순수한 수익률

  • (대학 기금과 수익률 내용 생략)

자본과 규모의 경제

  • 하버드 대는 현재 자신의 기금을 운용하는데 매년 거의 1억 달러를 사용하는데 이 금액은 일류 자산운용자들에게 지불된다.
    • 그러나 하버드대 기금이 약 300억 달러임을 생각해 보면 1억 달러의 관리 비용은 0.3%에 불과하고, 이만큼 비용을 지불해서 수익률을 5%에서 10%로 높일 수 있으면 매우 바람직한 거래다.
    • 반면 기금이 10억 달러에 그치는 대학이 관리 비용으로 전체 자산의 10%에 달하는 비용을 지불할 수는 없다.
    • 이렇게 높은 수익률은 미국 최고 일류 대학의 번영을 잘 설명해 준다. 그들의 부흥은 졸업생들이 대학에 준 기부금 때문이 아니다.
    • 졸업생의 연간 기부금은 기금 수익의 10-20%로 기금의 수익에 비해 훨씬 적다.
  • (이하 이런 메커니즘에 의해 커지는 불평등 관련 내용 생략)

인플레이션이 자본수익률의 불평등에 미치는 영향은 무엇인가?

  • 0%가 아닌 2% 혹은 5%에 이르는 인플레이션이 자본수익률에 미치는 영향은 무엇인가?
  • 일부 사람들은 인플레이션이 평균 자본수익률을 감소시켰다는 그릇된 생각을 갖고 있는데, 평균 자산 가격은 소비자물가와 동일한 속도로 상승하는 경향이 있기 때문에 이 생각은 옳지 않다.
    • 만약 소비자물가가 연 2% 상승한다면 평균적으로 자산 가격 역시 2% 상승할 것이다. 따라서 어떤 자본이득이나 자본손실도 발생하지 않을 것이며, 자본수익률은 여전히 5%일 것이다.
    • 반면 인플레이션은 개별 시민 간 자본수익률의 분표를 변화시킬 가능성이 있다.
  • 인플레이션이 계속되는 상황에서 은행에 돈을 맡겨 놓고 마냥 앉아 있다면 부에 대해 세금을 물지 않아도 눈 앞에서 그 돈의 가치가 조금씩 줄어들어 마침내 아무것도 남아 있지 않게 될 것이다.
    • 이렇게 보면 인플레이션은 게으른 부자에 대한 세금, 혹은 더 정확히 말해 투자되지 않은 재산에 부과되는 세금이다.
    • 부동산이나 주식 같은 실질자산에 투자하는 것만으로도 인플레이션이라는 세금은 충분히, 완전하게 회피할 수 있다.
    • (사실 자산은 Risk를 동반하기 때문에, 금융위기 같은 일이 벌어지면 손실이 발생할 수 있다. 이런 경우에는 오히려 자산이 아니라 화폐를 들고 있는게 더 나은 상태가 됨)
  • (이하 인플레이션과 자산 수익률에 대한 설명 생략)
  • 요약하자면 인플레이션의 주요한 영향은 평균 자본수익률을 감소시키는 것이 아니라 자본수익을 재분배하는 것이다.
    • 인플레이션의 효과가 복잡하고 다차원적이기는 해도 수많은 증거를 볼때, 인플레이션이 유발하는 재분배 효과는 주로 가난한 사람들에게는 손해가, 부유한 사람들에게는 이익이 된다.
    • 따라서 인플레이션은 일반적으로 바람직한 방향과 반대되는 결과를 가져온다.
  • 인플레이션은 지대를 없애지 못한다. 아마도 그와 반대로 자본 분배의 불평등을 더 심화시킬 뿐이다.

국부펀드의 수익: 자본과 정치

  • (석유를 가진 나라들의 국부 펀드 내용 생략)

국부펀드는 세계를 소유할 것인가?

  • 2013년 국부펀드의 총투자가치는 5조 3000억 달러를 조금 넘었는데 –이중 석유수출국은 3조 2000억이고, 비산유국 펀드는 2조 1000억을 차지한다–, 이는 포브스에서 억만장자로 지목한 무자들의 재산 총계와 정확히 동일한 금액이라는 사실에 주목할 필요가 있다.
    • 달리 말하면 오늘날 억만장자는 세계 총민간자산 가운데 1.5%를 소유하며, 국부펀드가 또 다른 1.5%를 소유한다.
  • (이하 국부펀드와 억맍장자의 투자처 설명 생략)

중국은 세계를 소유할 것인가?

  • 비석유수출국의 국부펀드는 다른 종류의 문제를 제기한다. 어째서 이렇다 할 특정한 천연자원이 없는 나라가 다른 나라를 소유하려 할까?
    • 한 가지 가능성은 물론 유럽 식민주의 시대와 같은 신식민주의적 야심 및 권력에 대한 순수 의지다.
    • 그러나 차이점은 그 당시 유럽 국가들은 그들의 지배를 확실하게 해주는 기술적 우위를 향휴하고 있었다는 사실이다.
    • 중국과 다른 신흥 비산유국들은 분명 빠르게 성장하고 있지만, 일단 그들의 생산성 및 생활수준 면에서 선두 주자를 따라잡는다면 이런 습속한 성장은 끝난다는 것을 시사하는 증거가 많다.
  • 지식과 생산 기술의 확산은 근본적으로 균등화 과정이다. 다시 말해 덜 발전된 국가가 더 발전된 국가를 따라잡게 되면 그들은 선진국보다 더 급속한 성장을 멈추게 된다.
  • (이하 설명 생략)

국제적 격차 확대와 과두적 격차 확대

  • 어쨌든 중국(또는 석유 수출국들의 국부펀드)이 부유한 국가들을 점진적으로 사들임으로써 발생하는 이 국제적 격차 확대의 위협은 한 국가 내의 과두적 형태의 격차 확대(oligarchic divergence) 보다는 발생 가능성이나 위험성이 적어 보인다.
    • 과두적 형태의 격차 확대는 부유한 국가들이 자국의 억만장자에 의해 소유되는 과정, 혹은 더 일반적으로 말하면 중국과 석유 수출국을 포함한 모든 국가가 점점 더 지구촌 부호들의 소유가 되는 과정을 의미한다.
    • 이러한 과정은 이미 상당히 진행되고 있다.
  • 전 세계에서 중국의 소유가 확대되는 현상과 관련하여 현재 확산되고 있는 두려움은 순전히 환상이라는 점을 강조하는 것이 중요하다.
    • 부유한 국가들은 그들이 생각하는 것보다 사실 훨씬 더 부유하다.
    • 오늘날 유럽의 가계가 소유한 부동산과 금융자산의 총가치는 부채를 빼고 대략 70조 유로에 달하는데, 이에 반해 중국의 다양한 국부펀드에 중국런민은행의 외환보유액을 더한 총 자산은 3조 유로로 유럽 가계 자산의 1/20 미만이다.
    • 부유한 국가들은 가난한 국가들에게 넘어갈 위험에 처해있지 않다. 그와 같은 일이 벌어지기 위해서는 가난한 국가들이 한참 더 부유해져야 하는데, 그러려면 수십 년 이상이 걸릴 것이다.
  • (이하 설명 생략)

부유한 국가들은 정말로 가난한가?

  • 우리는 지금 적어도 부유한 국가들이 세계의 나머지 국가들에 비해 훨씬 더 큰 플러스의 순자산 포지션을 향유하던 식민지 시대에 비하면 국제적 포지션이 비교적 균형을 이룬 시대에 살고 있다.
  • 물론 이런 공식적인 자료에서 약간 마이너스 값을 기록한 순자산 포지션은 원칙적으로 세계 나머지 국가들에게 상응하는 플러스 값으로 균형이 맞춰져야 한다.
    • 그러나 실제로는 그렇지 않은데, 즉 세계 여러 국가의 금융 통계자료를 종합하면 가난한 나라들 역시 순자산 포지션이 마이너스 수준이고, 따라서 세계 전체의 순자산 포지션이 상당한 마이너스 상태다.
    • 다시 말해 지구는 화성을 소유한 것이 틀림 없다.
    • 이것은 상당히 오래된 ‘통계적 모순’이지만, 다양한 국제기구에 따르면 이런 상황은 최근에 더 악화되었다. (전 세계 국제수지의 총합은 보통 마이너스로, 국가들에게 유입되는 돈보다 유출되는 돈이 더 많다)

21세기 자본/ 장기적 관점에서 본 능력과 상속

  • 자본의 중요성은 18세기와 크게 다르지 않고, 그 형태만 달라졌다.
    • 자본은 이전에 주로 토지였으나, 현재는 산업자본, 금융자본, 부동산이다.
    • 우리는 100년 전보다는 덜하지만 부의 집중이 여전하다는 것을 살펴 보았다.
  • 전세계적으로 자본의 규모는 똑같이 유지되었다. 그러나 자본이 과거에는 주로 상속되었으나 이제는 스스로 벌어들인 소득 가운데 일부가 저축되어 평생 동안 누적된다는 의미에서 그 심층적인 구조는 극적으로 변화한 듯 하다.
    • 그러한 변화를 설명해 주는 것 중 하나는 기대수명의 연장인데, 이는 사람들이 퇴직 이후를 대비하여 구조적으로 자본축적을 늘리게 했을 수 있다.
    • 그러나 자본의 속성상 일어났다고 추정되는 거대한 전환은 실제로는 생각만큼 극적이지는 않았다.
  • 나는 다음과 같은 결론을 제시할 것이다. 자본수익률이 현저하게 그리고 지속적으로 경제성장률보다 높은 경우, 거의 필연적으로 상속이 저축을 압도한다.

상속액의 장기적인 추이

  • 모든 사회에는 부를 축적하는 두 가지 주요한 방법이 있는데, 바로 노동과 상속이다. 부의 계층 구조에서 상위 1%와 10%에게 각각의 방법이 얼마나 흔하게 나타날까 하는 것이 핵심적인 질문이다.
  • 장기간에 걸친 연간 상속액의 변화를 살펴보는 것에서 시작하면 도움이 될 것이다. 그것은 국민소득에 대비한 비율로 표시되는 1년 동안의 유산의 총가치를 의미한다.
    • 아래 도표는 해당 연도에 벌어들인 총소득과 비교한 과거 자산의 연간 상속액을 보여준다.

  • 도표 11.1은 1820-2010년까지 프랑스의 연간 상속액의 변화 추이인데, 두 가지 사실이 뚜렷히 드러난다.
    • 첫째, 19세기에는 상속액이 매년 소득의 20-25%에 이르렀고, 19세기 말이 되면서 약간 상승 추세를 보였다.
    • (이하 도표 설명 생략)

조세적 추정과 경제적 추정

  • (자료 수집에 대한 설명 생략)

세가지 힘: 상속의 종말이라는 환상

  • 일반적으로 b_{y} 로 표시되는 국민소득 대비 연간 상속액과 증여액의 비율은 세 가지 힘을 곱한 값과 같다.

b_{y} = \mu \times m \times \beta

  • 여기서 \beta 는 자본/소득 비율, m 은 사망률, \mu 는 사망자의 평균 자산과 살아 있는 개인들의 평균 자산의 비율이다.
  • 세 가지 힘을 살펴보자
    • 첫째는 자본/소득 비율 \beta 이다. 이 힘은 자명한데, 만약 어떤 사회에서 상속되는 부의 금액이 크려면 상속될 수 있는 민간자산의 총량도 당연히 커야 할 것이다.
    • 두 번째 힘 사망률 m 도 이와 같은 자명한 메커니즘을 보여준다.다른 모든 조건이 동일하다면 사망률이 높을수록 상속액이 커진다.
    • 세 번째 힘, 사망자의 평균 자산과 살아 있는 개인들의 평균 자산의 비율 \mu 도 마찬가지다.
  • 사망자의 평균 자산이 인구 전체의 평균 자산과 같다고 가정해 보자
    • 그러면 \mu = 1 이고 상속액 b_{y} 는 단순하게 사망률 m 과 자본/소득 비율 \beta 를 곱한 값이 될 것이다.
    • 예컨대 자본/소득 비율이 600%이고 성인 인구의 사망률이 2%라면 연간 상속액은 자동적으로 국민소득의 12%가 될 것이다.
    • 분명 \mu 는 연령별 분포표에 달려 있다. 연령과 함께 부가 증가할 수록 \mu 는 더욱 높아질 것이고 따라서 상속액도 커질 것이다.
  • (이하 설명 생략)

사망률의 장기적 변화 추이

  • 상속의 자연적인 종말을 설명할 수 있는 두 번째 힘은 기대수명의 상승인데, 이는 사망률 m 을 하락시키고 상속받을 때까지 기다리는 시간을 길게 만든다.

  • 그러나 사망률의 변화로 경제의 중요한 요소인 상속자산이 필연적으로 사라지리라는 생각은 심각한 잘못일 것이다.
  • (이하 설명 생략)

부도 인구와 함께 늙는다: \mu \times m 효과

  • 나는 장기적인 관점을 택해 인구 집단의 규모는 안정적이라고 가정할 것이다. 그러면 기대수명의 상승은 상속자산의 중요성에 실제로 어떤 영향을 미칠까?
    • 분명 기대수명의 증가는 사망률의 구조적인 감소를 가져온다.
  • 그러나 사람들이 더 늦게 사망하고 더 늦게 상속받는다는 사실이 상속 자산의 중요성이 약화되었다는 것을 의미할까? 꼭 그렇지는 않다.
    • 부분적으로는 살아 있는 개인들 사이의 증여가 더 중요해져서 이 고령화 효과를 상쇄하기 때문이고, 부분적으로는 고령화 사회에서 부도 나이가 들어서 나중에 상속받는 이들이 더 많은 액수를 상속 받기 때문이다.

  • 구체적으로 말하면, 사망률의 지속적인 하락에도 불구하고 정의상 상속에 의한 연간 이전율을 나타내는 \mu m 의 곱은 지난 수십 년 동안 확실히 상승하기 시작했다.
  • (중간 설명 생략)

  • 요약하자면 고령화 사회에서는 상속이 더 나중에 이루어지지만 부도 함께 늙어가기 때문에 이 효과가 고령화 효과를 상쇄한다.

사망자의 자산과 살아 있는 사람의 자산

  • 사망자의 평균 자산과 살아 있는 사람의 평균 자산의 비율 \mu 의 변화 추이를 더욱 자세히 살펴보면 흥미롭다.
  • (이하 설명 생략)

50대와 80대: 벨 에포크 시대의 연령과 재산

  • 부의 축적 동학과 \mu 를 계산하기 위해 사용된 상세한 데이터를 더 잘 이해하기 위해서는 평균적인 부의 분포를 연령 함수로 검토하는 것이 유용할 것이다.
  • (이하 설명 생략)

  • 그럼에도 부의 집중 현상을 대부분 설명해 주는 지배적인 동학은 r>g라는 부등식의 필연적인 결과이다.
    • 개인이 50세나 60세에 보유한 자산이 상속된 것이든 노동으로 얻은 것이든, 어떤 한도를 넘어서면 자본은 스스로 재생산하고 기하급수적으로 증가하는 경향이 있다.
    • r>g의 논리는 기업가가 언제나 자본소득자로 변하는 경향이 있음을 의미한다.
    • 그런 일이 인생의 뒤늦은 시기에 일어난다 해도, 기대수명이 늘어나면서 그런 현상은 더욱 중요해진다.

전쟁으로 젊음을 되찾은 부

  • 이런 자립적인 메커니즘은 1914-1945년 자본과 그 소유자들이 겪었던 반복된 충격들로 인해 붕괴되고 말았다.
    • 두 차례 세계대전이 가져온 결과는 상당한 수준에서 일어난 부의 회춘이었다.
    • 도표 11.5가 이를 뚜렷이 보여준다.
  • (중간 설명 생략)
  • 이것이 2차대전 이후 수십 년간 상속액이 예외적으로 감소했던 현실에 대한 주된 설명이다.
    • 1950-1960년 재산을 상속받았어야 할 개인들은 그리 많이 상속받지 못했다. 그들의 부모가 이전 수십 년 동안의 충격으로부터 회복할 만한 충분한 시간이 없었고 그들의 이름으로 지닌 재산이 많지 않은 상태에서 죽었기 때문이다.
  • (이하 설명 생략)

21세기에는 상속액이 어떻게 변화될 것인가

  • 최근 수십 년간 나타난 상속액의 급격한 증가를 고려하면 이러한 증가가 계속될 것인지 묻는게 당연하다.
    • 아래 그림은 21세기 가능한 두 가지 변화를 보여준다. 중심 시나리오는 2010-2100년의 연간 성장률을 1.7%, 자본수익률을 3%로 가정한다.
    • 다른 대안적인 시나리오는 2010-2100년 자본수익률이 5%로 상승하는 반면 연간 성장률은 1% 하락한다고 추정한다.

  • 첫 번째 시나리오를 따르면 상속액은 2060-2070까지 많이 증가한 뒤 국민소득의 24-25% 수준에서 안정을 찾는다.
    • 첫 번째의 경우 상속 자산은 부분적으로만 귀환하지만 두 번째 경우는 모조리 귀환할 것이다.
  • (이하 설명 생략)
  • 여기서 본질적인 요점은 주어진 저축 행위의 구조에서 자본수익률이 상승하고 성장률이 하락하면 누적적 과정이 더욱 빨라지고 불평등해진다는 것이다.
  • (이하 설명 생략)

연간 상속액에서 상속자산 총액까지

  • 연간 상속액이 국민소득의 20-25%이던 19세기와 20세기 초에는 상속자산이 민간자산의 거의 전부를 차지했다.
    • 이때 상속자산은 민간자산의 80-90%를 차지했을 뿐만 아니라 증가 추세였다.
    • 그러나 모든 사회, 모든 계층에서 10-20%에 이르는 상당수의 부유한 개인들이 무일푼으로 시작해 일생 동안 재산을 모았다는 점에 주의하자.
    • 그럼에도 상속받은 자산으로 부유해진 경우가 대다수를 차지했다.
    • 국민소득의 20%에 해당되는 연간 상속액을 30년간 더하면 국민소득의 약 6배에 상당하는 거액의 유산과 증여 재산이 축적되는데, 이는 민간자산의 거의 전부를 차지한다.
  • 20세기에 상속액이 격감하면서 이 균형 상태가 극적으로 변화했다. 1970년대 상속액이 최저 수준으로 떨어졌다.
    • 수십 년간 상속과 새로운 자산축적이 소규모로 이뤄진 뒤, 총민간자본에서 상속받은 자본이 차지하는 몫은 40%를 약간 넘는 수준으로 감소했다.
    • 신생국을 제외하면 역사상 처음으로 개인이 살명서 축적한 재산이 전체 부의 거의 60%에 육박하며 대부분을 차지한 것이다.
  • (이하 설명 생략)

  • 저축률은 일반적으로 국민소득의 약 10%다.
    • 19세기 처럼 상속액이 20-25%라면 해마다 유산과 증여로 받는 액수가 신규 저축의 두 배가 넘는다. 신규 저축의 일부가 상속받은 자본에서 얻은 소득이라는 점까지 더하면 상속자산이 저축한 자산을 크게 능가한다.
    • 역으로 1950년대 상속액이 국민소득의 5%, 즉 신규 저축의 절반으로 떨어지면 당연히 저축된 자본이 상속받은 자본보다 우세할 것이다.
    • 핵심은 1980년대 연간 상속액이 저축액을 다시 넘어섰고 2000-2010년에는 저축액을 훨씬 웃돌았다는 사실이다.
    • 오늘날에는 국민소득의 거의 15%를 차지한다.

보트랭의 설교로 돌아가기

  • 1790년대 프랑스에서 태어난 모든 사람을 살펴보면 평생 이용할 수 있었던 총자원에서 상속이 약 24%를 차지했다. 따라서 노동소득의 비율은 약 76%였다.
    • 이는 1차대전 전까지 모든 집단에서 대략적으로 같은 양상이 나타났다.
  • 1870년대 그 이후 태어난 집단에서는 총자원에서 상속이 차지하는 비율이 서서히 감소하기 시작한다.
  • (이하 내용은 앞선 내용을 계속 반복하고 있어서 생략)

라스티냐크의 딜레마

  • 상속자산의 주요 특징 중 하나는 매우 불평등하게 분배되어 있다는 것이다.
    • 아래 도표는 18세기 말과 19세기에 태어난 집단들이 실제로 보트랭이 설명한 끔찍한 딜레마에 직면했다는 것을 보여준다.
    • 어떻게든 상속받은 자산을 손에 넣은 사람들은 공부와 일을 해서 생활해야 하는 사람들보다 훨씬 더 잘살았다.

  • 19세기 가장 부유한 1%의 상속인들이 평생 이용할 수 있었던 자원은 하류층이 이용할 수 있었던 자원의 25-30배였다.
    • 다시 말해 부모나 배우자를 통해 그 정도의 상속을 받을 수 있는 사람은 평생 25-30명의 하인을 부리며 임금을 지불할 수 있었다.
    • 동시에 상위 1의 노동소득자가 이용할 수 있는 자원은 하류층의 10배였는데, 이 수치는 무시할 정도는 아니지만 상위 1%의 상속인들에 비하면 분명 낮았다.
  • (이하 설명 생략)

자본소득자와 경영자에 대한 기초적 계산

  • 요약하자면 사회계층 구조의 최상위층이 상속자본에서 얻는 소득이 노동소득보다 우세한 사회에서는 두 가지 조건이 충족되어야 한다.
  • 먼저 자본총량이 많아야 하고, 그중 상속받은 자본의 비율이 높아야 한다.
    • 일반적으로 자본/소득 비율이 대략 6, 7이 되어야 하고 자본총량 대부분이 상속받은 자본으로 구성되어야 한다.
    • 그런 사회에서 상속자산은 각 집단이 이용할 수 있는 평균 자원의 약 1/4을 차지할 수 있다.
  • 두 번째 조건은 상속자산이 극도로 집중되어야 한다는 것이다.
    • 상속자산이 노동소득과 같은 방식으로 분배되면 보트랭이 말한 세계는 결코 존재할 수 없을 것이다.
    • 노동소득이 상속자산에서 얻는 소득보다 항상 훨씬 더 많을 것이고 (적어도 3배) 노동소득 상위 1%의 소득이 상속자산 소득 상위 1%의 소득을 체계적이고 자동적으로 넘어설 것이기 때문이다.
  • 집중효과가 물량효과를 누르려면 상속계츠으이 상위 1%가 상속받은 부에서 대단히 큰 몫을 차지해야 한다.
    • 상속계층의 상위 1%가 총자산의 50-60%를 소유해 노동소득 상위 1%가 노동소득에서 차지하는 몫 보다 거의 10배가 높았던 18-19세기가 이런 경우였다.
  • 자본소득자와 경영자에 대해 이런 기초적인 계산을 해보면 오늘날 상속 자산 상위 1%와 노동소득 상위 1%가 거의 균형이 맞는 이유를 이해하는데도 도움이 된다.
  • (이하 설명 생략)

고전적 세습사회: 발자크와 오스틴의 세계

  • (소설 속 등장한 당시 사회 불평등 내용 생략)

부의 극심한 불평등: 가난한 사회에서 문명의 한 조건인가?

  • (소설 속 등장한 당시 사회 불평등 내용 생략)

부유한 사회에서의 극단적인 능력주의

  • 임금불평등은 상속에 따른 불평등보다 더 많이 정당화된다는 생각들이 있다.
  • (중간 설명 생략)
  • 현대사회의 불평등을 능력주의로 정당화 하는 모습은 최상위층 뿐만 아니라 하층과 중산층 사이의 더 낮은 계층에서도 뚜렷이 나타난다는 점 역시 강조해야 한다.
  • (이하 설명 생략)

소자본소득자들의 사회

  • 1970년 이후 태어난 집단에게 상속은 평생의 총자원에서 1/4을 차지한다. 총액의 관점에서 보면 상속은 19세기 태어난 인구집단에서만큼의 중요성을 회복했다.
    • 그러나 총액이 과거 수준을 회복했다고 해서 상속이 동일한 사횢거 역할을 수행한다는 의미는 아니다.
    • 부의 현저한 분산과 세습 중산층의 등장은 오늘날 19세기에 비해 아주 많은 재산을 소유한 사람이 훨씬 더 드물다는 것을 암시한다.
  • (이하 소설 속 내용 설명 생략)
  • 불평등에 대한 사회적 표현의 이러한 커다란 변화는 어느 정도는 당연하지만 많은 오해에 근거하고 있다.
    • 첫째, 분명 오늘날에는 18세기보다 교육이 더 중요한 역할을 한다. 그렇다고 사회가 더욱 능력 본위로 바뀌었다고 말할 수는 없다.
    • 사실 교육 불평등은 그저 상향 이동했을 뿐이며, 교육으로 세대 간의 이동성이 높아졌다는 증거도 없다.
  • 상속자산이 사라져 더 공정한 사회로 나아왔다는 믿음이 널리 퍼지고 부분적으로 정당화 되었지만 여기에는 중요한 오해가 있다.
    • 첫째, 상속은 거의 사라지지 않았다. 상속자본의 분배가 변화했을 뿐이므로 이것은 전적으로 다른 문제다.
    • (저자의 글에 특징 중 하나인데, 첫째라고 해놓고 둘째가 안보이는 경우가 대단히 많다. 뒤에 나오는 title 밑에서 둘째가 나오는 경우도 있음)
  • 다시 말해 우리는 소수로 이루어진 아주 부유한 자본소득자의 사회에서 훨씬 더 많은 수의 덜 부유한 자본소득자의 사회로 옮겨왔다. 말하자면 소자본소득자(pefits rentiers)의 사회인 셈이다.
    • (이하 그래프 설명 생략)

자본소득자, 민주주의의 적

  • 둘째, 21세기에 상속자본의 분배가 19세기만큼 불평등해지지 않으리라는 보장이 없다.
    • (관련 설명 생략)
  • (이하 지대에 대한 설명 생략)
  • 경제적, 기술적 합리성은 계몽주의에서 유래했고, 사람들은 흔히 민주주의적 합리성이 경제적, 기술적 합리성에서 마치 마술처럼 저절로 파생될 것이라고 가정한다.
    • 그러나 진정한 민주주의와 사회적 정의를 이루려면 시장의 제도, 단지 의회나 그 외의 형식적인 민주주의적 제도 뿐만 아니라 민주주의와 사회적의 스스로의 특정한 제도들이 필요하다.
  • 이 책에서 계속 강조했던, 격차를 확대하는 근본적인 힘은 r>g라는 부등식으로 요약될 수 있는데, 이것은 시장의 불완정성과는 아무 관계가 없으며 시장이 더욱 자유로워지고 경쟁이 강화되어도 사라지지 않을 것이다.
    • 무제한적인 경쟁이 상속을 없애고 능력이 더욱 중시되는 사회를 향해 움직일 것이라는 생각은 위험한 착각이다.
    • 보통 선거권이 생기고 투표시 재산에 대한 자격이 없어지면서 부자들의 합법적인 정치적 지배는 끝났다.
    • 그러나 이것이 자본소득자 사회를 낳을 수 있는 경제적 힘을 없애지는 않았다.

상속자산의 귀환: 유럽의 현상인가 아니면 세계적 현상인가?

  • (프랑스의 사례를 다른 국가에 적용할 수 있는가에 대한 설명 생략. 나라별로 조건이 다르고, 자료가 부족한 경우도 있다)