Google I / O, 18-20 Mayıs'ta geri dönüyor! Yer ayırın ve programınızı oluşturun Şimdi kaydolun
Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Kendi Birleşik Öğrenme Algoritmanızı Oluşturmak

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Başlamadan önce

Başlamadan önce, lütfen ortamınızın doğru kurulduğundan emin olmak için aşağıdakileri çalıştırın. Bir karşılama mesajı görmezseniz, talimatlar için lütfen Kurulum kılavuzuna bakın.

!pip install --quiet --upgrade tensorflow-federated-nightly
!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)

Görüntü sınıflandırma ve metin oluşturma eğitimlerinde, Birleşik Öğrenme (FL) için model ve veri işlem hatlarının nasıl kurulacağını öğrendik ve TFF'nin tff.learning API katmanı aracılığıyla birleşik eğitim gerçekleştirdik.

Bu, FL araştırması söz konusu olduğunda buzdağının sadece görünen kısmı. Bu eğitimde, ertelemek olmadan federe öğrenme algoritmaları nasıl uygulanacağını tartışmak tff.learning API. Aşağıdakileri başarmayı hedefliyoruz:

Hedefler:

  • Birleşik öğrenme algoritmalarının genel yapısını anlayın.
  • TFF'nin Federe Çekirdeğini keşfedin.
  • Doğrudan Federated Averaging uygulamak için Federated Core'u kullanın.

Bu eğitim bağımsız olsa da, önce görüntü sınıflandırması ve metin oluşturma eğitimlerini okumanızı öneririz.

Giriş verilerinin hazırlanması

Önce TFF'ye dahil olan EMNIST veri setini yükler ve önceden işleriz. Daha fazla ayrıntı için, görüntü sınıflandırma eğitimine bakın.

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

Veri kümesini modelimize beslemek için verileri düzleştiriyoruz ve her örneği formun bir demetine (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)

Şimdi az sayıda müşteriyi örnekliyoruz ve yukarıdaki ön işlemi veri kümelerine uyguluyoruz.

client_ids = np.random.choice(emnist_train.client_ids, size=NUM_CLIENTS, replace=False)

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

Modeli hazırlamak

Görüntü sınıflandırma eğitiminde olduğu gibi aynı modeli kullanıyoruz. Bu model ( tf.keras aracılığıyla tf.keras ) tek bir gizli katmana ve ardından bir softmax katmanına sahiptir.

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

Bu modeli TFF'de kullanmak için tff.learning.Model modelini tff.learning.Model olarak tff.learning.Model . Bu, modelin TFF içinde ileri geçişini gerçekleştirmemize ve model çıktılarını çıkarmamıza olanak tanır. Daha fazla ayrıntı için, görüntü sınıflandırma eğitimine de bakın.

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

Bir tf.keras oluşturmak için tff.learning.Model , TFF çok daha genel modelleri destekliyor. Bu modeller, model ağırlıklarını yakalayan aşağıdaki ilgili özelliklere sahiptir:

  • trainable_variables : trainable tabakalarına tekabül eden tansörleri bir iterable.
  • non_trainable_variables : Eğitilemeyen katmanlara karşılık gelen tensörlerin yinelenebilirliği.

Amaçlarımız doğrultusunda, yalnızca trainable_variables kullanacağız. (modelimizde sadece bunlara sahip olduğu için!).

Kendi Federe Öğrenme algoritmanızı oluşturma

tff.learning API, bir kişinin Federe Ortalama tff.learning birçok çeşidini oluşturmasına izin verirken, bu çerçeveye tam olarak uymayan başka birleşik algoritmalar da vardır. Örneğin, düzenleme, kırpma veya birleşik GAN eğitimi gibi daha karmaşık algoritmalar eklemek isteyebilirsiniz. Bunun yerine birleşik analitikle de ilgilenebilirsiniz.

Bu daha gelişmiş algoritmalar için, TFF kullanarak kendi özel algoritmamızı yazmamız gerekecek. Çoğu durumda, birleşik algoritmaların 4 ana bileşeni vardır:

  1. Sunucudan istemciye yayın adımı.
  2. Yerel bir istemci güncelleme adımı.
  3. İstemciden sunucuya yükleme adımı.
  4. Bir sunucu güncelleme adımı.

