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

مشاهده در 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.
  • از Federated Core برای پیاده سازی مستقیم میانگین فدرال استفاده کنید.

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

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

ابتدا پایگاه داده 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. (توجه: این نوع رویکرد "نقطه میانی" مشابه آثار اخیر در مورد است بهینه ساز پیشبینی !).

تا اینجا ، ما فقط کد خالص TensorFlow را نوشته ایم. این از نظر طراحی است ، زیرا 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 یک محیط برنامه نویسی تابعی به شدت تایپ که واحد پایه محاسبات فدرال می باشد. اینها منطقی هستند که مقادیر فدرال را به عنوان ورودی می پذیرند و مقادیر فدرال را به عنوان خروجی برمی گردانند.

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

@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 تزئین.
  • این بلوک ها سپس می توانند در محاسبات فدرال گنجانده شوند.

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

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