Zapisz datę! Google I / O powraca w dniach 18-20 maja Zarejestruj się teraz
Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Federated Core

Ten dokument przedstawia podstawową warstwę TFF, która służy jako podstawa dla Federated Learning i możliwych przyszłych nieuczących się federacyjnych algorytmów.

Aby uzyskać delikatne wprowadzenie do Federated Core, przeczytaj poniższe samouczki, które przedstawiają niektóre z podstawowych pojęć na przykładzie i demonstrują krok po kroku budowę prostego federacyjnego algorytmu uśredniania.

Zachęcamy również do zapoznania się z uczeniem federacyjnym i powiązanymi samouczkami dotyczącymi klasyfikacji obrazów i generowania tekstu , ponieważ użycie Federated Core API (FC API) do uczenia federacyjnego zapewnia ważny kontekst dla niektórych wyborów, których dokonaliśmy w projektowanie tej warstwy.

Przegląd

Cele, zamierzone zastosowania i zakres

Federated Core (FC) najlepiej rozumieć jako środowisko programistyczne do wdrażania obliczeń rozproszonych, tj. Obliczeń obejmujących wiele komputerów (telefony komórkowe, tablety, urządzenia wbudowane, komputery stacjonarne, czujniki, serwery baz danych itp.), Z których każdy może wykonywać inne czynności niż trywialne przetwarzanie lokalnie i komunikowanie się przez sieć w celu koordynowania ich pracy.

Termin rozproszony jest bardzo ogólny, a TFF nie jest ukierunkowany na wszystkie możliwe typy rozproszonych algorytmów, dlatego wolimy używać mniej ogólnego terminu obliczenie federacyjne do opisania typów algorytmów, które można wyrazić w tej strukturze.

Definiowanie terminu obliczenie federacyjne w sposób w pełni formalny wykracza poza zakres tego dokumentu, należy jednak pomyśleć o typach algorytmów, które można zobaczyć w pseudokodzie w publikacji badawczej opisującej nowy algorytm uczenia rozproszonego.

Celem FC, w skrócie, jest umożliwienie podobnie zwartej reprezentacji, na podobnym poziomie abstrakcji podobnym do pseudokodu, logiki programu, która nie jest pseudokodem, ale raczej jest wykonywalna w różnych środowiskach docelowych.

Kluczową cechą definiującą rodzaje algorytmów, do wyrażania których ma służyć FC, jest zbiorcze opisywanie działań uczestników systemu. Dlatego mamy tendencję do mówienia o każdym urządzeniu, które lokalnie przekształca dane, oraz o urządzeniach koordynujących pracę scentralizowanego koordynatora, nadając , zbierając lub agregując swoje wyniki.

Chociaż TFF został zaprojektowany, aby móc wyjść poza prostą architekturę klient-serwer , pojęcie zbiorowego przetwarzania ma fundamentalne znaczenie. Wynika to z początków TFF w uczeniu federacyjnym, technologii pierwotnie zaprojektowanej do obsługi obliczeń na potencjalnie wrażliwych danych, które pozostają pod kontrolą urządzeń klienckich i których nie można po prostu pobrać do scentralizowanej lokalizacji ze względu na ochronę prywatności. Podczas gdy każdy klient w takich systemach przekazuje dane i moc obliczeniową w celu obliczenia wyniku przez system (wyniku, którego generalnie oczekiwalibyśmy, że będzie wartościowy dla wszystkich uczestników), staramy się również zachować prywatność i anonimowość każdego klienta.

Tak więc, podczas gdy większość frameworków dla obliczeń rozproszonych jest zaprojektowana tak, aby wyrażać przetwarzanie z perspektywy indywidualnych uczestników - to znaczy na poziomie indywidualnej wymiany komunikatów punkt-punkt, oraz współzależności lokalnych przejść uczestnika z wiadomościami przychodzącymi i wychodzącymi , Federated Core TFF ma na celu opisanie zachowania systemu z globalnej perspektywy systemu (podobnie jak np. MapReduce ).

W związku z tym, chociaż rozproszone struktury do celów ogólnych mogą oferować operacje, takie jak wysyłanie i odbieranie jako bloki konstrukcyjne, FC zapewnia bloki konstrukcyjne, takie jak tff.federated_sum , tff.federated_reduce lub tff.federated_broadcast które hermetyzują proste rozproszone protokoły.

