الگوریتم های سفارشی فدراسیون ، قسمت 1: مقدمه ای بر هسته فدراسیون

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

این آموزش قسمت اول از یک سری دو قسمتی که نشان می دهد که چگونه برای اجرای انواع سفارشی از الگوریتم های فدرال در TensorFlow فدرال (TFF) با استفاده از است فدرال هسته (FC) - مجموعه ای از رابط های سطح پایین تر که به عنوان یک پایه و اساس خدمت که بر اساس آن ما را اجرا کرده اند فدرال آموزش (FL) لایه.

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

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

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

موارد استفاده در نظر گرفته شده

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

شما ممکن است از آن آگاه tf.contrib.distribute ، و یک سوال طبیعی به درخواست در این نقطه ممکن است: در چه راه هایی این چارچوب متفاوت است؟ هر دو چارچوب تلاش می کنند تا محاسبات TensorFlow را توزیع کنند.

یکی از راه های در مورد آن فکر می کنم این است که، در حالی که هدف اعلام شده از tf.contrib.distribute است به کاربران اجازه استفاده از مدل های موجود و کد آموزش با کمترین تغییرات را قادر می سازد آموزش توزیع شده، و تمرکز زیادی است در مورد چگونگی استفاده از زیرساخت های توزیع برای کارآمدتر کردن کد آموزشی موجود، هدف هسته فدرال TFF این است که به محققان و متخصصان کنترل صریح بر الگوهای خاص ارتباط توزیع شده ای که در سیستم های خود استفاده خواهند کرد، بدهد. تمرکز در FC بر روی ارائه یک زبان منعطف و توسعه پذیر برای بیان الگوریتم های جریان داده های توزیع شده است، به جای مجموعه ای مشخص از قابلیت های آموزشی توزیع شده پیاده سازی شده.

یکی از مخاطبان اصلی TFF FC API محققان و متخصصانی هستند که ممکن است بخواهند با الگوریتم‌های یادگیری فدرال جدید آزمایش کنند و پیامدهای انتخاب‌های طراحی ظریف را که بر نحوه تنظیم جریان داده در سیستم توزیع شده تأثیر می‌گذارند، ارزیابی کنند. بدون اینکه درگیر جزئیات پیاده سازی سیستم شوید. سطح انتزاعی که FC API به دنبال آن است تقریباً با شبه کدی مطابقت دارد که می توان از آن برای توصیف مکانیک یک الگوریتم یادگیری فدرال در یک نشریه تحقیقاتی استفاده کرد - چه داده هایی در سیستم وجود دارد و چگونه تبدیل می شود، اما بدون افت به سطح مبادلات پیام شبکه نقطه به نقطه فردی

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

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

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

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

import nest_asyncio
nest_asyncio.apply()
import collections

import numpy as np
import tensorflow as tf
import tensorflow_federated as tff
@tff.federated_computation
def hello_world():
  return 'Hello, World!'

hello_world()
b'Hello, World!'

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

یکی از ویژگی های متمایز TFF است که اجازه می دهد شما را به طور فشرده بیان محاسبات بر اساس TensorFlow-بر روی داده های فدرال. ما خواهد بود با استفاده از داده های فدرال مدت در این آموزش برای اشاره به یک مجموعه ای از داده در سراسر یک گروه از دستگاه میزبان در یک سیستم توزیع شده است. برای مثال، برنامه‌هایی که روی دستگاه‌های تلفن همراه اجرا می‌شوند ممکن است داده‌ها را جمع‌آوری کرده و به صورت محلی ذخیره کنند، بدون اینکه در یک مکان متمرکز آپلود شوند. یا، مجموعه ای از حسگرهای توزیع شده ممکن است خوانش های دما را در مکان خود جمع آوری و ذخیره کنند.

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

نکته مهمی که باید درک کرد این است که ما کل مجموعه داده‌ها را در همه دستگاه‌ها (مثلاً کل خوانش دمای مجموعه از همه حسگرها در یک آرایه توزیع‌شده) به‌عنوان یک مقدار واحد واحد مدل‌سازی می‌کنیم.

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

federated_float_on_clients = tff.type_at_clients(tf.float32)

به طور کلی، یک نوع فدرال در TFF با مشخص نوع تعریف T از ترکیبات عضو آن - مورد از داده ها که اقامت به دستگاه های فردی، و گروه G دستگاههایی که ارزش فدرال از این نوع میزبانی (به علاوه یک سوم، اطلاعات کمی اختیاری که به زودی به آنها اشاره خواهیم کرد). ما به گروه مراجعه G از دستگاه های میزبانی یک ارزش فدرال به عنوان قرار دادن ارزش است. بنابراین، tff.CLIENTS یک مثال از یک قرار دادن است.

