למידה מאוחדת

סקירה כללית

מסמך זה מציג ממשקים המקלים על משימות למידה מאוחדות, כגון הדרכה מאוחדת או הערכה עם מודלים קיימים של למידת מכונה המיושמים ב-TensorFlow. בתכנון הממשקים הללו, המטרה העיקרית שלנו הייתה לאפשר להתנסות בלמידה מאוחדת מבלי להידרש לידע כיצד היא פועלת מתחת למכסה המנוע, ולהעריך את אלגוריתמי הלמידה המאוחדים המיושמים על מגוון מודלים ונתונים קיימים. אנו ממליצים לך לתרום בחזרה לפלטפורמה. TFF תוכנן מתוך מחשבה על יכולת הרחבה והרכבה, ואנו מברכים על תרומות; אנחנו נרגשים לראות מה יצא לך!

הממשקים שמציעה שכבה זו מורכבים משלושת חלקי המפתח הבאים:

  • דגמים . שיעורים ופונקציות עוזרות המאפשרות לך לעטוף את הדגמים הקיימים שלך לשימוש עם TFF. גלישת מודל יכולה להיות פשוטה כמו קריאה לפונקציית גלישה בודדת (למשל, tff.learning.models.from_keras_model ), או הגדרת תת מחלקה של ממשק tff.learning.models.VariableModel להתאמה אישית מלאה.

  • בוני חישובים מאוחדים . פונקציות עוזר הבונות חישובים מאוחדים להדרכה או הערכה, תוך שימוש במודלים הקיימים שלך.

  • מערכי נתונים . אוספים מוכנים של נתונים שאתה יכול להוריד ולגשת אליהם ב-Python לשימוש בהדמיית תרחישי למידה מאוחדים. למרות שלמידה מאוחדת מיועדת לשימוש עם נתונים מבוזרים שלא ניתנים להורדה במיקום מרכזי, בשלבי המחקר והפיתוח לרוב נוח לערוך ניסויים ראשוניים באמצעות נתונים שניתן להוריד ולתפעל באופן מקומי, במיוחד עבור מפתחים שעלולים להיות חדש בגישה.

ממשקים אלו מוגדרים בעיקר במרחב השמות tff.learning , למעט מערכי נתונים מחקריים ויכולות אחרות הקשורות לסימולציה שקובצו ב- tff.simulation . שכבה זו מיושמת באמצעות ממשקים ברמה נמוכה יותר המוצעים על ידי ה- Federated Core (FC) , המספקת גם סביבת זמן ריצה.

לפני שתמשיך, אנו ממליצים שתקרא תחילה את המדריכים על סיווג תמונות ויצירת טקסט , מכיוון שהם מציגים את רוב המושגים המתוארים כאן באמצעות דוגמאות קונקרטיות. אם אתה מעוניין ללמוד עוד על אופן הפעולה של TFF, אולי תרצה לדפדף על המדריך לאלגוריתמים מותאמים אישית כהקדמה לממשקים ברמה נמוכה יותר שבהם אנו משתמשים כדי לבטא את ההיגיון של חישובים מאוחדים, וכדי ללמוד את היישום הקיים של ממשקי tff.learning .

דגמים

הנחות ארכיטקטוניות

סדרה

TFF שואפת לתמוך במגוון תרחישי למידה מבוזרת שבהם קוד מודל למידת המכונה שאתה כותב עשוי להיות מופעלת על מספר רב של לקוחות הטרוגניים עם יכולות מגוונות. בעוד שבקצה אחד של הספקטרום, ביישומים מסוימים, לקוחות אלה עשויים להיות שרתי מסד נתונים רבי עוצמה, שימושים חשובים רבים שהפלטפורמה שלנו מתכוונת לתמוך כוללים מכשירים ניידים ומשובצים עם משאבים מוגבלים. איננו יכולים להניח שהמכשירים הללו מסוגלים לארח זמני ריצה של Python; הדבר היחיד שאנו יכולים להניח בשלב זה הוא שהם מסוגלים לארח זמן ריצה מקומי של TensorFlow. לפיכך, הנחה ארכיטקטונית בסיסית שאנו מניחים ב-TFF היא שקוד הדגם שלך חייב להיות ניתן לסידרה כגרף TensorFlow.

אתה עדיין יכול (וצריך) לפתח את קוד ה-TF שלך בהתאם לשיטות המומלצות העדכניות ביותר כמו שימוש במצב להוט. עם זאת, הקוד הסופי חייב להיות ניתן לסידרה (למשל, ניתן לעטוף כפונקציה tf.function עבור קוד במצב להוט). זה מבטיח שכל מצב Python או זרימת בקרה הדרושים בזמן הביצוע ניתנים להסדרה (אולי בעזרת Autograph ).

נכון לעכשיו, TensorFlow אינו תומך באופן מלא ב-Serializing ו-deserializing TensorFlow במצב להוט. לפיכך, הסדרה ב-TFF פועלת כיום לפי תבנית TF 1.0, כאשר כל הקוד חייב להיות בנוי בתוך tf.Graph ש-TFF שולט בו. המשמעות היא שכרגע TFF לא יכול לצרוך מודל שכבר נבנה; במקום זאת, הלוגיקה של הגדרת המודל ארוזה בפונקציה no-arg שמחזירה tff.learning.models.VariableModel . לאחר מכן, פונקציה זו נקראת על ידי TFF כדי להבטיח שכל רכיבי המודל מסודרים. בנוסף, בהיותה סביבה עם הקלדה חזקה, TFF ידרוש מעט מטא נתונים נוספים, כגון מפרט של סוג הקלט של הדגם שלך.

צבירה

אנו ממליצים בחום לרוב המשתמשים לבנות מודלים באמצעות Keras, עיין בסעיף ממירים עבור Keras להלן. עטיפות אלו מטפלות באופן אוטומטי בצבירה של עדכוני מודל, כמו גם בכל המדדים המוגדרים עבור המודל. עם זאת, עדיין עשוי להיות שימושי להבין כיצד מטופל צבירה עבור tff.learning.models.VariableModel כללי.

תמיד יש לפחות שתי שכבות של צבירה בלמידה מאוחדת: צבירה מקומית במכשיר, וצבירה חוצה-מכשירים (או מאוחדת):

  • צבירה מקומית . רמת צבירה זו מתייחסת לצבירה על פני מספר אצוות של דוגמאות בבעלות לקוח בודד. זה חל גם על פרמטרי המודל (משתנים), שממשיכים להתפתח ברצף ככל שהמודל מאומן באופן מקומי, וגם על הסטטיסטיקה שאתה מחשב (כגון הפסד ממוצע, דיוק ומדדים אחרים), שהמודל שלך יעודכן שוב באופן מקומי. כפי שהוא חוזר על זרם הנתונים המקומי של כל לקוח בודד.

    ביצוע צבירה ברמה זו הוא באחריות קוד הדגם שלך, והוא מתבצע באמצעות מבנים סטנדרטיים של TensorFlow.

    המבנה הכללי של העיבוד הוא כדלקמן:

    • המודל בונה תחילה tf.Variable s כדי להחזיק אגרגטים, כגון מספר אצווה או מספר דוגמאות שעובדו, סכום הפסדים לכל אצווה או לכל דוגמה וכו'.

    • TFF מפעיל את שיטת forward_pass Model שלך מספר פעמים, ברצף על פני אצווה של נתוני לקוח, מה שמאפשר לך לעדכן את המשתנים המכילים אגרגטים שונים כתופעת לוואי.

    • לבסוף, TFF מפעיל את שיטת report_local_unfinalized_metrics במודל שלך כדי לאפשר למודל שלך לאסוף את כל הנתונים הסטטיסטיים המסכמים שהוא אסף לתוך קבוצה קומפקטית של מדדים שייצא על ידי הלקוח. זה המקום שבו קוד הדגם שלך עשוי, למשל, לחלק את סכום ההפסדים במספר הדוגמאות שעובדו לייצוא ההפסד הממוצע וכו'.

  • צבירה מאוחדת . רמת צבירה זו מתייחסת לצבירה על פני מספר לקוחות (מכשירים) במערכת. שוב, זה חל הן על פרמטרי המודל (משתנים), אשר ממוצעים בין לקוחות, כמו גם על המדדים שהמודל שלך ייצא כתוצאה מצבירה מקומית.

    ביצוע צבירה ברמה זו הוא באחריות TFF. עם זאת, בתור יוצר מודל, אתה יכול לשלוט בתהליך הזה (עוד על כך בהמשך).

    המבנה הכללי של העיבוד הוא כדלקמן:

    • המודל הראשוני, וכל הפרמטרים הנדרשים להדרכה, מופצים על ידי שרת לקבוצת משנה של לקוחות שישתתפו בסבב הדרכה או הערכה.

    • בכל לקוח, באופן עצמאי ובמקביל, קוד הדגם שלך מופעל שוב ושוב בזרם של אצוות נתונים מקומיים כדי לייצר קבוצה חדשה של פרמטרים של מודל (בעת אימון), וקבוצה חדשה של מדדים מקומיים, כמתואר לעיל (זהו מקומי צבירה).

    • TFF מפעיל פרוטוקול צבירה מבוזר כדי לצבור ולצבור את פרמטרי המודל והמדדים המיוצאים מקומית על פני המערכת. ההיגיון הזה בא לידי ביטוי בצורה הצהרתית תוך שימוש בשפת החישוב המאוחדת של TFF (לא ב-TensorFlow). עיין במדריך האלגוריתמים המותאמים אישית למידע נוסף על ממשק ה-API לצבירה.