Język

Interfejs Pythona

TFF używa języka wewnętrznego do reprezentowania obliczeń federacyjnych, których składnia jest zdefiniowana przez możliwą do serializacji reprezentację w computation.proto . Użytkownicy FC API na ogół nie muszą jednak bezpośrednio wchodzić w interakcję z tym językiem. Zamiast tego zapewniamy interfejs API Pythona (przestrzeń nazw tff ), który otacza go jako sposób definiowania obliczeń.

W szczególności TFF zapewnia dekoratory funkcji Pythona, takie jak tff.federated_computation które śledzą ciała dekorowanych funkcji i tworzą zserializowane reprezentacje federacyjnej logiki obliczeniowej w języku TFF. Funkcja ozdobiona tff.federated_computation działa jako nośnik takiej serializowanej reprezentacji i może osadzić ją jako element konstrukcyjny w treści innego obliczenia lub wykonać na żądanie po wywołaniu.

Oto tylko jeden przykład; więcej przykładów można znaleźć w samouczkach dotyczących niestandardowych algorytmów .

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

Czytelnicy zaznajomieni z niezbyt chętnym TensorFlow uznają to podejście za analogiczne do pisania kodu Pythona, który wykorzystuje funkcje takie jak tf.add lub tf.reduce_sum w sekcji kodu Pythona, która definiuje wykres TensorFlow. Chociaż kod jest technicznie wyrażony w Pythonie, jego celem jest stworzenie tf.Graph do serializacji reprezentacji tf.Graph pod spodem i to wykres, a nie kod Pythona, jest wewnętrznie wykonywany przez środowisko wykonawcze TensorFlow. Podobnie można myśleć o tff.federated_mean jako o wstawianiu federacyjnej tff.federated_mean do obliczeń stowarzyszonych reprezentowanych przez get_average_temperature .

Po części powodem definiowania języka przez FC jest fakt, że, jak wspomniano powyżej, obliczenia federacyjne określają rozproszone zachowania zbiorowe i jako takie ich logika jest nielokalna. Na przykład TFF zapewnia operatorom, których wejścia i wyjścia mogą istnieć w różnych miejscach w sieci.

Wymaga to języka i systemu typów, które uchwycą pojęcie rozproszenia.

Wpisz System

Federated Core oferuje następujące kategorie typów. Opisując te typy, wskazujemy na konstruktory typów, a także wprowadzamy notację zwartą, ponieważ jest to wygodny sposób lub opisujemy typy obliczeń i operatorów.

Po pierwsze, oto kategorie typów, które są koncepcyjnie podobne do tych występujących w istniejących językach głównego nurtu:

  • Typy tff.TensorType ( tff.TensorType ). Podobnie jak w TensorFlow, mają one dtype i shape . Jedyną różnicą jest to, że obiekty tego typu nie są ograniczone do instancji tf.Tensor w Pythonie, które reprezentują dane wyjściowe operacji TensorFlow na wykresie TensorFlow, ale mogą również zawierać jednostki danych, które można wygenerować, np. Jako wyjście rozproszonego protokół agregacji. Zatem typ tensora TFF jest po prostu abstrakcyjną wersją konkretnej fizycznej reprezentacji tego typu w Pythonie lub TensorFlow.

    Zwarta notacja dla typów tensorów to dtype lub dtype[shape] . Na przykład int32 i int32[10] to odpowiednio typy liczb całkowitych i wektorów int.

  • Typy sekwencji ( tff.SequenceType ). Są to abstrakcyjne odpowiedniki konkretnej koncepcjitf.data.Dataset s.tf.data.Dataset . Elementy sekwencji mogą być konsumowane w sposób sekwencyjny i mogą obejmować typy złożone.

    Zwarta reprezentacja typów sekwencji to T* , gdzie T jest typem elementów. Na przykład int32* reprezentuje sekwencję liczb całkowitych.

  • Nazwane typy krotek ( tff.StructType ). Są to sposoby konstruowania krotek i struktur podobnych do słownika, które mają wstępnie zdefiniowaną liczbę elementów z określonymi typami, nazwanymi lub nienazwanymi. Co ważne, koncepcja nazwanej krotki w TFF obejmuje abstrakcyjny odpowiednik krotek argumentów Pythona, tj. Kolekcje elementów, z których niektóre, ale nie wszystkie, są nazwane, a niektóre są pozycyjne.

    Zwarta notacja dla nazwanych krotek to <n_1=T_1, ..., n_k=T_k> , gdzie n_k to opcjonalne nazwy elementów, a T_k to typy elementów. Na przykład <int32,int32> to zwarta notacja dla pary nienazwanych liczb całkowitych, a <X=float32,Y=float32> to zwarta notacja dla pary liczb <X=float32,Y=float32> o nazwach X i Y która może reprezentować punkt na płaszczyźnie . Krotki mogą być zagnieżdżane, a także mieszane z innymi typami, np. <X=float32,Y=float32>* byłby zwartą notacją dla sekwencji punktów.

  • Typy funkcji ( tff.FunctionType ). TFF to funkcjonalna platforma programistyczna, w której funkcje są traktowane jako wartości pierwszej klasy . Funkcje mają co najwyżej jeden argument i dokładnie jeden wynik.

    Zwarta notacja funkcji to (T -> U) , gdzie T jest typem argumentu, a U jest typem wyniku lub ( -> U) jeśli nie ma argumentu (chociaż funkcje bezargumentowe są zdegenerowane koncepcja, która istnieje głównie na poziomie Pythona). Na przykład (int32* -> int32) jest notacją dla typu funkcji, które redukują sekwencję liczb całkowitych do jednej wartości całkowitej.