str(federated_float_on_clients.member)
'float32'
str(federated_float_on_clients.placement)
'CLIENTS'

یک نوع فدرال با حوزه های عضو T و قرار دادن G می تواند نشان فشرده به عنوان {T}@G ، به عنوان زیر نشان داده شده.

str(federated_float_on_clients)
'{float32}@CLIENTS'

آکولاد {} در این مختصر نماد به عنوان یک یادآوری خدمت که اجزای عضو (مورد از داده ها در دستگاه های مختلف) ممکن است متفاوت باشد، به عنوان شما انتظار می رود به عنوان مثال، قرائت سنسور درجه حرارت، تا مشتریان به عنوان یک گروه به طور مشترک میزبانی یک چند تنظیم از T آیتم هایی که با هم ارزش فدرال را تشکیل می دهند -typed.

آن را به توجه داشته باشید مهم است که ترکیبات عضو یک ارزش فدرال به طور کلی به برنامه نویس مات، به عنوان مثال، یک مقدار فدرال باید به عنوان یک ساده تصور نشود dict کوک شده با یک شناسه از یک دستگاه در سیستم - این مقادیر در نظر گرفته شده توان در مجموع تنها توسط اپراتورهای فدرال که انتزاعی نشان دهنده انواع مختلف از پروتکل های ارتباطی توزیع شده (مانند دانه) تبدیل شده است. اگر این خیلی انتزاعی به نظر می رسد، نگران نباشید - به زودی به این موضوع باز خواهیم گشت و آن را با مثال های عینی توضیح خواهیم داد.

انواع فدرال در TFF به دو شکل می‌آیند: آنهایی که در آن اجزای تشکیل دهنده یک مقدار فدرال ممکن است متفاوت باشند (همانطور که در بالا مشاهده شد)، و آنهایی که همه آنها با هم برابر هستند. این است که با سوم، اختیاری کنترل all_equal پارامتر در tff.FederatedType سازنده (متخلف به False ).

federated_float_on_clients.all_equal
False

یک نوع فدرال با قرار دادن G که در آن همه از T -typed ترکیبات عضو هستند شناخته شده به مساوی را می توان فشرده به عنوان نمایندگی T@G (به عنوان مخالف {T}@G ، این است که، با آکولاد کاهش یافته است تا منعکس کننده این واقعیت که چند مجموعه از اجزای عضو از یک آیتم تشکیل شده است).

str(tff.type_at_clients(tf.float32, all_equal=True))
'float32@CLIENTS'

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

مثال دیگر مجموعه‌ای از پارامترها برای یک مدل یادگیری ماشینی است که از قبل در سرور آموزش داده شده است، که سپس به گروهی از دستگاه‌های سرویس گیرنده پخش می‌شوند، جایی که می‌توانند برای هر کاربر شخصی‌سازی شوند.

به عنوان مثال، فرض کنید ما یک جفت از float32 پارامترهای و a b برای یک مدل رگرسیون خطی یک بعدی ساده. ما می توانیم نوع (غیر فدرال) چنین مدل هایی را برای استفاده در TFF به صورت زیر بسازیم. ابروها زاویه <> در نوع رشته چاپ شده است یک نماد TFF جمع و جور برای تاپل نام و یا نامش ذکر نشده.

simple_regression_model_type = (
    tff.StructType([('a', tf.float32), ('b', tf.float32)]))

str(simple_regression_model_type)
'<a=float32,b=float32>'

توجه داشته باشید که ما فقط تعیین dtype بازدید کنندگان بالا. انواع غیر اسکالر نیز پشتیبانی می شوند. در کد بالا، tf.float32 است یک نماد میانبر برای کلی تر tff.TensorType(dtype=tf.float32, shape=[]) .

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

str(tff.type_at_clients(
    simple_regression_model_type, all_equal=True))
'<a=float32,b=float32>@CLIENTS'

میانگین پستها در طول تقارن با شناور فدرال فوق، ما به این نوع A به عنوان یک تاپل فدرال مراجعه کنید. به طور کلی، ما اغلب برای اشاره به یک ارزش فدرال که اجزاء عضو XYZ مانند استفاده از XYZ فدرال مدت. بنابراین، ما در مورد چیزهایی مثل تاپل فدرال، توالی فدرال، مدل های فدرال، و غیره صحبت کنید.

در حال حاضر، آینده را به float32@CLIENTS - در حالی که به نظر می رسد تکرار سراسر دستگاه های متعدد، آن است که در واقع یک float32 ، از همه اعضای آن یکسان است. به طور کلی، شما ممکن است از هر نوع فدرال همه برابر یعنی فکر می کنم، یکی از فرم T@G به یک نوع غیر فدرال، به عنوان ریخت T ، چرا که در هر دو مورد، در واقع وجود دارد تنها یک (البته به طور بالقوه تکرار) مورد از نوع T .