ממשקים מופשטים

ממשק הבנאי + מטא נתונים בסיסי זה מיוצג על ידי הממשק tff.learning.models.VariableModel , באופן הבא:

  • השיטות constructor, forward_pass ו- report_local_unfinalized_metrics צריכות לבנות משתני מודל, העברה קדימה וסטטיסטיקה שאתה רוצה לדווח, בהתאם. ה-TensorFlow שנבנה בשיטות אלו חייב להיות ניתן לסידרה, כפי שנדון לעיל.

  • המאפיין input_spec , כמו גם 3 המאפיינים שמחזירים קבוצות משנה של המשתנים הניתנים לאימון, הלא ניתנים לאימון והמקומיים שלך מייצגים את המטא נתונים. TFF משתמש במידע זה כדי לקבוע כיצד לחבר חלקים מהמודל שלך לאלגוריתמי האופטימיזציה המאוחדים, וכדי להגדיר חתימות סוג פנימיות כדי לסייע באימות נכונות המערכת הבנויה (כדי שלא ניתן להפעיל את המודל שלך על פני נתונים שאינם תואמים למה הדגם נועד לצרוך).

בנוסף, הממשק המופשט tff.learning.models.VariableModel חושף מאפיין metric_finalizers שמקבל את הערכים הלא סופיים של המדד (מוחזר על ידי report_local_unfinalized_metrics() ) ומחזיר את ערכי המדד הסופיים. שיטת metric_finalizers ו- report_local_unfinalized_metrics() ישמשו יחד כדי לבנות צובר מדדי חוצה לקוחות בעת הגדרת תהליכי ההדרכה המאוחדים או חישובי ההערכה. לדוגמה, אגרגטור פשוט tff.learning.metrics.sum_then_finalize יסכם תחילה את ערכי המדדים הלא סופיים מלקוחות, ולאחר מכן יקרא לפונקציות הסופיות בשרת.

תוכל למצוא דוגמאות כיצד להגדיר את tff.learning.models.VariableModel המותאם אישית שלך בחלק השני של המדריך שלנו לסיווג תמונות , כמו גם במודלים לדוגמה שבהם אנו משתמשים לבדיקה ב- model_examples.py .

ממירים עבור Keras

ניתן להפיק כמעט את כל המידע שנדרש על ידי TFF על ידי קריאה לממשקי tf.keras , כך שאם יש לך מודל של Keras, אתה יכול להסתמך על tff.learning.models.from_keras_model כדי לבנות tff.learning.models.VariableModel .

שים לב ש-TFF עדיין רוצה שתספק בנאי - פונקציית מודל ללא ויכוח, כגון:

def model_fn():
  keras_model = ...
  return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)

בנוסף למודל עצמו, אתה מספק אצווה לדוגמה של נתונים שבה TFF משתמש כדי לקבוע את הסוג והצורה של הקלט של המודל שלך. זה מבטיח ש-TFF יכול להמחיש כראוי את המודל עבור הנתונים שיהיו קיימים בפועל במכשירי הלקוח (מכיוון שאנו מניחים שהנתונים הללו אינם זמינים בדרך כלל בזמן שאתה בונה את TensorFlow להסדרה).

השימוש בעטיפות Keras מומחש במדריכי סיווג התמונות ויצירת טקסטים שלנו.

בוני חישובים מאוחדים

חבילת tff.learning מספקת מספר בונים עבור tff.Computation s המבצעים משימות הקשורות ללמידה; אנו מצפים שמערך החישובים הללו יתרחב בעתיד.

הנחות ארכיטקטוניות

ביצוע

ישנם שני שלבים נפרדים בהפעלת חישוב מאוחד.

  • קומפיל : TFF מרכיב תחילה אלגוריתמי למידה מאוחדים לייצוג מופשט מופשט של כל החישוב המבוזר. זה הזמן שבו מתרחשת סריאליזציה של TensorFlow, אבל שינויים אחרים יכולים להתרחש כדי לתמוך בביצוע יעיל יותר. אנו מתייחסים לייצוג הסדרתי הנפלט על ידי המהדר כחישוב מאוחד .

  • הפעל TFF מספק דרכים לביצוע חישובים אלה. לעת עתה, הביצוע נתמך רק באמצעות סימולציה מקומית (למשל, במחברת באמצעות נתונים מבוזרים מדומה).

חישוב מאוחד שנוצר על ידי ה-API Federated Learning של TFF, כגון אלגוריתם אימון המשתמש בממוצע מודלים מאוחדים , או הערכה מאוחדת, כולל מספר אלמנטים, בעיקר:

  • צורה מסודרת של קוד המודל שלך, כמו גם קוד TensorFlow נוסף שנבנה על ידי מסגרת הלמידה הפדרתית כדי להניע את לולאת ההדרכה/הערכה של המודל שלך (כגון בניית אופטימיזציה, החלת עדכוני מודל, איטרציה על s tf.data.Dataset ומדדי מחשוב, והחלת העדכון המצטבר על השרת, אם להזכיר כמה).

  • מפרט הצהרתי של התקשורת בין הלקוחות לשרת (בדרך כלל צורות שונות של צבירה על פני התקני הלקוח, ושידור מהשרת לכל הלקוחות), וכיצד תקשורת מבוזרת זו משתלבת בביצוע הלקוח-מקומי או שרת-מקומי של קוד TensorFlow.

החישובים המאוחדים המיוצגים בצורה מסודרת זו באים לידי ביטוי בשפה פנימית בלתי תלויה בפלטפורמה הנבדלת מ-Python, אך כדי להשתמש בממשק ה-Federated Learning API, לא תצטרכו להתעסק בפרטים של ייצוג זה. החישובים מיוצגים בקוד Python שלך כאובייקטים מסוג tff.Computation , שלרוב אתה יכול להתייחס אליהם כאל Python אטום callable .

במדריכים, תפעיל את החישובים המאוחדים האלה כאילו היו פונקציות Python רגילות, לביצוע מקומי. עם זאת, TFF נועד לבטא חישובים מאוחדים בצורה אגנוסטית לרוב ההיבטים של סביבת הביצוע, כך שהם יכולים להיות ניתנים לפריסה, למשל, קבוצות של מכשירים המריצים Android , או אשכולות במרכז נתונים. שוב, התוצאה העיקרית של זה הן הנחות חזקות לגבי סריאליזציה . בפרט, כאשר אתה מפעיל את אחת משיטות build_... המתוארות להלן, החישוב מתבצע בסידרה מלאה.

מצב דוגמנות

TFF היא סביבת תכנות פונקציונלית, אך תהליכים רבים של עניין בלמידה מאוחדת הם ממלכתיים. לדוגמה, לולאת אימון הכוללת סבבים מרובים של ממוצע מודלים מאוחדים היא דוגמה למה שאנו יכולים לסווג כתהליך ממלכתי . בתהליך זה, המצב שמתפתח מסיבוב לסיבוב כולל את קבוצת פרמטרי המודל המתאמנים, ואולי מצב נוסף הקשור לאופטימיזר (למשל, וקטור מומנטום).

