ساخت الگوریتم یادگیری فدرال خود

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

قبل از اینکه شروع کنیم

قبل از شروع، لطفاً موارد زیر را اجرا کنید تا مطمئن شوید که محیط شما به درستی تنظیم شده است. اگر شما یک تبریک نمی بینم، لطفا به مراجعه نصب و راه اندازی راهنمای دستورالعمل.

!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

در طبقه بندی تصویر و متن نسل آموزش، ما آموخته است که چگونه به راه اندازی مدل و داده خطوط لوله برای فدرال آموزش (FL)، و آموزش فدرال از طریق انجام tff.learning لایه API از TFF.

این تنها نوک کوه یخ در مورد تحقیقات FL است. در این آموزش، ما در مورد چگونگی پیاده سازی الگوریتم های یادگیری فدرال بدون تعویق انداختن به tff.learning API. هدف ما رسیدن به موارد زیر است:

اهداف:

  • ساختار کلی الگوریتم های یادگیری فدرال را درک کنید.
  • کاوش فدرال هسته TFF.
  • از هسته فدرال برای اجرای مستقیم میانگین گیری فدرال استفاده کنید.

در حالی که این آموزش خود شامل است، توصیه می کنیم خواندن اولین طبقه بندی تصویر و متن آموزش.

آماده سازی داده های ورودی

ابتدا مجموعه داده EMNIST موجود در TFF را بارگیری و پیش پردازش می کنیم. برای جزئیات بیشتر، نگاه کنید به طبقه بندی تصویر آموزش.

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

به منظور تغذیه از مجموعه داده به مدل ما، ما پهن کردن داده ها، و تبدیل هر عنوان مثال به یک تاپل از فرم (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)

اکنون تعداد کمی از مشتریان را انتخاب می کنیم و پیش پردازش فوق را در مجموعه داده های آنها اعمال می کنیم.

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
]

آماده سازی مدل

ما با استفاده از همان مدل در طبقه بندی تصویر آموزش. این مدل (اجرا از طریق tf.keras ) دارای یک لایه تنها پنهان، دنبال آن یک لایه softmax.

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

به منظور استفاده از این مدل در TFF، ما مدل Keras به عنوان یک بسته بندی tff.learning.Model . این اجازه می دهد تا ما را به انجام مدل پاس رو به جلو در TFF و خروجی مدل عصاره . برای اطلاعات بیشتر، همچنین نگاه کنید به طبقه بندی تصویر آموزش.

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

در حالی که ما استفاده tf.keras برای ایجاد یک tff.learning.Model ، TFF از مدل های بسیار کلی تر. این مدل ها دارای ویژگی های مرتبط زیر برای گرفتن وزن مدل هستند:

  • trainable_variables : یک iterable از تانسورها مربوط به لایه های تربیت شدنی
  • non_trainable_variables : یک iterable از تانسورها مربوط به لایه های غیر تربیت شدنی

برای اهداف ما، ما فقط استفاده trainable_variables . (به عنوان مدل ما فقط آن ها را دارد!).

الگوریتم یادگیری فدرال خود را بسازید

در حالی که tff.learning API اجازه می دهد تا یک برای ایجاد انواع بسیاری از به طور متوسط فدرال، دیگر الگوریتم های فدرال که به این چارچوب، قرار نمی گیرند وجود دارد. به عنوان مثال، شما ممکن است بخواهید به اضافه کردن تنظیم، قطع، یا الگوریتم های پیچیده تر مانند آموزش GAN فدرال . شما همچنین ممکن است به جای در علاقه مند می شود تجزیه و تحلیل فدرال .

برای این الگوریتم های پیشرفته تر، ما باید الگوریتم سفارشی خود را با استفاده از TFF بنویسیم. در بسیاری از موارد، الگوریتم های فدرال دارای 4 جزء اصلی هستند:

  1. مرحله پخش از سرور به مشتری.
  2. مرحله به روز رسانی مشتری محلی.
  3. مرحله آپلود مشتری به سرور.
  4. مرحله به روز رسانی سرور

در TFF، ما به طور کلی نشان دهنده الگوریتم فدرال به عنوان یک tff.templates.IterativeProcess (که ما آن را فقط برای اشاره IterativeProcess در سراسر). این یک کلاس است که شامل initialize و next توابع. در اینجا، initialize استفاده می شود برای مقداردهی اولیه سرور، و next خواهد یک دور ارتباطات از الگوریتم فدرال انجام دهد. بیایید اسکلتی بنویسیم که فرآیند تکراری ما برای FedAvg چگونه باید باشد.