با توجه به ریخت بین T و T@G ، شما ممکن است چه هدفی، در صورت وجود، در حالت دوم ممکن است خدمت می کنند. ادامه مطلب

قرارگیری ها

نمای کلی طراحی

در بخش قبل، ما مفهوم از دادن معرفی کرده ایم - گروه از شرکت کنندگان سیستم که ممکن است به طور مشترک میزبانی ارزش فدرال، و ما استفاده از نشان داده ایم tff.CLIENTS به عنوان مثال مشخصات یک قرار دادن.

برای توضیح دهد که چرا مفهوم قرار دادن چنین بنیادی است که ما نیاز به آن ترکیب را به سیستم نوع TFF است، به یاد آنچه که ما در ابتدای این آموزش در مورد برخی از کاربردهای مورد نظر از TFF ذکر شده است.

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

این امر به ویژه در هنگام برخورد با داده های برنامه در دستگاه های تلفن همراه بسیار مهم است. از آنجایی که داده‌ها خصوصی هستند و می‌توانند حساس باشند، ما به توانایی تأیید استاتیکی نیاز داریم که این داده‌ها هرگز از دستگاه خارج نمی‌شوند (و حقایقی را درباره نحوه پردازش داده‌ها ثابت کنیم). مشخصات قرارگیری یکی از مکانیسم هایی است که برای پشتیبانی از این امر طراحی شده است.

TFF به عنوان یک محیط برنامه نویسی داده محور طراحی شده است، و به عنوان مثل، بر خلاف برخی از چارچوب های موجود که تمرکز بر عملیات و که در آن این عملیات ممکن است اجرا، TFF در داده ها، که در آن است که تحقق داده، و چگونه آن را در حال تبدیل متمرکز است. در نتیجه، مکان‌یابی به‌عنوان ویژگی داده‌ها در TFF مدل‌سازی می‌شود، نه به‌عنوان ویژگی عملیات روی داده‌ها. در واقع، همانطور که در بخش بعدی می‌بینید، برخی از عملیات TFF در سراسر مکان‌ها گسترده می‌شوند و به‌عبارتی «در شبکه» اجرا می‌شوند، نه اینکه توسط یک ماشین یا گروهی از ماشین‌ها اجرا شوند.

به نمایندگی از نوع یک مقدار مشخص به عنوان T@G یا {T}@G (به عنوان تنها مخالف T با تجزیه و تحلیل استاتیک برنامههای نوشته شده در TFF) تصمیم گیری می کند قرار دادن داده صریح و روشن، و با هم، می تواند به عنوان یک پایه برای ارائه خدمت تضمین حریم خصوصی رسمی برای داده های حساس روی دستگاه.

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

در داخل بدن از کد TFF، طراحی، هیچ راهی برای شمردن دستگاه هایی که این گروه به نمایندگی را تشکیل می دهند وجود دارد tff.CLIENTS ، و یا به پروب برای وجود یک دستگاه خاص در این گروه است. هیچ مفهومی از هویت دستگاه یا مشتری در هیچ کجای API هسته مرکزی، مجموعه اساسی انتزاعات معماری، یا زیرساخت اصلی زمان اجرا که برای پشتیبانی از شبیه سازی ها ارائه می کنیم، وجود ندارد. تمام منطق محاسباتی که می نویسید به صورت عملیات روی کل گروه مشتری بیان می شود.

به یاد بیاورید در اینجا چیزی است که ما قبلا در مورد ارزش های انواع فدرال بودن برعکس پایتون ذکر dict ، که در یکی به سادگی نمی تواند شمردن ترکیبات عضو خود. به مقادیری فکر کنید که منطق برنامه TFF شما آن‌ها را به‌عنوان مرتبط با مکان‌ها (گروه‌ها) و نه با شرکت‌کنندگان منفرد، دستکاری می‌کند.

کارگماری طراحی شده اند به یک شهروند درجه اول در TFF و همچنین، و می تواند به عنوان پارامترها و نتایج حاصل از یک نظر می رسد placement نوع (به این صورت بیان می شود tff.PlacementType در API). در آینده، ما قصد داریم تا اپراتورهای مختلفی را برای تبدیل یا ترکیب مکان‌ها ارائه کنیم، اما این خارج از محدوده این آموزش است. در حال حاضر، آن کافی است به فکر می کنم از placement به عنوان یک مات بدوی ساخته شده در نوع در TFF، شبیه به int و bool می مات، ساخته شده در انواع در پایتون با tff.CLIENTS بودن یک لفظ ثابت از این نوع، بر خلاف 1 بودن یک لفظ ثابت از نوع int .

تعیین مکان ها