מכיוון ש-TFF הוא פונקציונלי, תהליכים מצביים מעוצבים ב-TFF כחישובים המקבלים את המצב הנוכחי כקלט ולאחר מכן מספקים את המצב המעודכן כפלט. על מנת להגדיר באופן מלא תהליך מצבי, צריך גם לציין מאיפה מגיע המצב ההתחלתי (אחרת לא נוכל להפעיל את התהליך). זה נלכד בהגדרה של מחלקת העזר tff.templates.IterativeProcess , כאשר 2 המאפיינים initialize next תואמים את האתחול והאיטרציה, בהתאמה.

בונים זמינים

נכון לעכשיו, TFF מספק פונקציות בונה שונות המייצרות חישובים מאוחדים לאימון והערכה מאוחדים. שתי דוגמאות בולטות כוללות:

מערכי נתונים

הנחות ארכיטקטוניות

בחירת לקוח

בתרחיש למידה מאוחדת טיפוסי, יש לנו אוכלוסייה גדולה של מאות מיליוני מכשירי לקוח, שרק חלק קטן מהם עשוי להיות פעיל וזמין להדרכה בכל רגע נתון (לדוגמה, זה עשוי להיות מוגבל ללקוחות שהם מחובר למקור מתח, לא ברשת מדורגת, ובדרך אחרת לא פעיל). בדרך כלל, קבוצת הלקוחות הזמינה להשתתף בהדרכה או הערכה היא מחוץ לשליטת המפתח. יתר על כן, מכיוון שזה לא מעשי לתאם מיליוני לקוחות, סבב הדרכה או הערכה טיפוסי יכלול רק חלק קטן מהלקוחות הזמינים, אשר עשויים להידגם באקראי .

התוצאה המרכזית של זה היא שחישובים מאוחדים, לפי התכנון, באים לידי ביטוי באופן שאינו מודע לקבוצת המשתתפים המדויקת; כל העיבוד מתבטא כפעולות מצטברות על קבוצה מופשטת של לקוחות אנונימיים, וקבוצה זו עשויה להשתנות מסבב אימון אחד לאחר. הכריכה בפועל של החישוב למשתתפים הקונקרטיים, ובכך לנתונים הקונקרטיים שהם מזינים לחישוב, מעוצבת אפוא מחוץ לחישוב עצמו.

על מנת לדמות פריסה מציאותית של קוד הלמידה המאוחד שלך, בדרך כלל תכתוב לולאת אימון שנראית כך:

trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...

def sample(federate_data):
  return ...

while True:
  data_for_this_round = sample(federated_training_data)
  result = trainer.next(state, data_for_this_round)
  state = result.state

על מנת להקל על כך, בעת שימוש ב-TFF בסימולציות, נתונים מאוחדים מתקבלים כ-Python list s, עם רכיב אחד לכל התקן לקוח משתתף כדי לייצג את tf.data.Dataset המקומי של המכשיר הזה.

ממשקים מופשטים

על מנת לתקן את ההתמודדות עם מערכי נתונים מאוחדים מדומים, TFF מספק ממשק מופשט tff.simulation.datasets.ClientData , המאפשר למנות את קבוצת הלקוחות, ולבנות מערך tf.data.Dataset המכיל את הנתונים של נתון מסוים לָקוּחַ. ניתן להזין את tf.data.Dataset הללו ישירות כקלט לחישובים המאוחדים שנוצרו במצב להוט.

יש לציין שהיכולת לגשת לזהות לקוחות היא תכונה שמסופקת רק על ידי מערכי הנתונים לשימוש בסימולציות, שבהן עשויה להיות צורך ביכולת להתאמן על נתונים מתת-קבוצות ספציפיות של לקוחות (למשל, כדי לדמות את הזמינות היומית של שונים סוגי לקוחות). החישובים שנאספו וזמן הריצה הבסיסי אינם כרוכים בשום מושג של זהות הלקוח. לאחר שנבחרו נתונים מתת-קבוצה ספציפית של לקוחות כקלט, למשל, בקריאה ל- tff.templates.IterativeProcess.next , זהויות הלקוח אינן מופיעות בו עוד.

ערכות נתונים זמינות

הקדשנו את מרחב השמות tff.simulation.datasets עבור מערכי נתונים המיישמים את ממשק tff.simulation.datasets.ClientData לשימוש בסימולציות, וזרמנו אותו עם מערכי נתונים כדי לתמוך במדריכי סיווג תמונות ויצירת טקסט . אנו רוצים לעודד אותך לתרום מערכי נתונים משלך לפלטפורמה.

,

סקירה כללית

מסמך זה מציג ממשקים המקלים על משימות למידה מאוחדות, כגון הדרכה מאוחדת או הערכה עם מודלים קיימים של למידת מכונה המיושמים ב-TensorFlow. בתכנון הממשקים הללו, המטרה העיקרית שלנו הייתה לאפשר להתנסות בלמידה מאוחדת מבלי להידרש לידע כיצד היא פועלת מתחת למכסה המנוע, ולהעריך את אלגוריתמי הלמידה המאוחדים המיושמים על מגוון מודלים ונתונים קיימים. אנו ממליצים לך לתרום בחזרה לפלטפורמה. TFF תוכנן מתוך מחשבה על יכולת הרחבה והרכבה, ואנו מברכים על תרומות; אנחנו נרגשים לראות מה יצא לך!

הממשקים שמציעה שכבה זו מורכבים משלושת חלקי המפתח הבאים:

  • דגמים . שיעורים ופונקציות עוזרות המאפשרות לך לעטוף את הדגמים הקיימים שלך לשימוש עם TFF. גלישת מודל יכולה להיות פשוטה כמו קריאה לפונקציית גלישה בודדת (למשל, tff.learning.models.from_keras_model ), או הגדרת תת מחלקה של ממשק tff.learning.models.VariableModel להתאמה אישית מלאה.

  • בוני חישובים מאוחדים . פונקציות עוזר הבונות חישובים מאוחדים להדרכה או הערכה, תוך שימוש במודלים הקיימים שלך.

  • מערכי נתונים . אוספים מוכנים של נתונים שאתה יכול להוריד ולגשת אליהם ב-Python לשימוש בהדמיית תרחישי למידה מאוחדים. למרות שלמידה מאוחדת מיועדת לשימוש עם נתונים מבוזרים שלא ניתנים להורדה במיקום מרכזי, בשלבי המחקר והפיתוח לרוב נוח לערוך ניסויים ראשוניים באמצעות נתונים שניתן להוריד ולתפעל באופן מקומי, במיוחד עבור מפתחים שעלולים להיות חדש בגישה.

ממשקים אלו מוגדרים בעיקר במרחב השמות tff.learning , למעט מערכי נתונים מחקריים ויכולות אחרות הקשורות לסימולציה שקובצו ב- tff.simulation . שכבה זו מיושמת באמצעות ממשקים ברמה נמוכה יותר המוצעים על ידי ה- Federated Core (FC) , המספקת גם סביבת זמן ריצה.

לפני שתמשיך, אנו ממליצים שתקרא תחילה את המדריכים על סיווג תמונות ויצירת טקסט , מכיוון שהם מציגים את רוב המושגים המתוארים כאן באמצעות דוגמאות קונקרטיות. אם אתה מעוניין ללמוד עוד על אופן הפעולה של TFF, אולי תרצה לדפדף על המדריך לאלגוריתמים מותאמים אישית כהקדמה לממשקים ברמה נמוכה יותר שבהם אנו משתמשים כדי לבטא את ההיגיון של חישובים מאוחדים, וכדי ללמוד את היישום הקיים של ממשקי tff.learning .

דגמים

הנחות ארכיטקטוניות

סדרה

