페이지

2022년 7월 17일 일요일

2.2 신경망을 위한 데이터 표현

 이전 예제에서 텐서(tensor)라 부르는 다차원 넘파이 배열에 데이터를 저장하는 것부터 시작했습니다. 최근의 모든 머신러닝 시스템은 일반적으로 턴서를 기본 데이터 구조로 사용합니다. 텐서는 머신러닝의 기본 구성 요소입니다. 구글의 텐서릎로 이름을 여기에서 따왔습니다. 그럼 텐서는 무엇일까요?

핵심적으로 텐서는 데이터를 위한 컨테이너(container)입니다. 거의 항상 수치형 데이터를 다루므로 숫자를 위한 컨테이너입니다. 아마 2D 텐서인 행렬에 대해 이미 알고 있을 것입니다. 텐서는 임의의 차원 개수를 가지는 행렬의 일반화된 모습니다(텐서에서는 차워(dimension)을 종종 축(axis)이라고 부릅니다).


2.1 신경망과의 첫 만남

 케라스 파이썬 라이브러리를 사용하여 손글시 숫자 분류를 학습하는 구체적인 신경망 예제를 살펴보겠습니다. 케라스나 비슷한 라이브러리를 사용한 경험이 없다면 당장은 이 첫 번째 예제를 모두 이행하지 못할 것입니다. 어쩌면 아직 케라스를 설치하지 않았을지도 모릅니다. 괜찮습니다. 다음 장에서 이 예제를 하나하나 자세히 설명합니다. 코드가 좀 이상하거나 요출처럼 보이더라도 너무 걱저앟지 마세요. 일단 시작해 보겠습니다.

지금 풀려는 문제는 흑백 손글씨 숫자 이미지(28*28픽셀)ㄹ르 10개의 범주(0에서 9까지)로 분류하는 것입니다. 머신 러닝 커뮤니티에서 고전으로 취급받는 데이터셋인 MNIST를 사용하겠습니다. 이 데이터셋은 머신 러닝의 역사만큼 오래되었고 많은 연구에 사용되었습니다. 이 데이터셋은 1980년대 미국 국립표준기술연구소(National Institue of Standards and Technology, NIST)에서 수집한 6만 개의 훈련 이미지와 1만 개의 테스트 이미지로 구성되어 있습니다.  MNIST 문제를 알고리즘의 제대로 작동하는지 확인하기 위한 딥러닝 계의 "hello world"라고 생각해도 됩니다. 머신러닝 기술자가 되기까지 연구 논문이나 블로그 포스트 등에서 MNIST를 보고 또 보게 될 것입니다.

클래스와 레이블에 관한 노트

머신러닝에서 분류 문제의 범주(category)를 클래스(class)라고 합니다. 데이터 포인트는 샘플(sample)이라고 합니다. 특정 샘플의 클래스는 레이블(label)이라고 합니다.

이 예제를 당장 실습할 필요는 없습니다. 하고 싶다면 3.3절에 나와 있는 대로 케라스 환경을 먼저 설정해 주어야 합니다.

MNIST데이터셋은 넘파이(Numpy) 배열 형태로 케라스에 이미 포함되어 있습니다.

from keras.dataset 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_babels

array([5,0,4,...,5,6,8], dtype=uint8)

다음은 테스트 데이터입니다.

>>> 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_image에 대한 예측을 네트워크에 요청합니다. 그리고 이 예측이 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(layer.Dense(10, activation='softmax'))

신경만의 핵심 구성 요소는 일종의 데이터 처리 필터라고 생각할 수 있는 층(layer)입니다. 어떤 데이터가 들어가면 더 유용한 형태로 출력됩니다. 조금 더 구체적으로 층은 주어진 문제에 더 의미있는 표현(representation)을 입력된 데이터로부터 추출합니다. 대부분의 딥러닝은 간단한 층을 연결하여 구성되어 있고, 점진적으로 데이터를 정제하는 현태를 띠고 있습니다. 딥러닝 모델은 데이터 정제 필터(층)가 연속되어 있는 데이터 프로세싱을 위한 여과기와 같습니다.