TFF فراهم می کند دو لیترال قرار دادن پایه، tff.CLIENTS و tff.SERVER ، آن را آسان برای بیان انواع غنی از سناریوهای عملی که به طور طبیعی به عنوان معماری کلاینت سرور مدل، با دستگاه های چند مشتری (تلفن همراه، دستگاه تعبیه شده، پایگاه داده توزیع شده ، سنسور، و غیره) هماهنگ شده با یک هماهنگ کننده سرور متمرکز است. TFF برای پشتیبانی از مکان‌های سفارشی، گروه‌های مشتری متعدد، چند لایه و دیگر معماری‌های توزیع شده عمومی‌تر طراحی شده است، اما بحث در مورد آنها خارج از محدوده این آموزش است.

TFF می کند تجویز که چه یا tff.CLIENTS یا tff.SERVER در واقع نشان دهنده.

به طور خاص، tff.SERVER ممکن است یک دستگاه فیزیکی منفرد (یک عضو از یک گروه تک قلو)، اما آن را فقط به عنوان به خوبی ممکن است یک گروه از کپی در یک دستگاه تکثیر دولت خوشه مقاوم در برابر خطا در حال اجرا باشد - ما هیچ معماری خاص را ندارد مفروضات در عوض، ما با استفاده از all_equal کمی ذکر شده در بخش قبل برای بیان این واقعیت است که ما در حال به طور کلی خرید و فروش با تنها یک آیتم از داده ها در سرور.

به همین ترتیب، tff.CLIENTS در برخی از برنامه های کاربردی ممکن است همه مشتریان نشان دهنده در سیستم - در زمینه یادگیری فدرال ما گاهی اوقات به عنوان جمعیت مراجعه کنید، اما به عنوان مثال، در چه پیاده سازی تولید به طور متوسط فدرال ، ممکن است نشان دهنده یک گروه - یک زیر مجموعه از مشتریانی که برای شرکت در دور خاصی از آموزش انتخاب می شوند. زمانی که محاسباتی که در آن به نظر می رسند برای اجرا به کار گرفته می شود (یا به سادگی مانند یک تابع پایتون در یک محیط شبیه سازی شده، همانطور که در این آموزش نشان داده شده است) به مکان های تعریف شده به طور انتزاعی معنای مشخصی داده می شود. در شبیه سازی های محلی ما، گروه مشتریان توسط داده های فدرال ارائه شده به عنوان ورودی تعیین می شود.

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

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

TFF به عنوان یک محیط برنامه نویسی عملکردی قوی طراحی شده است که از توسعه ماژولار پشتیبانی می کند.

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

@tff.federated_computation(tff.type_at_clients(tf.float32))
def get_average_temperature(sensor_readings):
  return tff.federated_mean(sensor_readings)

نگاهی به کد بالا، در این نقطه شاید بپرسید - نه در حال حاضر وجود دکوراتور سازه به تعریف واحد ساخت مجموع مانند tf.function در TensorFlow، و اگر چنین است، چرا معرفی یکی دیگر، و چگونه آن را متفاوت است؟

پاسخ کوتاه این است که کد تولید شده توسط tff.federated_computation است لفاف بسته بندی نه TensorFlow، و نه آن پایتون - این یک مشخصات یک سیستم توزیع شده در یک مستقل از پلتفرم زبان چسب داخلی است. در این مرحله، این بدون شک رمزآلود به نظر می رسد، اما لطفاً این تفسیر شهودی از یک محاسبات فدرال را به عنوان مشخصات انتزاعی یک سیستم توزیع شده در ذهن داشته باشید. یک دقیقه دیگر توضیح خواهیم داد.

ابتدا اجازه دهید کمی با تعریف بازی کنیم. محاسبات TFF عموماً به عنوان توابع مدل‌سازی می‌شوند - با یا بدون پارامتر، اما با امضاهای نوع کاملاً تعریف شده. شما می توانید امضا نوع محاسبات توسط پرس و جو خود را چاپ type_signature اموال، به عنوان زیر نشان داده شده.

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

امضای نوع به ما می‌گوید که محاسبات مجموعه‌ای از خوانش‌های حسگر مختلف را در دستگاه‌های کلاینت می‌پذیرد و میانگین واحدی را روی سرور برمی‌گرداند.

قبل از اینکه ما به هر بیشتر، اجازه دهید در این منعکس برای یک دقیقه - ورودی و خروجی از این محاسبات در مکان های مختلف (در می CLIENTS در مقابل در SERVER ). به یاد بیاورید که ما در بخش قبل در مورد چگونگی دادن عملیات TFF ممکن است در سراسر نقاط دهانه و در شبکه اجرا شود، و آنچه که ما فقط در مورد محاسبات فدرال به عنوان نمایندگی مشخصات انتزاعی از سیستم های توزیع شده گفت گفت. ما فقط یکی از این محاسبات را تعریف کرده‌ایم - یک سیستم توزیع شده ساده که در آن داده‌ها در دستگاه‌های مشتری مصرف می‌شوند و نتایج انبوه در سرور ظاهر می‌شوند.

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

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