TFF שואפת לתמוך במגוון תרחישי למידה מבוזרת שבהם קוד מודל למידת המכונה שאתה כותב עשוי להיות מופעלת על מספר רב של לקוחות הטרוגניים עם יכולות מגוונות. בעוד שבקצה אחד של הספקטרום, ביישומים מסוימים, לקוחות אלה עשויים להיות שרתי מסד נתונים רבי עוצמה, שימושים חשובים רבים שהפלטפורמה שלנו מתכוונת לתמוך כוללים מכשירים ניידים ומשובצים עם משאבים מוגבלים. איננו יכולים להניח שהמכשירים הללו מסוגלים לארח זמני ריצה של Python; הדבר היחיד שאנו יכולים להניח בשלב זה הוא שהם מסוגלים לארח זמן ריצה מקומי של TensorFlow. לפיכך, הנחה ארכיטקטונית בסיסית שאנו מניחים ב-TFF היא שקוד הדגם שלך חייב להיות ניתן לסידרה כגרף TensorFlow.

אתה עדיין יכול (וצריך) לפתח את קוד ה-TF שלך בהתאם לשיטות המומלצות העדכניות ביותר כמו שימוש במצב להוט. עם זאת, הקוד הסופי חייב להיות ניתן לסידרה (למשל, ניתן לעטוף כפונקציה tf.function עבור קוד במצב להוט). זה מבטיח שכל מצב Python או זרימת בקרה הדרושים בזמן הביצוע ניתנים להסדרה (אולי בעזרת Autograph ).

נכון לעכשיו, TensorFlow אינו תומך באופן מלא ב-Serializing ו-deserializing TensorFlow במצב להוט. לפיכך, הסדרה ב-TFF פועלת כיום לפי תבנית TF 1.0, כאשר כל הקוד חייב להיות בנוי בתוך tf.Graph ש-TFF שולט בו. המשמעות היא שכרגע TFF לא יכול לצרוך מודל שכבר נבנה; במקום זאת, הלוגיקה של הגדרת המודל ארוזה בפונקציה no-arg שמחזירה tff.learning.models.VariableModel . לאחר מכן, פונקציה זו נקראת על ידי TFF כדי להבטיח שכל רכיבי המודל מסודרים. בנוסף, בהיותה סביבה עם הקלדה חזקה, TFF ידרוש מעט מטא נתונים נוספים, כגון מפרט של סוג הקלט של הדגם שלך.

צבירה

אנו ממליצים בחום לרוב המשתמשים לבנות מודלים באמצעות Keras, עיין בסעיף ממירים עבור Keras להלן. עטיפות אלו מטפלות באופן אוטומטי בצבירה של עדכוני מודל, כמו גם בכל המדדים המוגדרים עבור המודל. עם זאת, עדיין עשוי להיות שימושי להבין כיצד מטופל צבירה עבור tff.learning.models.VariableModel כללי.

תמיד יש לפחות שתי שכבות של צבירה בלמידה מאוחדת: צבירה מקומית במכשיר, וצבירה חוצה-מכשירים (או מאוחדת):

  • צבירה מקומית . רמת צבירה זו מתייחסת לצבירה על פני מספר אצוות של דוגמאות בבעלות לקוח בודד. זה חל גם על פרמטרי המודל (משתנים), שממשיכים להתפתח ברצף ככל שהמודל מאומן באופן מקומי, וגם על הסטטיסטיקה שאתה מחשב (כגון הפסד ממוצע, דיוק ומדדים אחרים), שהמודל שלך יעודכן שוב באופן מקומי. כפי שהוא חוזר על זרם הנתונים המקומי של כל לקוח בודד.

    ביצוע צבירה ברמה זו הוא באחריות קוד הדגם שלך, והוא מתבצע באמצעות מבנים סטנדרטיים של TensorFlow.

    המבנה הכללי של העיבוד הוא כדלקמן:

    • המודל בונה תחילה tf.Variable s כדי להחזיק אגרגטים, כגון מספר אצווה או מספר דוגמאות שעובדו, סכום הפסדים לכל אצווה או לכל דוגמה וכו'.

    • TFF מפעיל את שיטת forward_pass Model שלך מספר פעמים, ברצף על פני אצווה של נתוני לקוח, מה שמאפשר לך לעדכן את המשתנים המכילים אגרגטים שונים כתופעת לוואי.

    • לבסוף, TFF מפעיל את שיטת report_local_unfinalized_metrics במודל שלך כדי לאפשר למודל שלך לאסוף את כל הנתונים הסטטיסטיים המסכמים שהוא אסף לתוך קבוצה קומפקטית של מדדים שייצא על ידי הלקוח. זה המקום שבו קוד הדגם שלך עשוי, למשל, לחלק את סכום ההפסדים במספר הדוגמאות שעובדו לייצוא ההפסד הממוצע וכו'.

  • צבירה מאוחדת . רמת צבירה זו מתייחסת לצבירה על פני מספר לקוחות (מכשירים) במערכת. שוב, זה חל הן על פרמטרי המודל (משתנים), אשר ממוצעים בין לקוחות, כמו גם על המדדים שהמודל שלך ייצא כתוצאה מצבירה מקומית.

    ביצוע צבירה ברמה זו הוא באחריות TFF. עם זאת, בתור יוצר מודל, אתה יכול לשלוט בתהליך הזה (עוד על כך בהמשך).

    המבנה הכללי של העיבוד הוא כדלקמן:

    • המודל הראשוני, וכל הפרמטרים הנדרשים להדרכה, מופצים על ידי שרת לקבוצת משנה של לקוחות שישתתפו בסבב הדרכה או הערכה.

    • בכל לקוח, באופן עצמאי ובמקביל, קוד הדגם שלך מופעל שוב ושוב בזרם של אצוות נתונים מקומיים כדי לייצר קבוצה חדשה של פרמטרים של מודל (בעת אימון), וקבוצה חדשה של מדדים מקומיים, כמתואר לעיל (זהו מקומי צבירה).

    • TFF מפעיל פרוטוקול צבירה מבוזר כדי לצבור ולצבור את פרמטרי המודל והמדדים המיוצאים מקומית על פני המערכת. ההיגיון הזה בא לידי ביטוי בצורה הצהרתית תוך שימוש בשפת החישוב המאוחדת של TFF (לא ב-TensorFlow). עיין במדריך האלגוריתמים המותאמים אישית למידע נוסף על ממשק ה-API לצבירה.

ממשקים מופשטים

ממשק הבנאי + מטא נתונים בסיסי זה מיוצג על ידי הממשק tff.learning.models.VariableModel , באופן הבא:

  • השיטות constructor, forward_pass ו- report_local_unfinalized_metrics צריכות לבנות משתני מודל, העברה קדימה וסטטיסטיקה שאתה רוצה לדווח, בהתאם. ה-TensorFlow שנבנה בשיטות אלו חייב להיות ניתן לסידרה, כפי שנדון לעיל.

  • המאפיין input_spec , כמו גם 3 המאפיינים שמחזירים קבוצות משנה של המשתנים הניתנים לאימון, הלא ניתנים לאימון והמקומיים שלך מייצגים את המטא נתונים. TFF משתמש במידע זה כדי לקבוע כיצד לחבר חלקים מהמודל שלך לאלגוריתמי האופטימיזציה המאוחדים, וכדי להגדיר חתימות סוג פנימיות כדי לסייע באימות נכונות המערכת הבנויה (כדי שלא ניתן להפעיל את המודל שלך על פני נתונים שאינם תואמים למה הדגם נועד לצרוך).

בנוסף, הממשק המופשט tff.learning.models.VariableModel חושף מאפיין metric_finalizers שמקבל את הערכים הלא סופיים של המדד (מוחזר על ידי report_local_unfinalized_metrics() ) ומחזיר את ערכי המדד הסופיים. שיטת metric_finalizers ו- report_local_unfinalized_metrics() ישמשו יחד כדי לבנות צובר מדדי חוצה לקוחות בעת הגדרת תהליכי ההדרכה המאוחדים או חישובי ההערכה. לדוגמה, אגרגטור פשוט tff.learning.metrics.sum_then_finalize יסכם תחילה את ערכי המדדים הלא סופיים מלקוחות, ולאחר מכן יקרא לפונקציות הסופיות בשרת.

