Tff এর ClientData এর সাথে কাজ করা।

TensorFlow.org এ দেখুন Google Colab-এ চালান GitHub-এ উৎস দেখুন নোটবুক ডাউনলোড করুন

ক্লায়েন্টদের (যেমন ব্যবহারকারীদের) দ্বারা চাবিকৃত ডেটাসেটের ধারণাটি TFF-তে মডেল হিসাবে ফেডারেটেড গণনার জন্য অপরিহার্য। TFF ইন্টারফেস প্রদান tff.simulation.datasets.ClientData এই ধারণা উপর বিমূর্ত, এবং ডেটাসেট যা TFF হোস্ট ( Stackoverflow , শেক্সপীয়ার , emnist , cifar100 এবং gldv2 ) সমস্ত এই ইন্টারফেস বাস্তবায়ন।

আপনি আপনার নিজের ডেটা সেটটি সঙ্গে ফেডারেট শেখার উপর কাজ করেন, তাহলে TFF দৃঢ়ভাবে আপনাকে পারেন বাস্তবায়ন উৎসাহিত ClientData একটি জেনারেট করতে TFF এর সাহায্যকারী ফাংশন ইন্টারফেস বা ব্যবহারের এক ClientData যা ডিস্ক এ আপনার ডেটা প্রতিনিধিত্ব করে, যেমন tff.simulation.datasets.ClientData.from_clients_and_fn .

TFF শেষে-টু-এন্ড উদাহরণ অধিকাংশ দিয়ে শুরু হিসাবে ClientData বস্তু, বাস্তবায়ন ClientData আপনার কাস্টম ডেটা সেটটি সঙ্গে ইন্টারফেস এটা TFF সঙ্গে লিখিত বিদ্যমান কোড মাধ্যমে spelunk সহজ করতে হবে। উপরন্তু, tf.data.Datasets যা ClientData নির্মানের কাঠামো উত্পাদ সরাসরি উপর iterated যাবে numpy অ্যারে, তাই ClientData বস্তু TFF থেকে সরানোর আগে কোনো পাইথন ভিত্তিক এমএল ফ্রেমওয়ার্ক ব্যবহার করা যেতে পারে।

আপনি যদি অনেক মেশিনে আপনার সিমুলেশন স্কেল করতে চান বা সেগুলি স্থাপন করতে চান তবে এমন বেশ কয়েকটি প্যাটার্ন রয়েছে যার সাহায্যে আপনি আপনার জীবনকে আরও সহজ করে তুলতে পারেন। নীচে আমরা উপায়ে আমরা ব্যবহার করতে পারি কয়েক ভিতর দিয়ে হেটে হবে ClientData এবং TFF আমাদের ক্ষুদ্র পুনরাবৃত্তির-টু বড় মাপের উৎপাদন পরীক্ষা-টু স্থাপনার অভিজ্ঞতা করতে যতটা সম্ভব মসৃণ।

ক্লায়েন্টডেটা টিএফএফ-এ পাস করতে আমার কোন প্যাটার্ন ব্যবহার করা উচিত?

