【发布时间】: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