اول، ما باید یک تابع مقداردهی اولیه که به سادگی ایجاد یک tff.learning.Model ، و وزن تربیت شدنی خود برمی گردد.

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

این تابع خوب به نظر می رسد، اما همانطور که بعداً خواهیم دید، باید یک اصلاح کوچک ایجاد کنیم تا آن را به یک "محاسبات TFF" تبدیل کنیم.

ما همچنین می خواهیم به طرح 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

ما بر پیاده سازی این چهار جزء به طور جداگانه تمرکز خواهیم کرد. ما ابتدا روی قسمت هایی تمرکز می کنیم که می توانند در TensorFlow خالص پیاده سازی شوند، یعنی مراحل به روز رسانی کلاینت و سرور.

بلوک های TensorFlow

به روز رسانی مشتری

ما ما استفاده خواهد کرد tff.learning.Model به انجام این آموزش مشتری در اساس به همان شیوه شما می توانید یک مدل TensorFlow آموزش. به طور خاص، ما استفاده از tf.GradientTape برای محاسبه شیب در دسته از داده ها، پس از آن اعمال این شیب با استفاده از یک client_optimizer . ما فقط روی وزنه های قابل تمرین تمرکز می کنیم.

@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

به روز رسانی سرور

به روز رسانی سرور برای FedAvg ساده تر از به روز رسانی مشتری است. ما میانگین‌گیری فدرال «وانیلی» را پیاده‌سازی می‌کنیم که در آن وزن مدل سرور را با میانگین وزن مدل مشتری جایگزین می‌کنیم. باز هم، ما فقط روی وزنه های قابل تمرین تمرکز می کنیم.

@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

قطعه را می توان با بازگشت ساده ساده شده mean_client_weights . با این حال، پیاده سازی پیشرفته تر از فدرال استفاده به طور متوسط mean_client_weights با تکنیک های پیچیده تر، مانند حرکت یا انطباق.

چالش: پیاده سازی یک نسخه از server_update که به روز رسانی وزن سرور به شود از نقطه میانی model_weights و mean_client_weights. (توجه: این نوع رویکرد "نقطه میانی" مشابه آثار اخیر در مورد است بهینه ساز پیشبینی !).

تا کنون، ما فقط کد تنسورفلو خالص را نوشته ایم. این بر اساس طراحی است، زیرا TFF به شما اجازه می دهد تا از بسیاری از کدهای TensorFlow که قبلاً با آن آشنا هستید استفاده کنید. با این حال، در حال حاضر ما باید برای مشخص کردن منطق ارکستراسیون، این است که، که منطق چه پخش سرور به مشتری، و چه ارسال کلاینت به سرور.

با این کار فدرال هسته TFF نیاز داشته باشد.

مقدمه ای بر هسته فدرال

فدرال هسته (FC) مجموعه ای از رابط سطح پایین تر که به عنوان پایه و اساس برای خدمت است tff.learning API. با این حال، این رابط ها به یادگیری محدود نمی شوند. در واقع، آنها را می توان برای تجزیه و تحلیل و بسیاری از محاسبات دیگر بر روی داده های توزیع شده استفاده کرد.

در سطح بالا، هسته فدرال یک محیط توسعه است که منطق برنامه به طور فشرده بیان شده را قادر می سازد تا کد TensorFlow را با اپراتورهای ارتباطی توزیع شده (مانند مبالغ توزیع شده و پخش) ترکیب کند. هدف این است که بدون نیاز به جزئیات پیاده سازی سیستم (مانند مشخص کردن تبادل پیام شبکه نقطه به نقطه) به محققان و متخصصان کنترل صریح بر ارتباطات توزیع شده در سیستم هایشان داده شود.

یک نکته کلیدی این است که TFF برای حفظ حریم خصوصی طراحی شده است. بنابراین، امکان کنترل صریح محل قرارگیری داده ها را فراهم می کند تا از تجمع ناخواسته داده ها در محل سرور متمرکز جلوگیری شود.

داده های فدرال

یک مفهوم کلیدی در TFF "داده های فدرال" است که به مجموعه ای از اقلام داده ای اشاره دارد که در میان گروهی از دستگاه ها در یک سیستم توزیع شده میزبانی می شوند (به عنوان مثال مجموعه داده های مشتری یا وزن مدل سرور). ما در مدل کل مجموعه ای از داده ها در تمام دستگاه به عنوان یک ارزش فدرال است.