به طور کلی، امضا نوع کاربردی فشرده به عنوان نمایندگی (T -> U) برای انواع T و U ورودی و خروجی، به ترتیب. نوع پارامتر رسمی (مانند sensor_readings در این مورد) به عنوان آرگومان به دکوراتور مشخص شده است. نیازی نیست نوع نتیجه را مشخص کنید - به طور خودکار تعیین می شود.

اگرچه TFF اشکال محدودی از چندشکلی را ارائه می دهد، برنامه نویسان به شدت تشویق می شوند تا در مورد انواع داده هایی که با آنها کار می کنند صریح باشند، زیرا درک، اشکال زدایی و تأیید رسمی ویژگی های کد شما را آسان تر می کند. در برخی موارد، مشخص کردن صریح انواع یک الزام است (به عنوان مثال، محاسبات چند شکلی در حال حاضر مستقیماً قابل اجرا نیستند).

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

به منظور پشتیبانی از توسعه و اشکال زدایی، TFF به شما اجازه می دهد تا محاسباتی را که به این صورت به عنوان توابع پایتون تعریف شده اند، به طور مستقیم فراخوانی کنید، همانطور که در زیر نشان داده شده است. که در آن محاسبات انتظار مقدار از نوع فدرال با all_equal بیت به False ، شما می توانید آن را به عنوان یک دشت تغذیه list در پایتون، و برای انواع فدرال با all_equal بیت به True ، شما فقط می توانید به طور مستقیم تغذیه (تک) تشکیل دهنده عضو نتایج نیز به این ترتیب به شما گزارش می شود.

get_average_temperature([68.5, 70.3, 69.8])
69.53334

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

در حال حاضر، بازگشت اجازه دهید به توجه داشته باشید که ما قبلا در مورد ساخته شده tff.federated_computation دکوراتور رهبری کد در یک زبان چسب. اگر چه منطق محاسبات TFF می تواند به عنوان توابع معمولی در پایتون بیان (شما فقط نیاز به آنها را تزئین با tff.federated_computation همانطور که در بالا انجام داده ام)، و شما به طور مستقیم می توانید فراخوان آنها را با استدلال پایتون مانند هر توابع پایتون دیگر در این نوت بوک، پشت صحنه، همانطور که ما قبلا اشاره شد، محاسبات TFF در واقع پایتون است.

چه این منظور ما این است که وقتی مفسر پایتون یک تابع تزئین شده با برخورد tff.federated_computation ، آن آثار اظهارات در بدن این تابع را یک بار (در زمان تعریف)، و سپس به ساختن یک نمایندگی سریال منطق محاسبات را برای استفاده در آینده - چه برای اجرا، یا به عنوان یک جزء فرعی در محاسبات دیگر گنجانده شود.

شما می توانید این را با افزودن یک عبارت چاپی به شرح زیر تأیید کنید:

@tff.federated_computation(tff.type_at_clients(tf.float32))
def get_average_temperature(sensor_readings):

  print ('Getting traced, the argument is "{}".'.format(
      type(sensor_readings).__name__))

  return tff.federated_mean(sensor_readings)
Getting traced, the argument is "ValueImpl".

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

به همین ترتیب، محاسبات TFF در پایتون تعریف شده است، اما اظهارات پایتون در بدن آنها، مانند tff.federated_mean در مثال نشان داده شده است فقط ایم، به نمایندگی serializable قابل حمل و مستقل از پلتفرم در زیر کاپوت وارد شده است.

به‌عنوان یک توسعه‌دهنده، نیازی نیست که خودتان را به جزئیات این نمایش بپردازید، زیرا هرگز نیازی به کار مستقیم با آن نخواهید داشت، اما باید از وجود آن آگاه باشید، این واقعیت که محاسبات TFF اساساً مشتاق نیستند. و نمی تواند حالت پایتون دلخواه را بگیرد. کد پایتون موجود در بدن یک محاسبه TFF است در زمان تعریف اعدام، زمانی که بدن از تابع پایتون تزئین شده با tff.federated_computation است قبل از گرفتن مرتب پیش بینی کرد. در زمان فراخوانی مجدداً ردیابی نمی شود (به جز زمانی که تابع چند شکلی است؛ لطفاً برای جزئیات به صفحات مستندات مراجعه کنید).

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

