【问题标题】:Tensorflow federated (TFF) 0.19 performs significantly worse than TFF 0.17 when running "Building Your Own Federated Learning Algorithm" tutorial在运行“构建您自己的联邦学习算法”教程时,Tensorflow federated (TFF) 0.19 的性能明显低于 TFF 0.17
【发布时间】:2021-07-12 01:54:37
【问题描述】:

在“构建你自己的联邦学习算法”教程的最后指出,在训练我们的模型 15 轮之后,我们预计 sparse_categorical_accuracy 大约为 0.25,但运行教程在 colab 中,根据我的运行结果,结果在 0.09 到 0.11 之间。然而,只需将 tf 和 tff 版本分别更改为 2.3.x 和 0.17,就会得到大约 0.25 的结果,正如我们预期的那样!

要按原样复制运行上述教程,它应该使用 tf 2.5 和 tff 0.19。之后,只需更改即可运行相同的教程

!pip install --quiet --upgrade tensorflow-federated

!pip install --quiet tensorflow==2.3.0
!pip install --quiet --upgrade tensorflow-federated==0.17.0

tf 2.4 和 tff 0.18 组合也可以正常工作,得分约为 0.25。所以只有 tf 2.5 和 tff 0.19 的组合没有给出预期的结果。

为了清楚起见,我并不是说第一次设置不会训练模型;运行 200 轮显示得分稳步提高,达到 0.7-0.8 左右。我希望能澄清为什么会这样,或者如果我做错了什么,请指出。

编辑:为了确保在不同的 tff 版本中使用相同的客户端,我使用了以下代码

用于训练数据

sorted_client_ids = sorted(emnist_train.client_ids)
sorted_client_ids2 = sorted_client_ids[0:10]

federated_train_data = [preprocess(emnist_train.create_tf_dataset_for_client(x))
                       for x in sorted_client_ids2]

用于测试数据

sorted_client_ids = sorted(emnist_test.client_ids)
sorted_client_ids2 = sorted_client_ids[0:100]

def data(client, source=emnist_test):
    return preprocess(source.create_tf_dataset_for_client(client))

central_emnist_test = (tf.data.Dataset.from_tensor_slices(
    [data(client) for client in sorted_client_ids2])).flat_map(lambda x: x)

我每个人都训练了 50 轮。我用这些设置得到的结果是

对于 tff 0.17:损失:1.8676 - sparse_categorical_accuracy:0.5115

对于 tff 0.18:损失:1.8503 - sparse_categorical_accuracy:0.5160

对于 tff 0.19:损失:2.2007 - sparse_categorical_accuracy:0.1014

所以我的问题是所有三个版本的 tff 都使用了相同的训练数据、相同的测试数据,模型具有相同的初始化和相同的训练轮次,但 tff 0.19 和 tff 0.18/0.17 的结果大不相同,而tff 0.18 和 0.17 产生了非常相似的结果。

再次澄清 tff 0.19 也提高了其准确性,但程度明显降低。

编辑 2: 按照 Zachary Charles 的建议,我使用了联合 sgd。对于 tff 0.18 和 0.17 编辑第一行。

!pip install --quiet --upgrade tensorflow-federated
!pip install --quiet --upgrade nest-asyncio

import nest_asyncio
nest_asyncio.apply()

import collections
import attr
import functools
import numpy as np
import tensorflow as tf
import tensorflow_federated as tff

np.random.seed(0)

print(tf.__version__)
print(tff.__version__)

emnist_train, emnist_test = tff.simulation.datasets.emnist.load_data()

NUM_CLIENTS = 10
BATCH_SIZE = 20

def preprocess(dataset):
    def batch_format_fn(element):
        return(tf.reshape(element['pixels'],[-1,784]),
              tf.reshape(element['label'],[-1,1]))
    return dataset.batch(BATCH_SIZE).map(batch_format_fn)

sorted_client_ids = sorted(emnist_train.client_ids)
sorted_client_ids2 = sorted_client_ids[0:10]

federated_train_data = [preprocess(emnist_train.create_tf_dataset_for_client(x))
                       for x in sorted_client_ids2]

def create_keras_model():
    return tf.keras.models.Sequential([
        tf.keras.layers.InputLayer(input_shape=(784,)),
        tf.keras.layers.Dense(10, kernel_initializer='zeros'),
        tf.keras.layers.Softmax(),
    ])