TFF'de, genellikle federe algoritmaları bir tff.templates.IterativeProcess olarak temsil tff.templates.IterativeProcess (ki buna sadece bir IterativeProcess tff.templates.IterativeProcess ). Bu, initialize ve next işlevleri içeren bir sınıftır. Burada, initialize , sunucuyu initialize için kullanılır ve daha next , birleşik algoritmanın bir iletişim turunu gerçekleştirir. FedAvg için yinelemeli sürecimizin nasıl olması gerektiğine dair bir iskelet yazalım.

İlk olarak, basitçe bir tff.learning.Model yaratan ve eğitilebilir ağırlıklarını döndüren bir başlatma fonksiyonumuz var.

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

Bu işlev iyi görünüyor, ancak daha sonra göreceğimiz gibi, onu bir "TFF hesaplaması" yapmak için küçük bir değişiklik yapmamız gerekecek.

Ayrıca next_fn de çizmek istiyoruz.

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

Bu dört bileşeni ayrı ayrı uygulamaya odaklanacağız. Öncelikle saf TensorFlow'da uygulanabilecek parçalara, yani istemci ve sunucu güncelleme adımlarına odaklanıyoruz.

TensorFlow Blokları

İstemci güncellemesi

tff.learning.Model bir TensorFlow modelini eğittiğiniz şekilde müşteri eğitimi yapmak için tff.learning.Model kullanacağız. Özellikle, veri yığınları üzerindeki gradyanı hesaplamak içintf.GradientTape kullanacağız, sonra bu gradyanı bir client_optimizer kullanarak client_optimizer . Sadece eğitilebilir ağırlıklara odaklanıyoruz.

@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

Sunucu Güncellemesi

FedAvg için sunucu güncellemesi, istemci güncellemesinden daha basittir. Sunucu modeli ağırlıklarını basitçe istemci modeli ağırlıklarının ortalaması ile değiştirdiğimiz "vanilya" birleşik ortalama uygulayacağız. Yine, sadece eğitilebilir ağırlıklara odaklanıyoruz.

@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

Snippet, basitçe mean_client_weights basitleştirilebilir. Bununla birlikte, Birleşik Ortalama mean_client_weights daha gelişmiş uygulamaları, momentum veya mean_client_weights gibi daha karmaşık tekniklerle ortalama_ mean_client_weights kullanır.

Zorluk : Sunucu ağırlıklarını model_weights ve mean_client_weights'ın orta noktası olacak şekilde güncelleyen bir server_update sürümü uygulayın. (Not: Bu tür bir "orta nokta" yaklaşımı, Lookahead optimizer üzerindeki son çalışmaya benzer!).

Şimdiye kadar sadece saf TensorFlow kodu yazdık. Bu, tasarım gereğidir, çünkü TFF zaten aşina olduğunuz TensorFlow kodunun çoğunu kullanmanıza izin verir. Ancak, şimdi düzenleme mantığını , yani sunucunun istemciye ne yayınlayacağını ve istemcinin sunucuya ne yükleyeceğini belirleyen mantığı belirtmemiz gerekiyor.

Bu, TFF'nin Federasyon Çekirdeğini gerektirecektir.

Birleşik Çekirdeğe Giriş

Federated Core (FC), tff.learning API'sinin temelini oluşturan bir dizi alt düzey arabirimdir. Ancak bu arayüzler öğrenmeyle sınırlı değildir. Aslında, analitik ve diğer birçok hesaplama için dağıtılmış veriler üzerinden kullanılabilirler.

Yüksek düzeyde, federe çekirdek, kompakt bir şekilde ifade edilen program mantığının TensorFlow kodunu dağıtılmış iletişim operatörleriyle (dağıtılmış toplamlar ve yayınlar gibi) birleştirmesini sağlayan bir geliştirme ortamıdır. Amaç, araştırmacılara ve uygulayıcılara, sistem uygulama ayrıntılarını (noktadan noktaya ağ mesaj alışverişini belirtme gibi) gerektirmeden, sistemlerindeki dağıtılmış iletişim üzerinde kapsamlı kontrol sağlamaktır.

Önemli bir nokta, TFF'nin gizliliğin korunması için tasarlanmış olmasıdır. Bu nedenle, merkezi sunucu konumunda istenmeyen veri birikimini önlemek için verilerin bulunduğu yer üzerinde açık kontrole izin verir.

Birleşik veriler

TFF'deki temel kavram, dağıtılmış bir sistemdeki bir grup cihazda (örneğin, istemci veri kümeleri veya sunucu modeli ağırlıkları) barındırılan veri öğelerinin bir koleksiyonunu ifade eden "birleştirilmiş veriler" dir. Tüm cihazlardaki veri öğelerinin tüm koleksiyonunu tek bir birleşik değer olarak modelleriz.

