TFF: как имитировать обучение на случайных выборках пользователей в каждом раунде

Я хотел бы смоделировать этот код федеративного обучения для классификации изображений со случайными выборками пользователей в каждом раунде. В этом руководстве используются все клиенты при обучении, поэтому я бы изменил этот код таким образом, в каждом раунде случайные выборки клиенты выбираются. Итак, что мы можем изменить в этом коде, чтобы заставить его выбирать клиента случайным образом

import collections
import time

import tensorflow as tf
tf.compat.v1.enable_v2_behavior()

import tensorflow_federated as tff

source, _ = tff.simulation.datasets.emnist.load_data()


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


def client_data(n):
  ds = source.create_tf_dataset_for_client(source.client_ids[n])
  return ds.repeat(10).shuffle(500).batch(20).map(map_fn)


train_data = [client_data(n) for n in range(10)]
element_spec = train_data[0].element_spec

def model_fn():
  model = tf.keras.models.Sequential([
      tf.keras.layers.Input(shape=(784,)),
      tf.keras.layers.Dense(units=10, kernel_initializer='zeros'),
      tf.keras.layers.Softmax(),
  ])
  return tff.learning.from_keras_model(
      model,
      input_spec=element_spec,
      loss=tf.keras.losses.SparseCategoricalCrossentropy(),
      metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])


trainer = tff.learning.build_federated_averaging_process(
    model_fn, client_optimizer_fn=lambda: tf.keras.optimizers.SGD(0.02))

....
NUM_ROUNDS = 11
for round_num in range(2, NUM_ROUNDS):
  state, metrics = trainer.next(state, federated_train_data)
  print('round {:2d}, metrics={}'.format(round_num, metrics))

person Eliza    schedule 02.04.2020    source источник


Ответы (2)


tff.simulation.ClientData объекты предоставляют атрибут client_ids, который представляет список строк, идентифицирующих пользователей в этом наборе данных.

Таким образом, вы можете напрямую выбирать из этого списка и использовать метод create_tf_dataset_for_client для того же объекта, чтобы создать набор данных из данных этого пользователя. Предполагая tff.simulation.ClientData объект client_data, псевдокод будет выглядеть так:

import random
...

for round_num in range(2, NUM_ROUNDS):
  selected_clients = random.sample(client_data.client_ids, USERS_PER_ROUND)
  federated_data = [
      client_data.create_tf_dataset_for_client(n) for n in selected_clients]
  state, metrics = iterative_process.next(state, federated_data)

Большая часть исследовательского кода, включенного в TFF, несколько отделяет проблему выбора клиентов от запуска цикла обучения, поэтому я не могу указать на хороший пример этого шаблона, но TFF, я думаю, был бы рад принять обновление вклада учебные пособия по использованию подобного шаблона, чтобы немного лучше продемонстрировать гибкость ClientData API.

person Keith Rush    schedule 04.04.2020
comment
Ага! Но их может быть сколько угодно - в этом наборе данных тысячи пользователей, если я правильно помню. - person Keith Rush; 16.04.2020
comment
Спасибо, господа, но это вызвало ошибку TypeError: The target type <x=float32[?,784],y=int32[?]>* is not assignable from source type ``<label=int32,pixels=float32[28,28]>* - person Eliza; 17.04.2020
comment
Ах, мне кажется, что эти данные клиента нужно предварительно обработать. Попробуйте предварительно обработать эти данные клиента с помощью функции типа lambda example: collections.OrderedDict(x=tf.reshape(example['pixel'], [-1, 784]), y=example['label']). Если этот фрагмент кода взят из учебника, там должна быть функция предварительной обработки. - person Keith Rush; 17.04.2020
comment
Большое тебе спасибо - person Eliza; 20.04.2020

Это сделает это (следуя псевдокоду Кита):

selected_clients = np.random.choice(emnist_train.client_ids, size=USERS_PER_ROUND)
round_federated_train_data = make_federated_data(emnist_train, selected_clients)
person Nuutti Sten    schedule 11.06.2021