이 예에서는 조밀하게 연결된(또는 완전 연결(fully connected)된) 신경망 층인 Dense층 2개가 연속되어 있습니다. 두 번째(즉 마지막) 층은 10개의 확률 점수가 들어 있는 배열(모두 더하면 1입니다)을 반환하는 소프트맥스(softmax)층입니다. 각 점수는 현재 숫자 이미지가 10개의 숫자 클래스 중 하나에 속할 확률입니다.

신경망이 훈련 준비를 마치기 위해서 컴파일 단계에 포함될 세 가지가 더 필요합니다.

- 손실 함수(loss function): 훈련 데이터에서 신경망의 성능을 측정하는 방법으로 네트워크가 옳은 방향으로 학습될 수 있도록 도와줍니다.

- 옵티마이저(optimizer): 입력된 데이터와 손실 함수를 기반으로 네트워크를 업데이트하는 매커니즘입니다.

- 훈련과 테스트 과정을 모니터링할 지표: 여기에서는 정화도(정확히 분류된 이미지의 비율)만 고려하겠습니다.

손실 함수와 옵티마이저의 정확한 목적은 이어지는 2개의 장에서 자세히 설명합니다.

network.compile(optimizer='rmsprop',

                        loss='categorical_crossentropy',

                        metrics=['accuracy'])

