신경망과의 첫 만남
- 딥러닝의 “hello world”인 MNIST 데이터셋을 이용해서 신경망 예제를 살펴보겠다.
- 실제 실습은 3장에서 할 것이고, 여기서는 개념만 살펴본다.
- 머신 러닝에서 분류 문제의 범주(category)를 클래스(class)라고 한다. 데이터 포인트는 샘플(sample)이라고 한다. 특정 샘플의 클래스는 레이블(label)이라고 한다.
https://drive.google.com/uc?id=1UyDgI4HfpwCOeGOM9t_W5pWFgEjpicsF
- 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