به عنوان مثال، فرض کنید دستگاه های مشتری داریم که هر کدام یک شناور دارند که دمای یک سنسور را نشان می دهد. ما که به آن به عنوان یک شناور فدرال توسط نماینده

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

انواع فدرال توسط یک نوع مشخص T از ترکیبات عضو آن (به عنوان مثال. tf.float32 ) و یک گروه G از دستگاه. ما در مواردی که تمرکز خواهد G هم است tff.CLIENTS یا tff.SERVER . چنین نوع فدرال به عنوان نمایندگی {T}@G ، به عنوان زیر نشان داده شده.

str(federated_float_on_clients)
'{float32}@CLIENTS'

چرا ما اینقدر به جایگاه ها اهمیت می دهیم؟ هدف اصلی TFF فعال کردن کد نوشتن است که می تواند در یک سیستم توزیع شده واقعی مستقر شود. این به این معنی است که بسیار مهم است که در مورد اینکه کدام زیرمجموعه از دستگاه‌ها کدام کد را اجرا می‌کنند و قطعات مختلف داده در کجا قرار دارند، استدلال کنیم.

TFF بر سه چیز است: داده ها، که در آن داده قرار داده شده است، و چگونه داده ها در حال تبدیل شده است. در دو مورد اول در انواع فدرال و محصور شده، در حالی که آخرین در محاسبات فدرال محصور شده.

محاسبات فدرال

TFF یک محیط برنامه نویسی تابعی به شدت تایپ که واحد پایه محاسبات فدرال می باشد. اینها قطعات منطقی هستند که مقادیر فدرال را به عنوان ورودی می پذیرند و مقادیر فدرال را به عنوان خروجی برمی گرداند.

به عنوان مثال، فرض کنید می‌خواهیم دمای سنسورهای مشتری خود را میانگین کنیم. ما می توانیم موارد زیر را تعریف کنیم (با استفاده از شناور فدرال):

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

شما ممکن است بپرسید، چگونه این متفاوت از است tf.function دکوراتور در TensorFlow؟ پاسخ کلیدی این است که کد تولید شده توسط tff.federated_computation نه TensorFlow و نه پایتون فعال است. این خصوصیات از یک سیستم توزیع در مستقل از پلتفرم زبان چسب داخلی است.

در حالی که این ممکن است پیچیده به نظر برسد، می توانید محاسبات TFF را به عنوان توابعی با امضاهای نوع کاملاً تعریف شده در نظر بگیرید. این نوع امضاها را می توان مستقیماً پرس و جو کرد.

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

این tff.federated_computation آرگومان از نوع فدرال می پذیرد {float32}@CLIENTS ، و بازده ارزش از نوع فدرال {float32}@SERVER . محاسبات فدرال ممکن است از سروری به کلاینت دیگر، از کلاینت به کلاینت، یا از سروری به سرور دیگر بروند. محاسبات فدرال نیز می توانند مانند توابع عادی ترکیب شوند، تا زمانی که نوع امضای آنها مطابقت داشته باشد.

برای حمایت از توسعه، TFF شما اجازه می دهد استناد به tff.federated_computation به عنوان یک تابع پایتون. مثلاً می توانیم تماس بگیریم

get_average_temperature([68.5, 70.3, 69.8])
69.53334

محاسبات غیر مشتاق و TensorFlow

دو محدودیت کلیدی وجود دارد که باید از آنها آگاه بود. اول، هنگامی که مفسر پایتون یک برخورد tff.federated_computation دکوراتور، تابع یک بار ترسیم و مرتب برای استفاده در آینده. به دلیل ماهیت غیرمتمرکز یادگیری فدرال، این استفاده در آینده ممکن است در جاهای دیگر مانند محیط اجرای از راه دور رخ دهد. بنابراین، محاسبات TFF اساسا غیر مشتاق. این رفتار تا حدودی به آن از مشابه است tf.function دکوراتور در TensorFlow.

دوم، یک محاسبه فدرال تنها می تواند از اپراتورهای فدرال (مانند تشکیل tff.federated_mean )، آنها می توانند عملیات TensorFlow است. کد TensorFlow باید به بلوک های تزئین شده با محدود tff.tf_computation . ترین کد TensorFlow معمولی را می توان به طور مستقیم تزئین شده، مانند تابع زیر را که طول می کشد یک تعداد و می افزاید: 0.5 به آن است.

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

این نیز امضا نوع داشت، اما بدون دادن. مثلاً می توانیم تماس بگیریم

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

