페이지

2022년 7월 17일 일요일

2.2.7 배치 데이터

 일반적으로 딥러닝에서 사용하는 모든 데이터 텐서의 첫 번째 축(인텍스가 0부터 시작하므로 0번째 축)은 샘플 축(sample axis)입니다(이따금 샘플 차원(sample dimension)이라고 부릅니다. 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)이라고 부릅니다. 케라스나 다른 딥러닝 라이브러리를 사용할 때 이런 용어를 자주 만날 것입니다.

2.2.6 넘파이로 텐서 조작하기

 이전 예제에서 train_images[i] 같은 형식으로 첫 번째 축을 따라 특정 숫자를 선택했습니다. 배열에 있는 특정 원소들을 선탟하는 것을 슬라이싱(slicing)이라고 합니다. 넘파이 배열에서 할 수 있는 슬라이싱 연산을 살펴보겠습니다.

다음 예는 11번째에서 101번째까지(101번째는 포함하지 않고) 숫자를 선택하여(90, 28, 28) 크기의 배열을 만듭니다.

>>> my_slice = train_images[10:100]

>>> print(myu_slice.shape)

(90, 28, 28)

동일하지만 조금 더 자세한 표기법은 각 배열의 축을 따라 슬라이싱의 시작 인덱스와 마지막 인텍스를 지정하는 것입니다. :(클론)은 전체 인텍스를 선택합니다.

>>> my_slice = train_images[10:100, :, :] .....이전 예와 동일합니다.

>>> my_slice.shape

(90, 28, 28)

>>> my_slice = train_images[10:1000, 0:28, 0:28] .... 역시 이전과 동일합니다.

>>>  my_slice.shape

(90, 28, 28)

일반적으로 각 배열의 축을 따라 어떤 인덱스 사이도 선택할 수 있습니다. 옐르 들어 이미지의 오른쪽 아래 14 * 14 픽셀을 선택하려면 다음과 같이 합니다.

my_slice = train_images[:, 14:, 14:]
음수 인텍스도 사용할 수 있습니다. 파이씬 리스트의 음수 인텍스와 마찬가지로 현재 축의 끈에서 상대적인 위칙를 나타냅니다. 정중앙에 위치한 14 * 14 픽셀 조각을 이미지에서 잘라 내려면 다음과 같이 합니다.

my_slice = train_images[:, 7:-7, 7:-7]

2.2.5 핵심 속성

 텐서는 3개의 핵심 속성으로 정의됩니다.

- 축의 개수(랭크): 예를 들어 3D 텐서에는 3개의 축이 있고, 행렬에는 2개의 축이 있습니다. 넘파이 라이브러리에서는 ndim속성에 저장되어 있습니다.

- 크기(shape): 텐서의 각 축을 따라 얼마나 많은 차원이 있는지를 나타낸 파이썬의 튜플(tuple)입니다. 예를 들어 앞에 나온 행렬의 크기는 (3, 5)이고 3D 텐서의 크기는 (3, 3, 5)입니다. 벡터의 크기는 (5,) 처럼 1개의 원소로 이루어진 튜플입니다. 배열 스칼라는 ()처럼 크기가 없습니다.

- 데이터 타입(넘파이에서는 dtype에 저장됩니다): 텐서에  포함된 데이터의 타입입니다. 예를 들어 텐서의 타입은 float32, unit8, float64 등이 될 수 있습니다. 드물게 char타입을 사용합니다. 텐서는 사전에 할당되어 연속된 메모리에 저장되어야 하므로 넘파이 배열은(그리고 대부분 다른 라이브러리는) 가변 길이의 문자열을 지원하지 않습니다.

이를 구체적으로 확인 해 보기 위해서 MNIST예제에서 사용했던 데이터를 다시 들여다 봅시다. 먼저 MNIST데이터셋을 불러들입니다.

from keras.datasets import mnist

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

 그다음 train_images 배열의 ndim 속성으로 축의 개수를 확인 합니다.

>>> print(train_images.ndim)

3

다음은 배열의 크기입니다.

>>> print(train_images.shape)

(60000, 28, 28)

dtype 속성으로 데이터 타입을 확인합니다.

