Pomoc chronić Wielkiej Rafy Koralowej z TensorFlow na Kaggle Dołącz Wyzwanie

Budowanie własnego algorytmu sfederowanego uczenia się

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Zanim zaczniemy

Zanim zaczniemy, wykonaj następujące czynności, aby upewnić się, że Twoje środowisko jest poprawnie skonfigurowane. Jeśli nie pojawi się powitanie, proszę odnieść się do montażu prowadnicy do instrukcji.

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

import nest_asyncio
nest_asyncio.apply()
import tensorflow as tf
import tensorflow_federated as tff

W klasyfikacji obraz i tekst generacji tutoriale, dowiedzieliśmy się, jak skonfigurować modelu i danych rurociągi dla Federacji Learning (FL) i przeprowadzono szkolenia stowarzyszonego przez tff.learning warstwy API TFF.

To tylko wierzchołek góry lodowej, jeśli chodzi o badania nad FL. W tym tutorialu omówimy jak zaimplementować algorytmy uczenia stowarzyszonych bez odroczenia do tff.learning API. Naszym celem jest:

Cele:

  • Zapoznaj się z ogólną strukturą algorytmów sfederowanego uczenia się.
  • Przeglądaj stowarzyszonej Core of TFF.
  • Użyj federacyjnego rdzenia, aby bezpośrednio zaimplementować federacyjne uśrednianie.

Chociaż ten poradnik jest samowystarczalny, zalecamy pierwszym czytaniu klasyfikacji obrazu i generowanie tekstu tutoriale.

Przygotowanie danych wejściowych

Najpierw ładujemy i wstępnie przetwarzamy zbiór danych EMNIST zawarty w TFF. Aby uzyskać więcej informacji, zobacz klasyfikacji obrazu samouczek.

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

W celu zasilania zestawu danych w naszym modelu spłaszczyć dane i konwertować każdego przykładu w krotce formularza (flattened_image_vector, label) .

NUM_CLIENTS = 10
BATCH_SIZE = 20

def preprocess(dataset):

  def batch_format_fn(element):
    """Flatten a batch of EMNIST data and return a (features, label) tuple."""
    return (tf.reshape(element['pixels'], [-1, 784]), 
            tf.reshape(element['label'], [-1, 1]))

  return dataset.batch(BATCH_SIZE).map(batch_format_fn)

Teraz wybieramy niewielką liczbę klientów i stosujemy powyższe przetwarzanie wstępne do ich zestawów danych.

client_ids = sorted(emnist_train.client_ids)[:NUM_CLIENTS]
federated_train_data = [preprocess(emnist_train.create_tf_dataset_for_client(x))
  for x in client_ids
]

Przygotowanie modelu

Używamy ten sam model jak w klasyfikacji obrazu tutoriala. Model (realizowane poprzez tf.keras ) ma jeden ukryty warstwę, a następnie przez Softmax warstwy.

def create_keras_model():
  initializer = tf.keras.initializers.GlorotNormal(seed=0)
  return tf.keras.models.Sequential([
      tf.keras.layers.Input(shape=(784,)),
      tf.keras.layers.Dense(10, kernel_initializer=initializer),
      tf.keras.layers.Softmax(),
  ])

W celu wykorzystania tego modelu w TFF, możemy owinąć model Keras jako tff.learning.Model . To pozwala nam na wykonywanie modelki podaniu w ciągu TFF, a modelowe ekstrakt wyjścia . Aby uzyskać więcej informacji, zobacz również klasyfikacja obraz samouczek.

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()])

Podczas gdy użyliśmy tf.keras stworzyć tff.learning.Model , TFF obsługuje wiele bardziej ogólnych modeli. Modele te mają następujące istotne atrybuty rejestrujące wagi modeli:

  • trainable_variables : AN iterowalny z tensorów odpowiadających nadającego się warstwy.
  • non_trainable_variables : AN iterowalny z tensorów odpowiadających nie nadającego się warstwy.

Dla naszych celów użyjemy tylko trainable_variables . (ponieważ nasz model ma tylko te!).

Budowanie własnego algorytmu Federated Learning

Choć tff.learning API pozwala na tworzenie wielu wariantów Federalne uśredniania, istnieją inne stowarzyszone algorytmy, które nie pasują idealnie do tych ram. Na przykład, może chcesz dodać regularyzacji, strzyżenie, lub bardziej skomplikowanych algorytmów, takich jak stowarzyszonym szkolenia GAN . Użytkownik może również zamiast być zainteresowany federacyjnych analityki .