Örneğin, her biri bir sensörün sıcaklığını temsil eden bir şamandıraya sahip istemci cihazlarımız olduğunu varsayalım. Bunu bir federe şamandıra olarak temsil edebiliriz.

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

Birleşik tipler, üye bileşenlerinin bir T tipi (örn. tf.float32 ) ve bir cihaz grubu G ile belirtilir. G tff.CLIENTS veya tff.SERVER olduğu durumlara odaklanacağız. Böyle bir federe türü, aşağıda gösterildiği gibi {T}@G olarak temsil edilir.

str(federated_float_on_clients)
'{float32}@CLIENTS'

Yerleşimleri neden bu kadar önemsiyoruz? TFF'nin temel amacı, gerçek bir dağıtılmış sistemde konuşlandırılabilen kod yazmayı mümkün kılmaktır. Bu, hangi cihaz alt kümelerinin hangi kodu çalıştırdığını ve farklı veri parçalarının nerede bulunduğunu düşünmenin hayati önem taşıdığı anlamına gelir.

TFF üç şeye odaklanır: veriler , verilerin nereye yerleştirildiği ve verilerin nasıl dönüştürüldüğü . İlk ikisi federe türlerde, sonuncusu ise federe hesaplamalarda kapsüllenir.

Birleşik hesaplamalar

TFF, temel birimleri birleşik hesaplamalar olan, türü güçlü bir işlevsel programlama ortamıdır. Bunlar, birleşik değerleri girdi olarak kabul eden ve çıktı olarak birleşik değerleri döndüren mantık parçalarıdır.

Örneğin, müşteri sensörlerimizdeki sıcaklıkların ortalamasını almak istediğimizi varsayalım. Aşağıdakileri tanımlayabiliriz (federe şamandıramızı kullanarak):

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

Bunun tf.function dekoratöründen ne kadar farklı olduğunu sorabilirsiniz. Temel yanıt, tff.federated_computation tarafından üretilen kodun TensorFlow veya Python kodu olmamasıdır; Dahili bir platformdan bağımsız tutkal dilinde dağıtılmış bir sistemin bir özelliğidir.

Kulağa karmaşık gelse de, TFF hesaplamalarını iyi tanımlanmış tip imzalarına sahip işlevler olarak düşünebilirsiniz. Bu tip imzalar doğrudan sorgulanabilir.

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

Bu tff.federated_computation birleşik Çeşidi bağımsız değişkenleri kabul {float32}@CLIENTS ve birleşik Çeşidi döner değerleri {float32}@SERVER . Federe hesaplamalar ayrıca sunucudan istemciye, istemciden istemciye veya sunucudan sunucuya gidebilir. Birleşik hesaplamalar, tür imzaları eşleştiği sürece normal işlevler gibi de oluşturulabilir.

Geliştirmeyi desteklemek için TFF, tff.federated_computation bir Python işlevi olarak çağırmanıza izin verir. Örneğin arayabiliriz

get_average_temperature([68.5, 70.3, 69.8])
69.53334

İstekli olmayan hesaplamalar ve TensorFlow

Dikkat edilmesi gereken iki temel kısıtlama vardır. İlk olarak, Python yorumlayıcısı bir tff.federated_computation dekoratörüyle karşılaştığında, işlev bir kez izlenir ve ileride kullanılmak üzere serileştirilir. Federe Öğrenmenin merkezi olmayan doğası nedeniyle, bu gelecekteki kullanım, uzaktan yürütme ortamı gibi başka bir yerde gerçekleşebilir. Bu nedenle, TFF hesaplamaları temelde isteksizdir . Bu davranış, tf.function dekoratörünün davranışına biraz benzer.

İkinci olarak, bir federe hesaplama yalnızca birleşik operatörlerden ( tff.federated_mean gibi) oluşabilir, TensorFlow işlemlerini içeremez. TensorFlow kodu, tff.tf_computation ile dekore edilmiş bloklarla sınırlandırılmalıdır. Çoğu sıradan TensorFlow kodu, bir sayı alan ve ona 0.5 ekleyen aşağıdaki işlev gibi doğrudan dekore edilebilir.

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

Bunların da tür imzaları vardır, ancak yerleşim yoktur . Örneğin arayabiliriz

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

Burada tff.federated_computation ve tff.tf_computation arasında önemli bir fark tff.tf_computation . İlki açık yerleşimlere sahipken, ikincisi yok.