در اینجا ما یک تفاوت مهم بین دیدن tff.federated_computation و tff.tf_computation . اولی دارای قرارگیری صریح است، در حالی که دومی ندارد.

ما می توانید استفاده کنید tff.tf_computation بلوک در محاسبات فدرال را بوسیله دادن. بیایید تابعی ایجاد کنیم که نصف، اما فقط به شناورهای فدرال در کلاینت ها اضافه کند. ما می توانیم با استفاده از این انجام tff.federated_map است، که به داده اعمال tff.tf_computation ، در حالی که حفظ قرار دادن.

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

این تابع تقریبا به یکسان است add_half ، به جز آن تنها مقادیر با قرار دادن در می پذیرد tff.CLIENTS ، و ارزش بازده با قرار دادن همان. ما می توانیم این را در امضای نوع آن ببینیم:

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

به طور خلاصه:

  • TFF بر اساس ارزش های فدرال عمل می کند.
  • هر مقدار فدرال دارای یک نوع فدرال، با یک نوع (به عنوان مثال. tf.float32 ) و قرار دادن (به عنوان مثال. tff.CLIENTS ).
  • ارزش فدرال می توان با استفاده از محاسبات فدرال، که باید با تزئین می شود تبدیل tff.federated_computation و امضا نوع فدرال.
  • کد TensorFlow باید در بلوک با مهار شود tff.tf_computation تزئین.
  • سپس این بلوک ها می توانند در محاسبات فدرال گنجانده شوند.

ساختن الگوریتم یادگیری فدرال خود، مورد بازبینی مجدد قرار گرفت

اکنون که نگاهی اجمالی به هسته فدرال یافته‌ایم، می‌توانیم الگوریتم یادگیری فدرال خود را بسازیم. به یاد داشته باشید که در بالا، ما یک تعریف initialize_fn و next_fn برای الگوریتم ما. next_fn استفاده از را client_update و server_update ما تعریف با استفاده از کد TensorFlow خالص است.

با این حال، به منظور ایجاد الگوریتم ما محاسبات فدرال، ما هر دو نیاز next_fn و initialize_fn به هر یک tff.federated_computation .

بلوک های فدرال TensorFlow

ایجاد محاسبات اولیه

تابع مقداردهی اولیه می شود کاملا ساده است: ما یک مدل با استفاده از ایجاد خواهد model_fn . با این حال، به یاد داشته باشید که ما باید جدا کردن کد TensorFlow ما با استفاده از tff.tf_computation .

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

ما می توانیم پس از آن به طور مستقیم به این محاسبات فدرال با استفاده از پاس tff.federated_value .

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

ایجاد next_fn

ما اکنون از کد به روز رسانی سرویس گیرنده و سرور خود برای نوشتن الگوریتم واقعی استفاده می کنیم. ما برای اولین بار خواهد ما به نوبه خود client_update به یک tff.tf_computation که می پذیرد مجموعه داده مشتری و وزن سرور، و خروجی به روز وزن مشتری تانسور.

ما به انواع مربوطه نیاز داریم تا عملکرد خود را به درستی تزئین کنیم. خوشبختانه، نوع وزن سرور را می توان مستقیماً از مدل ما استخراج کرد.

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

بیایید به امضای نوع مجموعه داده نگاه کنیم. به یاد داشته باشید که ما تصاویر 28 در 28 (با برچسب اعداد صحیح) گرفتیم و آنها را صاف کردیم.

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

ما همچنین می توانید نوع وزن مدل با استفاده از ما استخراج server_init تابع بالا.

model_weights_type = server_init.type_signature.result

با بررسی امضای نوع، می‌توانیم معماری مدل خود را ببینیم!

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

ما هم اکنون می توانید ما ایجاد tff.tf_computation برای به روز رسانی مشتری.

@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 نسخه از به روز رسانی سرور می تواند در یک روش مشابه تعریف شده، با استفاده از انواع ما در حال حاضر استخراج است.

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

تاریخ و زمان آخرین، اما نه کم، ما نیاز به ایجاد tff.federated_computation که این همه با هم به ارمغان می آورد. این تابع دو مقدار فدرال، یکی مربوط به وزن سرور (با قرار دادن قبول tff.SERVER )، و از سوی دیگر متناظر با مجموعه داده های مشتری (با قرار دادن tff.CLIENTS ).

توجه داشته باشید که هر دو نوع در بالا تعریف شد! ما به سادگی نیاز به آنها را تا محل صحیح با استفاده از به tff.FederatedType .

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