def model_fn():
    keras_model = create_keras_model()
    return tff.learning.from_keras_model(
        keras_model,
        input_spec=federated_train_data[0].element_spec,
        loss=tf.keras.losses.SparseCategoricalCrossentropy(),
        metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
    
sorted_client_ids = sorted(emnist_test.client_ids)
sorted_client_ids2 = sorted_client_ids[0:10]

def data(client, source=emnist_test):
    return preprocess(source.create_tf_dataset_for_client(client))

central_emnist_test = (tf.data.Dataset.from_tensor_slices(
    [data(client) for client in sorted_client_ids2])).flat_map(lambda x: x)

def evaluate(server_state):
    keras_model = create_keras_model()
    keras_model.compile(
      loss=tf.keras.losses.SparseCategoricalCrossentropy(),
      metrics=[tf.keras.metrics.SparseCategoricalAccuracy()]  
    )
    keras_model.set_weights(server_state)
    keras_model.evaluate(central_emnist_test)


iterative_process = tff.learning.build_federated_sgd_process(
    model_fn,
    server_optimizer_fn=lambda: tf.keras.optimizers.SGD(learning_rate=0.01))

state = iterative_process.initialize()
evaluate(state.model.trainable)

for round in range(50):
    print(round)
    state,_ = iterative_process.next(state, federated_train_data)

evaluate(state.model.trainable)

我得到的结果是

训练前

  • tff 0.19:损失:2.3026 - sparse_categorical_accuracy:0.1207
  • tff 0.18:损失:2.3026 - sparse_categorical_accuracy:0.1010
  • tff 0.17:损失:2.3026 - sparse_categorical_accuracy:0.1207

训练后

  • tff 0.19:损失:2.2122 - sparse_categorical_accuracy:0.1983
  • tff 0.18:损失:2.2158 - sparse_categorical_accuracy:0.1700
  • tff 0.17:损失:2.2122 - sparse_categorical_accuracy:0.1983

【问题讨论】:

    标签: tensorflow-federated


    【解决方案1】:

    TFF 0.19 将提供的数据集(包括本教程中使用的 EMNIST)从支持 HDF5 的实现移到了支持 SQL 的实现 (commit)。这可能会改变客户端的顺序,从而改变教程中用于训练的客户端。

    值得注意的是,在大多数模拟中,这不会改变任何东西。客户通常应该在每一轮随机抽样(由于说明原因,教程中没有这样做),并且通常至少应该完成 100 轮(如你所说)。

    我将更新教程以通过对客户端 ID 进行排序,然后按顺序选择它们来保证可重复性。

    对于任何感兴趣的人,更好的做法是 a) 对客户端 ID 进行排序,然后 b) 使用 np.random.RandomState 之类的东西进行采样,如下面的 sn-p:

    emnist_train, _ = tff.simulation.datasets.emnist.load_data()
    random_state = np.random.RandomState(seed=1729)
    sorted_client_ids = sorted(emnist_train.client_ids)
    sampled_client_ids = random_state.choice(sorted_client_ids, size=NUM_CLIENTS)
    

    【讨论】:

    • 感谢您的回答。最初我认为这是有道理的,所以我批准了它,但在不同 tff 版本使用相同的客户端后,我仍然在 tff 0.19 和 tff 0.18/0.17 之间发现了巨大的差异。您可以在我的问题的已编辑部分查看我用于选择客户的完整结果和代码。你说的很有道理,但我认为这不是问题的原因。因此,如果您能再看一下,我将不胜感激
    • 版本之间可能发生变化的一件事是每个客户端数据集中示例的顺序,这将改变训练动态。您可以做的一项测试(将不胜感激)是在不同的 TFF 版本中使用federated SGD,看看情况是否仍然不同。
    • 非常感谢您的帮助。您可以检查我使用的代码的第二次编辑。它与您提供的教程代码非常相似。根据我提供的结果,您是否同意我的结论,即“tff 0.17 和 0.19 具有相同的数据集但顺序不同,而 tff 0.18 具有不同的数据集,可能大一点,也许小一点”?您对此的评论将不胜感激
    • 不幸的是,我不确定为什么 TFF v0.18 具有不同的训练后值。数据集本身在版本之间没有变化,除了客户端和示例的顺序。 TFF v0.18 在初始化时给出了不同的精度似乎很重要,所以这可能是由于 TF 的潜在变化(例如,如何计算指标),或者它可能只是浮点问题,很难说。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 2022-08-20
    相关资源
    最近更新 更多