Yerleşimleri belirleyerek federe hesaplamalarda tff.tf_computation bloklarını kullanabiliriz. Yarım ekleyen, ancak yalnızca istemcilerdeki birleşik kayan noktalara ekleyen bir işlev oluşturalım. Bunu, yerleşimi korurken belirli bir tff.tf_computation uygulayan tff.federated_map kullanarak tff.federated_map .

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

Bu işlev add_half işleviyle hemen hemen aynıdır, tek fark, yalnızca tff.CLIENTS yerleşimle değerleri kabul eder ve aynı yerleşime sahip değerleri döndürür. Bunu tip imzasında görebiliriz:

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

Özetle:

  • TFF, federe değerlerle çalışır.
  • Her bir federasyon değerinin bir türü (ör. tf.float32 ) ve yerleşimi (ör. tff.CLIENTS ) olan bir federe türü vardır.
  • Birleşik değerler, tff.federated_computation ve bir federe tür imzası ile dekore edilmesi gereken birleşik hesaplamalar kullanılarak dönüştürülebilir.
  • TensorFlow kodu, tff.tf_computation dekoratörlerine sahip bloklarda yer tff.tf_computation .
  • Bu bloklar daha sonra birleşik hesaplamalara dahil edilebilir.

Kendi Federe Öğrenme algoritmanızı oluşturma, yeniden gözden geçirildi

Artık Federe Çekirdeğe bir göz attığımıza göre, kendi birleşik öğrenme algoritmamızı oluşturabiliriz. Yukarıda algoritmamız için bir initialize_fn ve next_fn tanımladığımızı unutmayın. next_fn , saf TensorFlow kodunu kullanarak tanımladığımız client_update ve server_update kullanacaktır.

Ancak, bizim algoritma federe hesaplama yapmak için, biz de gerekecektir next_fn ve initialize_fn her bir olmak tff.federated_computation .

TensorFlow Federasyon blokları

Başlatma hesaplamasının oluşturulması

Başlatma işlevi oldukça basit olacaktır: model_fn kullanarak bir model oluşturacağız. Ancak, TensorFlow kodumuzu tff.tf_computation kullanarak tff.tf_computation gerektiğini unutmayın.

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

Daha sonra bunu tff.federated_value kullanarak doğrudan bir federasyon hesaplamasına tff.federated_value .

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

next_fn oluşturma

Artık gerçek algoritmayı yazmak için istemci ve sunucu güncelleme kodumuzu kullanıyoruz. Önce client_update bir istemci veri kümelerini ve sunucu ağırlıklarını kabul eden ve güncellenmiş bir istemci ağırlık tensörü client_update bir tff.tf_computation .

İşlevimizi düzgün bir şekilde dekore etmek için karşılık gelen türlere ihtiyacımız olacak. Neyse ki, sunucu ağırlıklarının türü doğrudan modelimizden çıkarılabilir.

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

Veri kümesi tipi imzasına bakalım. Unutmayın ki 28'e 28 adet resim (tamsayı etiketleriyle) alıp onları düzleştirdik.

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

Yukarıdaki server_init fonksiyonumuzu kullanarak model ağırlıkları türünü de çıkarabiliriz.

model_weights_type = server_init.type_signature.result

Tip imzasını inceleyerek, modelimizin mimarisini görebileceğiz!

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

Artık istemci güncellemesi için tff.tf_computation oluşturabiliriz.

@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)

Sunucu güncellemesinin tff.tf_computation sürümü, daha önce çıkardığımız türleri kullanarak benzer şekilde tanımlanabilir.

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

Son olarak, tüm bunları bir araya getiren tff.federated_computation yaratmamız gerekiyor. Bu fonksiyon iki birleşik değerleri, bir (yerleşim sunucu ağırlıklarına karşılık gelen kabul tff.SERVER ) ve (yerleşim istemci veri setleri karşı gelen tff.CLIENTS ).

Bu tiplerin her ikisinin de yukarıda tanımlandığını unutmayın! Onlara tff.FederatedType kullanarak uygun yerleşimi tff.FederatedType .

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

FL algoritmasının 4 unsurunu hatırlıyor musunuz?

  1. Sunucudan istemciye yayın adımı.
  2. Yerel bir istemci güncelleme adımı.
  3. İstemciden sunucuya yükleme adımı.
  4. Bir sunucu güncelleme adımı.