W przypadku tych bardziej zaawansowanych algorytmów będziemy musieli napisać własny algorytm niestandardowy przy użyciu TFF. W wielu przypadkach algorytmy sfederowane składają się z 4 głównych elementów:

  1. Krok emisji serwer-klient.
  2. Krok aktualizacji klienta lokalnego.
  3. Krok przesyłania klient-serwer.
  4. Krok aktualizacji serwera.

W TFF, na ogół reprezentują federacyjnych algorytmy jak tff.templates.IterativeProcess (które nazywamy tylko IterativeProcess całej). Jest to klasa, która zawiera initialize i next funkcje. Tutaj initialize służy do inicjowania serwer, a next będzie wykonać jedną rundę komunikacji algorytmu stowarzyszonym. Napiszmy szkielet tego, jak powinien wyglądać nasz iteracyjny proces dla FedAvg.

Po pierwsze, mamy initialize funkcji, które po prostu tworzy tff.learning.Model i zwraca jego wyszkolić ciężarów.

def initialize_fn():
  model = model_fn()
  return model.trainable_variables

Ta funkcja wygląda dobrze, ale jak zobaczymy później, będziemy musieli dokonać niewielkiej modyfikacji, aby była to "obliczenie TFF".

Chcemy także szkic next_fn .

def next_fn(server_weights, federated_dataset):
  # Broadcast the server weights to the clients.
  server_weights_at_client = broadcast(server_weights)

  # Each client computes their updated weights.
  client_weights = client_update(federated_dataset, server_weights_at_client)

  # The server averages these updates.
  mean_client_weights = mean(client_weights)

  # The server updates its model.
  server_weights = server_update(mean_client_weights)

  return server_weights

Skoncentrujemy się na wdrażaniu tych czterech komponentów osobno. Najpierw skupiamy się na częściach, które można zaimplementować w czystym TensorFlow, a mianowicie na krokach aktualizacji klienta i serwera.

Bloki TensorFlow

Aktualizacja klienta

Będziemy wykorzystywać nasze tff.learning.Model zrobić szkolenie klienta w zasadzie w ten sam sposób, byś trenowania modelu TensorFlow. W szczególności, będziemy używać tf.GradientTape obliczyć gradient na seriach danych, a następnie zastosować te gradientu przy użyciu client_optimizer . Skupiamy się tylko na ciężarach do trenowania.

@tf.function
def client_update(model, dataset, server_weights, client_optimizer):
  """Performs training (using the server model weights) on the client's dataset."""
  # Initialize the client model with the current server weights.
  client_weights = model.trainable_variables
  # Assign the server weights to the client model.
  tf.nest.map_structure(lambda x, y: x.assign(y),
                        client_weights, server_weights)

  # Use the client_optimizer to update the local model.
  for batch in dataset:
    with tf.GradientTape() as tape:
      # Compute a forward pass on the batch of data
      outputs = model.forward_pass(batch)

    # Compute the corresponding gradient
    grads = tape.gradient(outputs.loss, client_weights)
    grads_and_vars = zip(grads, client_weights)

    # Apply the gradient using a client optimizer.
    client_optimizer.apply_gradients(grads_and_vars)

  return client_weights

Aktualizacja serwera

Aktualizacja serwera dla FedAvg jest prostsza niż aktualizacja klienta. Wdrożymy „waniliowe” uśrednianie sfederowane, w którym po prostu zastąpimy wagi modelu serwera średnią wag modelu klienta. Ponownie skupiamy się tylko na ciężarach do trenowania.

@tf.function
def server_update(model, mean_client_weights):
  """Updates the server model weights as the average of the client model weights."""
  model_weights = model.trainable_variables
  # Assign the mean client weights to the server model.
  tf.nest.map_structure(lambda x, y: x.assign(y),
                        model_weights, mean_client_weights)
  return model_weights

Fragment kodu może zostać uproszczone poprzez proste odesłanie mean_client_weights . Jednak bardziej zaawansowane implementacje Federated użytku uśredniania mean_client_weights z bardziej zaawansowanych technik, takich jak pęd lub adaptacyjności.