תוכל למצוא דוגמאות כיצד להגדיר את tff.learning.models.VariableModel המותאם אישית שלך בחלק השני של המדריך שלנו לסיווג תמונות , כמו גם במודלים לדוגמה שבהם אנו משתמשים לבדיקה ב- model_examples.py .

ממירים עבור Keras

ניתן להפיק כמעט את כל המידע שנדרש על ידי TFF על ידי קריאה לממשקי tf.keras , כך שאם יש לך מודל של Keras, אתה יכול להסתמך על tff.learning.models.from_keras_model כדי לבנות tff.learning.models.VariableModel .

שים לב ש-TFF עדיין רוצה שתספק בנאי - פונקציית מודל ללא ויכוח, כגון:

def model_fn():
  keras_model = ...
  return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)

בנוסף למודל עצמו, אתה מספק אצווה לדוגמה של נתונים שבה TFF משתמש כדי לקבוע את הסוג והצורה של הקלט של המודל שלך. זה מבטיח ש-TFF יכול להמחיש כראוי את המודל עבור הנתונים שיהיו קיימים בפועל במכשירי הלקוח (מכיוון שאנו מניחים שהנתונים הללו אינם זמינים בדרך כלל בזמן שאתה בונה את TensorFlow להסדרה).

השימוש בעטיפות Keras מומחש במדריכי סיווג התמונות ויצירת טקסטים שלנו.

בוני חישובים מאוחדים

חבילת tff.learning מספקת מספר בונים עבור tff.Computation s המבצעים משימות הקשורות ללמידה; אנו מצפים שמערך החישובים הללו יתרחב בעתיד.

הנחות ארכיטקטוניות

ביצוע

ישנם שני שלבים נפרדים בהפעלת חישוב מאוחד.

  • קומפיל : TFF מרכיב תחילה אלגוריתמי למידה מאוחדים לייצוג מופשט מופשט של כל החישוב המבוזר. זה הזמן שבו מתרחשת סריאליזציה של TensorFlow, אבל שינויים אחרים יכולים להתרחש כדי לתמוך בביצוע יעיל יותר. אנו מתייחסים לייצוג הסדרתי הנפלט על ידי המהדר כחישוב מאוחד .

  • הפעל TFF מספק דרכים לביצוע חישובים אלה. לעת עתה, הביצוע נתמך רק באמצעות סימולציה מקומית (למשל, במחברת באמצעות נתונים מבוזרים מדומה).

חישוב מאוחד שנוצר על ידי ה-API Federated Learning של TFF, כגון אלגוריתם אימון המשתמש בממוצע מודלים מאוחדים , או הערכה מאוחדת, כולל מספר אלמנטים, בעיקר:

  • צורה מסודרת של קוד המודל שלך, כמו גם קוד TensorFlow נוסף שנבנה על ידי מסגרת הלמידה הפדרתית כדי להניע את לולאת ההדרכה/הערכה של המודל שלך (כגון בניית אופטימיזציה, החלת עדכוני מודל, איטרציה על s tf.data.Dataset ומדדי מחשוב, והחלת העדכון המצטבר על השרת, אם להזכיר כמה).

  • מפרט הצהרתי של התקשורת בין הלקוחות לשרת (בדרך כלל צורות שונות של צבירה על פני התקני הלקוח, ושידור מהשרת לכל הלקוחות), וכיצד תקשורת מבוזרת זו משתלבת בביצוע הלקוח-מקומי או שרת-מקומי של קוד TensorFlow.

החישובים המאוחדים המיוצגים בצורה מסודרת זו באים לידי ביטוי בשפה פנימית בלתי תלויה בפלטפורמה הנבדלת מ-Python, אך כדי להשתמש בממשק ה-Federated Learning API, לא תצטרכו להתעסק בפרטים של ייצוג זה. החישובים מיוצגים בקוד Python שלך כאובייקטים מסוג tff.Computation , שלרוב אתה יכול להתייחס אליהם כאל Python אטום callable .

במדריכים, תפעיל את החישובים המאוחדים האלה כאילו היו פונקציות Python רגילות, לביצוע מקומי. עם זאת, TFF נועד לבטא חישובים מאוחדים בצורה אגנוסטית לרוב ההיבטים של סביבת הביצוע, כך שהם יכולים להיות ניתנים לפריסה, למשל, קבוצות של מכשירים המריצים Android , או אשכולות במרכז נתונים. שוב, התוצאה העיקרית של זה הן הנחות חזקות לגבי סריאליזציה . בפרט, כאשר אתה מפעיל את אחת משיטות build_... המתוארות להלן, החישוב מתבצע בסידרה מלאה.

מצב דוגמנות

TFF היא סביבת תכנות פונקציונלית, אך תהליכים רבים של עניין בלמידה מאוחדת הם ממלכתיים. לדוגמה, לולאת אימון הכוללת סבבים מרובים של ממוצע מודלים מאוחדים היא דוגמה למה שאנו יכולים לסווג כתהליך ממלכתי . בתהליך זה, המצב שמתפתח מסיבוב לסיבוב כולל את קבוצת פרמטרי המודל המתאמנים, ואולי מצב נוסף הקשור לאופטימיזר (למשל, וקטור מומנטום).

מכיוון ש-TFF הוא פונקציונלי, תהליכים מצביים מעוצבים ב-TFF כחישובים המקבלים את המצב הנוכחי כקלט ולאחר מכן מספקים את המצב המעודכן כפלט. על מנת להגדיר באופן מלא תהליך מצבי, צריך גם לציין מאיפה מגיע המצב ההתחלתי (אחרת לא נוכל להפעיל את התהליך). זה נלכד בהגדרה של מחלקת העזר tff.templates.IterativeProcess , כאשר 2 המאפיינים initialize next תואמים את האתחול והאיטרציה, בהתאמה.

בונים זמינים

At the moment, TFF provides various builder functions that generate federated computations for federated training and evaluation. Two notable examples include:

Datasets

Architectural assumptions

Client selection

In the typical federated learning scenario, we have a large population of potentially hundreds of millions of client devices, of which only a small portion may be active and available for training at any given moment (for example, this may be limited to clients that are plugged in to a power source, not on a metered network, and otherwise idle). Generally, the set of clients available to participate in training or evaluation is outside of the developer's control. Furthermore, as it's impractical to coordinate millions of clients, a typical round of training or evaluation will include only a fraction of the available clients, which may be sampled at random .

The key consequence of this is that federated computations, by design, are expressed in a manner that is oblivious to the exact set of participants; all processing is expressed as aggregate operations on an abstract group of anonymous clients , and that group might vary from one round of training to another. The actual binding of the computation to the concrete participants, and thus to the concrete data they feed into the computation, is thus modeled outside of the computation itself.

In order to simulate a realistic deployment of your federated learning code, you will generally write a training loop that looks like this:

trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...

def sample(federate_data):
  return ...

while True:
  data_for_this_round = sample(federated_training_data)
  result = trainer.next(state, data_for_this_round)
  state = result.state

In order to facilitate this, when using TFF in simulations, federated data is accepted as Python list s, with one element per participating client device to represent that device's local tf.data.Dataset .

Abstract interfaces

In order to standardize dealing with simulated federated data sets, TFF provides an abstract interface tff.simulation.datasets.ClientData , which allows one to enumerate the set of clients, and to construct a tf.data.Dataset that contains the data of a particular client. Those tf.data.Dataset s can be fed directly as input to the generated federated computations in eager mode.

It should be noted that the ability to access client identities is a feature that's only provided by the datasets for use in simulations, where the ability to train on data from specific subsets of clients may be needed (eg, to simulate the diurnal availability of different types of clients). The compiled computations and the underlying runtime do not involve any notion of client identity. Once data from a specific subset of clients has been selected as an input, eg, in a call to tff.templates.IterativeProcess.next , client identities no longer appear in it.

Available data sets

We have dedicated the namespace tff.simulation.datasets for datasets that implement the tff.simulation.datasets.ClientData interface for use in simulations, and seeded it with datasets to support the image classification and text generation tutorials. We'd like to encourage you to contribute your own datasets to the platform.

,

Overview