دلیل دیگر این است که محاسبات TFF رفتار جهانی سیستم های توزیع شده را بیان می کند، در مقابل برنامه های پایتون که رفتار محلی تک تک شرکت کنندگان را بیان می کنند. شما می توانید در مثال ساده بالا می بینیم که، با اپراتور خاص tff.federated_mean که داده ها در دستگاه های مشتری، اما سپرده نتایج بر روی سرور می پذیرد.

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

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

نوشتن محاسبات فدرال

همانطور که در بالا ذکر شد، محاسبات فدرال و اجزای آنها به بهترین شکل به عنوان مدل های سیستم های توزیع شده درک می شوند، و می توانید ترکیب محاسبات فدرال را به عنوان ترکیب سیستم های توزیع پیچیده تر از سیستم های ساده تر در نظر بگیرید. شما می توانید از فکر می کنم tff.federated_mean اپراتور عنوان یک نوع از ساخته شده است در قالب محاسبات فدرال با امضای نوع ({T}@CLIENTS -> T@SERVER) (در واقع، درست مثل محاسبات شما ارسال، این اپراتور همچنین دارای یک مجموعه ساختار - در زیر هود آن را به عملگرهای ساده تر تقسیم می کنیم).

همین امر در مورد نوشتن محاسبات فدرال نیز صادق است. محاسبه get_average_temperature ممکن است در یک بدن دیگر تابع پایتون تزئین شده با استناد tff.federated_computation - انجام این کار باعث می شود آن را به در بدن از پدر و مادر جاسازی شده باشد، بسیار در همان راه tff.federated_mean در بدن خود زودتر جاسازی شده بود.

محدودیت مهم است که از این است که بدن از توابع پایتون تزئین شده با آگاه tff.federated_computation باید تنها از اپراتورهای فدرال، یعنی تشکیل شده است، آنها نمی توانند مستقیما شامل عملیات TensorFlow. به عنوان مثال، شما می توانید به طور مستقیم استفاده tf.nest رابط برای اضافه کردن یک جفت از ارزش فدرال. کد TensorFlow باید به بلوک از کد تزئین شده با محدود tff.tf_computation بحث شده در بخش های زیر است. تنها زمانی که در این روش پیچیده می توانید کد TensorFlow پیچیده می شود در بدن یک استناد tff.federated_computation .

دلایل این جدایی فنی است (آن را سخت برای فریب اپراتورهای مانند tf.add به کار با غیر تانسورها) و همچنین معماری. زبان محاسبات فدرال (یعنی منطق ساخته شده از بدن مرتب از توابع پایتون تزئین شده با tff.federated_computation ) طراحی شده است که به عنوان یک زبان مستقل از پلتفرم چسب خدمت می کنند. این زبان چسب در حال حاضر به سیستم ساخت توزیع از بخش های جاسازی شده از کد TensorFlow (محدود به استفاده tff.tf_computation بلوک). در پری از زمان، ما پیش بینی نیاز به بخش های جاسازی دیگر، منطق غیر TensorFlow، مانند نمایش داده شد پایگاه داده رابطه ای که ممکن است خط لوله ورودی نشان، همه با هم متصل با استفاده از زبان چسب همان (به tff.federated_computation بلوک).

منطق TensorFlow

اعلام محاسبات TensorFlow

TFF برای استفاده با TensorFlow طراحی شده است. به این ترتیب، بخش عمده ای از کدهایی که در TFF خواهید نوشت احتمالاً کد TensorFlow معمولی (یعنی اجرا کننده محلی) است. به منظور استفاده از این کد با TFF، همانطور که در بالا اشاره شد، آن را فقط باید با تزئین می شود tff.tf_computation .

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

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

یک بار دیگر، به دنبال در این، شما ممکن است تعجب کنید که چرا ما باید یکی دیگر از دکوراتور تعریف tff.tf_computation به جای به سادگی با استفاده از یک مکانیزم موجود مانند tf.function . برخلاف بخش قبل، در اینجا با یک بلوک معمولی از کد TensorFlow سروکار داریم.

چند دلیل برای این وجود دارد که درمان کامل آنها از محدوده این آموزش خارج است، اما بد نیست به نام اصلی آن اشاره کنیم:

  • به منظور جاسازی بلوک‌های ساختمانی قابل استفاده مجدد که با استفاده از کد TensorFlow در بدنه‌های محاسباتی فدرال اجرا می‌شوند، باید ویژگی‌های خاصی را برآورده کنند - مانند ردیابی و سریال‌سازی در زمان تعریف، داشتن امضای نوع، و غیره. این معمولاً به نوعی تزئین کننده نیاز دارد.

به طور کلی، توصیه می کنیم با استفاده از مکانیسم های بومی TensorFlow برای ترکیب، مانند tf.function ، هر کجا که ممکن است، به عنوان شیوه ای دقیق که در آن تعامل دکوراتور TFF با توابع مشتاق می توان انتظار داشت به تکامل است.

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

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