Wyzwanie: Wdrożenie wersji server_update który aktualizuje wagi serwera będzie środkiem boku model_weights i mean_client_weights. (Uwaga: Ten rodzaj podejścia „środkowym” jest analogiczna do ostatnich prac na optymalizator uprzedzona !).

Do tej pory pisaliśmy tylko czysty kod TensorFlow. Jest to zgodne z projektem, ponieważ TFF pozwala na użycie znacznej części kodu TensorFlow, który już znasz. Jednak teraz musimy określić logikę orkiestracji, czyli logika dyktuje, co transmisje serwera do klienta, a co dodane klienta do serwera.

Będzie to wymagało Federalne Core of TFF.

Wprowadzenie do sfederowanego rdzenia

Sfederowane Rdzeń (FC) to zestaw interfejsów niższego poziomu, które służą jako podstawa do tff.learning API. Jednak te interfejsy nie ograniczają się do nauki. W rzeczywistości mogą być używane do analiz i wielu innych obliczeń na danych rozproszonych.

Na wysokim poziomie rdzeń sfederowany jest środowiskiem programistycznym, które umożliwia zwartą logikę programu w celu połączenia kodu TensorFlow z operatorami komunikacji rozproszonej (takimi jak sumy rozproszone i rozgłaszanie). Celem jest zapewnienie naukowcom i praktykom wyraźnej kontroli nad komunikacją rozproszoną w ich systemach, bez wymagania szczegółów implementacji systemu (takich jak określanie wymiany komunikatów w sieci punkt-punkt).

Jedną z kluczowych kwestii jest to, że TFF jest przeznaczony do ochrony prywatności. W związku z tym umożliwia wyraźną kontrolę nad miejscem przechowywania danych, aby zapobiec niepożądanemu gromadzeniu danych w scentralizowanej lokalizacji serwera.

Dane federacyjne

Kluczową koncepcją w TFF są „dane sfederowane”, które odnoszą się do zbioru elementów danych hostowanych na grupie urządzeń w systemie rozproszonym (np. zestawy danych klientów lub wagi modelu serwera). Modelujemy cały zbiór elementów danych na wszystkich urządzeniach jako pojedyncza wartość stowarzyszonym.

Załóżmy na przykład, że mamy urządzenia klienckie, z których każde ma pływak reprezentujący temperaturę czujnika. Możemy reprezentować go jako stowarzyszonym płyną

federated_float_on_clients = tff.FederatedType(tf.float32, tff.CLIENTS)

Stowarzyszone typów określa typu T z jego składników członków (np. tf.float32 ) i grupy G urządzeń. Skupimy się na przypadkach, gdzie G jest albo tff.CLIENTS lub tff.SERVER . Taki typ stowarzyszonego reprezentowane {T}@G , jak pokazano poniżej.

str(federated_float_on_clients)
'{float32}@CLIENTS'

Dlaczego tak bardzo zależy nam na stażach? Kluczowym celem TFF jest umożliwienie pisania kodu, który można wdrożyć w rzeczywistym systemie rozproszonym. Oznacza to, że konieczne jest ustalenie, które podzbiory urządzeń wykonują dany kod i gdzie znajdują się różne fragmenty danych.

TFF skupia się na trzech rzeczach: danych, gdzie dane są wprowadzane, oraz w jaki sposób dane są przekształcane. Pierwsze dwa są obudowane w federacyjnych typów, natomiast ostatni jest zamknięty w federacyjnych obliczeń.

Obliczenia federacyjne

TFF jest silnie wpisany funkcjonalne środowisko programistyczne, którego podstawowym jednostki stowarzyszoneobliczenia. Są to elementy logiki, które akceptują wartości stowarzyszone jako dane wejściowe i zwracają wartości stowarzyszone jako dane wyjściowe.

Załóżmy na przykład, że chcemy uśrednić temperatury na czujnikach naszych klientów. Możemy zdefiniować:

@tff.federated_computation(tff.FederatedType(tf.float32, tff.CLIENTS))
def get_average_temperature(client_temperatures):
  return tff.federated_mean(client_temperatures)

Można zapytać, jak to jest różne od tf.function dekoratora w TensorFlow? Klucz odpowiedzi jest to, że kod wygenerowany przez tff.federated_computation jest ani TensorFlow ani Python kod; Jest to specyfikacja systemu rozproszonego w wewnętrznym języku klej niezależny od platformy.

