TensorFlow.org에서 보기 | Google Colab에서 실행 | GitHub에서 보기 | 노트북 다운로드 |
이 문서에서는 다음을 설명합니다.
- TFDS는 결정론을 보장합니다.
- TFDS는 어떤 순서로 예제를 읽습니까?
- 다양한 주의 사항 및 문제
설정
데이터세트
TFDS가 데이터를 읽는 방법을 이해하려면 몇 가지 컨텍스트가 필요합니다.
세대 동안, TFDS 표준화에 원본 데이터 쓰기 .tfrecord
파일을. 큰 데이터 세트의 경우, 여러 .tfrecord
파일이 생성되며, 각각의 여러 예제를 포함. 우리는 서로 전화 .tfrecord
파편을 제기.
이 가이드에서는 1024개의 샤드가 있는 imagenet을 사용합니다.
import re
import tensorflow_datasets as tfds
imagenet = tfds.builder('imagenet2012')
num_shards = imagenet.info.splits['train'].num_shards
num_examples = imagenet.info.splits['train'].num_examples
print(f'imagenet has {num_shards} shards ({num_examples} examples)')
imagenet has 1024 shards (1281167 examples)
데이터세트 예시 ID 찾기
결정론에 대해서만 알고 싶다면 다음 섹션으로 건너뛸 수 있습니다.
각 데이터 세트는 예를 고유로 식별 id
(예를 들어 'imagenet2012-train.tfrecord-01023-of-01024__32'
). 이 복구 할 수있는 id
전달하여 read_config.add_tfds_id = True
추가 할 것 'tfds_id'
로부터의 DICT에 키를 tf.data.Dataset
.
이 튜토리얼에서는 데이터 세트의 예제 ID를 인쇄할 작은 유틸리티를 정의합니다(사람이 더 읽기 쉽게 정수로 변환).
def load_dataset(builder, **as_dataset_kwargs):
"""Load the dataset with the tfds_id."""
read_config = as_dataset_kwargs.pop('read_config', tfds.ReadConfig())
read_config.add_tfds_id = True # Set `True` to return the 'tfds_id' key
return builder.as_dataset(read_config=read_config, **as_dataset_kwargs)
def print_ex_ids(
builder,
*,
take: int,
skip: int = None,
**as_dataset_kwargs,
) -> None:
"""Print the example ids from the given dataset split."""
ds = load_dataset(builder, **as_dataset_kwargs)
if skip:
ds = ds.skip(skip)
ds = ds.take(take)
exs = [ex['tfds_id'].numpy().decode('utf-8') for ex in ds]
exs = [id_to_int(tfds_id, builder=builder) for tfds_id in exs]
print(exs)
def id_to_int(tfds_id: str, builder) -> str:
"""Format the tfds_id in a more human-readable."""
match = re.match(r'\w+-(\w+).\w+-(\d+)-of-\d+__(\d+)', tfds_id)
split_name, shard_id, ex_id = match.groups()
split_info = builder.info.splits[split_name]
return sum(split_info.shard_lengths[:int(shard_id)]) + int(ex_id)
읽을 때의 결정론
이 섹션의 deterministim 보증을 설명 tfds.load
.
와 shuffle_files=False
(기본)
기본 TFDS는 결정 론적으로 예를 산출하여 ( shuffle_files=False
)
# Same as: imagenet.as_dataset(split='train').take(20)
print_ex_ids(imagenet, split='train', take=20)
print_ex_ids(imagenet, split='train', take=20)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254]
성능을 위해, TFDS 사용하여 동시에 여러 파편을 읽을 tf.data.Dataset.interleave을 . 우리 TFDS 16 예를 읽은 후 샤드 (2)에 전환하는 것이 본 실시 예에서 볼 ( ..., 14, 15, 1251, 1252, ...
). 인터리브에 대한 자세한 내용은 아래를 참조하세요.
마찬가지로 subsplit API도 결정적입니다.
print_ex_ids(imagenet, split='train[67%:84%]', take=20)
print_ex_ids(imagenet, split='train[67%:84%]', take=20)
[858382, 858383, 858384, 858385, 858386, 858387, 858388, 858389, 858390, 858391, 858392, 858393, 858394, 858395, 858396, 858397, 859533, 859534, 859535, 859536] [858382, 858383, 858384, 858385, 858386, 858387, 858388, 858389, 858390, 858391, 858392, 858393, 858394, 858395, 858396, 858397, 859533, 859534, 859535, 859536]
있는 거 교육 이상의 시대에 당신이 경우 (임의성이 제한되어 있으므로 모든 시대는 같은 순서로 파편을 읽으로, 위의 설정은하지 않는 것이 좋습니다 ds = ds.shuffle(buffer)
버퍼 사이즈).
와 shuffle_files=True
함께 shuffle_files=True
읽기가 더 이상 결정되지 않도록, 파편, 각 시대에 대한 섞습니다.
print_ex_ids(imagenet, split='train', shuffle_files=True, take=20)
print_ex_ids(imagenet, split='train', shuffle_files=True, take=20)
[568017, 329050, 329051, 329052, 329053, 329054, 329056, 329055, 568019, 568020, 568021, 568022, 568023, 568018, 568025, 568024, 568026, 568028, 568030, 568031] [43790, 43791, 43792, 43793, 43796, 43794, 43797, 43798, 43795, 43799, 43800, 43801, 43802, 43803, 43804, 43805, 43806, 43807, 43809, 43810]
결정적 파일 셔플링을 얻으려면 아래 레시피를 참조하십시오.
결정론 주의 사항: 인터리브 인수
변경 read_config.interleave_cycle_length
, read_config.interleave_block_length
예제의 순서를 변경합니다.
TFDS은에 의존 tf.data.Dataset.interleave 성능을 향상시키고 메모리 사용량을 줄이고, 한 번에 몇 파편을로드 할 수 있습니다.
예제 순서는 인터리브 인수의 고정 값에 대해서만 동일하도록 보장됩니다. 참조 인터리브 문서 를 이해하기 cycle_length
및 block_length
대응도합니다.
-
cycle_length=16
,block_length=16
(기본적으로 상기와 동일) :
print_ex_ids(imagenet, split='train', take=20)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254]
-
cycle_length=3
,block_length=2
:
read_config = tfds.ReadConfig(
interleave_cycle_length=3,
interleave_block_length=2,
)
print_ex_ids(imagenet, split='train', read_config=read_config, take=20)
[0, 1, 1251, 1252, 2502, 2503, 2, 3, 1253, 1254, 2504, 2505, 4, 5, 1255, 1256, 2506, 2507, 6, 7]
두 번째 예에서, 우리는 데이터 세트 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,...
).
서브스플릿 및 예시 주문
각 예는 보유 ID 0, 1, ..., num_examples-1
. subsplit의 API는 (예를 들어 실시 예 슬라이스 선택 train[:x]
선택 0, 1, ..., x-1
).
그러나 subsplit 내에서 예제는 id 순서가 오름차순으로 읽히지 않습니다(shard 및 interleave로 인해).
구체적으로는, ds.take(x)
과 split='train[:x]'
동등하지!
이것은 예제가 다른 샤드에서 오는 위의 인터리브 예제에서 쉽게 볼 수 있습니다.
print_ex_ids(imagenet, split='train', take=25) # tfds.load(..., split='train').take(25)
print_ex_ids(imagenet, split='train[:25]', take=-1) # tfds.load(..., split='train[:25]')
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
16 (block_length의) 예 후 .take(25)
동안 다음 샤드 스위치 train[:25]
제 샤드 예에서 계속 읽기.
조리법
결정적 파일 셔플링 가져오기
결정적 셔플링에는 2가지 방법이 있습니다.
- 설정
shuffle_seed
. 참고: 이를 위해서는 각 에포크에서 시드를 변경해야 합니다. 그렇지 않으면 에포크 간에 동일한 순서로 샤드를 읽습니다.
read_config = tfds.ReadConfig(
shuffle_seed=32,
)
# Deterministic order, different from the default shuffle_files=False above
print_ex_ids(imagenet, split='train', shuffle_files=True, read_config=read_config, take=22)
print_ex_ids(imagenet, split='train', shuffle_files=True, read_config=read_config, take=22)
[176411, 176412, 176413, 176414, 176415, 176416, 176417, 176418, 176419, 176420, 176421, 176422, 176423, 176424, 176425, 176426, 710647, 710648, 710649, 710650, 710651, 710652] [176411, 176412, 176413, 176414, 176415, 176416, 176417, 176418, 176419, 176420, 176421, 176422, 176423, 176424, 176425, 176426, 710647, 710648, 710649, 710650, 710651, 710652]
- 사용
experimental_interleave_sort_fn
:이 파편 읽고 어떤 순서로, 오히려에 의존하는 것보다하는 동안 완벽하게 제어 할 수 있습니다ds.shuffle
순서를.
def _reverse_order(file_instructions):
return list(reversed(file_instructions))
read_config = tfds.ReadConfig(
experimental_interleave_sort_fn=_reverse_order,
)
# Last shard (01023-of-01024) is read first
print_ex_ids(imagenet, split='train', read_config=read_config, take=5)
[1279916, 1279917, 1279918, 1279919, 1279920]
결정적 선점형 파이프라인 가져오기
이것은 더 복잡합니다. 쉽고 만족스러운 솔루션은 없습니다.
않고
ds.shuffle
결정적으로 셔플 이론적는 (의 함수로서 각 실시 예에 샤드에서 판독 된 판독를 추론 된 예를 계산하는 것이 가능해야cycle_length
,block_length
및 샤드 순서). 그 후skip
,take
각 샤드 용 관통 삽입 될 수experimental_interleave_sort_fn
.로
ds.shuffle
는 전체 교육 파이프 라인을 재생하지 않고 가능성이 불가능합니다. 그것은 구원의 필요ds.shuffle
예 읽은 추론 버퍼 상태. 예를 들면 (예를 들어, 비 연속 일 수shard5_ex2
,shard5_ex4
읽을 수 있지만하지shard5_ex3
).로
ds.shuffle
, 한 가지 방법은 / example_ids이 (추론 읽기 모든 shards_ids 저장하는 것입니다tfds_id
그에서 파일 명령을 추론).
가장 간단한 경우 1.
에 가지고있다 .skip(x).take(y)
검색 train[x:x+y]
매치. 다음이 필요합니다.
- 집합
cycle_length=1
(파편 순차적으로 판독되도록) - 설정
shuffle_files=False
- 사용하지 마십시오
ds.shuffle
훈련이 1 epoch에 불과한 거대한 데이터 세트에서만 사용해야 합니다. 예제는 기본 셔플 순서로 읽습니다.
read_config = tfds.ReadConfig(
interleave_cycle_length=1, # Read shards sequentially
)
print_ex_ids(imagenet, split='train', read_config=read_config, skip=40, take=22)
# If the job get pre-empted, using the subsplit API will skip at most `len(shard0)`
print_ex_ids(imagenet, split='train[40:]', read_config=read_config, take=22)
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61] [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61]
주어진 하위 분할에 대해 읽은 샤드/예제 찾기
으로 tfds.core.DatasetInfo
, 당신은 읽기 지침에 직접 액세스 할 수 있습니다.
imagenet.info.splits['train[44%:45%]'].file_instructions
[FileInstruction(filename='imagenet2012-train.tfrecord-00450-of-01024', skip=700, take=-1, num_examples=551), FileInstruction(filename='imagenet2012-train.tfrecord-00451-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00452-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00453-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00454-of-01024', skip=0, take=-1, num_examples=1252), FileInstruction(filename='imagenet2012-train.tfrecord-00455-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00456-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00457-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00458-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00459-of-01024', skip=0, take=-1, num_examples=1251), FileInstruction(filename='imagenet2012-train.tfrecord-00460-of-01024', skip=0, take=1001, num_examples=1001)]