مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
مفهوم مجموعه داده کلید شده توسط مشتریان (به عنوان مثال کاربران) برای محاسبات فدرال همانطور که در TFF مدل شده است ضروری است. TFF فراهم می کند رابط tff.simulation.datasets.ClientData
به انتزاعی بیش از این مفهوم، و مجموعه داده که میزبان TFF ( استک اورفلو ، شکسپیر ، emnist ، cifar100 و gldv2 ) تمام پیاده سازی این رابط.
اگر شما در حال کار بر یادگیری فدرال با مجموعه داده های خود را، TFF شدت تشویق می کند به شما یا اجرای ClientData
رابط یا استفاده از یکی از توابع کمکی TFF به تولید یک ClientData
که نشان دهنده داده های خود را بر روی دیسک، به عنوان مثال tff.simulation.datasets.ClientData.from_clients_and_fn
.
همانطور که بسیاری از نمونه های پایان به پایان TFF با شروع ClientData
اشیاء، اجرای ClientData
رابط با مجموعه داده های سفارشی خود را آن را به spelunk آسان تر از طریق کد موجود نوشته شده با TFF خواهد شد. علاوه بر این، tf.data.Datasets
که ClientData
سازه می تواند بیش از تکرار به طور مستقیم به عملکرد ساختارهای numpy
آرایه، بنابراین ClientData
اشیاء را می توان با هر چارچوب ML بر اساس پایتون قبل از حرکت به TFF استفاده می شود.
الگوهای مختلفی وجود دارد که با استفاده از آنها میتوانید زندگی خود را آسانتر کنید، اگر قصد دارید شبیهسازیهای خود را به ماشینهای زیادی افزایش دهید یا آنها را به کار بگیرید. در زیر ما از طریق چند از راه های ما می توانید استفاده کنید راه رفتن ClientData
و TFF به مقیاس کوچک تکرار به مقیاس بزرگ آزمایش به تجربه تولید استقرار ما را به عنوان که ممکن است صاف.
از کدام الگو برای انتقال ClientData به TFF استفاده کنم؟
ما دو کاربرد از TFF مورد بحث قرار خواهد ClientData
در عمق. اگر در هر یک از دو دسته زیر قرار می گیرید، به وضوح یکی را بر دیگری ترجیح می دهید. اگر نه، ممکن است برای انتخاب دقیقتر به درک دقیقتری از مزایا و معایب هر کدام نیاز داشته باشید.
من می خواهم در سریع ترین زمان ممکن روی یک ماشین محلی تکرار کنم. نیازی نیست که بتوانم به راحتی از زمان اجرای توزیع شده TFF استفاده کنم.
- شما می خواهید به تصویب
tf.data.Datasets
به TFF به طور مستقیم. - این اجازه می دهد تا شما را به برنامه آمرانه با
tf.data.Dataset
اشیاء، و پردازش آنها را خودسرانه. - انعطاف پذیری بیشتری نسبت به گزینه زیر فراهم می کند. فشار دادن منطق به مشتریان مستلزم آن است که این منطق قابل سریال سازی باشد.
- شما می خواهید به تصویب
من می خواهم محاسبات فدرال خود را در زمان اجرا از راه دور TFF اجرا کنم، یا قصد دارم به زودی این کار را انجام دهم.
- در این مورد شما می خواهید ساخت و پیش پردازش مجموعه داده را به مشتریان نگاشت کنید.
- این نتایج در شما عبور سادگی یک لیست از
client_ids
به طور مستقیم به محاسبات فدرال خود را. - فشار ساختن مجموعه داده و پیش پردازش برای مشتریان از تنگناها در سریال سازی جلوگیری می کند و عملکرد صدها تا هزاران مشتری را به طور قابل توجهی افزایش می دهد.
محیط متن باز را تنظیم کنید
# tensorflow_federated_nightly also bring in tf_nightly, which
# can causes a duplicate tensorboard install, leading to errors.
!pip uninstall --yes tensorboard tb-nightly
!pip install --quiet --upgrade tensorflow_federated_nightly
!pip install --quiet --upgrade nest_asyncio
import nest_asyncio
nest_asyncio.apply()
بسته های وارداتی
import collections
import time
import tensorflow as tf
import tensorflow_federated as tff
دستکاری یک شی ClientData
بیایید با بارگیری و کاوش EMNIST TFF شروع ClientData
:
client_data, _ = tff.simulation.datasets.emnist.load_data()
Downloading emnist_all.sqlite.lzma: 100%|██████████| 170507172/170507172 [00:19<00:00, 8831921.67it/s] 2021-10-01 11:17:58.718735: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
بازرسی مجموعه داده اول توانید به ما بگویید که چه نوع از نمونه در می ClientData
.
first_client_id = client_data.client_ids[0]
first_client_dataset = client_data.create_tf_dataset_for_client(
first_client_id)
print(first_client_dataset.element_spec)
# This information is also available as a `ClientData` property:
assert client_data.element_type_structure == first_client_dataset.element_spec
OrderedDict([('label', TensorSpec(shape=(), dtype=tf.int32, name=None)), ('pixels', TensorSpec(shape=(28, 28), dtype=tf.float32, name=None))])
توجه داشته باشید که بازده مجموعه داده collections.OrderedDict
اشیاء است که pixels
و label
کلید، که در آن پیکسل یک تانسور با شکل است [28, 28]
. فرض کنید ما به پهن ورودی ما به شکل [784]
. یکی از راه های ممکن ما می توانیم این کار را انجام، می تواند اعمال یک تابع قبل از پردازش به ما ClientData
شی.
def preprocess_dataset(dataset):
"""Create batches of 5 examples, and limit to 3 batches."""
def map_fn(input):
return collections.OrderedDict(
x=tf.reshape(input['pixels'], shape=(-1, 784)),
y=tf.cast(tf.reshape(input['label'], shape=(-1, 1)), tf.int64),
)
return dataset.batch(5).map(
map_fn, num_parallel_calls=tf.data.experimental.AUTOTUNE).take(5)
preprocessed_client_data = client_data.preprocess(preprocess_dataset)
# Notice that we have both reshaped and renamed the elements of the ordered dict.
first_client_dataset = preprocessed_client_data.create_tf_dataset_for_client(
first_client_id)
print(first_client_dataset.element_spec)
OrderedDict([('x', TensorSpec(shape=(None, 784), dtype=tf.float32, name=None)), ('y', TensorSpec(shape=(None, 1), dtype=tf.int64, name=None))])
ممکن است بخواهیم علاوه بر این، پیش پردازش پیچیده تری (و احتمالاً حالتی) را انجام دهیم، برای مثال درهم ریختن.
def preprocess_and_shuffle(dataset):
"""Applies `preprocess_dataset` above and shuffles the result."""
preprocessed = preprocess_dataset(dataset)
return preprocessed.shuffle(buffer_size=5)
preprocessed_and_shuffled = client_data.preprocess(preprocess_and_shuffle)
# The type signature will remain the same, but the batches will be shuffled.
first_client_dataset = preprocessed_and_shuffled.create_tf_dataset_for_client(
first_client_id)
print(first_client_dataset.element_spec)
OrderedDict([('x', TensorSpec(shape=(None, 784), dtype=tf.float32, name=None)), ('y', TensorSpec(shape=(None, 1), dtype=tf.int64, name=None))])
واسط با tff.Computation
حالا که ما می توانیم برخی دستکاری اساسی با انجام ClientData
اشیاء، ما آماده به داده های خوراک به یک هستند tff.Computation
. تعریف می کنیم tff.templates.IterativeProcess
که پیاده سازی فدرال به طور متوسط ، اکتشاف و روش های مختلف انتقال آن داده است.
def model_fn():
model = tf.keras.models.Sequential([
tf.keras.layers.InputLayer(input_shape=(784,)),
tf.keras.layers.Dense(10, kernel_initializer='zeros'),
])
return tff.learning.from_keras_model(
model,
# Note: input spec is the _batched_ shape, and includes the
# label tensor which will be passed to the loss function. This model is
# therefore configured to accept data _after_ it has been preprocessed.
input_spec=collections.OrderedDict(
x=tf.TensorSpec(shape=[None, 784], dtype=tf.float32),
y=tf.TensorSpec(shape=[None, 1], dtype=tf.int64)),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
trainer = tff.learning.build_federated_averaging_process(
model_fn,
client_optimizer_fn=lambda: tf.keras.optimizers.SGD(learning_rate=0.01))
قبل از شروع به کار با این IterativeProcess
، یک نظر در معناشناسی ClientData
در نظم است. ClientData
شیء نشان دهنده کل جمعیت در دسترس برای آموزش فدرال، که به طور کلی در دسترس نیست به محیط زیست اجرای یک سیستم FL تولید و خاص به شبیه سازی است. ClientData
واقع به کاربر اجازه میدهد ظرفیت برای دور زدن محاسبات فدرال به طور کامل و به سادگی آموزش یک مدل در سمت سرور به طور معمول از طریق ClientData.create_tf_dataset_from_all_clients
.
محیط شبیه سازی TFF محقق را در کنترل کامل حلقه بیرونی قرار می دهد. به طور خاص این به معنی ملاحظات در دسترس بودن کلاینت، خروج مشتری و غیره است که باید توسط کاربر یا اسکریپت درایور پایتون مورد توجه قرار گیرد. یک نفر می تواند برای مثال مدل ترک تحصیل مشتری با تنظیم توزیع نمونه خود را بیش از ClientData's
client_ids
به طوری که کاربران با داده ها (و نسبت به دیگر در حال اجرا محاسبات محلی) خواهد بود که با احتمال کمتر انتخاب شده است.
با این حال، در یک سیستم فدرال واقعی، مشتریان نمی توانند به صراحت توسط مربی مدل انتخاب شوند. انتخاب مشتریان به سیستمی که محاسبات فدرال را اجرا می کند، واگذار می شود.
عبور tf.data.Datasets
به طور مستقیم به TFF
یکی از گزینه های ما برای واسط بین دارند ClientData
و IterativeProcess
که ساخت است tf.data.Datasets
در پایتون، و عبور این مجموعه داده ها به TFF.
توجه داشته باشید که اگر ما با استفاده پیش پردازش ما ClientData
مجموعه داده های عملکرد ما از نوع مناسب انتظار می رود توسط مدل ما در بالا تعریف شده است.
selected_client_ids = preprocessed_and_shuffled.client_ids[:10]
preprocessed_data_for_clients = [
preprocessed_and_shuffled.create_tf_dataset_for_client(
selected_client_ids[i]) for i in range(10)
]
state = trainer.initialize()
for _ in range(5):
t1 = time.time()
state, metrics = trainer.next(state, preprocessed_data_for_clients)
t2 = time.time()
print('loss {}, round time {}'.format(metrics['train']['loss'], t2 - t1))
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_federated/python/core/impl/compiler/tensorflow_computation_transformations.py:62: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.compat.v1.graph_util.extract_sub_graph` WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_federated/python/core/impl/compiler/tensorflow_computation_transformations.py:62: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.compat.v1.graph_util.extract_sub_graph` loss 2.9005744457244873, round time 4.576513767242432 loss 3.113278388977051, round time 0.49641919136047363 loss 2.7581865787506104, round time 0.4904160499572754 loss 2.87259578704834, round time 0.48976993560791016 loss 3.1202380657196045, round time 0.6724586486816406
اگر ما به این مسیر، با این حال، ما قادر به بدیهی به شبیه سازی multimachine حرکت می کند. مجموعه داده های ما در زمان اجرا TensorFlow محلی ساخت می تواند دولت را از محیط اطراف پایتون ضبط، و شکست در ترتیب و یا deserialization زمانی که آنها به دولت مرجع است که دیگر به آنها در دسترس نیست تلاش. این می تواند به عنوان مثال در خطا مرموز از TensorFlow را آشکار tensor_util.cc
:
Check failed: DT_VARIANT == input.dtype() (21 vs. 20)
نقشه برداری ساخت و ساز و پیش پردازش بر روی مشتریان
برای جلوگیری از این مسئله، TFF توصیه کاربران آن به در نظر گرفتن مجموعه داده نمونه و پیش پردازش به عنوان چیزی که به صورت محلی بر هر مشتری اتفاق می افتد، و برای استفاده از یاران TFF یا federated_map
به صراحت این کد از پیش پردازش در هر اجرا می شود.
از نظر مفهومی، دلیل ترجیح این امر واضح است: در زمان اجرا محلی TFF، مشتریان تنها "به طور تصادفی" به محیط جهانی پایتون دسترسی دارند، زیرا کل ارکستراسیون فدرال روی یک ماشین واحد انجام می شود. در این مرحله شایان ذکر است که تفکر مشابه باعث ایجاد فلسفه عملکردی بین پلتفرمی و همیشه سریالپذیر TFF میشود.
TFF باعث می شود چنین ساده تغییر از طریق ClientData's
ویژگی dataset_computation
، یک tff.Computation
که طول می کشد client_id
و ارتباط گرداند tf.data.Dataset
.
توجه داشته باشید که preprocess
به سادگی با این نسخهها کار dataset_computation
؛ dataset_computation
ویژگی از پیش پردازش ClientData
شامل کل خط لوله پردازش ما فقط تعریف می شود:
print('dataset computation without preprocessing:')
print(client_data.dataset_computation.type_signature)
print('\n')
print('dataset computation with preprocessing:')
print(preprocessed_and_shuffled.dataset_computation.type_signature)
dataset computation without preprocessing: (string -> <label=int32,pixels=float32[28,28]>*) dataset computation with preprocessing: (string -> <x=float32[?,784],y=int64[?,1]>*)
ما می توانیم استناد dataset_computation
و دریافت مجموعه داده مشتاق در زمان اجرا پایتون، اما قدرت واقعی این رویکرد اعمال می شود زمانی که ما با یک روند تکراری و یا محاسبات دیگر برای جلوگیری از تحقق این مجموعه داده ها در زمان اجرا مشتاق جهانی در همه آهنگسازی. TFF یک تابع کمکی فراهم می کند tff.simulation.compose_dataset_computation_with_iterative_process
است که می تواند مورد استفاده قرار گیرد به دقیقا این است.
trainer_accepting_ids = tff.simulation.compose_dataset_computation_with_iterative_process(
preprocessed_and_shuffled.dataset_computation, trainer)
هر دو این tff.templates.IterativeProcesses
و یکی در بالا اجرا به همان شیوه. اما سابق می پذیرد مجموعه داده مشتری پیش پردازش، و دومی رشته به نمایندگی شناسه مشتری، دست زدن به هر دو ساخت و ساز مجموعه داده ها و پیش پردازش در بدن خود می پذیرد - در واقع state
را می توان بین این دو به تصویب رسید.
for _ in range(5):
t1 = time.time()
state, metrics = trainer_accepting_ids.next(state, selected_client_ids)
t2 = time.time()
print('loss {}, round time {}'.format(metrics['train']['loss'], t2 - t1))
loss 2.8417396545410156, round time 1.6707067489624023 loss 2.7670371532440186, round time 0.5207102298736572 loss 2.665048122406006, round time 0.5302855968475342 loss 2.7213189601898193, round time 0.5313887596130371 loss 2.580148935317993, round time 0.5283482074737549
مقیاس بندی به تعداد زیادی مشتری
trainer_accepting_ids
می توانید بلافاصله در زمان اجرا multimachine TFF استفاده می شود، و اجتناب تحقق tf.data.Datasets
و کنترل (و در نتیجه serialize کردن آنها و ارسال آنها را به کارگران).
این امر به طور قابل توجهی شبیهسازیهای توزیعشده را، بهویژه با تعداد زیادی از مشتریان، سرعت میبخشد و تجمیع میانی را قادر میسازد تا از هزینههای سربار سریالسازی/آسیالیزدایی مشابه جلوگیری کند.
Deepdive اختیاری: نوشتن دستی منطق پیش پردازش در TFF
TFF برای ترکیب بندی از ابتدا طراحی شده است. نوع ترکیبی که فقط توسط کمک کننده TFF انجام می شود کاملاً تحت کنترل ما به عنوان کاربران است. ما می توانیم به صورت دستی دارند نوشتن محاسبات پیش پردازش ما فقط با تعریف مربی خود next
کاملا به سادگی:
selected_clients_type = tff.FederatedType(preprocessed_and_shuffled.dataset_computation.type_signature.parameter, tff.CLIENTS)
@tff.federated_computation(trainer.next.type_signature.parameter[0], selected_clients_type)
def new_next(server_state, selected_clients):
preprocessed_data = tff.federated_map(preprocessed_and_shuffled.dataset_computation, selected_clients)
return trainer.next(server_state, preprocessed_data)
manual_trainer_with_preprocessing = tff.templates.IterativeProcess(initialize_fn=trainer.initialize, next_fn=new_next)
در واقع، این عملاً همان کاری است که کمکی که ما استفاده کردیم در زیر کاپوت انجام می دهد (به علاوه انجام بررسی و دستکاری نوع مناسب). ما حتی می تواند از همین منطق را ابراز کرده اند کمی متفاوت، توسط serialize کردن preprocess_and_shuffle
به یک tff.Computation
، و تجزیه federated_map
به یک مرحله که ساخت مجموعه داده سازمان ملل متحد پیش پردازش و دیگری اجرا می شود که preprocess_and_shuffle
در هر مشتری.
ما میتوانیم تأیید کنیم که این مسیر دستیتر منجر به محاسباتی با همان نوع امضای کمکی TFF میشود (نام پارامترهای مدول):
print(trainer_accepting_ids.next.type_signature)
print(manual_trainer_with_preprocessing.next.type_signature)
(<server_state=<model=<trainable=<float32[784,10],float32[10]>,non_trainable=<>>,optimizer_state=<int64>,delta_aggregate_state=<value_sum_process=<>,weight_sum_process=<>>,model_broadcast_state=<>>@SERVER,federated_dataset={string}@CLIENTS> -> <<model=<trainable=<float32[784,10],float32[10]>,non_trainable=<>>,optimizer_state=<int64>,delta_aggregate_state=<value_sum_process=<>,weight_sum_process=<>>,model_broadcast_state=<>>@SERVER,<broadcast=<>,aggregation=<mean_value=<>,mean_weight=<>>,train=<sparse_categorical_accuracy=float32,loss=float32>,stat=<num_examples=int64>>@SERVER>) (<server_state=<model=<trainable=<float32[784,10],float32[10]>,non_trainable=<>>,optimizer_state=<int64>,delta_aggregate_state=<value_sum_process=<>,weight_sum_process=<>>,model_broadcast_state=<>>@SERVER,selected_clients={string}@CLIENTS> -> <<model=<trainable=<float32[784,10],float32[10]>,non_trainable=<>>,optimizer_state=<int64>,delta_aggregate_state=<value_sum_process=<>,weight_sum_process=<>>,model_broadcast_state=<>>@SERVER,<broadcast=<>,aggregation=<mean_value=<>,mean_weight=<>>,train=<sparse_categorical_accuracy=float32,loss=float32>,stat=<num_examples=int64>>@SERVER>)