توجه داشته باشید که این نوع امضا جایگذاری ندارد. محاسبات TensorFlow نمی توانند انواع فدرال را مصرف یا برگردانند.

شما هم اکنون می توانید با استفاده از add_half عنوان یک بلوک ساختمان در محاسبات. به عنوان مثال، در اینجا شما می توانید استفاده از tff.federated_map اپراتور به درخواست add_half نقطه به نقطه به تمام اجزاء عضو یک شناور فدرال به دستگاه های مشتری.

@tff.federated_computation(tff.type_at_clients(tf.float32))
def add_half_on_clients(x):
  return tff.federated_map(add_half, x)
str(add_half_on_clients.type_signature)
'({float32}@CLIENTS -> {float32}@CLIENTS)'

اجرای محاسبات TensorFlow

اجرای محاسبات تعریف شده با tff.tf_computation به پیروی از قوانین همان کسانی که ما برای توصیف tff.federated_computation . آنها را می توان به عنوان فراخوانی های معمولی در پایتون به شرح زیر فراخوانی کرد.

add_half_on_clients([1.0, 3.0, 2.0])
[<tf.Tensor: shape=(), dtype=float32, numpy=1.5>,
 <tf.Tensor: shape=(), dtype=float32, numpy=3.5>,
 <tf.Tensor: shape=(), dtype=float32, numpy=2.5>]

یک بار دیگر، شایان ذکر است که با استناد به محاسبات است add_half_on_clients در این روش شبیه سازی یک فرآیند توزیع شده است. داده ها بر روی مشتریان مصرف می شوند و به مشتریان بازگردانده می شوند. در واقع، این محاسبات هر مشتری را وادار می کند تا یک عمل محلی را انجام دهد. وجود ندارد tff.SERVER به صراحت در این سیستم ذکر شده (حتی اگر در عمل، سازماندهی پردازش چنین ممکن است شامل یک و). فکر می کنم از یک محاسبه این راه به عنوان مفهومی شبیه به تعریف Map مرحله در MapReduce .

همچنین، به خاطر داشته باشید که آنچه که ما در بخش قبل در مورد محاسبات TFF گرفتن در زمان تعریف مرتب گفت درست است برای باقی می ماند tff.tf_computation کد و همچنین - بدن پایتون از add_half_on_clients می شود یک بار در زمان تعریف پیش بینی کرد. در فراخوان های بعدی، TFF از نمایش سریالی خود استفاده می کند.

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

در زیر هود، هر روش تزئین شده با tff.tf_computation به طور موقت اجرای مشتاق به منظور اجازه ساختار محاسبات را به اسیر غیر فعال. در حالی که اجرای مشتاق به صورت محلی غیرفعال است، می‌توانید از ساختارهای TensorFlow، AutoGraph، TensorFlow 2.0 و غیره استفاده کنید، تا زمانی که منطق محاسبات خود را به گونه‌ای بنویسید که بتواند به درستی سریال‌سازی شود.

به عنوان مثال، کد زیر ناموفق خواهد بود:

try:

  # Eager mode
  constant_10 = tf.constant(10.)

  @tff.tf_computation(tf.float32)
  def add_ten(x):
    return x + constant_10

except Exception as err:
  print (err)
Attempting to capture an EagerTensor without building a function.

فوق نتواند به دلیل constant_10 در حال حاضر در خارج از نمودار که ساخته شده tff.tf_computation سازه داخلی در بدن از add_ten در طول فرایند ترتیب است.

از سوی دیگر، با استناد به توابع پایتون است که تغییر نمودار فعلی زمانی که در داخل یک نام tff.tf_computation خوب است:

def get_constant_10():
  return tf.constant(10.)

@tff.tf_computation(tf.float32)
def add_ten(x):
  return x + get_constant_10()

add_ten(5.0)
15.0

توجه داشته باشید که مکانیسم‌های سریال‌سازی در TensorFlow در حال تکامل هستند و ما انتظار داریم جزئیات نحوه سریال‌سازی محاسبات TFF نیز تکامل یابد.

کار با tf.data.Dataset بازدید کنندگان

همانطور که قبلا اشاره شد، یکی از ویژگی های منحصر به فرد از tff.tf_computation این است که آنها به شما اجازه می دهد تا برای کار با tf.data.Dataset بازدید کنندگان انتزاعی به عنوان پارامترهای رسمی توسط کد خود را تعریف شده است. پارامترهای در TensorFlow نشان داده می شود به عنوان مجموعه داده باید با استفاده از به تعریف tff.SequenceType سازنده.