Şimdi yukarıdakileri oluşturduğumuza göre, her parça tek bir TFF kodu satırı olarak kompakt bir şekilde temsil edilebilir. Bu basitlik, federasyon türleri gibi şeyleri belirtmek için ekstra özen göstermemizin nedenidir!

@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

Artık hem algoritma başlatma hem de algoritmanın bir adımını çalıştırmak için tff.federated_computation . Algoritmamızı bitirmek için bunları tff.templates.IterativeProcess .

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

initialize ve yinelemeli sürecimizin next işlevlerinin tür imzasına bakalım.

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

Bu gerçeğini yansıtır federated_algorithm.initialize no-Arg fonksiyonudur döndürdüğü (bir 784-ile-10 ağırlık matrisi ile ve 10 ön gerilim birimleri) tek katmanlı modeli.

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

Burada, federated_algorithm.next bir sunucu modelini ve istemci verilerini kabul ettiğini ve güncellenmiş bir sunucu modeli döndürdüğünü görüyoruz.

Algoritmanın değerlendirilmesi

Birkaç tur koşalım ve kaybın nasıl değiştiğini görelim. İlk olarak, ikinci derste tartışılan merkezi yaklaşımı kullanarak bir değerlendirme işlevi tanımlayacağız.

Önce merkezi bir değerlendirme veri kümesi oluştururuz ve ardından eğitim verileri için kullandığımız aynı ön işlemi uygularız.

Not sadece o take hesaplama verimlilik nedeniyle ilk 1000 unsurları, ama genelde biz tüm test veri kümesi kullanmayı tercih ediyorum.

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

Ardından, bir sunucu durumunu kabul eden ve test veri kümesinde değerlendirmek için Keras'ı kullanan bir işlev yazıyoruz. tf.Keras aşina tf.Keras , bunların hepsi tanıdık gelecektir, yine de set_weights kullanımına dikkat edin!

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)

Şimdi algoritmamızı başlatalım ve test seti üzerinde değerlendirelim.

server_state = federated_algorithm.initialize()
evaluate(server_state)
50/50 [==============================] - 0s 2ms/step - loss: 2.3026 - sparse_categorical_accuracy: 0.0910

Birkaç tur antrenman yapalım ve bir değişiklik olup olmadığına bakalım.

for round in range(15):
  server_state = federated_algorithm.next(server_state, federated_train_data)
evaluate(server_state)
50/50 [==============================] - 0s 1ms/step - loss: 2.1706 - sparse_categorical_accuracy: 0.2440

Kayıp fonksiyonunda hafif bir düşüş görüyoruz. Atlama küçük olsa da, yalnızca 10 eğitim turu ve küçük bir müşteri alt kümesinde gerçekleştirdik. Daha iyi sonuçlar görmek için binlerce tur olmasa da yüzlerce tur yapmak zorunda kalabiliriz.

Algoritmamızı değiştirmek

Bu noktada durup neler başardığımızı düşünelim. Saf TensorFlow kodunu (istemci ve sunucu güncellemeleri için) TFF'nin Federated Core'undan birleşik hesaplamalarla birleştirerek doğrudan Federated Averaging'i uyguladık.

Daha sofistike bir öğrenme gerçekleştirmek için yukarıda sahip olduğumuz şeyi basitçe değiştirebiliriz. Özellikle, yukarıdaki saf TF kodunu düzenleyerek, istemcinin eğitimi nasıl gerçekleştirdiğini veya sunucunun modelini nasıl güncelleyeceğini değiştirebiliriz.

Zorluk: client_update işlevine gradyan kırpma ekleyin.

Daha büyük değişiklikler yapmak isteseydik, sunucunun daha fazla veri depolamasını ve yayınlamasını da sağlayabilirdik. Örneğin, sunucu ayrıca istemcinin öğrenme oranını saklayabilir ve zamanla azalmasını sağlayabilir! Bunun yukarıdaki tff.tf_computation çağrılarında kullanılan tip imzalarında değişiklik gerektireceğini unutmayın.

Daha Zor Zorluk: İstemcilerde öğrenme oranı azalması ile Federe Ortalama Alma'yı uygulayın.

Bu noktada, bu çerçevede uygulayabileceğiniz şeylerde ne kadar esneklik olduğunu fark etmeye başlayabilirsiniz. Fikirler için (yukarıdaki daha zor sorunun cevabı dahil) tff.learning.build_federated_averaging_process için kaynak kodunu görebilir veya TFF kullanarak çeşitli araştırma projelerine göz atabilirsiniz.