【问题标题】:How to do data augmentation with tensorflow federated?如何使用 tensorflow 联合进行数据增强?
【发布时间】:2021-04-15 01:55:57
【问题描述】:

我希望探索数据增强如何在联邦学习中发挥作用,我目前正在使用 tff 来实现它。我注意到 tff 提供的数据集是由张量组成的,而张量不能直接调整,所以一个天真的想法是将其更改为 numpy 数组然后进行扩充。我试过了

tfds.as_numpy(emnist_train.create_tf_dataset_for_client(n)) 它确实为我提供了 numpy 数组,但是在尝试将它传递给预处理函数时遇到了问题。如果我做: preprocess(tfds.as_numpy(emnist_train.create_tf_dataset_for_client(n)))

预处理定义为

def preprocess(dataset):

    def batch_format_fn(element):
        """Flatten a batch `pixels` and return the features as an `OrderedDict`."""

        return collections.OrderedDict(
            x=tf.reshape(element['pixels'], [-1, 784]),
            y=tf.reshape(element['label'], [-1, 1]))

    return dataset.repeat(NUM_EPOCHS).shuffle(SHUFFLE_BUFFER).batch(
        BATCH_SIZE).map(batch_format_fn).prefetch(PREFETCH_BUFFER)

我会收到以下错误:

return dataset.repeat(NUM_EPOCHS).shuffle(SHUFFLE_BUFFER).batch(
AttributeError: '_IterableDataset' object has no attribute 'repeat'

这似乎意味着numpy数组的这个_IterableDataset对象不能应用于这些方法。

我尝试将tf.data.Dataset.from_tensor_slices 方法包装为tf.data.Dataset.from_tensor_slices(tfds.as_numpy(emnist_train.create_tf_dataset_for_client(n))),但最终出现此错误:

ValueError: Attempt to convert a value (<tensorflow_datasets.core.dataset_utils._IterableDataset object at 0x00000280AA695DF0>) with an unsupported type (<class 'tensorflow_datasets.core.dataset_utils._IterableDataset'>) to a Tensor.

有什么办法可以解决这个问题吗?或者我可以只对它提供的数据进行扩充吗?

更新

如果我只想将数据集中的每个样本转换为增强样本,只使用 map 函数就足够了。但是,如果我想向数据集添加新样本(例如添加不同标签的样本),我该怎么做?由于我们不能直接修改客户端数据集,我正在考虑将其转换为 numpy 数组并进行进一步处理,但如果我这样做:

state, metrics = iterative_process.next(state, tfds.as_numpy(federated_train_data)) 其中federated_train_data 是客户端数据集,我得到了

TypeError: Expected tensorflow.python.data.ops.dataset_ops.DatasetV2 or tensorflow.python.data.ops.dataset_ops.DatasetV1, found tensorflow_datasets.core.dataset_utils._IterableDataset.

似乎这个_IterableDataset 无法应用于进程。有没有办法可以将此数据集转换回tff.learning.build_federated_averaging_process() 可接受的数据?或者有没有更好的方法来做这种增强?

更新 2

我试图使用来自 GAN 模型的生成器来生成新图像以扩充数据集。我有一个预训练的 GAN(由 tf.keras 编写),我编写了一个 dataGenerator 来包装这个模型以增强客户端数据集。但是,当我进行 fed-avg 训练时,出现以下错误:

  File "D:\Research\GAN_AUG_FL\utils\augment_utils.py", line 53, in generate_once
    generated_images = generator(generator_input)
  File "D:\Research\GAN_AUG_FL\venv\lib\site-packages\tensorflow\python\keras\engine\base_layer_v1.py", line 665, in __call__
    self._assert_built_as_v1()
  File "D:\Research\GAN_AUG_FL\venv\lib\site-packages\tensorflow\python\keras\engine\base_layer_v1.py", line 836, in _assert_built_as_v1
    raise ValueError(
ValueError: Your Layer or Model is in an invalid state. This can happen for the following cases:
 1. You might be interleaving estimator/non-estimator models or interleaving models/layers made in tf.compat.v1.Graph.as_default() with models/layers created outside of it. Converting a model to an estimator (via model_to_estimator) invalidates all models/layers made before the conversion (even if they were not the model converted to an estimator). Similarly, making a layer or a model inside a a tf.compat.v1.Graph invalidates all layers/models you previously made outside of the graph.
2. You might be using a custom keras layer implementation with  custom __init__ which didn't call super().__init__.  Please check the implementation of <class 'tensorflow.python.keras.engine.functional.Functional'> and its bases.

这里generator 只是用于生成的 keras 模型。我怀疑这是因为在 tff 中,计算图与我用来创建生成器模型实例的计算图不同。训练代码就像教程here

emnist_train, emnist_test = tff.simulation.datasets.emnist.load_data(only_digits=True, cache_dir="data/emnist")

example_dataset = emnist_train.create_tf_dataset_for_client(emnist_train.client_ids[0])
example_dataset = preprocess(example_dataset)

def model_fn():
    keras_model = create_keras_model()
    return tff.learning.from_keras_model(
        keras_model,
        input_spec=example_dataset.element_spec,
        loss=tf.keras.losses.SparseCategoricalCrossentropy(),
        metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
    )


iterative_process = tff.learning.build_federated_averaging_process(
    model_fn,
    client_optimizer_fn=lambda: tf.keras.optimizers.SGD(learning_rate=0.02),
    server_optimizer_fn=lambda: tf.keras.optimizers.SGD(learning_rate=1.0),
)

state = iterative_process.initialize()

# state, metrics = iterative_process.next(state, [example_dataset])
# print('round  1, metrics={}'.format(metrics))


for round_num in range(NUM_ROUNDS):
    selected_clients = random.sample(emnist_train.client_ids, 1)
    federated_data = [
        preprocess(emnist_train.create_tf_dataset_for_client(n))
        for n in selected_clients
    ]
    state, metrics = iterative_process.next(state, federated_data)
    print(f"round  {round_num + 1}, metrics={metrics}")

但是在这一点上,如果我在进入循环之前取消注释这两行,就会发生奇怪的事情。这次训练可以顺利进行,但进入循环后仍然报告相同的错误。因此我猜在第一次完成这个预处理之后,tff 正在使用一些不同的图表?有什么可能的解决办法吗?

【问题讨论】:

    标签: tensorflow data-augmentation tensorflow-federated


    【解决方案1】:

    我认为答案是直接在tf.data.Dataset 对象上进行增强,使用tf.data.Dataset.map,例如this TF tutorial

    主要原因是 TFF 将计算序列化并稍后执行,因此无论您在 Python / numpy 中执行什么处理,都需要事先进行。原则上,您也可以使用 py/np 加载、扩充和保存数据集,然后将扩充后的数据集提供给 TFF,但这可能是一个复杂的解决方法。

    【讨论】:

    • 感谢您的建议!似乎通过映射的增强功能适合它。我之前陷入了对 numpy 数组进行扩充的想法。
    • 我试图做一种不同的增强,这次我不能仅仅通过地图来做。有什么可能的解决方案吗?
    • 从更新的 Q 中,我假设您想将新元素添加到客户的数据中。这也应该在 TFF 之外,在tf.data 操作中完成。 tf.data.Dataset.concatenate 可能是一个很好的起点。一般来说,tensorflow.org/guide/data 可能是有用的阅读。
    • Dataset.concatenate 似乎是一个好方法。再次感谢!
    • 在部署另一个模型来生成样本以扩充客户端数据集时,仍然会遇到更多问题。和tff的graph设置有关系吗?
    猜你喜欢
    • 2016-04-20
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2022-01-21
    • 1970-01-01
    • 2020-01-15
    相关资源
    最近更新 更多