আমরা TFF এর দুই ব্যবহারগুলির আলোচনা করব ClientData গভীরতা; আপনি যদি নীচের দুটি বিভাগের যেকোন একটিতে ফিট হন, আপনি স্পষ্টভাবে একটিকে অন্যটির চেয়ে পছন্দ করবেন। যদি তা না হয়, তাহলে আরও সূক্ষ্ম পছন্দ করার জন্য আপনাকে প্রতিটির সুবিধা এবং অসুবিধা সম্পর্কে আরও বিশদ বোঝার প্রয়োজন হতে পারে।

  • আমি একটি স্থানীয় মেশিনে যত তাড়াতাড়ি সম্ভব পুনরাবৃত্তি করতে চাই; TFF এর বিতরণ করা রানটাইম থেকে সহজে সুবিধা নিতে সক্ষম হওয়ার দরকার নেই।

    • আপনি পাস করতে চান tf.data.Datasets সরাসরি TFF হবে।
    • এই আপনি imperatively প্রোগ্রামের সাথে করতে পারবেন tf.data.Dataset বস্তু, এবং তাদের ইচ্ছামত প্রক্রিয়া হয়।
    • এটি নীচের বিকল্পের চেয়ে আরও নমনীয়তা প্রদান করে; ক্লায়েন্টদের কাছে লজিক পুশ করার জন্য এই লজিকটি সিরিয়ালাইজেবল হওয়া প্রয়োজন।
  • আমি TFF এর দূরবর্তী রানটাইমে আমার ফেডারেটেড গণনা চালাতে চাই, অথবা আমি শীঘ্রই করার পরিকল্পনা করছি।

    • এই ক্ষেত্রে আপনি ক্লায়েন্টদের কাছে ডেটাসেট নির্মাণ এবং প্রিপ্রসেসিং ম্যাপ করতে চান।
    • আপনি এই ফলাফল কেবল একটি তালিকা ক্ষণস্থায়ী client_ids সরাসরি আপনার ফেডারেট গণনার জন্য।
    • ক্লায়েন্টদের কাছে ডেটাসেট নির্মাণ এবং প্রি-প্রসেসিং ধাক্কা দেওয়া সিরিয়ালাইজেশনে বাধা এড়ায় এবং শত শত থেকে হাজার হাজার ক্লায়েন্টের সাথে উল্লেখযোগ্যভাবে কর্মক্ষমতা বাড়ায়।

ওপেন সোর্স পরিবেশ সেট আপ করুন

প্যাকেজ আমদানি করুন

একটি ক্লায়েন্টডেটা অবজেক্ট ম্যানিপুলেট করা

এর লোড হচ্ছে এবং TFF এর EMNIST অন্বেষণ করে শুরু করা যাক 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 বস্তুর জনসংখ্যা ফেডারেট প্রশিক্ষণ, যা সাধারণভাবে জন্য উপলব্ধ সম্পূর্ণতা প্রতিনিধিত্ব করে একটি প্রকাশনা এফএল সিস্টেম সঞ্চালনের পরিবেশ পাওয়া যায় না এবং সিমুলেশন নির্দিষ্ট। ClientData প্রকৃতপক্ষে ব্যবহারকারী বাইপাস ফেডারেট কম্পিউটিং ক্ষমতা সম্পূর্ণরূপে দেয় এবং কেবল মাধ্যমে যথারীতি একটি সার্ভার সাইড মডেল প্রশিক্ষণ ClientData.create_tf_dataset_from_all_clients

TFF এর সিমুলেশন পরিবেশ গবেষককে বাইরের লুপের সম্পূর্ণ নিয়ন্ত্রণে রাখে। বিশেষ করে এটি ক্লায়েন্টের প্রাপ্যতা, ক্লায়েন্ট ড্রপআউট, ইত্যাদির বিবেচনাকে বোঝায়, ব্যবহারকারী বা পাইথন ড্রাইভার স্ক্রিপ্ট দ্বারা অবশ্যই সমাধান করা উচিত। এক পারা আপনার উপর স্যাম্পলিং বন্টন সামঞ্জস্য করে উদাহরণস্বরূপ মডেল ক্লায়েন্ট ড্রপআউট জন্য ClientData's client_ids যেমন যে আরো ডেটা ব্যবহারকারীদের (এবং সঙ্গতিপূর্ণভাবেই স্থানীয় কম্পিউটেশন দীর্ঘ চলমান) কম সম্ভাবনা সঙ্গে বাছাই করা হবে।

একটি বাস্তব ফেডারেটেড সিস্টেমে, তবে, মডেল প্রশিক্ষক দ্বারা ক্লায়েন্টদের স্পষ্টভাবে নির্বাচন করা যায় না; ক্লায়েন্টদের নির্বাচন সেই সিস্টেমে অর্পণ করা হয় যা ফেডারেটেড গণনা চালাচ্ছে।

পাসিং tf.data.Datasets TFF সরাসরি

একটি বিকল্প আমরা মধ্যে পোশাকের জন্য আছে ClientData এবং IterativeProcess যে নির্মানের হয় tf.data.Datasets পাইথন, এবং TFF এইসব ডেটাসেট ক্ষণস্থায়ী।

