다운로드
작성자: admin 작성일시: 2019-10-18 11:29:42 조회수: 996 다운로드: 50
카테고리: 머신 러닝 태그목록:

3.6 텐서플로 데이터셋 API

텐서플로는 tf.data 서브패키지에서 데이터 입력 파이프라인을 위한 데이터셋 API를 제공한다. 데이터 입력 파이프라인은 모델에 공급되는 데이터에 대한 모든 작업을 담당한다. 예를 들어 이미지 데이터의 경우 분산 파일시스템으로부터 이미지를 모으는 작업, 이미지에 노이즈를 주거나 변형하는 작업, 배치 학습을 위해 무작위로 데이터를 선택하여 배치데이터를 만드는 작업을 할 수 있다. 텍스트 데이터의 경우 원문을 토큰화하거나 임베팅하는 작업, 길이가 다른 데이터를 패딩하여 합치는 작업등을 한다.

데이터셋 API는 최종적으로 tf.data.Dataset 추상 클래스에서 상속된 여러가지 클래스 객체를 만든다.

데이터셋 API를 사용하려면 세 가지 단계를 거친다.

  1. 데이터셋 생성: from_tensor_slices(), from_generator() 클래스 메서드 또는 tf.data.TFRecordDataset 클래스를 사용하여 메모리나 파일에 있는 데이터를 데이터 소스로 만든다.
  2. 데이터셋 변형: map(), filter(), batch() 등의 메서드를 사용하여 데이터 소스를 변형한다.
  3. for 반복문에서 데이터셋 사용

데이터셋 생성

In [1]:
import tensorflow as tf 
tf.__version__
Out:
'2.0.0'

from_tensor_slices 클래스 메서드를 사용하면 리스트, 넘파이, 텐서플로 자료형에서 데이터셋을 만들 수 있다.

In [2]:
dataset1 = tf.data.Dataset.from_tensor_slices([8, 3, 0, 8, 2, 1])
dataset1
Out:

생성된 데이터셋을 사용하면 for 문에서 반복작업을 할 수 있다.

In [3]:
for elem in dataset1:
  print(elem.numpy())
8
3
0
8
2
1

데이터셋의 원소들은 모두 동일한 자료구조를 가지고 있어야 한다. 데이터셋의 element_spec 속성은 원소의 자료구조를 반환한다.

In [4]:
dataset1.element_spec
Out:
TensorSpec(shape=(), dtype=tf.int32, name=None)

데이터셋의 원소는 단일 텐서가 될 수도 있고 튜플이나 리스트가 될 수도 있다. 예를 들어 4x10 행렬로부터 만들어진 데이터셋 소스는 길이가 10인 1차원 텐서를 4개 출력한다.

In [5]:
dataset2 = tf.data.Dataset.from_tensor_slices(
    tf.random.uniform([4, 10], minval=1, maxval=10, dtype=tf.int32))
In [6]:
for elem in dataset2:
  print(elem.numpy())
[8 6 8 4 6 2 4 5 6 1]
[8 2 4 5 2 9 8 5 2 8]
[3 7 3 5 9 8 3 5 5 4]
[8 4 1 7 2 2 3 5 9 6]

예를 들어 (4벡터, 4x5 행렬)인 튜플로부터 만들어진 데이터셋 소스는 (스칼라, 길이가 5인 1차원 텐서) 데이터 튜플을 4개 출력한다.

In [7]:
dataset3 = tf.data.Dataset.from_tensor_slices(
   (tf.random.uniform([4]),
    tf.random.uniform([4, 10], maxval=10, dtype=tf.int32)))

dataset3.element_spec
Out:
(TensorSpec(shape=(), dtype=tf.float32, name=None),
 TensorSpec(shape=(10,), dtype=tf.int32, name=None))
In [8]:
for elem in dataset3:
  print(elem)
(, )
(, )
(, )
(, )

zip 클래스 메서드로 이미 만들어진 데이터셋을 조합하여 다른 데이터셋을 만들수도 있다.

In [9]:
dataset4 = tf.data.Dataset.zip((dataset2, dataset3))

dataset4.element_spec
Out:
(TensorSpec(shape=(10,), dtype=tf.int32, name=None),
 (TensorSpec(shape=(), dtype=tf.float32, name=None),
  TensorSpec(shape=(10,), dtype=tf.int32, name=None)))

from_generator 클래스 메서드를 사용하면 생성자에서 데이터셋을 만들 수도 있다. 이 때는 output_types, output_shapes 인수로 출력 자료형과 크기를 지정해주어야 한다.

In [10]:
def count(stop):
  i = 0
  while i < stop:
    yield i
    i += 1

dataset5 = tf.data.Dataset.from_generator(
    count, args=[4], 
    output_types=tf.int32, output_shapes = ())
dataset5
Out:
In [11]:
for elem in dataset5:
  print(elem.numpy())
0
1
2
3

데이터셋 변형

  • repeat()
  • take()
  • skip()
  • batch()
  • shuffle()
  • map()
  • filter()
  • concatenate()

repeat() 메서드는 데이터를 반복시킨다. 숫자를 지정하지 않으면 계속 반복한다.

In [12]:
for elem in dataset5.repeat(2):
  print(elem.numpy())
0
1
2
3
0
1
2
3

take() 메서드는 전체 데이터 중 지정한 개수의 일부 데이터로만 출력을 제한한다.

In [13]:
for elem in dataset5.take(3):
  print(elem.numpy())
0
1
2

skip() 메서드는 일부 데이터를 건너뛰고 다음 데이터를 출력한다.

In [14]:
for elem in dataset5.skip(2).take(3):
  print(elem.numpy())
2
3

batch() 메서드는 지정한 개수의 데이터를 묶어서 출력한다.

In [15]:
for elem in dataset5.batch(5):
  print(elem.numpy())
[0 1 2 3]

shuffle(buffer_size) 메서드는 buffer_size로 지정한 개수의 데이터를 무작위로 섞어서 출력한다.

In [16]:
for elem in dataset5.repeat().shuffle(buffer_size=3).take(3):
  print(elem.numpy())
0
2
0

concatenate() 메서드는 두 데이터셋을 연결한다.

In [17]:
dataset6 = dataset1.concatenate(dataset2)
for elem in dataset6:
  print(elem.numpy())
8
3
0
8
2
1
[8 6 8 4 6 2 4 5 6 1]
[8 2 4 5 2 9 8 5 2 8]
[3 7 3 5 9 8 3 5 5 4]
[8 4 1 7 2 2 3 5 9 6]

map() 메서드는 함수로 지정한 변환을 한 데이터를 출력한다.

In [18]:
f = lambda x: 2 * x
for elem in dataset5.map(f):
  print(elem.numpy())
0
2
4
6

filter() 메서드는 함수로 지정한 조건을 만족한 데이터만 출력한다.

In [19]:
f = lambda x: x % 2 == 0
for elem in dataset5.filter(f):
  print(elem.numpy())
0
2
In [ ]:
 
In [ ]:
 

질문/덧글

아직 질문이나 덧글이 없습니다. 첫번째 글을 남겨주세요!