|TensorFlow.org'da görüntüleyin||Google Colab'da çalıştırın||Kaynağı GitHub'da görüntüleyin||Defteri indirin|
Bu öğretici, TensorFlow Federated (TFF) 'de özel federe algoritma türlerinin Federated Core (FC) kullanılarak nasıl uygulanacağını gösteren iki bölümlü bir dizinin ilk bölümüdür - temel olarak hizmet veren bir dizi alt düzey arabirim Federated Learning (FL) katmanını uyguladık.
Bu ilk bölüm daha kavramsaldır; TFF'de kullanılan bazı temel kavramları ve programlama soyutlamalarını tanıtıyoruz ve bunların kullanımını çok basit bir örnek üzerinde dağıtılmış bir dizi sıcaklık sensörü ile gösteriyoruz. Bu serinin ikinci bölümünde , federe eğitim ve değerlendirme algoritmalarının basit bir sürümünü uygulamak için burada tanıttığımız mekanizmaları kullanıyoruz. Bir takip olarak,
tff.learning federe ortalamanın uygulamasını incelemenizi
tff.learning .
Bu serinin sonunda, Federated Core uygulamalarının mutlaka öğrenmeyle sınırlı olmadığını anlayabilmelisiniz. Sunduğumuz programlama soyutlamaları oldukça geneldir ve örneğin, analitik ve diğer özel hesaplama türlerini dağıtılmış veriler üzerinde uygulamak için kullanılabilir.
Bu eğitim kendi kendine yetecek şekilde tasarlanmış olsa da, TensorFlow Federated çerçevesine ve Federated Learning API'lerine (
tff.learning ) daha yüksek düzeyde ve daha nazik bir giriş için ilk olarak görüntü sınıflandırma ve metin oluşturma üzerine eğitimleri okumanızı öneririz. burada tanımladığımız kavramları bağlama oturtmanıza yardımcı olacaktır.
Amaçlanan Kullanımlar
Özetle, Federated Core (FC), TensorFlow kodunu Birleşik Ortalama'da kullanılanlar gibi dağıtılmış iletişim operatörleriyle birleştiren program mantığını kompakt bir şekilde ifade etmeyi mümkün kılan bir geliştirme ortamıdır - dağıtılmış toplamları, ortalamaları ve diğer türleri hesaplama sistemdeki bir dizi istemci cihaz üzerinden dağıtılmış toplamaların, bu cihazlara yayın modellerinin ve parametrelerinin vb.
tf.contrib.distribute haberdar olabilirsiniz ve bu noktada sormanız gereken doğal bir soru şu olabilir: Bu çerçeve hangi açılardan farklılık gösteriyor? Sonuçta her iki çerçeve de TensorFlow hesaplamalarını dağıtmaya çalışır.
Bunu düşünmenin bir yolu,
tf.contrib.distribute belirtilen amacı, dağıtılmış eğitimi sağlamak için kullanıcıların mevcut modelleri ve eğitim kodunu en az değişiklikle kullanmalarına izin vermek iken, dağıtılmış altyapıdan nasıl yararlanılacağına daha çok odaklanmaktır. Mevcut eğitim kodunu daha verimli hale getirmek için, TFF'nin Federe Çekirdeğinin amacı, araştırmacılara ve uygulayıcılara sistemlerinde kullanacakları belirli dağıtılmış iletişim modelleri üzerinde açık kontrol sağlamaktır. FC'deki odak, somut bir dizi uygulanan dağıtılmış eğitim yeteneklerinden ziyade, dağıtılmış veri akışı algoritmalarını ifade etmek için esnek ve genişletilebilir bir dil sağlamaktır.
TFF'nin FC API'sinin birincil hedef kitlelerinden biri, yeni birleşik öğrenme algoritmalarını denemek ve dağıtılmış sistemdeki veri akışının düzenlenme şeklini etkileyen ince tasarım seçimlerinin sonuçlarını değerlendirmek isteyebilecek araştırmacılar ve uygulayıcılardır. sistem uygulama ayrıntılarına takılıp kalmadan. FC API'nin amaçladığı soyutlama düzeyi, bir araştırma yayınındaki birleşik bir öğrenme algoritmasının mekaniğini tanımlamak için kullanılabilecek sahte koda kabaca karşılık gelir - sistemde hangi verilerin var olduğu ve nasıl dönüştürüldüğü, ancak düzeyine düşmeden bireysel noktadan noktaya ağ mesaj alışverişi.
Bir bütün olarak TFF, verilerin dağıtıldığı senaryoları hedeflemektedir ve örneğin gizlilik nedenleriyle ve tüm verilerin merkezi bir konumda toplanmasının uygun bir seçenek olmayabileceği durumlarda böyle kalması gerekir. Bu, tüm verilerin bir veri merkezinde merkezi bir konumda toplanabildiği senaryolarla karşılaştırıldığında, daha yüksek düzeyde açık kontrol gerektiren makine öğrenimi algoritmalarının uygulanması üzerinde etkiye sahiptir.
Başlamadan önce
Kodu incelemeden önce, ortamınızın doğru bir şekilde kurulduğundan emin olmak için lütfen aşağıdaki "Merhaba Dünya" örneğini çalıştırmayı deneyin. Çalışmazsa, talimatlar için lütfen Kurulum kılavuzuna bakın.
!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!'
Birleşik veriler
TFF'nin ayırt edici özelliklerinden biri, TensorFlow tabanlı hesaplamaları birleşik veriler üzerinde kompakt bir şekilde ifade etmenize olanak sağlamasıdır. Dağıtılmış bir sistemdeki bir grup cihazda barındırılan veri öğelerinin bir koleksiyonuna başvurmak için bu eğiticide federasyon verileri terimini kullanacağız. Örneğin, mobil cihazlarda çalışan uygulamalar, merkezi bir konuma yükleme yapmadan verileri toplayabilir ve yerel olarak depolayabilir. Veya, bir dizi dağıtılmış sensör sıcaklık okumalarını kendi konumlarında toplayabilir ve depolayabilir.
Yukarıdaki örneklerdeki gibi federe veriler, TFF'de birinci sınıf vatandaşlar olarak ele alınır, yani bunlar parametreler ve işlevlerin sonuçları olarak görünebilirler ve türleri vardır. Bu fikri pekiştirmek için, birleşik veri kümelerine birleşik değerler veya birleşik türlerin değerleri olarak atıfta bulunacağız.
Anlaşılması gereken önemli nokta, tüm cihazlardaki veri öğelerinin tüm koleksiyonunu (örneğin, dağıtılmış bir dizideki tüm sensörlerden alınan tüm toplama sıcaklığı okumaları) tek bir birleşik değer olarak modelliyor olmamızdır.
Örneğin, TFF'de bir istemci aygıt grubu tarafından barındırılan bir federasyon kayan nokta türü nasıl tanımlanır. Bir dizi dağıtılmış sensörde gerçekleşen bir sıcaklık okumaları koleksiyonu, bu birleşik tipte bir değer olarak modellenebilir.
federated_float_on_clients = tff.type_at_clients(tf.float32)
Daha genel olarak, TFF'de bir federasyon türü, üye bileşenlerinin
T türü - tek tek aygıtlarda bulunan veri öğeleri ve bu tür birleşik değerlerin barındırıldığı aygıtların
G grubu (artı üçüncüsü, isteğe bağlı bilgiler kısaca bahsedeceğiz). Birleştirilmiş değeri barındıran cihazların
G grubuna değerin yerleşimi olarak atıfta bulunuruz. Bu nedenle,
tff.CLIENTS bir yerleşim örneğidir.
str(federated_float_on_clients.member)
'float32'
str(federated_float_on_clients.placement)
'CLIENTS'
Üye bileşenleri
T ve yerleşim
G olan birleşik bir tür, aşağıda gösterildiği gibi
{T}@G olarak temsil edilebilir.
str(federated_float_on_clients)
'{float32}@CLIENTS'
Bu kısa gösterimdeki küme parantezleri
{} , üye bileşenlerinin (farklı cihazlardaki veri öğeleri), örneğin sıcaklık sensörü okumalarından beklediğiniz gibi farklılık gösterebileceğini, dolayısıyla bir grup olarak istemcilerin birlikte bir çoklu -birleşik birleşik değeri oluşturan
T tipi öğeler kümesi .
Birleştirilmiş bir değerin üye bileşenlerinin genellikle programcıya opak olduğuna dikkat etmek önemlidir, yani birleşik bir değer, sistemdeki bir aygıtın tanımlayıcısı tarafından anahtarlanan basit bir
dict olarak düşünülmemelidir - bu değerlerin amacı yalnızca çeşitli dağıtılmış iletişim protokollerini (toplama gibi) soyut olarak temsil eden federe operatörler tarafından toplu olarak dönüştürülebilir. Bu çok soyut geliyorsa endişelenmeyin - buna kısa süre sonra döneceğiz ve bunu somut örneklerle açıklayacağız.
TFF'deki federe türler iki şekilde gelir: federe bir değerin üye bileşenlerinin farklı olabileceği (yukarıda görüldüğü gibi) ve hepsinin eşit olduğu bilinen türler. Bu üçüncü, isteğe bağlı bir tarafından kontrol edilir
all_equal parametre
tff.FederatedType kurucusuna (varsaymak
False ).
federated_float_on_clients.all_equal
False
Tüm
T tipli üye bileşenlerinin eşit olduğu bilinen bir
G yerleşimine sahip bir federe türü, kompakt bir şekilde
T@G olarak temsil edilebilir (
{T}@G
T@G aksine, yani yansıtmak için kaşlı ayraçlar düşürülmüştür) çoklu üye bileşenlerinin tek bir maddeden oluşması gerçeği).
str(tff.type_at_clients(tf.float32, all_equal=True))
'float32@CLIENTS'
Pratik senaryolarda ortaya çıkabilecek bu tür bir federasyon değerinin bir örneği, bir sunucu tarafından federe eğitime katılan bir grup cihaza yayınlanan bir hiperparametredir (öğrenme hızı, kırpma normu vb.).
Diğer bir örnek, sunucuda önceden eğitilmiş ve daha sonra her kullanıcı için kişiselleştirilebilecekleri bir grup istemci cihazına yayınlanan bir makine öğrenimi modeli için bir dizi parametredir.
Örneğin, basit bir tek boyutlu doğrusal regresyon modeli için bir çift
float32 parametresi
a ve
b sahip olduğumuzu varsayalım. TFF'de kullanılmak üzere bu tür modellerin (federe olmayan) tipini aşağıdaki gibi oluşturabiliriz. Basılı tür dizgisindeki açılı ayraçlar
<> , adlandırılmış veya adlandırılmamış demetler için kompakt bir TFF gösterimidir.
simple_regression_model_type = ( tff.StructType([('a', tf.float32), ('b', tf.float32)])) str(simple_regression_model_type)
'<a=float32,b=float32>'
Yukarıda sadece
dtype ları belirttiğimizi unutmayın. Skaler olmayan türler de desteklenmektedir. Yukarıdaki kodda,
tf.float32 , daha genel
tff.TensorType(dtype=tf.float32, shape=[]) için bir kısayol gösterimidir.
Bu model istemcilere yayınlandığında, ortaya çıkan birleşik değerin türü aşağıda gösterildiği gibi temsil edilebilir.
str(tff.type_at_clients( simple_regression_model_type, all_equal=True))
'<a=float32,b=float32>@CLIENTS'
Yukarıdaki federe float ile simetri başına, böyle bir türe birleşik demet olarak atıfta bulunacağız. Daha genel olarak, üye bileşenlerin XYZ benzeri olduğu federe bir değeri ifade etmek için federasyon XYZ terimini sıklıkla kullanacağız. Bu nedenle, birleşik gruplar , birleşik diziler , birleşik modeller vb. Gibi şeyler hakkında konuşacağız.
Şimdi,
float32@CLIENTS geri
float32@CLIENTS - birden fazla cihazda kopyalanmış gibi görünse de, aslında tek bir
float32 , çünkü tüm üyeler aynıdır. Genel olarak, herhangi bir tamamen eşit birleşik türü, yani
T@G biçiminden birini, federe olmayan bir
T türüne izomorfik olarak düşünebilirsiniz, çünkü her iki durumda da aslında yalnızca tek bir (potansiyel olarak kopyalanmış olsa da) öğe vardır.
T türü.
T ve
T@G arasındaki izomorfizm göz önüne alındığında, eğer varsa, ikinci türlerin hangi amaca hizmet edebileceğini merak edebilirsiniz. Okumaya devam etmek.
Yerleşimler
Tasarıma Genel Bakış
Önceki bölümde, birleşik bir değeri ortaklaşa barındırabilecek sistem katılımcılarından oluşan gruplara yerleştirme kavramını tanıttık ve bir yerleşimin örnek
tff.CLIENTS olarak
tff.CLIENTS kullanımını gösterdik.
Yerleştirme kavramının neden bu kadar temel olduğunu ve onu TFF tipi sisteme dahil etmemiz gerektiğini açıklamak için, bu eğitimin başında TFF'nin amaçlanan kullanımlarından bazıları hakkında bahsettiklerimizi hatırlayın.
Bu öğreticide, TFF kodunun yalnızca simüle edilmiş bir ortamda yerel olarak yürütüldüğünü göreceksiniz, ancak amacımız, TFF'nin dağıtılmış bir sistemdeki fiziksel aygıt gruplarında, potansiyel olarak mobil veya gömülü aygıtlar da dahil olmak üzere dağıtmak için dağıtabileceğiniz kod yazmayı etkinleştirmesidir. Android çalıştırıyor. Bu cihazların her biri, sistemde oynadığı role (bir son kullanıcı cihazı, bir merkezi koordinatör, çok katmanlı bir mimaride bir ara katman, vb.) Bağlı olarak, yerel olarak yürütülmesi için ayrı bir talimat seti alacaktır. Hangi cihaz alt kümelerinin hangi kodu çalıştırdığını ve verilerin farklı bölümlerinin fiziksel olarak nerede gerçekleşebileceğini düşünebilmek önemlidir.
Bu, örneğin mobil cihazlardaki uygulama verileriyle uğraşırken özellikle önemlidir. Veriler özel olduğundan ve hassas olabileceğinden, bu verilerin cihazdan asla ayrılmayacağını statik olarak doğrulama (ve verilerin nasıl işlendiğine dair gerçekleri kanıtlama) yeteneğine ihtiyacımız var. Yerleştirme özellikleri, bunu desteklemek için tasarlanmış mekanizmalardan biridir.
TFF veri merkezli programlama ortamı olarak tasarlanmıştır ve olmuştur gibi, aksine bu işlemler aday olabileceğini nerede operasyonlar odaklama ve TFF verilerine veri gerçekleşmesi ve nasıl dönüştürdü ediliyor odaklanması mevcut çerçevelerin bazıları. Sonuç olarak, yerleştirme, veriler üzerindeki işlemlerin bir özelliği olarak değil, TFF'deki verilerin bir özelliği olarak modellenir. Aslında, bir sonraki bölümde göreceğiniz gibi, bazı TFF işlemleri, tek bir makine veya bir grup makine tarafından yürütülmek yerine, konumlara yayılır ve deyim yerindeyse "ağda" çalışır.
Belirli bir değerin türünü
T@G veya
{T}@G (yalnızca
T aksine) olarak temsil etmek, veri yerleştirme kararlarını açık hale getirir ve TFF'de yazılan programların statik analiziyle birlikte, resmi gizlilik, cihaz üzerindeki hassas veriler için garantiler.
Bununla birlikte, bu noktada dikkat edilmesi gereken önemli bir nokta, TFF kullanıcılarını verileri barındıran (yerleşimler) katılımcı cihaz grupları hakkında açık olmaya teşvik ederken, programcının hiçbir zaman bireysel katılımcıların ham verileri veya kimlikleriyle ilgilenmeyeceğidir. .
(Not: Bu öğreticinin kapsamının çok dışına
tff.federated_collect , yukarıdakinin dikkate değer bir istisnası olduğunu belirtmeliyiz:
tff.federated_collect operatörü, yalnızca özel durumlar için düşük seviyeli bir ilkel olarak tasarlanmıştır. Önlenebileceği durumlarda, gelecekteki olası uygulamaları sınırlayabileceğinden tavsiye edilmez. Örneğin, statik analiz sırasında bir hesaplamanın bu tür düşük seviyeli mekanizmalar kullandığını tespit edersek, bazılarına erişimini engelleyebiliriz. veri türleri.)
TFF kodunun gövdesi içinde, tasarım
tff.CLIENTS ,
tff.CLIENTS tarafından temsil edilen grubu oluşturan aygıtları numaralandırmanın veya gruptaki belirli bir aygıtın varlığını araştırmanın bir yolu yoktur. Federated Core API, temel mimari soyutlamalar kümesi veya simülasyonları desteklemek için sağladığımız çekirdek çalışma zamanı altyapısının hiçbir yerinde bir cihaz veya istemci kimliği kavramı yoktur. Yazdığınız tüm hesaplama mantığı, tüm istemci grubundaki işlemler olarak ifade edilecektir.
Burada daha önce federe türlerin değerlerinin Python'un
dict benzemediğinden bahsettiğimizi hatırlayın, çünkü üye bileşenlerini basitçe sıralayamazsınız. TFF program mantığınızın manipüle ettiği değerleri, bireysel katılımcılardan ziyade yerleşimlerle (gruplar) ilişkili olarak düşünün.
Yerleşimler , TFF'de de birinci sınıf vatandaş olacak şekilde tasarlanmıştır ve bir
placement türünün parametreleri ve sonuçları olarak görünebilir (
tff.PlacementType ile temsil edilecektir). Gelecekte, yerleşimleri dönüştürmek veya birleştirmek için çeşitli operatörler sağlamayı planlıyoruz, ancak bu, bu eğitimin kapsamı dışındadır. Şimdilik, bu düşünmek yeterli
placement olarak opak ilkel yerleşik benzer TFF, tip nasıl
int ve
bool opak yerleşik olan Python türleriyle
tff.CLIENTS değil aksine bu tip sabit değişmezi olmak
1
int türünün sabit değişmez değeri.
Yerleşimleri Belirtme
TFF, birden çok istemci cihazıyla (cep telefonları, gömülü cihazlar, dağıtılmış veritabanları), istemci-sunucu mimarileri olarak doğal olarak modellenen çok çeşitli pratik senaryoları ifade etmeyi kolaylaştırmak için iki temel yerleştirme değişmezi sağlar:
tff.CLIENTS ve
tff.SERVER , sensörler, vb.) tek bir merkezi sunucu koordinatörü tarafından yönetilir. TFF ayrıca özel yerleşimleri, birden çok istemci grubunu, çok katmanlı ve diğer, daha genel dağıtılmış mimarileri desteklemek için tasarlanmıştır, ancak bunları tartışmak bu öğreticinin kapsamı dışındadır.
Özellikle,
tff.SERVER tek bir fiziksel cihaz (bir singleton grubunun üyesi) olabilir, ancak hata toleranslı bir kümede çalışan durum makine replikasyonundaki bir replikalar grubu da olabilir - özel bir mimari yapmayız. varsayımlar. Bunun yerine, önceki bölümde bahsedilen
all_equal bitini, genellikle sunucuda yalnızca tek bir veri öğesiyle uğraştığımız gerçeğini ifade etmek için kullanırız.
Benzer şekilde, bazı uygulamalardaki
tff.CLIENTS , sistemdeki tüm istemcileri temsil edebilir - federe öğrenme bağlamında bazen popülasyon olarak adlandırırız, ancak örneğin, Birleşik Ortalamanın üretim uygulamalarında, bir kohortu temsil edebilir - bir alt kümesi belirli bir eğitim turuna katılım için seçilen müşteriler. Soyut olarak tanımlanan yerleşimlere, içinde göründükleri bir hesaplama yürütme için dağıtıldığında (veya bu eğitimde gösterildiği gibi, simüle edilmiş bir ortamda bir Python işlevi gibi basitçe çağrıldığında) somut bir anlam verilir. Yerel simülasyonlarımızda, istemci grubu girdi olarak sağlanan federe verilerle belirlenir.
Birleşik hesaplamalar
Federe hesaplamaları bildirme
TFF, modüler geliştirmeyi destekleyen, güçlü biçimde yazılmış bir işlevsel programlama ortamı olarak tasarlanmıştır.
TFF'deki temel kompozisyon birimi, federe bir hesaplamadır - federe değerleri girdi olarak kabul edebilen ve federasyon değerlerini çıktı olarak döndürebilen bir mantık bölümü. Önceki örneğimizden sensör dizisi tarafından bildirilen sıcaklıkların ortalamasını hesaplayan bir hesaplamayı nasıl tanımlayabileceğiniz aşağıda açıklanmıştır.
@tff.federated_computation(tff.type_at_clients(tf.float32)) def get_average_temperature(sensor_readings): return tff.federated_mean(sensor_readings)
Yukarıdaki koda baktığımızda, bu noktada soruyor olabilirsiniz -
tf.function gibi birleştirilebilir birimleri tanımlamak için zaten dekoratör yapılar yok mu ve öyleyse, neden başka bir tane daha tanıtın ve nasıl farklıdır?
Kısa cevap,
tff.federated_computation sarmalayıcısı tarafından üretilen kodun ne TensorFlow ne de Python olduğudur - bu, dahili bir platformdan bağımsız yapıştırıcı dilinde dağıtılmış bir sistemin bir belirtimidir. Bu noktada, bu şüphesiz kulağa şifreli gelecektir, ancak lütfen federe bir hesaplamanın bu sezgisel yorumunu, dağıtılmış bir sistemin soyut bir özelliği olarak aklınızda bulundurun. Bir dakika içinde açıklayacağız.
Öncelikle tanımla biraz oynayalım. TFF hesaplamaları genellikle parametreli veya parametresiz, ancak iyi tanımlanmış tip imzalarıyla işlevler olarak modellenir. Aşağıda gösterildiği gibi,
type_signature özelliğini sorgulayarak bir hesaplamanın tür imzasını yazdırabilirsiniz.
str(get_average_temperature.type_signature)
'({float32}@CLIENTS -> float32@SERVER)'
Tip imzası bize hesaplamanın istemci cihazlarda farklı sensör okumaları koleksiyonunu kabul ettiğini ve sunucuda tek bir ortalama döndürdüğünü söyler.
Daha ileri gitmeden önce, en bir dakika bu yansıtmak izin - Bu hesaplamanın giriş ve çıkış (farklı yerlerde olan
CLIENTS de vs
SERVER ). Önceki bölümde, TFF işlemlerinin nasıl konumlara yayılabileceği ve ağda çalışabileceği hakkında yerleştirmelerle ilgili söylediğimizi ve dağıtılmış sistemlerin soyut özelliklerini temsil eden federe hesaplamalar hakkında söylediklerimizi hatırlayın. Sadece böyle bir hesaplama tanımladık - verilerin istemci cihazlarda tüketildiği ve toplu sonuçların sunucuda ortaya çıktığı basit bir dağıtılmış sistem.
Birçok pratik senaryoda, üst düzey görevleri temsil eden hesaplamalar, girdilerini kabul etme ve çıktılarını sunucuda rapor etme eğiliminde olacaktır - bu, hesaplamaların sunucuda başlayan ve sona eren sorgular tarafından tetiklenebileceği fikrini yansıtır.
Ancak, FC API bu varsayımı dayatmaz ve dahili olarak kullandığımız yapı taşlarının birçoğunun (
tff.federated_... bulabileceğiniz çok sayıda
tff.federated_... operatörü dahil) farklı yerleşimlere sahip girişleri ve çıkışları vardır, bu nedenle genel olarak federe bir hesaplamayı sunucuda çalışan veya bir sunucu tarafından yürütülen bir şey olarak düşünmeyin. Sunucu, birleşik hesaplamada yalnızca bir tür katılımcıdır. Bu tür hesaplamaların mekaniği hakkında düşünürken, tek bir merkezi koordinatörün perspektifinden ziyade, her zaman küresel ağ çapında perspektife geçmek en iyisidir.
Genel olarak, fonksiyonel tip imzalar sırasıyla giriş ve çıkışların
T ve
U tipleri için kısaca
(T -> U) olarak temsil edilir. Biçimsel parametrenin türü (bu durumda bu tür
sensor_readings ), dekoratörün argüman olarak belirtilir. Sonucun türünü belirtmenize gerek yoktur - otomatik olarak belirlenir.
TFF, sınırlı polimorfizm biçimleri sunsa da, programcıların, kodunuzun özelliklerini anlamayı, hata ayıklamayı ve resmi olarak doğrulamayı kolaylaştırdığı için birlikte çalıştıkları veri türleri hakkında açık olmaları şiddetle tavsiye edilir. Bazı durumlarda, türlerin açıkça belirtilmesi bir gerekliliktir (örneğin, polimorfik hesaplamalar şu anda doğrudan yürütülebilir değildir).
Birleşik hesaplamaları yürütme
Geliştirme ve hata ayıklamayı desteklemek için TFF, aşağıda gösterildiği gibi Python işlevleri olarak bu şekilde tanımlanan hesaplamaları doğrudan başlatmanıza izin verir. Hesaplama,
all_equal biti
False ayarlanmış bir federasyon türünün değerini beklediğinde, bunu Python'da düz bir
list olarak besleyebilirsiniz ve
all_equal biti
True ayarlanmış birleşik türler için doğrudan (tekli) besleyebilirsiniz. üye kurucu. Bu aynı zamanda sonuçların size nasıl bildirildiğidir.
get_average_temperature([68.5, 70.3, 69.8])
69.53334
Simülasyon modunda bunun gibi hesaplamaları çalıştırırken, sistem genelinde bir görüşe sahip, ağdaki herhangi bir konumda girdi sağlama ve çıktıları tüketme yeteneğine sahip harici bir gözlemci olarak hareket edersiniz, gerçekten de burada olduğu gibi - müşteri değerlerini sağladınız girişte ve sunucu sonucunu tüketti.
Şimdi,
tff.federated_computation dekoratörünün yapıştırıcı dilinde kod yayan hakkında daha önce yaptığımız bir nota
tff.federated_computation . TFF hesaplamalarının mantığı Python'da sıradan işlevler olarak ifade edilebilecekse de (yukarıda
tff.federated_computation gibi bunları
tff.federated_computation ile dekore etmeniz yeterlidir) ve
tff.federated_computation diğer Python işlevleri gibi bunları doğrudan Python argümanları ile çağırabilirsiniz. notebook, perde arkasında, daha önce de belirttiğimiz gibi, TFF hesaplamaları aslında Python değildir .
Bununla kastettiğimiz, Python yorumlayıcısının
tff.federated_computation ile süslenmiş bir işlevle karşılaştığında, bu işlevin gövdesindeki ifadeleri bir kez (tanım zamanında)
tff.federated_computation ve ardından hesaplamanın mantığının gelecekte kullanım için serileştirilmiş bir temsilini oluşturmasıdır. yürütmek için veya başka bir hesaplamaya bir alt bileşen olarak dahil edilmek için.
Aşağıdaki gibi bir print ifadesi ekleyerek bunu doğrulayabilirsiniz:
@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".
Federe bir hesaplamayı, istekli olmayan bir bağlamda bir TensorFlow grafiği oluşturan Python kodunu nasıl düşündüğünüze benzer şekilde tanımlayan Python kodunu düşünebilirsiniz (TensorFlow'un isteksiz kullanımlarına aşina değilseniz, Python kodu, daha sonra yürütülecek, ancak aslında onları anında çalıştırmayan bir işlem grafiğini tanımlar. TensorFlow'daki istekli olmayan grafik oluşturma kodu Python'dur, ancak bu kodla oluşturulan TensorFlow grafiği platformdan bağımsızdır ve serileştirilebilir.
Benzer şekilde, TFF hesaplamaları Python'da tanımlanır, ancak az önce gösterdiğimiz örnekteki
tff.federated_mean gibi gövdelerindeki Python ifadeleri, başlık altında taşınabilir ve platformdan bağımsız bir serileştirilebilir temsil olarak derlenir.
Bir geliştirici olarak, hiçbir zaman doğrudan onunla çalışmanıza gerek kalmayacağından, bu temsilin ayrıntılarıyla ilgilenmenize gerek yoktur, ancak varlığının, TFF hesaplamalarının temelde istekli olmadığı gerçeğinin farkında olmalısınız. ve keyfi Python durumunu yakalayamaz. Bir TFF hesaplamasının gövdesinde bulunan Python kodu,
tff.federated_computation ile süslenmiş Python işlevinin gövdesi serileştirilmeden önce
tff.federated_computation , tanımlama zamanında yürütülür. Çağrı sırasında tekrar izlenmez (işlevin polimorfik olduğu durumlar hariç; ayrıntılar için lütfen belge sayfalarına bakın).
Neden özel bir dahili Python dışı temsil sunmayı seçtiğimizi merak edebilirsiniz. Bunun bir nedeni, sonuçta, TFF hesaplamalarının gerçek fiziksel ortamlara dağıtılabilir olması ve Python'un kullanılamayabileceği mobil veya gömülü cihazlarda barındırılmasıdır.
Diğer bir neden de, bireysel katılımcıların yerel davranışlarını ifade eden Python programlarının aksine, TFF hesaplamalarının dağıtılmış sistemlerin küresel davranışını ifade etmesidir. Yukarıdaki basit örnekte,
tff.federated_mean özel operatörü ile istemci cihazlarında veri kabul eden, ancak sonuçları sunucuda
tff.federated_mean bunu görebilirsiniz.
tff.federated_mean operatörü, yerel olarak çalıştırılmadığı için Python'da sıradan bir operatör olarak kolayca modellenemez - daha önce belirtildiği gibi, birden çok sistem katılımcısının davranışını koordine eden dağıtılmış bir sistemi temsil eder. Bu tür operatörleri Python'daki sıradan (yerel) operatörlerden ayırmak için birleşik operatörler olarak adlandıracağız.
TFF tipi sistem ve TFF'nin dilinde desteklenen temel işlemler kümesi, bu nedenle Python'dakilerden önemli ölçüde sapmakta ve özel bir temsilin kullanılmasını gerektirmektedir.
Birleşik hesaplamaları oluşturma
Yukarıda belirtildiği gibi, birleşik hesaplamalar ve bileşenleri en iyi şekilde dağıtılmış sistem modelleri olarak anlaşılır ve birleşik hesaplamaları oluşturmayı daha basit olanlardan daha karmaşık dağıtılmış sistemleri oluşturmak olarak düşünebilirsiniz.
tff.federated_mean operatörünü bir tür imzalı
({T}@CLIENTS -> T@SERVER) bir tür yerleşik şablon federe hesaplaması olarak
({T}@CLIENTS -> T@SERVER) (aslında, yazdığınız hesaplamalar gibi, bu operatörün de karmaşık yapı - kaputun altında onu daha basit operatörlere ayırıyoruz).
Aynı şey, federe hesaplamaları oluşturmak için de geçerlidir.
get_average_temperature hesaplaması,
get_average_temperature ile dekore edilmiş başka bir Python işlevinin gövdesinde
tff.federated_computation - bunu yapmak,
tff.federated_mean daha önce kendi gövdesine gömüldüğü gibi, üst öğenin gövdesine gömülmesine neden olur.
Dikkat edilmesi gereken önemli bir kısıtlama,
tff.federated_computation ile süslenmiş Python işlevlerinin gövdelerinin yalnızca birleşik işleçlerden oluşması gerektiğidir, yani doğrudan TensorFlow işlemlerini içeremezler. Örneğin, bir çift birleşik değer eklemek için
tf.nest arabirimlerini doğrudan kullanamazsınız. TensorFlow kodu, aşağıdaki bölümde tartışılan
tff.tf_computation ile dekore edilmiş kod bloklarıyla sınırlandırılmalıdır. Yalnızca bu şekilde sarıldığında sarmalanmış TensorFlow kodu bir
tff.federated_computation gövdesinde
tff.federated_computation .
Bu ayrımın nedenleri teknik (
tf.add gibi operatörleri tensör olmayanlarla çalışmak için kandırmak zordur) ve mimaridir. Birleşik hesaplamaların dili (yani,
tff.federated_computation ile dekore edilmiş Python işlevlerinin serileştirilmiş gövdesinden oluşturulan mantık), platformdan bağımsız bir yapıştırıcı dili olarak hizmet etmek üzere tasarlanmıştır. Bu tutkal dili şu anda TensorFlow kodunun (
tff.tf_computation bloklarıyla sınırlı) gömülü bölümlerinden dağıtılmış sistemler oluşturmak için kullanılmaktadır. Zamanın doluluğunda, hepsi aynı tutkal dilini (
tff.federated_computation blokları) kullanarak birbirine bağlanan, girdi ardışık düzenlerini temsil edebilecek ilişkisel veritabanı sorguları gibi diğer TensorFlow mantığının bölümlerini gömme ihtiyacını bekliyoruz.
TensorFlow mantığı
TensorFlow hesaplamalarını bildirme
TFF, TensorFlow ile kullanılmak üzere tasarlanmıştır. Bu nedenle, TFF'de yazacağınız kodun büyük bir kısmı muhtemelen sıradan (yani yerel olarak çalıştırılan) TensorFlow kodu olacaktır. Bu kodu TFF ile kullanmak için, yukarıda belirtildiği gibi, sadece
tff.tf_computation ile dekore edilmesi gerekir.
Örneğin, bir sayıyı alıp ona
0.5 ekleyen bir işlevi nasıl uygulayabileceğimizi burada bulabilirsiniz.
@tff.tf_computation(tf.float32) def add_half(x): return tf.add(x, 0.5)
Biz başka dekoratör tanımlamalıdır neden kez daha, bu bakarak merak ediyor olabilirsiniz
tff.tf_computation basitçe gibi varolan mekanizmasını kullanmak yerine
tf.function . Önceki bölümden farklı olarak, burada sıradan bir TensorFlow kodu bloğuyla uğraşıyoruz.
Bunun birkaç nedeni var, bunların tamamı bu öğreticinin kapsamının ötesine geçiyor, ancak asıl olanı adlandırmaya değer:
- TensorFlow kodu kullanılarak uygulanan yeniden kullanılabilir yapı bloklarını federe hesaplamaların gövdelerine yerleştirmek için, belirli özellikleri karşılamaları gerekir - örneğin tanım zamanında izlenir ve serileştirilir, tip imzalarına sahip olur vb. Bu genellikle bir tür dekoratör gerektirir.
Genel olarak, TFF'nin dekoratörünün istekli işlevlerle tam olarak etkileşime girme biçiminin
tf.function , mümkün olan her yerde
tf.function kompozisyon için doğal mekanizmalarını (tf.function) kullanmanızı öneririz.
Şimdi, yukarıdaki örnek kod parçacığına geri
add_half , az önce tanımladığımız
add_half hesaplaması, diğer TFF hesaplamaları gibi TFF tarafından ele alınabilir. Özellikle, TFF tipi bir imzaya sahiptir.
str(add_half.type_signature)
'(float32 -> float32)'
Bu tür imzanın yerleşim içermediğini unutmayın. TensorFlow hesaplamaları, birleşik türleri tüketemez veya döndüremez.
Artık
add_half diğer hesaplamalarda yapı taşı olarak da kullanabilirsiniz. Örneğin, istemci cihazlarda federasyon kayan noktasının tüm üye bileşenlerine nokta şeklinde
add_half uygulamak için
tff.federated_map operatörünü nasıl kullanabileceğinizi buradan öğrenebilirsiniz.
@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 hesaplamalarını yürütme
tff.tf_computation ile tanımlanan hesaplamaların
tff.tf_computation ,
tff.tf_computation tanımladığımız kuralların aynısını
tff.federated_computation . Python'da aşağıdaki gibi sıradan çağrılabilirler olarak çağrılabilirler.
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>]
Bir kez daha,
add_half_on_clients hesaplamasını bu şekilde
add_half_on_clients dağıtılmış bir süreci simüle ettiğini belirtmek gerekir. Veriler istemcilerde tüketilir ve istemcilere iade edilir. Aslında, bu hesaplama her müşterinin bir yerel eylem gerçekleştirmesini sağlar. Bu sistemde açıkça belirtilen
tff.SERVER yoktur (pratikte böyle bir işlemenin düzenlenmesi bir tane içerebilir). Bu şekilde, kavramsal olarak
MapReduce
Map aşamasına benzer olarak tanımlanan bir hesaplamayı düşünün.
Ayrıca, önceki bölümde TFF hesaplamalarının tanım zamanında serileştirilmesi hakkında
tff.tf_computation kodu için de geçerli olduğunu
tff.tf_computation -
add_half_on_clients Python gövdesi tanım zamanında bir kez izlenir. Sonraki çağrılarda, TFF serileştirilmiş gösterimini kullanır.
Python dekore yöntemleri arasındaki tek fark
tff.federated_computation ve süslenmiş olan
tff.tf_computation (eski doğrudan bu gömülü TensorFlow kodu içeren izin verilmez ise) ikinci TensorFlow grafik olarak tefrika olmasıdır.
tff.tf_computation ,
tff.tf_computation ile süslenmiş her yöntem, hesaplamanın yapısının yakalanmasına izin vermek için istekli yürütmeyi geçici olarak devre dışı bırakır. İstekli yürütme yerel olarak devre dışı bırakılırken, hesaplamanızın mantığını doğru şekilde serileştirilebilecek şekilde yazdığınız sürece, istekli TensorFlow, AutoGraph, TensorFlow 2.0 yapıları vb. Kullanabilirsiniz.
Örneğin, aşağıdaki kod başarısız olacaktır:
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.
Çünkü yukarıda başarısız
constant_10 zaten bu grafik dışında inşa edilmiştir
tff.tf_computation gövdesine dahili olarak inşa
add_ten seri işlemi sırasında.
Öte yandan,
tff.tf_computation içinde çağrıldığında mevcut grafiği değiştiren python işlevlerini çağırmak iyidir:
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'daki serileştirme mekanizmalarının gelişmekte olduğunu ve TFF'nin hesaplamaları nasıl serileştirdiğinin ayrıntılarının da gelişmesini bekliyoruz.
tf.data.Dataset s ile çalışma
Daha önce belirtildiği gibi,
tff.tf_computation s'nin benzersiz bir özelliği,
tff.tf_computation tarafından soyut olarak biçimsel parametreler olarak tanımlanan
tf.data.Dataset ile çalışmanıza izin
tf.data.Dataset . Parameters to be represented in TensorFlow as data sets need to be declared using the
tff.SequenceType constructor.
For example, the type specification
tff.SequenceType(tf.float32) defines an abstract sequence of float elements in TFF. Sequences can contain either tensors, or complex nested structures (we'll see examples of those later). The concise representation of a sequence of
T -typed items is
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 .