Google I / O가 5 월 18 ~ 20 일에 돌아옵니다! 공간을 예약하고 일정을 짜세요 지금 등록하세요

성능 팁

이 문서는 TFDS 관련 성능 팁을 제공합니다. TFDS이 같은 데이터 세트를 제공하는 주tf.data.Dataset 로부터 조언 있도록들 tf.data 가이드가 여전히 적용됩니다.

벤치 마크 데이터 세트

tfds.benchmark(ds) 를 사용하여tf.data.Dataset 객체를 벤치마킹합니다.

결과를 정규화하려면 batch_size= 를 지정해야합니다 (예 : 100 iter / sec-> 3200 ex / sec). tfds.benchmark(tfds.as_numpy(ds)) 예 : tfds.benchmark(tfds.as_numpy(ds)) )과 함께 작동합니다.

ds = tfds.load('mnist', split='train').batch(32).prefetch()
# Display some benchmark statistics
tfds.benchmark(ds, batch_size=32)
# Second iteration is much faster, due to auto-caching
tfds.benchmark(ds, batch_size=32)

소규모 데이터 세트 (<GB)

모든 TFDS 데이터 세트는 TFRecord 형식으로 디스크에 데이터를 저장합니다. 작은 데이터 세트 (예 : Mnist, Cifar, ...)의 경우 .tfrecord 에서 읽는 것은 상당한 오버 헤드를 추가 할 수 있습니다.

이러한 데이터 세트가 메모리에 맞기 때문에 데이터 세트를 캐싱하거나 미리로드하여 성능을 크게 향상시킬 수 있습니다. TFDS는 작은 데이터 세트를 자동으로 캐시합니다 (자세한 내용은 다음 섹션 참조).

데이터 세트 캐싱

다음은 이미지를 정규화 한 후 데이터 세트를 명시 적으로 캐시하는 데이터 파이프 라인의 예입니다.

def normalize_img(image, label):
  """Normalizes images: `uint8` -> `float32`."""
  return tf.cast(image, tf.float32) / 255., label


ds, ds_info = tfds.load(
    'mnist',
    split='train',
    as_supervised=True,  # returns `(img, label)` instead of dict(image=, ...)
    with_info=True,
)
# Applying normalization before `ds.cache()` to re-use it.
# Note: Random transformations (e.g. images augmentations) should be applied
# after both `ds.cache()` (to avoid caching randomness) and `ds.batch()` (for
# vectorization [1]).
ds = ds.map(normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds = ds.cache()
# For true randomness, we set the shuffle buffer to the full dataset size.
ds = ds.shuffle(ds_info.splits['train'].num_examples)
# Batch after shuffling to get unique batches at each epoch.
ds = ds.batch(128)
ds = ds.prefetch(tf.data.experimental.AUTOTUNE)

이 데이터 세트를 반복 할 때 캐싱 덕분에 두 번째 반복이 첫 번째 반복보다 훨씬 빠릅니다.

자동 캐싱

기본적으로 TFDS는 다음 제약 조건을 충족하는 데이터 세트를 자동 캐시합니다.

  • 총 데이터 세트 크기 (모든 분할)가 정의되고 250MiB 미만
  • shuffle_files 가 비활성화되었거나 단일 샤드 만 읽음

전달하여 자동 캐싱을 거부 할 수 있습니다 try_autocaching=Falsetfds.ReadConfigtfds.load . 특정 데이터 세트가 자동 캐시를 사용하는지 확인하려면 데이터 세트 카탈로그 문서를 살펴보세요.

전체 데이터를 단일 Tensor로로드

데이터 세트가 메모리에 맞으면 전체 데이터 세트를 단일 Tensor 또는 NumPy 배열로로드 할 수도 있습니다. 단일 tf.Tensor 에서 모든 예제를 일괄 처리하도록 batch_size=-1 을 설정하여 그렇게 할 수 있습니다. 그런 다음 tfds.as_numpy 에서 tf.Tensor 로의 변환에 tf.Tensor 를 사용 np.array .

(img_train, label_train), (img_test, label_test) = tfds.as_numpy(tfds.load(
    'mnist',
    split=['train', 'test'],
    batch_size=-1,
    as_supervised=True,
))

대규모 데이터 세트

대용량 데이터 세트는 분할 (여러 파일로 분할)되며 일반적으로 메모리에 맞지 않으므로 캐시하지 않아야합니다.

셔플 및 훈련

훈련 중에는 데이터를 잘 섞는 것이 중요합니다. 잘못 섞인 데이터는 훈련 정확도를 떨어 뜨릴 수 있습니다.

ds.shuffle 을 사용하여 레코드를 셔플하는 것 외에도 shuffle_files=True 를 설정하여 여러 파일로 분할 된 더 큰 데이터 세트에 대해 좋은 셔플 링 동작을 가져와야합니다. 그렇지 않으면 epoch가 동일한 순서로 샤드를 읽으므로 데이터가 실제로 무작위 화되지 않습니다.

ds = tfds.load('imagenet2012', split='train', shuffle_files=True)

또한 shuffle_files=True 이면 TFDS는 options.experimental_deterministic 비활성화하여 약간의 성능 향상을 제공 할 수 있습니다. 결정적 셔플 링을 얻으려면 tfds.ReadConfig 를 설정하거나 read_config.options.experimental_deterministic 덮어 read_config.options.experimental_deterministic read_config.shuffle_seed 로이 기능을 옵트 아웃 할 수 있습니다.

작업자간에 데이터 자동 분할

여러 워커에 대해 학습 할 때 tfds.ReadConfiginput_context 인수를 사용하면 각 워커가 데이터의 하위 집합을 읽을 수 있습니다.

input_context = tf.distribute.InputContext(
    input_pipeline_id=1,  # Worker id
    num_input_pipelines=4,  # Total number of workers
)
read_config = tfds.ReadConfig(
    input_context=input_context,
)
ds = tfds.load('dataset', split='train', read_config=read_config)

이것은 subsplit API를 보완합니다. 먼저 subplit API가 적용되고 ( train[:50%] 는 읽을 파일 목록으로 변환 됨), ds.shard() 이 해당 파일에 적용됩니다. 예 : num_input_pipelines=2 와 함께 train[:50%]num_input_pipelines=2 때 두 작업자는 각각 데이터의 1/4을 읽습니다.

shuffle_files=True 이면 파일이 한 작업자 내에서 셔플되지만 작업자 간에는 shuffle_files=True 않습니다. 각 작업자는 Epoch간에 동일한 파일 하위 집합을 읽습니다.

더 빠른 이미지 디코딩

기본적으로 TFDS는 이미지를 자동으로 디코딩합니다. 그러나,으로 디코딩 이미지를 건너 뛸 더 확대됨에 될 수있는 경우가 있습니다 tfds.decode.SkipDecoding 수동으로 적용 tf.io.decode_image 영업 이익은 :

  • 예제를 필터링 할 때 ( ds.filter ) 예제가 필터링 된 후 이미지를 디코딩합니다.
  • 이미지를자를 때 융합 된 tf.image.decode_and_crop_jpeg op를 사용합니다.

두 예제의 코드는 디코드 가이드 에서 사용할 수 있습니다.