Następujące typy dotyczą aspektu systemów rozproszonych w obliczeniach TFF. Ponieważ te koncepcje są nieco unikalne dla TFF, zachęcamy do zapoznania się z samouczkiem dotyczącym niestandardowych algorytmów, aby uzyskać dodatkowe komentarze i przykłady.

  • Rodzaj miejsca docelowego . Ten typ nie jest jeszcze ujawniany w publicznym API inaczej niż w postaci 2 literałów tff.SERVER i tff.CLIENTS , które można traktować jako stałe tego typu. Jest jednak używany wewnętrznie i zostanie wprowadzony do publicznego interfejsu API w przyszłych wersjach. Kompaktową reprezentacją tego typu jest placement .

    Miejsce docelowe reprezentuje kolekcję uczestników systemu, którzy odgrywają określoną rolę. Pierwsza wersja jest ukierunkowana na obliczenia klient-serwer, w których są 2 grupy uczestników: klienci i serwer (możesz myśleć o tym ostatnim jako o grupie pojedynczej). Jednak w bardziej rozbudowanych architekturach mogą istnieć inne role, takie jak pośredni agregatorzy w systemie wielopoziomowym, którzy mogą wykonywać różne typy agregacji lub używać innych typów kompresji / dekompresji danych niż te używane przez serwer lub klienci.

    Podstawowym celem zdefiniowania pojęcia miejsc docelowych jest podstawa definiowania typów federacyjnych .

  • Typy stowarzyszone ( tff.FederatedType ). Wartość typu stowarzyszonego to taka, która jest hostowana przez grupę uczestników systemu zdefiniowaną przez określone miejsce docelowe (na przykład tff.SERVER lub tff.CLIENTS ). Typ stowarzyszony jest definiowany przez wartość umieszczenia (a zatem jest to typ zależny ), typ elementów składowych (jaki rodzaj treści każdy z uczestników all_equal lokalnie) oraz dodatkowy bit all_equal który określa, czy wszyscy uczestnicy są lokalnie hosting tego samego przedmiotu.

    Skrócona notacja dla stowarzyszonych typów wartości, które obejmują elementy (składniki składowe) typu T , z których każda jest hostowana przez grupę (miejsce docelowe) G to odpowiednio T@G lub {T}@G z ustawionym lub all_equal bitem all_equal .

    Na przykład:

    • {int32}@CLIENTS reprezentuje wartość stowarzyszoną, która składa się z zestawu potencjalnie różnych liczb całkowitych, po jednej na urządzenie klienckie. Zwróć uwagę, że mówimy o pojedynczej wartości federacyjnej jako obejmującej wiele elementów danych, które pojawiają się w wielu lokalizacjach w sieci. Można o tym pomyśleć jako o swego rodzaju tensorze o wymiarze „sieciowym”, chociaż ta analogia nie jest doskonała, ponieważ TFF nie pozwala na swobodny dostęp do składowych członków o wartości federacyjnej.

    • {<X=float32,Y=float32>*}@CLIENTS reprezentuje stowarzyszony zestaw danych , wartość składającą się z wielu sekwencji współrzędnych XY , po jednej na urządzenie klienckie.

    • <weights=float32[10,5],bias=float32[5]>@SERVER reprezentuje nazwaną krotkę tensorów wagi i odchylenia na serwerze. Ponieważ usunęliśmy nawiasy klamrowe, oznacza to, że all_equal jest bit all_equal , tj. Istnieje tylko jedna krotka (niezależnie od tego, ile replik serwera może znajdować się w klastrze obsługującym tę wartość).