Choć może to wydawać się skomplikowane, możesz myśleć o obliczeniach TFF jako o funkcjach z dobrze zdefiniowanymi sygnaturami typów. Te sygnatury mogą być bezpośrednio przeszukiwane.

str(get_average_temperature.type_signature)
'({float32}@CLIENTS -> float32@SERVER)'

Ten tff.federated_computation przyjmuje argumenty stowarzyszony typu {float32}@CLIENTS i zwraca wartości stowarzyszonego typu {float32}@SERVER . Obliczenia federacyjne mogą również przechodzić od serwera do klienta, od klienta do klienta lub od serwera do serwera. Obliczenia sfederowane mogą być również tworzone jak normalne funkcje, o ile ich sygnatury typów są zgodne.

Wspieranie rozwoju, TFF pozwala wywołać tff.federated_computation jako funkcję Pythona. Na przykład możemy zadzwonić

get_average_temperature([68.5, 70.3, 69.8])
69.53334

Niechętne obliczenia i TensorFlow

Należy pamiętać o dwóch kluczowych ograniczeniach. Po pierwsze, gdy interpreter Pythona napotka tff.federated_computation dekorator, funkcja jest prześledzić raz i szeregowane do wykorzystania w przyszłości. Ze względu na zdecentralizowany charakter Federated Learning, to przyszłe użycie może mieć miejsce gdzie indziej, na przykład w środowisku zdalnego wykonywania. Zatem obliczenia TFF to zasadniczo nie skory. Takie zachowanie jest nieco analogiczne do tego z tf.function dekoratora w TensorFlow.

Po drugie, stowarzyszony obliczenie może składać się wyłącznie z podmiotów stowarzyszonych (takich jak tff.federated_mean ), nie mogą zawierać operacje TensorFlow. Kod TensorFlow musi ograniczać się do bloków ozdobionych tff.tf_computation . Najzwyklejszy kod TensorFlow można bezpośrednio urządzony, jak na poniższym funkcję, która pobiera liczbę i dodaje 0.5 do niego.

@tff.tf_computation(tf.float32)
def add_half(x):
  return tf.add(x, 0.5)

Mają one również podpisy typu, ale bez miejsc docelowych. Na przykład możemy zadzwonić

str(add_half.type_signature)
'(float32 -> float32)'

Tutaj widzimy ważną różnicę między tff.federated_computation i tff.tf_computation . Pierwsza ma wyraźne lokacje, a druga nie.

Możemy użyć tff.tf_computation bloki w federacyjnych obliczeń określając docelowe. Stwórzmy funkcję, która dodaje połowę, ale tylko do sfederowanych pływaków na klientach. Możemy to zrobić za pomocą tff.federated_map , która dotyczy danego tff.tf_computation , zachowując położenie.

@tff.federated_computation(tff.FederatedType(tf.float32, tff.CLIENTS))
def add_half_on_clients(x):
  return tff.federated_map(add_half, x)

Funkcja ta jest niemal identyczna add_half , oprócz tego, że przyjmuje tylko wartości z umieszczenia w tff.CLIENTS i wartości wraca z tego samego miejsca. Widać to w sygnaturze typu:

str(add_half_on_clients.type_signature)
'({float32}@CLIENTS -> {float32}@CLIENTS)'

W podsumowaniu:

  • TFF działa na wartościach stowarzyszonych.
  • Każda wartość stowarzyszony ma stowarzyszonego typ, z rodzaju (np. tf.float32 ) i stażu (np. tff.CLIENTS ).
  • Wartości stowarzyszonych można przekształcić za pomocą stowarzyszonych obliczeń, które muszą być ozdobione tff.federated_computation i stowarzyszonym podpisu typu.
  • Kod TensorFlow muszą być zawarte w blokach z tff.tf_computation dekoratorów.
  • Bloki te można następnie włączyć do obliczeń stowarzyszonych.

Budowanie własnego algorytmu Federated Learning, ponownie

Teraz, gdy już rzuciliśmy okiem na Federated Core, możemy zbudować własny algorytm sfederowanego uczenia się. Pamiętaj, że powyżej, zdefiniował initialize_fn i next_fn dla naszego algorytmu. next_fn będzie skorzystać z client_update i server_update określiliśmy przy użyciu czystego kodu TensorFlow.

Jednak w celu zapewnienia nasz algorytm obliczeniowy federacyjnych, musimy zarówno next_fn i initialize_fn siebie być tff.federated_computation .