This document introduces interfaces that facilitate federated learning tasks, such as federated training or evaluation with existing machine learning models implemented in TensorFlow. In designing these interfaces, our primary goal was to make it possible to experiment with federated learning without requiring the knowledge of how it works under the hood, and to evaluate the implemented federated learning algorithms on a variety of existing models and data. We encourage you to contribute back to the platform. TFF has been designed with extensibility and composability in mind, and we welcome contributions; we are excited to see what you come up with!

The interfaces offered by this layer consist of the following three key parts:

  • Models . Classes and helper functions that allow you to wrap your existing models for use with TFF. Wrapping a model can be as simple as calling a single wrapping function (eg, tff.learning.models.from_keras_model ), or defining a subclass of the tff.learning.models.VariableModel interface for full customizability.

  • Federated Computation Builders . Helper functions that construct federated computations for training or evaluation, using your existing models.

  • Datasets . Canned collections of data that you can download and access in Python for use in simulating federated learning scenarios. Although federated learning is designed for use with decentralized data that cannot be simply downloaded at a centralized location, at the research and development stages it is often convenient to conduct initial experiments using data that can be downloaded and manipulated locally, especially for developers who might be new to the approach.

These interfaces are defined primarily in the tff.learning namespace, except for research data sets and other simulation-related capabilities that have been grouped in tff.simulation . This layer is implemented using lower-level interfaces offered by the Federated Core (FC) , which also provides a runtime environment.

Before proceeding, we recommend that you first review the tutorials on image classification and text generation , as they introduce most of the concepts described here using concrete examples. If you're interested in learning more about how TFF works, you may want to skim over the custom algorithms tutorial as an introduction to the lower-level interfaces we use to express the logic of federated computations, and to study the existing implementation of the tff.learning interfaces.

Models

Architectural assumptions

Serialization

TFF aims at supporting a variety of distributed learning scenarios in which the machine learning model code you write might be executing on a large number of heterogeneous clients with diverse capabilities. While at one end of the spectrum, in some applications those clients might be powerful database servers, many important uses our platform intends to support involve mobile and embedded devices with limited resources. We cannot assume that these devices are capable of hosting Python runtimes; the only thing we can assume at this point is that they are capable of hosting a local TensorFlow runtime. Thus, a fundamental architectural assumption we make in TFF is that your model code must be serializable as a TensorFlow graph.

You can (and should) still develop your TF code following the latest best practices like using eager mode. However, the final code must be serializable (eg, can be wrapped as a tf.function for eager-mode code). This ensures that any Python state or control flow necessary at execution time can be serialized (possibly with the help of Autograph ).

Currently, TensorFlow does not fully support serializing and deserializing eager-mode TensorFlow. Thus, serialization in TFF currently follows the TF 1.0 pattern, where all code must be constructed inside a tf.Graph that TFF controls. This means currently TFF cannot consume an already-constructed model; instead, the model definition logic is packaged in a no-arg function that returns a tff.learning.models.VariableModel . This function is then called by TFF to ensure all components of the model are serialized. In addition, being a strongly-typed environment, TFF will require a little bit of additional metadata , such as a specification of your model's input type.

Aggregation

We strongly recommend most users construct models using Keras, see the Converters for Keras section below. These wrappers handle the aggregation of model updates as well as any metrics defined for the model automatically. However, it may still be useful to understand how aggregation is handled for a general tff.learning.models.VariableModel .

There are always at least two layers of aggregation in federated learning: local on-device aggregation, and cross-device (or federated) aggregation:

  • Local aggregation . This level of aggregation refers to aggregation across multiple batches of examples owned by an individual client. It applies to both the model parameters (variables), which continue to sequentially evolve as the model is locally trained, as well as the statistics you compute (such as average loss, accuracy, and other metrics), which your model will again update locally as it iterates over each individual client's local data stream.

    Performing aggregation at this level is the responsibility of your model code, and is accomplished using standard TensorFlow constructs.

    The general structure of processing is as follows:

    • The model first constructs tf.Variable s to hold aggregates, such as the number of batches or the number of examples processed, the sum of per-batch or per-example losses, etc.

    • TFF invokes the forward_pass method on your Model multiple times, sequentially over subsequent batches of client data, which allows you to update the variables holding various aggregates as a side effect.

    • Finally, TFF invokes the report_local_unfinalized_metrics method on your Model to allow your model to compile all the summary statistics it collected into a compact set of metrics to be exported by the client. This is where your model code may, for example, divide the sum of losses by the number of examples processed to export the average loss, etc.

  • Federated aggregation . This level of aggregation refers to aggregation across multiple clients (devices) in the system. Again, it applies to both the model parameters (variables), which are being averaged across clients, as well as the metrics your model exported as a result of local aggregation.

    Performing aggregation at this level is the responsibility of TFF. As a model creator, however, you can control this process (more on this below).

    The general structure of processing is as follows:

    • The initial model, and any parameters required for training, are distributed by a server to a subset of clients that will participate in a round of training or evaluation.

    • On each client, independently and in parallel, your model code is invoked repeatedly on a stream of local data batches to produce a new set of model parameters (when training), and a new set of local metrics, as described above (this is local aggregation).

    • TFF runs a distributed aggregation protocol to accumulate and aggregate the model parameters and locally exported metrics across the system. This logic is expressed in a declarative manner using TFF's own federated computation language (not in TensorFlow). See the custom algorithms tutorial for more on the aggregation API.

Abstract interfaces

This basic constructor + metadata interface is represented by the interface tff.learning.models.VariableModel , as follows:

  • The constructor, forward_pass , and report_local_unfinalized_metrics methods should construct model variables, forward pass, and statistics you wish to report, correspondingly. The TensorFlow constructed by those methods must be serializable, as discussed above.

  • The input_spec property, as well as the 3 properties that return subsets of your trainable, non-trainable, and local variables represent the metadata. TFF uses this information to determine how to connect parts of your model to the federated optimization algorithms, and to define internal type signatures to assist in verifying the correctness of the constructed system (so that your model cannot be instantiated over data that does not match what the model is designed to consume).

In addition, the abstract interface tff.learning.models.VariableModel exposes a property metric_finalizers that takes in a metric's unfinalized values (returned by report_local_unfinalized_metrics() ) and returns the finalized metric values. The metric_finalizers and report_local_unfinalized_metrics() method will be used together to build a cross-client metrics aggregator when defining the federated training processes or evaluation computations. For example, a simple tff.learning.metrics.sum_then_finalize aggregator will first sum the unfinalized metric values from clients, and then call the finalizer functions at the server.

You can find examples of how to define your own custom tff.learning.models.VariableModel in the second part of our image classification tutorial, as well as in the example models we use for testing in model_examples.py .

Converters for Keras

Nearly all the information that's required by TFF can be derived by calling tf.keras interfaces, so if you have a Keras model, you can rely on tff.learning.models.from_keras_model to construct a tff.learning.models.VariableModel .

Note that TFF still wants you to provide a constructor - a no-argument model function such as the following:

def model_fn():
  keras_model = ...
  return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)

In addition to the model itself, you supply a sample batch of data which TFF uses to determine the type and shape of your model's input. This ensures that TFF can properly instantiate the model for the data that will actually be present on client devices (since we assume this data is not generally available at the time you are constructing the TensorFlow to be serialized).

The use of Keras wrappers is illustrated in our image classification and text generation tutorials.

Federated Computation Builders

The tff.learning package provides several builders for tff.Computation s that perform learning-related tasks; we expect the set of such computations to expand in the future.

Architectural assumptions

Execution

There are two distinct phases in running a federated computation.

  • Compile : TFF first compiles federated learning algorithms into an abstract serialized representation of the entire distributed computation. This is when TensorFlow serialization happens, but other transformations can occur to support more efficient execution. We refer to the serialized representation emitted by the compiler as a federated computation .

  • Execute TFF provides ways to execute these computations. For now, execution is only supported via a local simulation (eg, in a notebook using simulated decentralized data).

A federated computation generated by TFF's Federated Learning API, such as a training algorithm that uses federated model averaging , or a federated evaluation, includes a number of elements, most notably:

  • A serialized form of your model code as well as additional TensorFlow code constructed by the Federated Learning framework to drive your model's training/evaluation loop (such as constructing optimizers, applying model updates, iterating over tf.data.Dataset s, and computing metrics, and applying the aggregated update on the server, to name a few).

  • A declarative specification of the communication between the clients and a server (typically various forms of aggregation across the client devices, and broadcasting from the server to all clients), and how this distributed communication is interleaved with the client-local or server-local execution of TensorFlow code.