4 عنصر یک الگوریتم FL را به خاطر دارید؟

  1. مرحله پخش از سرور به مشتری.
  2. مرحله به روز رسانی مشتری محلی.
  3. مرحله آپلود مشتری به سرور.
  4. مرحله به روز رسانی سرور

اکنون که موارد فوق را ایجاد کردیم، هر قسمت را می توان به صورت فشرده به عنوان یک خط واحد از کد TFF نشان داد. همین سادگی به همین دلیل است که باید برای مشخص کردن مواردی مانند انواع فدرال دقت بیشتری می‌کردیم!

@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

ما در حال حاضر دارند tff.federated_computation برای هر دو مقدار دهی اولیه الگوریتم، و برای اجرای یک مرحله از الگوریتم. برای به پایان رساندن الگوریتم ما، ما این را به تصویب tff.templates.IterativeProcess .

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

نگاه اجازه دهید در امضای نوع initialize و next عملکرد فرآیند تکرار شونده است.

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

این موضوع نشان دهنده این واقعیت است که federated_algorithm.initialize یک تابع بدون ارگ است که بازده یک مدل تک لایه (با یک ماتریس وزن 784 های 10 و 10 واحد تعصب).

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

در اینجا، ما می بینیم که federated_algorithm.next یک مدل سرور و داده های مشتری، و بازده یک مدل سرور به روز می پذیرد.

ارزیابی الگوریتم

بیایید چند دور اجرا کنیم و ببینیم باخت چگونه تغییر می کند. اول، ما یک تابع ارزیابی با استفاده از رویکرد متمرکز مورد بحث در آموزش دوم را تعریف کنیم.

ابتدا یک مجموعه داده ارزیابی متمرکز ایجاد می کنیم و سپس همان پیش پردازشی را که برای داده های آموزشی استفاده می کردیم، اعمال می کنیم.

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

سپس، تابعی می نویسیم که حالت سرور را می پذیرد و از Keras برای ارزیابی مجموعه داده آزمایشی استفاده می کند. اگر شما با آن آشنا هستید tf.Keras ، این تمام نگاه آشنا، هر چند توجه داشته باشید که استفاده از 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)

حالا بیایید الگوریتم خود را مقداردهی اولیه کنیم و روی مجموعه تست ارزیابی کنیم.

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

بیایید چند دور تمرین کنیم و ببینیم آیا چیزی تغییر می کند یا خیر.

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

ما شاهد کاهش جزئی در تابع ضرر هستیم. در حالی که پرش کوچک است، ما فقط 15 دور تمرینی را انجام داده‌ایم، آن هم روی زیرمجموعه کوچکی از مشتریان. برای دیدن نتایج بهتر، ممکن است مجبور باشیم صدها و نه هزاران دور انجام دهیم.

اصلاح الگوریتم ما

در این مرحله، بیایید بایستیم و به آنچه که به دست آورده ایم فکر کنیم. ما میانگین‌گیری فدرال را مستقیماً با ترکیب کد خالص TensorFlow (برای به‌روزرسانی‌های سرویس گیرنده و سرور) با محاسبات فدرال از هسته مرکزی TFF پیاده‌سازی کرده‌ایم.

برای انجام یادگیری پیچیده تر، می توانیم به سادگی آنچه را که در بالا داریم تغییر دهیم. به طور خاص، با ویرایش کد TF خالص در بالا، می‌توانیم نحوه انجام آموزش توسط کلاینت یا نحوه به‌روزرسانی مدل خود را توسط سرور تغییر دهیم.

چالش: اضافه کردن قطع شیب به client_update تابع.

اگر می‌خواستیم تغییرات بزرگ‌تری ایجاد کنیم، می‌توانیم سرور را ذخیره کنیم و داده‌های بیشتری را پخش کنیم. به عنوان مثال، سرور همچنین می تواند نرخ یادگیری کلاینت را ذخیره کند و در طول زمان آن را کاهش دهد! توجه داشته باشید که این تغییرات را به امضا نوع مورد استفاده در نیاز tff.tf_computation خواستار کنید.

سخت تر چالش: پیاده سازی فدرال به طور متوسط با یادگیری پوسیدگی نرخ در مشتریان.

در این مرحله، ممکن است متوجه شوید که چقدر انعطاف پذیری در آنچه می توانید در این چارچوب پیاده سازی کنید وجود دارد. برای ایده (از جمله در پاسخ به این چالش سخت تر بالا) شما می توانید کد منبع برای دیدن tff.learning.build_federated_averaging_process ، و یا چک کردن های مختلف پروژه های تحقیقاتی با استفاده از TFF.