লক্ষ করুন যে, যদি আমরা আমাদের preprocessed ব্যবহার 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 তার ব্যবহারকারীদের ডেটা সেটটি ইনস্ট্যান্স এবং এমন কিছু বিষয় যা প্রতিটি ক্লায়েন্টের স্থানীয়ভাবে ঘটবে যেমন preprocessing বিবেচনা, এবং TFF পথে সাহায্যকারী ব্যবহার করুন অথবা করার বিশেষ পরামর্শ দেওয়া হচ্ছে federated_map স্পষ্টভাবে প্রতিটি ক্লায়েন্টের এই preprocessing কোড চালানোর জন্য।

ধারণাগতভাবে, এটি পছন্দ করার কারণটি পরিষ্কার: TFF-এর স্থানীয় রানটাইমে, ক্লায়েন্টদের শুধুমাত্র "দুর্ঘটনাক্রমে" বৈশ্বিক পাইথন পরিবেশে অ্যাক্সেস রয়েছে কারণ সমগ্র ফেডারেটেড অর্কেস্ট্রেশন একটি একক মেশিনে ঘটছে। এই মুহুর্তে এটি লক্ষণীয় যে অনুরূপ চিন্তাভাবনা TFF-এর ক্রস-প্ল্যাটফর্ম, সর্বদা-ক্রমিক, কার্যকরী দর্শনের জন্ম দেয়।

TFF মাধ্যমে এই ধরনের একটি পরিবর্তন সহজ করে তোলে ClientData's অ্যাট্রিবিউট dataset_computation , একটি tff.Computation যা লাগে client_id এবং সংশ্লিষ্ট ফেরৎ tf.data.Dataset

মনে রাখবেন যে, preprocess কেবল সাথে কাজ করে dataset_computation ; dataset_computation preprocessed এর অ্যাট্রিবিউট 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 এবং পাইথন রানটাইম একটি উৎসুক ডেটা সেটটি পাবেন, কিন্তু এই পদ্ধতির প্রকৃত শক্তি প্রয়োগ করা হয় যখন আমরা একটি প্রক্রিয়া পুনরাবৃত্ত বা অন্য গণনার এ সব বিশ্বব্যাপী উৎসুক রানটাইম এই ডেটাসেট materializing এড়াতে সঙ্গে রচনা। 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 এবং একই ভাবে চালাতে উপরে এক; কিন্তু সাবেক preprocessed ক্লায়েন্ট ডেটাসেট গ্রহণ, এবং পরবর্তীটি ক্লায়েন্ট আইডি প্রতিনিধিত্বমূলক স্ট্রিং উভয় ডেটা সেটটি নির্মাণ হ্যান্ডলিং এবং তার শরীরে preprocessing গ্রহণ - আসলে 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 অবিলম্বে TFF এর multimachine রানটাইম ব্যবহার করা যেতে পারে, এবং এড়াতে materializing tf.data.Datasets এবং নিয়ামক (এবং তাদের serializing ও কর্মীদের তাদের পাঠানোর)।

এটি উল্লেখযোগ্যভাবে বিতরণকৃত সিমুলেশনের গতি বাড়ায়, বিশেষ করে প্রচুর সংখ্যক ক্লায়েন্টের সাথে, এবং একই ধরনের সিরিয়ালাইজেশন/ডিসারিয়ালাইজেশন ওভারহেড এড়াতে মধ্যবর্তী সমষ্টি সক্ষম করে।

ঐচ্ছিক ডিপডাইভ: TFF-এ ম্যানুয়ালি প্রিপ্রসেসিং লজিক রচনা করা

TFF গ্রাউন্ড আপ থেকে compositionality জন্য ডিজাইন করা হয়েছে; 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)

প্রকৃতপক্ষে, আমরা যে সাহায্যকারীকে ব্যবহার করেছি তা কার্যকরভাবে হুডের নিচে করছে (এছাড়া উপযুক্ত টাইপ চেকিং এবং ম্যানিপুলেশন করা)। আমরা এমনকি serializing দ্বারা সামান্য ভিন্নভাবে একই যুক্তি প্রকাশ করতে পারত preprocess_and_shuffle একটি মধ্যে tff.Computation এবং decomposing federated_map এক ধাপ যা অ-preprocessed ডেটাসেট এবং অন্য যা রান নির্মান মধ্যে 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>)