このドキュメントは、TFDS固有のパフォーマンスのヒントを提供します。 TFDSはデータセットをtf.data.Dataset
として提供するため、 tf.data
ガイドのアドバイスが引き続き適用されることにtf.data
ください。
ベンチマークデータセット
tfds.benchmark(ds)
を使用して、tf.data.Dataset
オブジェクトのベンチマークをtf.data.Dataset
ます。
結果を正規化するには、 batch_size=
を必ず指定してください(例:100 iter / sec-> 3200 ex / sec)。これは、任意の反復可能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
形式でディスクにTFRecord
ます。小さなデータセット(Mnist、Cifarなど)の場合、 .tfrecord
から.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)
このデータセットを反復処理する場合、キャッシュのおかげで2回目の反復は最初の反復よりもはるかに高速になります。
自動キャッシュ
デフォルトでは、TFDSは次の制約を満たすデータセットを自動キャッシュします。
- 合計データセットサイズ(すべての分割)が定義されており、<250 MiB
-
shuffle_files
が無効になっているか、単一のシャードのみが読み取られます
渡すことによって、自動キャッシュをオプトアウトすることが可能であるtry_autocaching=False
にtfds.ReadConfig
にtfds.load
。データセットカタログのドキュメントを見て、特定のデータセットが自動キャッシュを使用するかどうかを確認してください。
単一のテンソルとして完全なデータをロードする
データセットがメモリに収まる場合は、データセット全体を単一の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
を使用してds.shuffle
をシャッフルすることに加えて、 shuffle_files=True
を設定して、複数のファイルにシャーディングされる大きなデータセットに対して適切なシャッフル動作を取得する必要があります。それ以外の場合、エポックは同じ順序でシャードを読み取るため、データは真にランダム化されません。
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.shuffle_seed
上書きします。
ワーカー間でデータを自動シャーディング
複数の労働者のトレーニングは、あなたが使用することができた場合input_context
の引数tfds.ReadConfig
各ワーカーは、データのサブセットを読み込みますので、。
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)
これは、サブスプリットAPIを補完するものです。最初にサブプリットAPIが適用され( train[:50%]
が読み取るファイルのリストに変換されます)、次にds.shard()
opがそれらのファイルに適用されます。例: num_input_pipelines=2
でtrain[:50%]
をnum_input_pipelines=2
すると、2人のワーカーのそれぞれがデータの1/4を読み取ります。
shuffle_files=True
場合、ファイルは1つのワーカー内でシャッフルされますが、ワーカー間ではシャッフルされません。各ワーカーは、エポック間で同じファイルのサブセットを読み取ります。
より高速な画像デコード
デフォルトでは、TFDSは画像を自動的にデコードします。ただし、 tfds.decode.SkipDecoding
を使用して画像のデコードをスキップし、手動でtf.io.decode_image
opを適用すると、パフォーマンスが向上する場合があります。
- (
ds.filter
)例をフィルタリングする場合、例がフィルタリングされた後に画像をデコードします。 - 画像をトリミングする場合、融合された
tf.image.decode_and_crop_jpeg
を使用します。
両方の例のコードは、デコードガイドに記載されています。