>>> print(train_images.dtype)

unit8

이 배열은 8비트 정수형 3D 텐서입니다. 좀 더 정확하게는 28 * 28 크기의 정수 행렬 6만 개가 있는 배열입니다. 각 행렬은 하나의 흑백 이미지이고, 행렬의 각 원소는 0에서 255 사이의 값을 가집니다.

이 3D 텐서에서 다섯 번째 샘플을 (파이썬의 표준 과학 라이브러리 중 하나인) 맷플롯립( Matplotlib) 라이브러리를 사용해서 확인해 봅시다

 digit = train_image[4]

import matplotlib.pyplot as plt

plt.imshow(digit, cmap=plt.cm.binary)

plt.show()


2.2.4 3D 텐서와 고차원 텐서

 이런 행렬들을 하나의 새로운 배열로 합치면 숫자가 채워진 직육면체 형태로 해석할 수 있는 3D텐서가 만들어집니다. 넘파이에서 3D 텐서를 나타내면 다음과 같습니다.

>>> x = np.array([[[5, 78,2, 34, 0],

                        [6, 79, 3, 35, 1],

                        [7, 80, 4, 36, 2]],

                        [[5,78, 2, 34, 0],

                        [6, 79, 3, 35, 1],

                        [7, 80, 4, 36, 2]],

                        [[5, 78, 2, 34, 0],

                        [6, 79, 3, 35, 1],

                        [7, 80, 4, 36, 2]]])

>>> x.ndim

3

3D 텐서들을 하나의 배열로 합치면 4D텐서를 만드는 식으로 이어집니다. 딥러닝에서는 보통 0D에서 4D까지의 텐서를 다룹니다. 동영상 데이터를 다룰 경우에는 5D 텐서까지 가기도 합니다.


2.2.3 행렬(2D 텐서)

 벸터의 배열의 행렬(matrix) 또는 2D 텐서입니다. 행령에서는 2개의 축이 있습니다(보통 행( row)과 열(column)이라고 부릅니다). 행렬은 숫자가 채워진 사각 격자라고 생각할 수 있습니다. 넘파이에서 행렬을 나타내면 다음과 같습니다.

>>> x = np.array([[5,78, 2, 34, 0],

                        [6, 79, 3, 35, 1],

                        [7, 80, 4, 36, 2]])

>>> x.dim

2

첫 번째 축에 놓여 있는 원소를 행이라 부르고, 두번째 축에 놓여 있는 워소를 열이라 부릅니다. 앞의 예에서는 x의 첫 번째 행은[5, 78, 2, 34, 0] 이고, 첫 번째 열은 [5, 6, 7] 입니다.


2.2.2 벡터(1D 텐서)

 숫자의 배열을 벡터(vector) 또는 1D 텐서라고 부릅니다. 1D 텐서는 딱 하나의 축을 가집니다. 넘파이에서 벡터를 나타내면 다음과 같습니다.

>>> x = np.array([12, 3, 6, 14, 7])

>>> x

array([12, 3, 6, 14, 7])

>>> x.ndim

1

이 벡터는 5개의 원소를 가지고 있으므로 5차원 벡터라고 부릅니다. 5D벡터와 5D 텐서를 혼동하지 마세요! 5D 벡터는 하나의 축을 따라 5개의 차원을 가진 것이고  5D 텐서는 5개의 축을 가진 것입니다(텐서의 각 축을 따라 여러 개의 차원을 가진 벡터가 놓일 수 있습니다). 차원수(dimensionality)는 특정 축을 따라 놓인 원소의 개수(5D 벡터와 같은 경우)이거나 텐서의 축 개수(5D 텐서와 같은 경우)를 의미하므로 가끔 혼동하기 쉽습니다. 후자의 경우 랭크 5인 텐서라고 말하는 것이 기술적으로 좀 더 정확합니다(텐서의 랭크가 축의 개수입니다). 그럼에도 5D 텐서처럼 모호한 표기가 통용됩니다.


2.2.1 스칼라(0D 텐서)

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

>>> import numpy as np

>>> x = np.array(12)

>>> x

array(12)

>>> x.ndim

0