具有多处理功能的Tensorflow2.x自定义数据生成器

具有多处理功能的Tensorflow2.x自定义数据生成器,tensorflow,keras,tf.keras,data-generation,custom-training,Tensorflow,Keras,Tf.keras,Data Generation,Custom Training,我刚升级到tensorflow 2.3。 我想为培训制作自己的数据生成器。 使用tensorflow 1.x,我做到了: def get_data_generator(test_flag): item_list = load_item_list(test_flag) print('data loaded') while True: X = [] Y = [] for _ in range(BATCH_SIZE): x, y = get_random

我刚升级到tensorflow 2.3。 我想为培训制作自己的数据生成器。 使用tensorflow 1.x,我做到了:

def get_data_generator(test_flag):
  item_list = load_item_list(test_flag)
  print('data loaded')
  while True:
    X = []
    Y = []
    for _ in range(BATCH_SIZE):
      x, y = get_random_augmented_sample(item_list)
      X.append(x)
      Y.append(y)
    yield np.asarray(X), np.asarray(Y)

data_generator_train = get_data_generator(False)
data_generator_test = get_data_generator(True)
model.fit_generator(data_generator_train, validation_data=data_generator_test, 
                    epochs=10000, verbose=2,
                    use_multiprocessing=True,
                    workers=8,
                    validation_steps=100,
                    steps_per_epoch=500,
                    )
这段代码在tensorflow 1.x上运行良好。系统中创建了8个流程。处理器和视频卡的加载非常完美。加载的数据打印了8次

使用tensorflow 2.3,我得到警告:

警告:tensorflow:多处理可能会与tensorflow严重交互,导致不确定死锁。对于高性能数据管道,建议使用tf.data

加载的数据打印了8次。GPU没有得到充分利用。它也有内存泄漏的每个时代,所以训练将停止后几个时代。使用多处理标志没有帮助

如何在tensorflowkeras 2.x中创建一个可以跨多个CPU进程轻松并行的生成器/迭代器?死锁和数据顺序并不重要。

对于tf.data管道,有几个点可以并行化。根据数据的存储和读取方式,可以并行读取。您还可以并行化增强,并且可以在训练时预取数据,这样您的GPU或其他硬件就永远不会需要数据

在下面的代码中,我演示了如何并行化增强和添加预取

import numpy as np
import tensorflow as tf

x_shape = (32, 32, 3)
y_shape = ()  # A single item (not array).
classes = 10

# This is tf.data.experimental.AUTOTUNE in older tensorflow.
AUTOTUNE = tf.data.AUTOTUNE

def generator_fn(n_samples):
    """Return a function that takes no arguments and returns a generator."""
    def generator():
        for i in range(n_samples):
            # Synthesize an image and a class label.
            x = np.random.random_sample(x_shape).astype(np.float32)
            y = np.random.randint(0, classes, size=y_shape, dtype=np.int32)
            yield x, y
    return generator

def augment(x, y):
    return x * tf.random.normal(shape=x_shape), y

samples = 10
batch_size = 5
epochs = 2

# Create dataset.
gen = generator_fn(n_samples=samples)
dataset = tf.data.Dataset.from_generator(
    generator=gen, 
    output_types=(np.float32, np.int32), 
    output_shapes=(x_shape, y_shape)
)
# Parallelize the augmentation.
dataset = dataset.map(
    augment, 
    num_parallel_calls=AUTOTUNE,
    # Order does not matter.
    deterministic=False
)
dataset = dataset.batch(batch_size, drop_remainder=True)
# Prefetch some batches.
dataset = dataset.prefetch(AUTOTUNE)

# Prepare model.
model = tf.keras.applications.VGG16(weights=None, input_shape=x_shape, classes=classes)
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy")

# Train. Do not specify batch size because the dataset takes care of that.
model.fit(dataset, epochs=epochs)
使用tf.data管道,有几个点可以并行化。根据数据的存储和读取方式,可以并行读取。您还可以并行化增强,并且可以在训练时预取数据,这样您的GPU或其他硬件就永远不会需要数据

在下面的代码中,我演示了如何并行化增强和添加预取

import numpy as np
import tensorflow as tf

x_shape = (32, 32, 3)
y_shape = ()  # A single item (not array).
classes = 10

# This is tf.data.experimental.AUTOTUNE in older tensorflow.
AUTOTUNE = tf.data.AUTOTUNE

def generator_fn(n_samples):
    """Return a function that takes no arguments and returns a generator."""
    def generator():
        for i in range(n_samples):
            # Synthesize an image and a class label.
            x = np.random.random_sample(x_shape).astype(np.float32)
            y = np.random.randint(0, classes, size=y_shape, dtype=np.int32)
            yield x, y
    return generator

def augment(x, y):
    return x * tf.random.normal(shape=x_shape), y

samples = 10
batch_size = 5
epochs = 2

# Create dataset.
gen = generator_fn(n_samples=samples)
dataset = tf.data.Dataset.from_generator(
    generator=gen, 
    output_types=(np.float32, np.int32), 
    output_shapes=(x_shape, y_shape)
)
# Parallelize the augmentation.
dataset = dataset.map(
    augment, 
    num_parallel_calls=AUTOTUNE,
    # Order does not matter.
    deterministic=False
)
dataset = dataset.batch(batch_size, drop_remainder=True)
# Prefetch some batches.
dataset = dataset.prefetch(AUTOTUNE)

# Prepare model.
model = tf.keras.applications.VGG16(weights=None, input_shape=x_shape, classes=classes)
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy")

# Train. Do not specify batch size because the dataset takes care of that.
model.fit(dataset, epochs=epochs)

您可以使用tf.data管道吗?正如警告所述,这是可以并行的。我尝试使用tf.keras.utils.Sequence。这个类可以工作,并且可以根据需要进行并行化。问题是我有很多使用标准python生成器的tensorflow 1代码。我希望这段代码能够继续使用tensorflow 2,而无需大量重写。您有没有研究过?您可能可以从现有生成器生成tf.data.Dataset。我认为生成器应该在每次迭代中生成一个样本,然后您可以使用dataset.batchBATCH\u SIZE进行批处理。您可以使用tf.data管道吗?正如警告所述,这是可以并行的。我尝试使用tf.keras.utils.Sequence。这个类可以工作,并且可以根据需要进行并行化。问题是我有很多使用标准python生成器的tensorflow 1代码。我希望这段代码能够继续使用tensorflow 2,而无需大量重写。您有没有研究过?您可能可以从现有生成器生成tf.data.Dataset。我认为生成器应该在每次迭代中生成一个样本,然后您可以使用dataset.batchBATCH\u SIZE进行批处理。是否可以在tf.data.dataset.from\u generator?@M.Innat中使用tf.keras.utils.Sequence generator?我确信这是可能的。请随意提出一个新问题。如果你把它链接到这里,我很乐意看一看。通过你展示的方法,我看到其他人也这么做。但我认为序列类生成器很少有问题。请看一看。是否可以在tf.data.Dataset.from_generator?@M.Innat中使用tf.keras.utils.Sequence generator?我相信这是可能的。请随意提出一个新问题。如果你把它链接到这里,我很乐意看一看。通过你展示的方法,我看到其他人也这么做。但我认为序列类生成器很少有问题。请看一看。