Bloki sfederowane TensorFlow

Tworzenie obliczeń inicjujących

Funkcja initialize będzie dość prosta: Stworzymy model używając model_fn . Należy jednak pamiętać, że musimy oddzielić nasz kod TensorFlow użyciu tff.tf_computation .

@tff.tf_computation
def server_init():
  model = model_fn()
  return model.trainable_variables

Następnie możemy przejść bezpośrednio do tego stowarzyszonej obliczeń przy użyciu tff.federated_value .

@tff.federated_computation
def initialize_fn():
  return tff.federated_value(server_init(), tff.SERVER)

Tworzenie next_fn

Używamy teraz naszego kodu aktualizacji klienta i serwera, aby napisać rzeczywisty algorytm. Będziemy najpierw zwrócić client_update w tff.tf_computation że akceptuje zestawów danych klienta i serwera, a ciężary wyjść zaktualizowany klient tensora ciężary.

Będziemy potrzebować odpowiednich typów, aby odpowiednio udekorować naszą funkcję. Na szczęście typ wag serwera można wydobyć bezpośrednio z naszego modelu.

whimsy_model = model_fn()
tf_dataset_type = tff.SequenceType(whimsy_model.input_spec)

Spójrzmy na sygnaturę typu zestawu danych. Pamiętaj, że zrobiliśmy zdjęcia 28 na 28 (z etykietami liczb całkowitych) i spłaszczyliśmy je.

str(tf_dataset_type)
'<float32[?,784],int32[?,1]>*'

Możemy także wyodrębnić typu modelu ciężarów za pomocą naszego server_init funkcję powyżej.

model_weights_type = server_init.type_signature.result

Analizując sygnaturę typu, będziemy mogli zobaczyć architekturę naszego modelu!

str(model_weights_type)
'<float32[784,10],float32[10]>'

Teraz możemy stworzyć naszą tff.tf_computation dla aktualizacji klienta.

@tff.tf_computation(tf_dataset_type, model_weights_type)
def client_update_fn(tf_dataset, server_weights):
  model = model_fn()
  client_optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
  return client_update(model, tf_dataset, server_weights, client_optimizer)

tff.tf_computation wersja aktualizacji serwera może być zdefiniowana w podobny sposób, przy użyciu typów mamy już wydobyte.

@tff.tf_computation(model_weights_type)
def server_update_fn(mean_client_weights):
  model = model_fn()
  return server_update(model, mean_client_weights)

Ostatni, ale nie najmniej, musimy stworzyć tff.federated_computation że przynosi to wszystko razem. Ta funkcja może przyjmować dwie wartości stowarzyszonym jeden odpowiadające ciężarami Server (z placement tff.SERVER ), az drugiej odpowiadające zestawów danych klienta (z pośrednictwa tff.CLIENTS ).

Zauważ, że oba te typy zostały zdefiniowane powyżej! Po prostu trzeba dać im właściwe rozmieszczenie używając tff.FederatedType .

federated_server_type = tff.FederatedType(model_weights_type, tff.SERVER)
federated_dataset_type = tff.FederatedType(tf_dataset_type, tff.CLIENTS)

Pamiętasz 4 elementy algorytmu FL?

  1. Krok emisji serwer-klient.
  2. Krok aktualizacji klienta lokalnego.
  3. Krok przesyłania klient-serwer.
  4. Krok aktualizacji serwera.

Teraz, gdy zbudowaliśmy powyższe, każdą część można zwięźle przedstawić jako pojedynczy wiersz kodu TFF. Ta prostota jest powodem, dla którego musieliśmy zachować szczególną ostrożność, aby określić takie rzeczy, jak typy sfederowane!

@tff.federated_computation(federated_server_type, federated_dataset_type)
def next_fn(server_weights, federated_dataset):
  # Broadcast the server weights to the clients.
  server_weights_at_client = tff.federated_broadcast(server_weights)

  # Each client computes their updated weights.
  client_weights = tff.federated_map(
      client_update_fn, (federated_dataset, server_weights_at_client))

  # The server averages these updates.
  mean_client_weights = tff.federated_mean(client_weights)

  # The server updates its model.
  server_weights = tff.federated_map(server_update_fn, mean_client_weights)

  return server_weights