The federated computations represented in this serialized form are expressed in a platform-independent internal language distinct from Python, but to use the Federated Learning API, you won't need to concern yourself with the details of this representation. The computations are represented in your Python code as objects of type tff.Computation , which for the most part you can treat as opaque Python callable s.

In the tutorials, you will invoke those federated computations as if they were regular Python functions, to be executed locally. However, TFF is designed to express federated computations in a manner agnostic to most aspects of the execution environment, so that they can potentially be deployable to, eg, groups of devices running Android , or to clusters in a datacenter. Again, the main consequence of this are strong assumptions about serialization . In particular, when you invoke one of the build_... methods described below the computation is fully serialized.

Modeling state

TFF is a functional programming environment, yet many processes of interest in federated learning are stateful. For example, a training loop that involves multiple rounds of federated model averaging is an example of what we could classify as a stateful process . In this process, the state that evolves from round to round includes the set of model parameters that are being trained, and possibly additional state associated with the optimizer (eg, a momentum vector).

Since TFF is functional, stateful processes are modeled in TFF as computations that accept the current state as an input and then provide the updated state as an output. In order to fully define a stateful process, one also needs to specify where the initial state comes from (otherwise we cannot bootstrap the process). This is captured in the definition of the helper class tff.templates.IterativeProcess , with the 2 properties initialize and next corresponding to the initialization and iteration, respectively.

Available builders

At the moment, TFF provides various builder functions that generate federated computations for federated training and evaluation. Two notable examples include:

Datasets

Architectural assumptions

Client selection

In the typical federated learning scenario, we have a large population of potentially hundreds of millions of client devices, of which only a small portion may be active and available for training at any given moment (for example, this may be limited to clients that are plugged in to a power source, not on a metered network, and otherwise idle). Generally, the set of clients available to participate in training or evaluation is outside of the developer's control. Furthermore, as it's impractical to coordinate millions of clients, a typical round of training or evaluation will include only a fraction of the available clients, which may be sampled at random .

The key consequence of this is that federated computations, by design, are expressed in a manner that is oblivious to the exact set of participants; all processing is expressed as aggregate operations on an abstract group of anonymous clients , and that group might vary from one round of training to another. The actual binding of the computation to the concrete participants, and thus to the concrete data they feed into the computation, is thus modeled outside of the computation itself.

In order to simulate a realistic deployment of your federated learning code, you will generally write a training loop that looks like this:

trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...

def sample(federate_data):
  return ...

while True:
  data_for_this_round = sample(federated_training_data)
  result = trainer.next(state, data_for_this_round)
  state = result.state

In order to facilitate this, when using TFF in simulations, federated data is accepted as Python list s, with one element per participating client device to represent that device's local tf.data.Dataset .

Abstract interfaces

In order to standardize dealing with simulated federated data sets, TFF provides an abstract interface tff.simulation.datasets.ClientData , which allows one to enumerate the set of clients, and to construct a tf.data.Dataset that contains the data of a particular client. Those tf.data.Dataset s can be fed directly as input to the generated federated computations in eager mode.

It should be noted that the ability to access client identities is a feature that's only provided by the datasets for use in simulations, where the ability to train on data from specific subsets of clients may be needed (eg, to simulate the diurnal availability of different types of clients). The compiled computations and the underlying runtime do not involve any notion of client identity. Once data from a specific subset of clients has been selected as an input, eg, in a call to tff.templates.IterativeProcess.next , client identities no longer appear in it.

Available data sets

We have dedicated the namespace tff.simulation.datasets for datasets that implement the tff.simulation.datasets.ClientData interface for use in simulations, and seeded it with datasets to support the image classification and text generation tutorials. We'd like to encourage you to contribute your own datasets to the platform.

,

Overview

This document introduces interfaces that facilitate federated learning tasks, such as federated training or evaluation with existing machine learning models implemented in TensorFlow. In designing these interfaces, our primary goal was to make it possible to experiment with federated learning without requiring the knowledge of how it works under the hood, and to evaluate the implemented federated learning algorithms on a variety of existing models and data. We encourage you to contribute back to the platform. TFF has been designed with extensibility and composability in mind, and we welcome contributions; we are excited to see what you come up with!

The interfaces offered by this layer consist of the following three key parts:

  • Models . Classes and helper functions that allow you to wrap your existing models for use with TFF. Wrapping a model can be as simple as calling a single wrapping function (eg, tff.learning.models.from_keras_model ), or defining a subclass of the tff.learning.models.VariableModel interface for full customizability.

  • Federated Computation Builders . Helper functions that construct federated computations for training or evaluation, using your existing models.

  • Datasets . Canned collections of data that you can download and access in Python for use in simulating federated learning scenarios. Although federated learning is designed for use with decentralized data that cannot be simply downloaded at a centralized location, at the research and development stages it is often convenient to conduct initial experiments using data that can be downloaded and manipulated locally, especially for developers who might be new to the approach.

These interfaces are defined primarily in the tff.learning namespace, except for research data sets and other simulation-related capabilities that have been grouped in tff.simulation . This layer is implemented using lower-level interfaces offered by the Federated Core (FC) , which also provides a runtime environment.

Before proceeding, we recommend that you first review the tutorials on image classification and text generation , as they introduce most of the concepts described here using concrete examples. If you're interested in learning more about how TFF works, you may want to skim over the custom algorithms tutorial as an introduction to the lower-level interfaces we use to express the logic of federated computations, and to study the existing implementation of the tff.learning interfaces.

Models

Architectural assumptions

Serialization

TFF aims at supporting a variety of distributed learning scenarios in which the machine learning model code you write might be executing on a large number of heterogeneous clients with diverse capabilities. While at one end of the spectrum, in some applications those clients might be powerful database servers, many important uses our platform intends to support involve mobile and embedded devices with limited resources. We cannot assume that these devices are capable of hosting Python runtimes; the only thing we can assume at this point is that they are capable of hosting a local TensorFlow runtime. Thus, a fundamental architectural assumption we make in TFF is that your model code must be serializable as a TensorFlow graph.

You can (and should) still develop your TF code following the latest best practices like using eager mode. However, the final code must be serializable (eg, can be wrapped as a tf.function for eager-mode code). This ensures that any Python state or control flow necessary at execution time can be serialized (possibly with the help of Autograph ).

Currently, TensorFlow does not fully support serializing and deserializing eager-mode TensorFlow. Thus, serialization in TFF currently follows the TF 1.0 pattern, where all code must be constructed inside a tf.Graph that TFF controls. This means currently TFF cannot consume an already-constructed model; instead, the model definition logic is packaged in a no-arg function that returns a tff.learning.models.VariableModel . This function is then called by TFF to ensure all components of the model are serialized. In addition, being a strongly-typed environment, TFF will require a little bit of additional metadata , such as a specification of your model's input type.

Aggregation

We strongly recommend most users construct models using Keras, see the Converters for Keras section below. These wrappers handle the aggregation of model updates as well as any metrics defined for the model automatically. However, it may still be useful to understand how aggregation is handled for a general tff.learning.models.VariableModel .