به عنوان مثال، مشخصات نوع tff.SequenceType(tf.float32) دنباله انتزاعی از عناصر شناور در TFF تعریف می کند. دنباله‌ها می‌توانند شامل تانسورها یا ساختارهای تودرتو پیچیده باشند (نمونه‌هایی از آن‌ها را بعداً خواهیم دید). نمایندگی مختصر از دنباله ای از T موارد -typed است T* .

float32_sequence = tff.SequenceType(tf.float32)

str(float32_sequence)
'float32*'

Suppose that in our temperature sensor example, each sensor holds not just one temperature reading, but multiple. Here's how you can define a TFF computation in TensorFlow that calculates the average of temperatures in a single local data set using the tf.data.Dataset.reduce operator.

@tff.tf_computation(tff.SequenceType(tf.float32))
def get_local_temperature_average(local_temperatures):
  sum_and_count = (
      local_temperatures.reduce((0.0, 0), lambda x, y: (x[0] + y, x[1] + 1)))
  return sum_and_count[0] / tf.cast(sum_and_count[1], tf.float32)
str(get_local_temperature_average.type_signature)
'(float32* -> float32)'

In the body of a method decorated with tff.tf_computation , formal parameters of a TFF sequence type are represented simply as objects that behave like tf.data.Dataset , ie, support the same properties and methods (they are currently not implemented as subclasses of that type - this may change as the support for data sets in TensorFlow evolves).

You can easily verify this as follows.

@tff.tf_computation(tff.SequenceType(tf.int32))
def foo(x):
  return x.reduce(np.int32(0), lambda x, y: x + y)

foo([1, 2, 3])
6

Keep in mind that unlike ordinary tf.data.Dataset s, these dataset-like objects are placeholders. They don't contain any elements, since they represent abstract sequence-typed parameters, to be bound to concrete data when used in a concrete context. Support for abstractly-defined placeholder data sets is still somewhat limited at this point, and in the early days of TFF, you may encounter certain restrictions, but we won't need to worry about them in this tutorial (please refer to the documentation pages for details).

When locally executing a computation that accepts a sequence in a simulation mode, such as in this tutorial, you can feed the sequence as Python list, as below (as well as in other ways, eg, as a tf.data.Dataset in eager mode, but for now, we'll keep it simple).

get_local_temperature_average([68.5, 70.3, 69.8])
69.53333

Like all other TFF types, sequences like those defined above can use the tff.StructType constructor to define nested structures. For example, here's how one could declare a computation that accepts a sequence of pairs A , B , and returns the sum of their products. We include the tracing statements in the body of the computation so that you can see how the TFF type signature translates into the dataset's output_types and output_shapes .

@tff.tf_computation(tff.SequenceType(collections.OrderedDict([('A', tf.int32), ('B', tf.int32)])))
def foo(ds):
  print('element_structure = {}'.format(ds.element_spec))
  return ds.reduce(np.int32(0), lambda total, x: total + x['A'] * x['B'])
element_structure = OrderedDict([('A', TensorSpec(shape=(), dtype=tf.int32, name=None)), ('B', TensorSpec(shape=(), dtype=tf.int32, name=None))])
str(foo.type_signature)
'(<A=int32,B=int32>* -> int32)'
foo([{'A': 2, 'B': 3}, {'A': 4, 'B': 5}])
26

The support for using tf.data.Datasets as formal parameters is still somewhat limited and evolving, although functional in simple scenarios such as those used in this tutorial.

Putting it all together

Now, let's try again to use our TensorFlow computation in a federated setting. Suppose we have a group of sensors that each have a local sequence of temperature readings. We can compute the global temperature average by averaging the sensors' local averages as follows.

@tff.federated_computation(
    tff.type_at_clients(tff.SequenceType(tf.float32)))
def get_global_temperature_average(sensor_readings):
  return tff.federated_mean(
      tff.federated_map(get_local_temperature_average, sensor_readings))

Note that this isn't a simple average across all local temperature readings from all clients, as that would require weighing contributions from different clients by the number of readings they locally maintain. We leave it as an exercise for the reader to update the above code; the tff.federated_mean operator accepts the weight as an optional second argument (expected to be a federated float).

Also note that the input to get_global_temperature_average now becomes a federated float sequence . Federated sequences is how we will typically represent on-device data in federated learning, with sequence elements typically representing data batches (you will see examples of this shortly).

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

Here's how we can locally execute the computation on a sample of data in Python. Notice that the way we supply the input is now as a list of list s. The outer list iterates over the devices in the group represented by tff.CLIENTS , and the inner ones iterate over elements in each device's local sequence.

get_global_temperature_average([[68.0, 70.0], [71.0], [68.0, 72.0, 70.0]])
70.0

This concludes the first part of the tutorial... we encourage you to continue on to the second part .