Cegiełki

Język Federated Core jest formą rachunku lambda z kilkoma dodatkowymi elementami.

Udostępnia następujące abstrakcje programistyczne obecnie dostępne w publicznym interfejsie API:

  • Obliczenia TensorFlow ( tff.tf_computation ). Są to sekcje kodu TensorFlow opakowane jako komponenty wielokrotnego użytku w TFF przy użyciu dekoratora tff.tf_computation . Zawsze mają typy funkcjonalne iw przeciwieństwie do funkcji w TensorFlow mogą przyjmować parametry strukturalne lub zwracać ustrukturyzowane wyniki typu sekwencji.

    Oto jeden przykład, obliczenie TF typu (int32* -> int) które używa operatora tf.data.Dataset.reduce do obliczenia sumy liczb całkowitych:

    @tff.tf_computation(tff.SequenceType(tf.int32))
    def add_up_integers(x):
      return x.reduce(np.int32(0), lambda x, y: x + y)
    
  • Operatory wewnętrzne lub federacyjne ( tff.federated_... ). Jest to biblioteka funkcji, takich jak tff.federated_sum lub tff.federated_broadcast które stanowią większość FC API, z których większość reprezentuje rozproszone operatory komunikacyjne do użytku z TFF.

    Nazywamy je wewnętrznymi, ponieważ, podobnie jak funkcje wewnętrzne , są one otwartym, rozszerzalnym zbiorem operatorów, które są rozumiane przez TFF i skompilowane w kodzie niższego poziomu.

    Większość z tych operatorów ma parametry i wyniki typów stowarzyszonych, a większość z nich to szablony, które można zastosować do różnych rodzajów danych.

    Na przykład tff.federated_broadcast można traktować jako operator szablonu typu funkcjonalnego T@SERVER -> T@CLIENTS .

  • Wyrażenia lambda ( tff.federated_computation ). Wyrażenie lambda w TFF jest odpowiednikiem lambda lub def w Pythonie; składa się z nazwy parametru i treści (wyrażenia), które zawiera odniesienia do tego parametru.

    W kodzie Pythona można je utworzyć, dekorując funkcje Pythona za pomocą tff.federated_computation i definiując argument.

    Oto przykład wyrażenia lambda, o którym już wspominaliśmy:

    @tff.federated_computation(tff.type_at_clients(tf.float32))
    def get_average_temperature(sensor_readings):
      return tff.federated_mean(sensor_readings)
    
  • Literały miejsca docelowego . Na razie tylko tff.SERVER i tff.CLIENTS pozwalają na definiowanie prostych obliczeń klient-serwer.

  • Wywołania funkcji ( __call__ ). Wszystko, co ma typ funkcjonalny, może zostać wywołane przy użyciu standardowej składni Pythona __call__ . Wywołanie jest wyrażeniem, którego typ jest taki sam, jak typ wyniku wywoływanej funkcji.

    Na przykład:

    • add_up_integers(x) reprezentuje wywołanie obliczenia TensorFlow zdefiniowanego wcześniej dla argumentu x . Typ tego wyrażenia to int32 .

    • tff.federated_mean(sensor_readings) reprezentuje wywołanie stowarzyszonego operatora uśredniania w sensor_readings . Typ tego wyrażenia to float32@SERVER (przyjmując kontekst z powyższego przykładu).

  • Tworzenie krotek i wybieranie ich elementów. Wyrażenia Pythona w postaci [x, y] , x[y] lub xy które pojawiają się w tff.federated_computation funkcji ozdobionych tff.federated_computation .