There are always at least two layers of aggregation in federated learning: local on-device aggregation, and cross-device (or federated) aggregation:

  • Local aggregation . This level of aggregation refers to aggregation across multiple batches of examples owned by an individual client. It applies to both the model parameters (variables), which continue to sequentially evolve as the model is locally trained, as well as the statistics you compute (such as average loss, accuracy, and other metrics), which your model will again update locally as it iterates over each individual client's local data stream.

    Performing aggregation at this level is the responsibility of your model code, and is accomplished using standard TensorFlow constructs.

    The general structure of processing is as follows:

    • The model first constructs tf.Variable s to hold aggregates, such as the number of batches or the number of examples processed, the sum of per-batch or per-example losses, etc.

    • TFF invokes the forward_pass method on your Model multiple times, sequentially over subsequent batches of client data, which allows you to update the variables holding various aggregates as a side effect.

    • Finally, TFF invokes the report_local_unfinalized_metrics method on your Model to allow your model to compile all the summary statistics it collected into a compact set of metrics to be exported by the client. This is where your model code may, for example, divide the sum of losses by the number of examples processed to export the average loss, etc.

  • Federated aggregation . This level of aggregation refers to aggregation across multiple clients (devices) in the system. Again, it applies to both the model parameters (variables), which are being averaged across clients, as well as the metrics your model exported as a result of local aggregation.

    Performing aggregation at this level is the responsibility of TFF. As a model creator, however, you can control this process (more on this below).

    The general structure of processing is as follows:

    • The initial model, and any parameters required for training, are distributed by a server to a subset of clients that will participate in a round of training or evaluation.

    • On each client, independently and in parallel, your model code is invoked repeatedly on a stream of local data batches to produce a new set of model parameters (when training), and a new set of local metrics, as described above (this is local aggregation).

    • TFF runs a distributed aggregation protocol to accumulate and aggregate the model parameters and locally exported metrics across the system. This logic is expressed in a declarative manner using TFF's own federated computation language (not in TensorFlow). See the custom algorithms tutorial for more on the aggregation API.

Abstract interfaces

This basic constructor + metadata interface is represented by the interface tff.learning.models.VariableModel , as follows:

  • The constructor, forward_pass , and report_local_unfinalized_metrics methods should construct model variables, forward pass, and statistics you wish to report, correspondingly. The TensorFlow constructed by those methods must be serializable, as discussed above.

  • The input_spec property, as well as the 3 properties that return subsets of your trainable, non-trainable, and local variables represent the metadata. TFF uses this information to determine how to connect parts of your model to the federated optimization algorithms, and to define internal type signatures to assist in verifying the correctness of the constructed system (so that your model cannot be instantiated over data that does not match what the model is designed to consume).

In addition, the abstract interface tff.learning.models.VariableModel exposes a property metric_finalizers that takes in a metric's unfinalized values (returned by report_local_unfinalized_metrics() ) and returns the finalized metric values. The metric_finalizers and report_local_unfinalized_metrics() method will be used together to build a cross-client metrics aggregator when defining the federated training processes or evaluation computations. For example, a simple tff.learning.metrics.sum_then_finalize aggregator will first sum the unfinalized metric values from clients, and then call the finalizer functions at the server.

You can find examples of how to define your own custom tff.learning.models.VariableModel in the second part of our image classification tutorial, as well as in the example models we use for testing in model_examples.py .

Converters for Keras

Nearly all the information that's required by TFF can be derived by calling tf.keras interfaces, so if you have a Keras model, you can rely on tff.learning.models.from_keras_model to construct a tff.learning.models.VariableModel .

Note that TFF still wants you to provide a constructor - a no-argument model function such as the following:

def model_fn():
  keras_model = ...
  return tff.learning.models.from_keras_model(keras_model, sample_batch, loss=...)

In addition to the model itself, you supply a sample batch of data which TFF uses to determine the type and shape of your model's input. This ensures that TFF can properly instantiate the model for the data that will actually be present on client devices (since we assume this data is not generally available at the time you are constructing the TensorFlow to be serialized).

The use of Keras wrappers is illustrated in our image classification and text generation tutorials.

Federated Computation Builders

The tff.learning package provides several builders for tff.Computation s that perform learning-related tasks; we expect the set of such computations to expand in the future.

Architectural assumptions

Execution

There are two distinct phases in running a federated computation.

  • Compile : TFF first compiles federated learning algorithms into an abstract serialized representation of the entire distributed computation. This is when TensorFlow serialization happens, but other transformations can occur to support more efficient execution. We refer to the serialized representation emitted by the compiler as a federated computation .

  • Execute TFF provides ways to execute these computations. For now, execution is only supported via a local simulation (eg, in a notebook using simulated decentralized data).

A federated computation generated by TFF's Federated Learning API, such as a training algorithm that uses federated model averaging , or a federated evaluation, includes a number of elements, most notably:

  • A serialized form of your model code as well as additional TensorFlow code constructed by the Federated Learning framework to drive your model's training/evaluation loop (such as constructing optimizers, applying model updates, iterating over tf.data.Dataset s, and computing metrics, and applying the aggregated update on the server, to name a few).

  • A declarative specification of the communication between the clients and a server (typically various forms of aggregation across the client devices, and broadcasting from the server to all clients), and how this distributed communication is interleaved with the client-local or server-local execution of TensorFlow code.

The federated computations represented in this serialized form are expressed in a platform-independent internal language distinct from Python, but to use the Federated Learning API, you won't need to concern yourself with the details of this representation. The computations are represented in your Python code as objects of type tff.Computation , which for the most part you can treat as opaque Python callable s.

In the tutorials, you will invoke those federated computations as if they were regular Python functions, to be executed locally. However, TFF is designed to express federated computations in a manner agnostic to most aspects of the execution environment, so that they can potentially be deployable to, eg, groups of devices running Android , or to clusters in a datacenter. Again, the main consequence of this are strong assumptions about serialization . In particular, when you invoke one of the build_... methods described below the computation is fully serialized.

Modeling state

TFF is a functional programming environment, yet many processes of interest in federated learning are stateful. For example, a training loop that involves multiple rounds of federated model averaging is an example of what we could classify as a stateful process . In this process, the state that evolves from round to round includes the set of model parameters that are being trained, and possibly additional state associated with the optimizer (eg, a momentum vector).

Since TFF is functional, stateful processes are modeled in TFF as computations that accept the current state as an input and then provide the updated state as an output. In order to fully define a stateful process, one also needs to specify where the initial state comes from (otherwise we cannot bootstrap the process). This is captured in the definition of the helper class tff.templates.IterativeProcess , with the 2 properties initialize and next corresponding to the initialization and iteration, respectively.

Available builders

At the moment, TFF provides various builder functions that generate federated computations for federated training and evaluation. Two notable examples include:

Datasets

Architectural assumptions

Client selection

In the typical federated learning scenario, we have a large population of potentially hundreds of millions of client devices, of which only a small portion may be active and available for training at any given moment (for example, this may be limited to clients that are plugged in to a power source, not on a metered network, and otherwise idle). Generally, the set of clients available to participate in training or evaluation is outside of the developer's control. Furthermore, as it's impractical to coordinate millions of clients, a typical round of training or evaluation will include only a fraction of the available clients, which may be sampled at random .

The key consequence of this is that federated computations, by design, are expressed in a manner that is oblivious to the exact set of participants; all processing is expressed as aggregate operations on an abstract group of anonymous clients , and that group might vary from one round of training to another. The actual binding of the computation to the concrete participants, and thus to the concrete data they feed into the computation, is thus modeled outside of the computation itself.

In order to simulate a realistic deployment of your federated learning code, you will generally write a training loop that looks like this:

trainer = tff.learning.algorithms.build_weighted_fed_avg(...)
state = trainer.initialize()
federated_training_data = ...

def sample(federate_data):
  return ...

while True:
  data_for_this_round = sample(federated_training_data)
  result = trainer.next(state, data_for_this_round)
  state = result.state

In order to facilitate this, when using TFF in simulations, federated data is accepted as Python list s, with one element per participating client device to represent that device's local tf.data.Dataset .

Abstract interfaces

In order to standardize dealing with simulated federated data sets, TFF provides an abstract interface tff.simulation.datasets.ClientData , which allows one to enumerate the set of clients, and to construct a tf.data.Dataset that contains the data of a particular client. Those tf.data.Dataset s can be fed directly as input to the generated federated computations in eager mode.

It should be noted that the ability to access client identities is a feature that's only provided by the datasets for use in simulations, where the ability to train on data from specific subsets of clients may be needed (eg, to simulate the diurnal availability of different types of clients). The compiled computations and the underlying runtime do not involve any notion of client identity. Once data from a specific subset of clients has been selected as an input, eg, in a call to tff.templates.IterativeProcess.next , client identities no longer appear in it.

Available data sets

We have dedicated the namespace tff.simulation.datasets for datasets that implement the tff.simulation.datasets.ClientData interface for use in simulations, and seeded it with datasets to support the image classification and text generation tutorials. We'd like to encourage you to contribute your own datasets to the platform.