훈련을 시작하기 전에 데이터를 네트워크에 맞는 크기로 바꾸고 모든 값을 0과 1 사이로 스케일을 조정합니다. 예를 들어 앞서 우리의 훈련 이미지는 [0, 255] 사이의 값인 unit8 타입의 (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_iomages = test_images.astype('float32') / 255

또 레이블을 범주형으로 인코딩해야 합니다. 이 단계는 3장에서 자세히 설명합니다.

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장에서 자세하게 농의 합니다.

이것으로 첫 번째 예제가 마루리되었습니다. 20줄 미만의 파이썬 코드로 손글씨 숫자를 분류하는 신경망을 만들고 훈련시켰습니다. 다음 장에서 여기서 보았던 코드 하나하나를 상세하게 설명하고 이들이 의미하는 바를 명확하게 알아보겠스ㅜㅂ니다. 이제 텐서, 신경망에 주입하는 데이터의 저장형태, 층을 만들어 주는 텐서 연산, 신경망을 훈련 샘플로부터 학스비키는 경사 하강법에 대해 알아봅니다.



2022년 7월 16일 토요일

2. 시작하기 전에: 신경망의 후삭적 구성요소

 딥러닝을 이해라려면 여러가지 수학 개념과 친숙해져야 합니다. 텐서, 텐서 연산, 미분, 경사 하강법(gradient descent)등 입니다. 이 장의 목표는 너무 기술적으로 깊게 들어가지 앟고 이 개념들을 이해하는 것입니다. 특히 수학에 익숙하지 않은 사람들이 어려워할 수 있고 설명을 위해 꼭 필요하지도 않기 때문에 수학 기호는 사용하지 않습니다.

텐서와 경사 하강법을 설명하기 위해 실제 신경망 예제로 이 장을 시작하겠습니다. 그리고 새로운 개념을 하나씩 소개합니다. 이 개념들은 이어진 장에 포함된 예제들을 이해하려면 꼭 알고 넘어가야 합니다.


1.3.6 지속될까?

 회사가 투자를 하고 연구자들이 모이는 것이 당연한 어떤 특별한 점이 심층 신경망에 있는 것일까요? 아니면 딥러닝은 그저 유행이라 사라지게 될까요? 20년 후에도 심층 신경망을 사용하고 있을 까요?

딥러닝의 현재 상태를 AI 혁명이라고 정의할 수 있는 몇 가지 특징이 있습니다. 지금부터 20년후에는 신경망을 사용하지 않을지도 모르지만, 딥러닝과 딥러닝의 핵심 개념에서 직접 파생된 무엇인가를 사용할 것입니다. 이 중요한 특징은 크게 세가지 범주로 나눌 수 있습니다.

- 단순함: 딥러닝은 특성 공학이 필요하지 않아 복잡하고 불안정한 많은 엔지니어링 과정을 엔드-투-엔드로 훈련시킬 수 있는 모델로 바꾸어 줍니다. 이 모델은 일반적으로 5-6개의 텐서 연산만을 사용하여 만들 수 있습니다.

- 확장성: 딥러닝은 GPU또는 TPU에서 쉽게 병렬화할 수 있기 때문에 무어의 법칙 혜택을 크게 볼 수 있습니다. 또 딥러닝 모델은 작은 배치(batch) 데이터에서 반복적으로 훈련되기 때문에 어떤 크기의 데이터셋에서도 훈련될 수 있습니다(유일한 병목은 가능한 병렬 계산능력이지만 무어의 법칙 덕택에 빠르게 그 장벽이 사라지고 있습니다).

- 다용도와 재사용성: 이전의 많은 머신 러닝 방법과는 다르게 딥러닝 모델은 처음부터 다시 시작하지 않고 추가되는 데이터로도 훈련할 수 있습니다. 대규모 제품에 상요되는 모델에는 아주 중요한 기능인 연속적인 온라인 학습(online learning)을 가능하게 합니다. 더불어 훈련된 딥러님 모델은 다른 용도로 쓰일 수 있어 재사용이 가능합니다. 옐르 들어 이미지 분류를 위해 훈련된 딥러닝 모델을 비디오 처리 작업 과정에 투입할 수 잇습니다. 더 복잡하고 강력한 모델을 만들기 위해 이전의 작업을 재활용할 수 있습니다. 또 아주 작은 데이터셋에도 딥러닝 모델을 적용할 수 있습니다.

딥러닝의 스포트라이트를 받는지 겨우 몇 년바에 되지 않았고 할 수 있는 모든 영역에 접목해 보지 못했습니다. 매달 새로운 사례ㅒ와 이전의 제약을 허무는 향상된 기술이 등장합니다. 과학 혁명뒤에는  일반적으로 시그모이드(sigmoid)고선 형태로 진행됩니다. 초창기에는 매우 빠르게 진행되고 연구자들이 험난한 난관에 부짖히면서 점차 안정되어 나중에는 조금씩 향사오딥니다. 2017년의 딥러닝은 시그모이드의 처음 절반 안쪽에 있는것 같습니다. 앞으로 몇 년 동앙 이 혁명은 훨씬 더 빠르게 진행될 것입니다.


1.3.5 딥러닝의 대중화

 딥러닝에 새로운 사람들이 참여할 수 있도록 만드는 핵심 요소 중 하나는 이 분야에서 상요한느 도구들의 대중화입니다. 초창기에 딥러닝을 하려면 흔치 않은 C++와 CUDA의 전문가가 되어야 했습니다. 요즘에는 기본 파이썬 스크립트 기술만 있으면 고수준의 딥러닝을 연구한느데 충분합니다. 대부분 씨아노(Theano)와 텐서플로(TensorFlow)가 개발된 덕분이었습니다. 심볼릭 텐서 조작 프레임워크인 이 두 프레임워크는 파이썬과 자동 미분을 지원하여 새로운 모델을 아주 간단하게 구현할 수 있게 만들었습니다. 그리고 레고(LEGO)블럭을 만들 듯 딥러닝 모델을 쉽게 만들 수 있는 케라스 같은 사용자 편의 도구들이 증장했습니다. 케라스가 2015년에 처음 공개된 이후 이 분야의 많은 스타트업과 학생, 연구자들에게 새로운 딥러닝의 주력 솔류션으로 금방 자리 잡았습니다.

1.3.4 새로운 투자의 바람

 딥러닝이 2012-2013년에 컴퓨터 비전과 지각에 관련된 모든 문제에서 최고의 성능을 내자 업계의 리더들이 주목하기 시작했습니다. 과거 AI의 역사에서 보얐던 것을 뛰어넘는 투자가 서서히 이루어지고 있습니다.

딥러닝의 주목을 받기 직전인 2011년에 전체 벤처 캐피탈이 AI 에 투자한 금액은 1,900만 달러였고 대부분은 얕은 학습 방식의 머신 러닝 애플리케이션이었습니다. 2014년에는 믿기 힘들지만 3억 9,400만 달라로 늘었습니다. 이 기간에 딥러닝의 인기에 힘입어 수십 개의 스타트업을 런칭했습니다. 한펴 구글, 페이스북, 바이두, 마이크로소프트 같은 테크 공룡들은 벤처 캐피탈의 투자를 무색하게 만들 정도로 많은 금액을 내부 연구 부문에 투자했으며, 그 중 아주 일부만 알려져 있습니다. 2013년 구글은 5억 달러에 딥러닝 스타트업인 딥마인드(DeepMind)를 인수했습니다. AI역사상 가장 큰 금액의 인수였습니다. 2014년에 바이두는 실리콘 밸리에 3억 달러를 투자하여 딥러닝 연구센터를 설립했습니다. 2016년에는 인테이 딥러닝 하드웨어 스타드업인 너바나(Nervana)시스템를 4억 달러에 인수 했습니다.

머신 러닝(특히 딥러닝)은 테크 공룡들의 핵심 상품 전략이 되었습니다. 2015년 후반에 구글의 CEO 선다 피차이(Sundar Pichai)는 "머신 러닝은 우리가 일을 하는 모든 방법을 다시 생각하게 만드는 중요하고 혁신적인 도구입니다. 우리는 머신 러닝을 검색, 광고, 유튜브, 그글 플레이 같은 전체 제품에 신중하게 적용하고 있습니다. 아직은 초기이지만 체계적으로 모든 분야에 머신러닝을 적용할 것입니다." 라고 말했ㅅ브니다.

이런 투자의 물결로 인해 딥러닝 분야에서 일하고 있는 사람들의 수가 지난 5년간 몇 백 명에서 몇 만 명으로 늘어났고 연구는 엄창난 속도로 진전되고 있습니다. 현재는 이런 트렌드가 느려질 어떤 징후도 없습니다.

1.3.3 알고리즘

 하드웨어 데이터에 이어 2000년대 후반까지는 매우 깊은 심층 신경망을 훈련시킬 수 있는 안정적인 방법을 찾지 못했습니다. 이런 이유로 하나 또는 2개의 층만 사용하는 매우 얕은 신경만만 가능했습니다. SVM과 랜덤 포레스트 처럼 잘 훈련된 얕은 학습 방법에 비해 크게 빛을 보지 못했습니다. 깊게 쌓은 층을 통과해서 그래디언트(gradient)를 전파하는 것이 가장 문제였습니다. 신경망을 훈련하기 위한 피드백 신호가 층이 늘어남에 따라 희미해지기 때문입니다.

2009-2010년경에 몇 가지 간단하지만 중요한 알고리즘이 개선되면서 그래디언트를 더 잘 전파되게 만들어 주었고 상황이 바뀌었습니다.

- 신경망이 층에 더 잘 맞는 활성화 함수(activation function)

- 층별 사전 훈려(pretraining)을 불필요하게 만든 가중치 초기화(weight initialization)방법

- RMSProp과 Adam같은 더 좋은 최적화 방법

이런 기술의 향상으로 10개 이상의 층을 가진 모델을 훈련시킬 수 있게 되었을 때 비로소 딥러닝이 빛을 발하기 시작했습니다.

2014-2016년 사이에 그래디언트를 더욱 잘 전파할 수 있는 배치 정규화(batch normalization), 전차 연결(residual connection), 깊이별 분리 합성곱(depthwise separable convolution)같은 고급 기술들이 개발되었습니다. 요즘에는 층의 깊이가 수천 개인 모델을 처음부터 훈련시킬 수 있습니다.