Mamy teraz tff.federated_computation zarówno inicjalizacji algorytmu, a na prowadzenie krok algorytmu. Aby zakończyć nasz algorytm, mijamy je w tff.templates.IterativeProcess .

federated_algorithm = tff.templates.IterativeProcess(
    initialize_fn=initialize_fn,
    next_fn=next_fn
)

Chodźmy na wygląd podpisu type initialize i next funkcji naszego procesu iteracyjnego.

str(federated_algorithm.initialize.type_signature)
'( -> <float32[784,10],float32[10]>@SERVER)'

Wynika to z faktu, że federated_algorithm.initialize jest nie-Arg funkcję, która zwraca modelu pojedynczej warstwy (z matrycą 784, przez -10 wagi i 10 jednostek bias).

str(federated_algorithm.next.type_signature)
'(<server_weights=<float32[784,10],float32[10]>@SERVER,federated_dataset={<float32[?,784],int32[?,1]>*}@CLIENTS> -> <float32[784,10],float32[10]>@SERVER)'

Tutaj widzimy, że federated_algorithm.next akceptuje model serwera i danych klienta i zwraca zaktualizowany model serwera.

Ocena algorytmu

Przeprowadźmy kilka rund i zobaczmy, jak zmienia się strata. Po pierwsze, możemy zdefiniować funkcję oceny za pomocą scentralizowanego podejścia omawianego w drugim kursie.

Najpierw tworzymy scentralizowany zestaw danych oceny, a następnie stosujemy to samo wstępne przetwarzanie, które wykorzystaliśmy do danych uczących.

central_emnist_test = emnist_test.create_tf_dataset_from_all_clients()
central_emnist_test = preprocess(central_emnist_test)

Następnie piszemy funkcję, która akceptuje stan serwera i używa Keras do oceny na testowym zestawie danych. Jeśli jesteś zaznajomiony z tf.Keras , będzie to wszystko wyglądać znajomo, choć uwaga użycie set_weights !

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)

Teraz zainicjujmy nasz algorytm i oceńmy na zestawie testowym.

server_state = federated_algorithm.initialize()
evaluate(server_state)
2042/2042 [==============================] - 2s 767us/step - loss: 2.8479 - sparse_categorical_accuracy: 0.1027

Poćwiczmy kilka rund i zobaczmy, czy coś się zmieni.

for round in range(15):
  server_state = federated_algorithm.next(server_state, federated_train_data)
evaluate(server_state)
2042/2042 [==============================] - 2s 738us/step - loss: 2.5867 - sparse_categorical_accuracy: 0.0980

Widzimy niewielki spadek funkcji straty. Chociaż skok jest niewielki, wykonaliśmy tylko 15 rund treningowych i na niewielkiej podgrupie klientów. Aby zobaczyć lepsze wyniki, być może będziemy musieli wykonać setki, jeśli nie tysiące rund.

Modyfikowanie naszego algorytmu

W tym momencie zatrzymajmy się i pomyślmy o tym, co osiągnęliśmy. Wdrożyliśmy Federated Averaging bezpośrednio, łącząc czysty kod TensorFlow (dla aktualizacji klienta i serwera) ze sfederowanymi obliczeniami z Federated Core TFF.

Aby przeprowadzić bardziej wyrafinowaną naukę, możemy po prostu zmienić to, co mamy powyżej. W szczególności, edytując powyższy czysty kod TF, możemy zmienić sposób, w jaki klient wykonuje szkolenie lub jak serwer aktualizuje swój model.

Wyzwaniem Dodaj wycinek gradientu do client_update funkcji.

Gdybyśmy chcieli dokonać większych zmian, moglibyśmy również mieć serwer przechowywania i transmitować więcej danych. Na przykład serwer może również przechowywać szybkość uczenia się klienta i powodować jej zanikanie w czasie! Należy pamiętać, że będzie to wymagało zmian w podpisach typu stosowanego w tff.tf_computation wzywa powyżej.

Trudniejsze wyzwanie: Wdrożenie Federalne Uśrednianie z nauką próchnicy oceń na klientach.

W tym momencie możesz zacząć zdawać sobie sprawę, ile elastyczności jest w tym, co możesz zaimplementować w tym frameworku. Pomysłów (w tym odpowiedzi na trudniejsze wyzwanie powyżej) można zobaczyć kod źródłowy dla tff.learning.build_federated_averaging_process , lub sprawdzić różne projekty badawcze z wykorzystaniem TFF.