Path: blob/master/site/ko/datasets/determinism.ipynb
25115 views
Copyright 2020 The TensorFlow Authors.
TFDS와 결정성
이 문서에서는 다음을 설명합니다.
결정성을 보장하는 TFDS
TFDS가 예시를 읽는 순서
다양한 주의사항과 문제들
설치
데이터 세트
TFDS가 데이터를 읽는 방식을 이해하려면 약간의 맥락이 필요합니다.
TFDS는 생성하는 동안 표준화된 .tfrecord
파일에 원본 데이터를 기록합니다. 큰 데이터 세트에서는 여러 .tfrecord
파일을 생성하며 각각에는 다양한 예시가 포함되어 있습니다. 우리는 각각의 .tfrecord
파일을 샤드라고 부릅니다.
이 가이드에서는 1024개의 샤드가 있는 이미지넷을 사용합니다.
데이터 세트 예시 ID 찾기
결정성에 대한 내용만 알고 싶은 경우 다음 섹션으로 건너뛸 수 있습니다.
각 데이터 세트 예시는 id
(예: 'imagenet2012-train.tfrecord-01023-of-01024__32'
)를 통해 고유하게 식별됩니다. tf.data.Dataset
로부터 dict의 'tfds_id'
키를 추가하는 read_config.add_tfds_id = True
를 전달하여 이 id
를 복구할 수 있습니다.
이 튜토리얼에서는 데이터 세트의 예시 ID를 인쇄하는 작은 유틸을 정의합니다(사람이 읽기 쉬도록 정수로 변환).
읽기 작업 시의 결정성
이 섹션에서는 tfds.load
의 결정성 보장에 대해 설명합니다.
shuffle_files=False
의 사용(기본값)
기본적으로 TFDS는 결정적으로 예시를 산출합니다(shuffle_files=False
).
성능을 위해 TFDS는 tf.data.Dataset.interleave를 사용하여 동시에 여러 샤드를 읽습니다. 이 예시에서는 TFDS가 16개의 예시(..., 14, 15, 1251, 1252, ...
)를 읽은 후 샤드 2로 전환하는 것을 보게 됩니다. 이터리브에 대한 자세한 내용은 아래를 참조합니다.
마찬가지로 subsplit API(하위 분할 API)도 다음과 같이 결정적입니다.
둘 이상의 epoch에 대한 훈련을 진행하는 경우 모든 epoch가 동일한 순서로 샤드를 읽기에 위의 설정은 권장되지 않습니다(따라서 임의성은 ds = ds.shuffle(buffer)
버퍼 크기로 제한됨).
shuffle_files=True
의 사용
shuffle_files=True
를 사용하는 경우 각 epoch에 대해 샤드가 셔플되므로 읽기 작업이 더 이상 결정적이지 않습니다.
참고: shuffle_files=True
를 설정하면 약간의 성능 향상을 위해 tf.data.Options
의 deterministic
도 비활성화됩니다. 따라서 단일 샤드(예: mnist)만 있는 작은 데이터 세트도 비결정적으로 됩니다.
결정적 파일 셔플링을 가져오려면 아래의 레시피를 참조하세요.
결정성 주의사항: 인터리브 args
read_config.interleave_cycle_length
를 변경하면 read_config.interleave_block_length
가 예시 순서를 변경합니다.
TFDS는 tf.data.Dataset.interleave에 의존하여 한 번에 몇 개의 샤드만 로드하여 성능을 개선하고 메모리 사용량을 줄입니다.
예시 순서는 인터리브 args의 고정값에 대해서만 동일하도록 보장됩니다. cycle_length
와 block_length
에 해당하는 대상이 무엇인지 이해하려면 interleave doc을 참조하여 인터리브 문서를 참조하세요.
cycle_length=16
,block_length=16
(기본값, 위와 동일):
cycle_length=3
,block_length=2
:
두 번째 예시에서 데이터 세트가 한 샤드에서 2 (block_length=2
)의 예시를 읽고 다음 샤드로 전환하는 것을 볼 수 있습니다. 2 * 3(cycle_length=3
) 예시마다 첫 번째 샤드(shard0-ex0, shard0-ex1, shard1-ex0, shard1-ex1, shard2-ex0, shard2-ex1, shard0-ex2, shard0-ex3, shard1-ex2, shard1-ex3, shard2-ex2,...
)로 돌아갑니다.
하위 분할(Subsplit)과 예시 순서
각 예시에는 ID 0, 1, ..., num_examples-1
가 있습니다. 하위 분할 API는 예시 조각을 선택합니다(예: train[:x]
는 0, 1, ..., x-1
을 선택).
다만 하위 분할 내에서 예시의 ID 순서가 오름차순으로 읽히지 않습니다(샤드 및 인터리브로 인함).
더 구체적으로 ds.take(x)
와 split='train[:x]'
는 동등하지 않습니다!
이는 예시가 다른 샤드로부터 오는 위의 인터리브 예시에서도 쉽게 확인할 수 있습니다.
16 (block_length) 예시 이후에 .take(25)
는 다음 샤드로 전환하고 train[:25]
는 첫 번째 샤드로부터 예시를 계속 읽습니다.
레시피
결정적 파일 셔플링 가져오기
결정적 셔플링을 보유하는 방법에는 2가지가 있습니다.
shuffle_seed
를 설정합니다. 참고: 이렇게 하려면 각 epoch에서 시드를 변경해야 합니다. 그렇지 않으면 epoch 사이에서 동일한 순서로 샤드를 읽습니다.
experimental_interleave_sort_fn
의 사용: 이 경우ds.shuffle
순서에 의존하지 않고 어떤 샤드를 어떤 순서로 읽을지 완전히 제어할 수 있습니다.
결정적 선점 가능 파이프라인 가져오기
이 방법은 더 복잡합니다. 쉽고 만족스러운 솔루션은 없습니다.
ds.shuffle
없이 결정적 셔플링을 사용할 경우 이론적으로 읽은 예시를 셀 수 있고 각 샤드 내에서 읽은 예시를 추론할 수 있어야 합니다(cycle_length
,block_length
및 샤드 순서의 함수로). 그런 다음experimental_interleave_sort_fn
를 통해 각 샤드에 대한skip
,take
를 삽입할 수 있습니다.ds.shuffle
을 사용하는 경우 전체 훈련 파이프라인을 재생하지 않으면 작업이 불가능할 수 있습니다. 읽은 예시를 추론하려면ds.shuffle
버퍼 상태를 저장해야 합니다. 예시는 비연속적일 수 있습니다(예:shard5_ex2
,shard5_ex4
읽기. 단,shard5_ex3
는 해당 없음).ds.shuffle
을 사용하는 경우 한 가지 방법은 읽은 모든 shards_ids/example_ids(tfds_id
에서 추론)를 저장한 후 여기로부터 파일 지침을 추론하는 것입니다.
1.
에 대한 가장 간단한 사례는 .skip(x).take(y)
와 train[x:x+y]
를 일치시키는 것입니다. 필요 사항:
cycle_length=1
설정하기(샤드를 순차적으로 읽기 위함)shuffle_files=False
설정하기ds.shuffle
사용하지 않기
훈련이 1 epoch에 불과한 대형 데이터 세트에만 사용해야 합니다. 예시는 기본 셔플 순서로 읽습니다.
제공된 하위 분할에서 읽은 샤드/예시 찾기
tfds.core.DatasetInfo
를 사용할 경우 읽기 지침에 직접 액세스할 수 있습니다.