مسارات بيانات سرعة وحدة معالجة الموتّر: tf.data.Dataset وTFRecords

1. نظرة عامة

وحدات معالجة الموتّرات سريعة جدًا. يجب أن يواكب مصدر بيانات التدريب سرعة التدريب. في هذا التمرين العملي، ستتعرّف على كيفية تحميل البيانات من "خدمة التخزين السحابي من Google" باستخدام واجهة برمجة التطبيقات tf.data.Dataset لتوفير البيانات لوحدة معالجة Tensor‏ (TPU).

هذا المختبر هو الجزء 1 من سلسلة "Keras على وحدات TPU". يمكنك تنفيذها بالترتيب التالي أو بشكل مستقل.

ca8cc21f6838eccc.png

أهداف الدورة التعليمية

  • لاستخدام tf.data.Dataset API لتحميل بيانات التدريب
  • لاستخدام تنسيق TFRecord لتحميل بيانات التدريب بكفاءة من "خدمة التخزين السحابي من Google"

الملاحظات

إذا لاحظت أي خطأ في هذا الدرس العملي، يُرجى إخبارنا بذلك. يمكن تقديم الملاحظات من خلال مشاكل GitHub [ رابط الملاحظات].

2. البدء السريع في Google Colaboratory

يستخدم هذا التمرين المعملي Google Collaboratory ولا يتطلّب أي إعداد من جانبك. ‫Colaboratory هي منصة دفاتر ملاحظات على الإنترنت لأغراض تعليمية. وتوفّر تدريبًا مجانيًا على وحدات المعالجة المركزية ووحدات معالجة الرسومات ووحدات معالجة الموتّرات.

688858c21e3beff2.png

يمكنك فتح دفتر الملاحظات النموذجي هذا وتجربة بعض الخلايا للتعرّف على Colaboratory.

c3df49e90e5a654f.png Welcome to Colab.ipynb

اختيار واجهة خلفية لوحدة معالجة الموتّرات

8832c6208c99687d.png

في قائمة Colab، اختَر بيئة التشغيل > تغيير نوع بيئة التشغيل، ثم اختَر TPU. في هذا الدرس العملي، ستستخدم وحدة معالجة الموتّرات (TPU) الفعّالة التي تتيح التدريب المُسارع بواسطة الأجهزة. سيتم الاتصال بوقت التشغيل تلقائيًا عند التنفيذ الأول، أو يمكنك استخدام الزر "ربط" في أعلى يسار الصفحة.

تنفيذ دفتر الملاحظات

76d05caa8b4db6da.png

نفِّذ الخلايا واحدة تلو الأخرى من خلال النقر على إحدى الخلايا واستخدام Shift-ENTER. يمكنك أيضًا تشغيل ورقة الملاحظات بأكملها من خلال بيئة التشغيل > تشغيل الكل

جدول المحتويات

429f106990037ec4.png

تحتوي جميع دفاتر الملاحظات على جدول محتويات. يمكنك فتحها باستخدام السهم الأسود على اليمين.

الخلايا المخفية

edc3dba45d26f12a.png

لن تعرض بعض الخلايا سوى عنوانها. هذه ميزة خاصة بأوراق ملاحظات Colab. يمكنك النقر مرّتين على هذه الملفات للاطّلاع على الرمز البرمجي بداخلها، ولكنّه عادةً لا يكون مثيرًا للاهتمام. عادةً ما تكون وظائف دعم أو تصور. ومع ذلك، يجب تشغيل هذه الخلايا لتعريف الدوال بداخلها.

المصادقة

cdd4b41413100543.png

يمكن أن يصل Colab إلى حِزم Google Cloud Storage الخاصة بك إذا تم إثبات هويتك باستخدام حساب معتمَد. سيؤدي مقتطف الرمز أعلاه إلى بدء عملية مصادقة.

3- [INFO] ما هي وحدات معالجة الموتّرات (TPU)؟

باختصار

f88cf6facfc70166.png

في ما يلي الرمز البرمجي لتدريب نموذج على وحدة معالجة الموتّرات في Keras (والرجوع إلى وحدة معالجة الرسومات أو وحدة المعالجة المركزية في حال عدم توفّر وحدة معالجة الموتّرات):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

سنستخدم وحدات TPU اليوم لإنشاء أداة تصنيف للزهور وتحسينها بسرعات تفاعلية (دقائق لكل عملية تدريب).

688858c21e3beff2.png

لماذا وحدات معالجة الموتّرات؟

يتم تنظيم وحدات معالجة الرسومات الحديثة حول "نوى" قابلة للبرمجة، وهي بنية مرنة للغاية تتيح لها التعامل مع مجموعة متنوعة من المهام، مثل عرض الرسومات الثلاثية الأبعاد والتعليم العميق والمحاكاة الفيزيائية وما إلى ذلك. من ناحية أخرى، تجمع وحدات TPU بين معالج متجهات تقليدي ووحدة ضرب مصفوفات مخصّصة، وتتفوق في أي مهمة تهيمن عليها عمليات ضرب المصفوفات الكبيرة، مثل الشبكات العصبية.

8eb3e718b8e2ed08.png

صورة توضيحية: طبقة شبكة عصبونية كثيفة كعملية ضرب مصفوفات، مع معالجة مجموعة من ثماني صور من خلال الشبكة العصبونية في وقت واحد يُرجى إجراء عملية ضرب صف واحد في عمود واحد للتأكّد من أنّها تجري بالفعل عملية جمع مرجّح لكل قيم وحدات البكسل في الصورة. يمكن تمثيل الطبقات الالتفافية كعمليات ضرب مصفوفات أيضًا، على الرغم من أنّها أكثر تعقيدًا ( يمكنك الاطّلاع على الشرح هنا، في القسم 1).

الأجهزة

وحدات MXU وVPU

يتكوّن قلب TPU v2 من وحدة ضرب المصفوفات (MXU) التي تنفّذ عمليات ضرب المصفوفات، ووحدة معالجة المتجهات (VPU) التي تنفّذ جميع المهام الأخرى، مثل عمليات التنشيط وsoftmax وما إلى ذلك. وتتعامل وحدة معالجة المتجهات مع عمليات الحساب float32 وint32. من ناحية أخرى، تعمل وحدة MXU بتنسيق نقطة عائمة مختلطة الدقة 16-32 بت.

7d68944718f76b18.png

الفاصلة العائمة ذات الدقة المختلطة وbfloat16

تحسب وحدة MXU عمليات ضرب المصفوفات باستخدام مدخلات bfloat16 ومخرجات float32. يتم إجراء عمليات التجميع الوسيطة بدقة float32.

19c5fc432840c714.png

عادةً ما يكون تدريب الشبكة العصبونية مقاومًا للتشويش الناتج عن دقة النقطة العائمة المنخفضة. في بعض الحالات، تساعد الضوضاء المحسِّن في التقارب. لقد تم استخدام دقة النقطة العائمة ذات 16 بت تقليديًا لتسريع العمليات الحسابية، ولكن نطاقات تنسيقات float16 وfloat32 مختلفة تمامًا. يؤدي تقليل الدقة من float32 إلى float16 عادةً إلى حدوث تجاوزات ونقص في التدفق. تتوفّر حلول، ولكن عادةً ما يكون من الضروري إجراء عمل إضافي لجعل float16 تعمل.

لهذا السبب، قدّمت Google تنسيق bfloat16 في وحدات TPU. ‏bfloat16 هو float32 مقطوع مع وحدات البت والمدى نفسها تمامًا كما في float32. بالإضافة إلى أنّ وحدات معالجة الموتّرات تحسب عمليات ضرب المصفوفات بدقة مختلطة مع مدخلات bfloat16 ومخرجات float32، يعني ذلك أنّه عادةً لا يلزم إجراء أي تغييرات على الرموز البرمجية للاستفادة من تحسينات الأداء الناتجة عن الدقة المنخفضة.

مصفوفة نبضية

تنفّذ وحدة MXU عمليات ضرب المصفوفات في الأجهزة باستخدام بنية تُعرف باسم "مصفوفة نبضية" تتدفق فيها عناصر البيانات عبر مصفوفة من وحدات حسابية للأجهزة. (في الطب، يشير مصطلح "انقباضي" إلى تقلّصات القلب وتدفّق الدم، ويشير هنا إلى تدفّق البيانات).

العنصر الأساسي لعملية ضرب المصفوفات هو الضرب النقطي بين صف من إحدى المصفوفتين وعمود من المصفوفة الأخرى (راجِع الرسم التوضيحي في أعلى هذا القسم). بالنسبة إلى عملية ضرب المصفوفات Y=X*W، سيكون أحد عناصر النتيجة كما يلي:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

على وحدة معالجة الرسومات، يمكن برمجة هذا المنتج النقطي في "نواة" وحدة معالجة الرسومات ثم تنفيذه على أكبر عدد ممكن من "النوى" المتاحة بالتوازي لمحاولة احتساب كل قيمة من المصفوفة الناتجة في وقت واحد. إذا كانت المصفوفة الناتجة كبيرة بحجم 128×128، سيتطلّب ذلك توفّر 128×128=16 ألف "نواة"، وهو أمر غير ممكن عادةً. تحتوي أكبر وحدات معالجة الرسومات على حوالي 4,000 نواة. من ناحية أخرى، تستخدم وحدة معالجة الموتّرات الحد الأدنى من الأجهزة لوحدات الحوسبة في MXU: bfloat16 x bfloat16 => float32 وحدات ضرب وتجميع فقط، ولا شيء آخر. وهي صغيرة جدًا لدرجة أنّ وحدة معالجة الموتّرات يمكنها تنفيذ 16 ألفًا منها في وحدة MXU بحجم 128x128 ومعالجة عملية ضرب المصفوفة هذه دفعة واحدة.

f1b283fc45966717.gif

صورة توضيحية: مصفوفة MXU المتزامنة عناصر الحوسبة هي وحدات ضرب وتجميع. يتم تحميل قيم إحدى المصفوفتين في الصفيفة (النقاط الحمراء). تنتقل قيم المصفوفة الأخرى عبر المصفوفة (النقاط الرمادية). تنقل الخطوط العمودية القيم إلى الأعلى. تنقل الخطوط الأفقية المجاميع الجزئية. يُترك للمستخدم مهمة التحقّق من أنّه أثناء انتقال البيانات عبر المصفوفة، ستحصل على نتيجة ضرب المصفوفة من الجانب الأيمن.

بالإضافة إلى ذلك، أثناء احتساب الجداءات النقطية في وحدة MXU، تتدفق المجموعات الوسيطة ببساطة بين وحدات الحوسبة المتجاورة. ولا تحتاج إلى تخزينها واسترجاعها من الذاكرة أو حتى من ملف السجلّ. والنتيجة النهائية هي أنّ بنية مصفوفة النبض في وحدة معالجة الموتّرات تتميّز بكثافة عالية وميزة كبيرة في استهلاك الطاقة، بالإضافة إلى ميزة سرعة لا يُستهان بها مقارنةً بوحدة معالجة الرسومات عند حساب عمليات ضرب المصفوفات.

Cloud TPU

عند طلب " وحدة معالجة الموتّرات من Cloud الإصدار الثاني" على Google Cloud Platform، ستحصل على جهاز افتراضي (VM) يحتوي على لوحة وحدة معالجة الموتّرات متصلة بواجهة PCI. تحتوي لوحة TPU على أربع شرائح TPU ثنائية النواة. تتضمّن كل نواة في وحدة معالجة الموتّرات (TPU) وحدة معالجة متجهات (VPU) ووحدة ضرب المصفوفات (MXU) بحجم 128x128. بعد ذلك، يتم عادةً ربط "Cloud TPU" بالجهاز الافتراضي الذي طلبها من خلال الشبكة. إذًا، تبدو الصورة الكاملة على النحو التالي:

dfce5522ed644ece.png

صورة توضيحية: جهازك الافتراضي مع أداة تسريع "Cloud TPU" متصلة بالشبكة تتكوّن "وحدة معالجة الموتّرات من Cloud" نفسها من جهاز افتراضي مزوّد بلوحة وحدة معالجة الموتّرات متصلة بواجهة PCI، وتحتوي هذه اللوحة على أربع شرائح وحدة معالجة موتّرات ثنائية النواة.

حِزم وحدات معالجة الموتّرات

في مراكز بيانات Google، يتم ربط وحدات معالجة الموتّرات (TPU) بنظام ربط داخلي للحوسبة العالية الأداء (HPC)، ما يجعلها تبدو وكأنّها مسرّع كبير جدًا. تطلق Google عليها اسم "حزم"، ويمكن أن تشمل ما يصل إلى 512 من أنوية TPU الإصدار 2 أو 2048 من أنوية TPU الإصدار 3.

2ec1e0d341e7fc34.jpeg

صورة توضيحية: مجموعة من وحدات TPU v3. لوحات ووحدات TPU متصلة من خلال شبكة ربط بينية للحوسبة عالية الأداء

أثناء التدريب، يتم تبادل التدرجات بين نوى TPU باستخدام خوارزمية all-reduce ( شرح جيد لخوارزمية all-reduce هنا). يمكن للنموذج الذي يتم تدريبه الاستفادة من الأجهزة من خلال التدريب على أحجام دفعات كبيرة.

d97b9cc5d40fdb1d.gif

صورة توضيحية: مزامنة التدرّجات أثناء التدريب باستخدام خوارزمية all-reduce على شبكة الحوسبة العالية الأداء (HPC) ذات الشكل الحلقي الثنائي الأبعاد في وحدات TPU من Google

البرنامج

التدريب باستخدام حجم الدفعة الكبير

حجم الدفعة المثالي لوحدات TPU هو 128 عنصر بيانات لكل نواة TPU، ولكن يمكن أن تُظهر الأجهزة بالفعل استخدامًا جيدًا من 8 عناصر بيانات لكل نواة TPU. تذكَّر أنّ وحدة Cloud TPU واحدة تتضمّن 8 نوى.

في هذا الدرس العملي، سنستخدم Keras API. في Keras، الدفعة التي تحدّدها هي حجم الدفعة العام لوحدة معالجة Tensor Processing Unit بأكملها. سيتم تقسيم الدفعات تلقائيًا إلى 8 أجزاء وتشغيلها على 8 نوى في وحدة معالجة Tensor.

da534407825f01e3.png

للحصول على نصائح إضافية بشأن الأداء، يُرجى الاطّلاع على دليل أداء وحدات معالجة Tensor. بالنسبة إلى أحجام الدُفعات الكبيرة جدًا، قد يلزم اتّخاذ عناية خاصة في بعض النماذج، راجِع LARSOptimizer لمزيد من التفاصيل.

الخيارات المتقدّمة: XLA

تحدّد برامج Tensorflow الرسومات البيانية للحساب. لا تشغّل وحدة معالجة Tensor رموز Python البرمجية مباشرةً، بل تشغّل الرسم البياني للحساب الذي يحدّده برنامج TensorFlow. في الخلفية، يحوّل برنامج التجميع المسمّى XLA (برنامج تجميع الجبر الخطي المسرَّع) الرسم البياني لعُقد العمليات الحسابية في TensorFlow إلى لغة آلة TPU. يُجري هذا المحوّل البرمجي أيضًا العديد من عمليات التحسين المتقدّمة على الرمز وتصميم الذاكرة. تتم عملية التجميع تلقائيًا عند إرسال العمل إلى وحدة معالجة الموتّرات. ليس عليك تضمين XLA في سلسلة الإصدار بشكلٍ صريح.

edce61112cd57972.png

توضيح: لتشغيل الرسم البياني للحساب الذي يحدّده برنامج TensorFlow على وحدة معالجة الموتّرات، يتم أولاً تحويله إلى تمثيل XLA (مترجم الجبر الخطي المسرَّع)، ثم يتم تجميعه بواسطة XLA في لغة آلة وحدة معالجة الموتّرات.

استخدام وحدات معالجة الموتّرات في Keras

يمكن استخدام وحدات TPU من خلال Keras API بدءًا من الإصدار 2.1 من TensorFlow. تعمل ميزة التوافق مع Keras على وحدات معالجة الموتّرات (TPU) ومجموعات وحدات معالجة الموتّرات. في ما يلي مثال يعمل على وحدة معالجة الموتّرات ووحدات معالجة الرسومات ووحدة المعالجة المركزية:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

في مقتطف الرمز هذا:

  • يبحث TPUClusterResolver().connect() عن وحدة معالجة الموتّرات على الشبكة. تعمل هذه الأداة بدون مَعلمات على معظم أنظمة Google Cloud (مهام AI Platform وColaboratory وKubeflow وDeep Learning VMs التي تم إنشاؤها من خلال الأداة المساعدة "ctpu up"). تعرف هذه الأنظمة مكان وحدة معالجة الموتّرات بفضل متغيّر البيئة TPU_NAME. إذا أنشأت وحدة TPU يدويًا، يمكنك إما ضبط متغير البيئة TPU_NAME على الجهاز الافتراضي الذي تستخدمه منه، أو استدعاء TPUClusterResolver باستخدام مَعلمات صريحة: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy هو الجزء الذي ينفّذ التوزيع وخوارزمية مزامنة التدرّج "all-reduce".
  • يتم تطبيق الاستراتيجية من خلال نطاق. يجب تحديد النموذج ضمن نطاق الاستراتيجية()
  • تتوقّع الدالة tpu_model.fit إدخال عنصر tf.data.Dataset للتدريب على وحدات TPU.

مهام تكييف البرامج الشائعة لوحدة معالجة الموتّرات

  • على الرغم من توفّر العديد من الطرق لتحميل البيانات في نموذج Tensorflow، إلا أنّه يجب استخدام واجهة برمجة التطبيقات tf.data.Dataset مع وحدات TPU.
  • تتميّز وحدات TPU بسرعة عالية، وغالبًا ما يصبح استيعاب البيانات هو نقطة الاختناق عند تشغيلها. تتوفّر أدوات يمكنك استخدامها لرصد الاختناقات في البيانات ونصائح أخرى بشأن الأداء في دليل أداء وحدة معالجة Tensor.
  • يتم التعامل مع الأرقام int8 أو int16 على أنّها int32. لا تتضمّن وحدة معالجة الموتّرات وحدة أجهزة للأعداد الصحيحة تعمل على أقل من 32 بت.
  • بعض عمليات Tensorflow غير متاحة. يمكنك الاطّلاع على القائمة هنا. والخبر السار هو أنّ هذا القيد ينطبق فقط على رمز التدريب، أي التمرير للأمام والخلف من خلال النموذج. سيظل بإمكانك استخدام جميع عمليات Tensorflow في مسار إدخال البيانات لأنّها سيتم تنفيذها على وحدة المعالجة المركزية.
  • لا تتوافق tf.py_func مع وحدة معالجة Tensor.

4. جارٍ تحميل البيانات

c0ecb860e4cad0a9.jpeg cc4781a7739c49ae.jpeg 81236b00f8bbf39e.jpeg 961e2228974076bb.jpeg 7517dc163bdffcd5.jpeg 96392df4767f566d.png

سنعمل على مجموعة بيانات لصور الزهور. والهدف هو تعلُّم تصنيفها إلى 5 أنواع من الزهور. يتم تحميل البيانات باستخدام واجهة برمجة التطبيقات tf.data.Dataset. أولاً، دعنا نتعرّف على واجهة برمجة التطبيقات.

التدريب العملي

يُرجى فتح دفتر الملاحظات التالي وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات حيثما ترى التصنيف "مطلوب العمل".

c3df49e90e5a654f.png Fun with tf.data.Dataset (playground).ipynb

معلومات إضافية

لمحة عن مجموعة بيانات "الزهور"

تم تنظيم مجموعة البيانات في 5 مجلدات. يحتوي كل مجلد على نوع واحد من الزهور. أسماء المجلدات هي دوّار الشمس والأقحوان والهندباء البرية والزنبق والورود. تتم استضافة البيانات في حزمة متاحة للجميع على Google Cloud Storage. مقتطف:

gs://flowers-public/sunflowers/5139971615_434ff8ed8b_n.jpg
gs://flowers-public/daisy/8094774544_35465c1c64.jpg
gs://flowers-public/sunflowers/9309473873_9d62b9082e.jpg
gs://flowers-public/dandelion/19551343954_83bb52f310_m.jpg
gs://flowers-public/dandelion/14199664556_188b37e51e.jpg
gs://flowers-public/tulips/4290566894_c7f061583d_m.jpg
gs://flowers-public/roses/3065719996_c16ecd5551.jpg
gs://flowers-public/dandelion/8168031302_6e36f39d87.jpg
gs://flowers-public/sunflowers/9564240106_0577e919da_n.jpg
gs://flowers-public/daisy/14167543177_cd36b54ac6_n.jpg

لماذا tf.data.Dataset؟

تقبل Keras وTensorflow مجموعات البيانات في جميع دوال التدريب والتقييم. بعد تحميل البيانات في مجموعة بيانات، توفّر واجهة برمجة التطبيقات جميع الوظائف الشائعة المفيدة لبيانات تدريب الشبكة العصبية:

dataset = ... # load something (see below)
dataset = dataset.shuffle(1000) # shuffle the dataset with a buffer of 1000
dataset = dataset.cache() # cache the dataset in RAM or on disk
dataset = dataset.repeat() # repeat the dataset indefinitely
dataset = dataset.batch(128) # batch data elements together in batches of 128
AUTOTUNE = tf.data.AUTOTUNE
dataset = dataset.prefetch(AUTOTUNE) # prefetch next batch(es) while training

يمكنك العثور على نصائح حول الأداء وأفضل الممارسات المتعلّقة بمجموعات البيانات في هذه المقالة. يمكنك الاطّلاع على المستندات المرجعية هنا.

أساسيات tf.data.Dataset

تتوفّر البيانات عادةً في ملفات متعددة، مثل الصور هنا. يمكنك إنشاء مجموعة بيانات لأسماء الملفات من خلال استدعاء:

filenames_dataset = tf.data.Dataset.list_files('gs://flowers-public/*/*.jpg')
# The parameter is a "glob" pattern that supports the * and ? wildcards.

بعد ذلك، يمكنك "ربط" دالة بكل اسم ملف، ما يؤدي عادةً إلى تحميل الملف وفك ترميزه إلى بيانات فعلية في الذاكرة:

def decode_jpeg(filename):
  bits = tf.io.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  return image

image_dataset = filenames_dataset.map(decode_jpeg)
# this is now a dataset of decoded images (uint8 RGB format)

لتكرار مجموعة بيانات:

for data in my_dataset:
  print(data)

مجموعات بيانات الصفوف

في التعلُّم الموجَّه، تتكوّن مجموعة بيانات التدريب عادةً من أزواج من بيانات التدريب والإجابات الصحيحة. للسماح بذلك، يمكن أن تعرض دالة فك الترميز صفوفًا. ستحصل بعد ذلك على مجموعة بيانات من الصفوف، وسيتم عرض الصفوف عند تكرارها. القيم المعروضة هي موترات Tensorflow جاهزة للاستهلاك من خلال النموذج. يمكنك استدعاء .numpy() للاطّلاع على القيم الأولية:

def decode_jpeg_and_label(filename):
  bits = tf.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  label = ... # extract flower name from folder name
  return image, label

image_dataset = filenames_dataset.map(decode_jpeg_and_label)
# this is now a dataset of (image, label) pairs 

for image, label in dataset:
  print(image.numpy().shape, label.numpy())

الخلاصة:تحميل الصور واحدة تلو الأخرى عملية بطيئة.

أثناء تكرار مجموعة البيانات هذه، ستلاحظ أنّه يمكنك تحميل صورة أو صورتَين في الثانية. هذا بطيء جدًا! يمكن لمسرّعات الأجهزة التي سنستخدمها في التدريب الحفاظ على هذا المعدّل عدة مرات. انتقِل إلى القسم التالي لمعرفة كيفية تحقيق ذلك.

Solution

إليك دفتر ملاحظات الحلّ. يمكنك استخدامها إذا واجهتك مشكلة.

c3df49e90e5a654f.png Fun with tf.data.Dataset (solution).ipynb

المواضيع التي تناولناها

  • 🤔 tf.data.Dataset.list_files
  • 🤔 tf.data.Dataset.map
  • 🤔 مجموعات بيانات الصفوف
  • 😀 تكرار مجموعات البيانات

يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.

5- تحميل البيانات بسرعة

إنّ مسرّعات الأجهزة "وحدة معالجة الموتّرات" (TPU) التي سنستخدمها في هذا الدرس التطبيقي سريعة جدًا. ويكمن التحدي غالبًا في تزويدها بالبيانات بسرعة كافية لإبقائها مشغولة. يمكن أن يحافظ Google Cloud Storage (GCS) على معدل نقل بيانات مرتفع جدًا، ولكن كما هو الحال مع جميع أنظمة التخزين السحابي، يؤدي بدء الاتصال إلى تكلفة بعض عمليات الإرسال والاستلام على الشبكة. لذلك، لا يُعدّ تخزين بياناتنا كآلاف الملفات الفردية خيارًا مثاليًا. سنجمّعها في عدد أقل من الملفات ونستخدم إمكانات tf.data.Dataset للقراءة من ملفات متعددة بالتوازي.

القراءة الكاملة

يمكنك العثور على الرمز البرمجي الذي يحمّل ملفات الصور ويغيّر حجمها إلى حجم شائع ثم يخزّنها في 16 ملف TFRecord في دفتر الملاحظات التالي. يُرجى قراءته بسرعة. ليس من الضروري تنفيذها لأنّه سيتم توفير بيانات منسَّقة بشكل صحيح بتنسيق TFRecord لبقية الدرس العملي.

c3df49e90e5a654f.png Flower pictures to TFRecords.ipynb

تصميم البيانات المثالي لتحقيق أفضل سرعة معالجة البيانات في GCS

تنسيق ملف TFRecord

تنسيق الملفات المفضّل في TensorFlow لتخزين البيانات هو تنسيق TFRecord المستند إلى protobuf. يمكن استخدام صيغ تسلسلية أخرى أيضًا، ولكن يمكنك تحميل مجموعة بيانات من ملفات TFRecord مباشرةً عن طريق كتابة ما يلي:

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

للحصول على الأداء الأمثل، يُنصح باستخدام الرمز الأكثر تعقيدًا التالي للقراءة من ملفات TFRecord متعددة في وقت واحد. سيقرأ هذا الرمز من N ملف بالتوازي ويتجاهل ترتيب البيانات لصالح سرعة القراءة.

AUTOTUNE = tf.data.AUTOTUNE
ignore_order = tf.data.Options()
ignore_order.experimental_deterministic = False

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
dataset = dataset.with_options(ignore_order)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

ورقة الملاحظات الموجزة عن TFRecord

يمكن تخزين ثلاثة أنواع من البيانات في TFRecords: سلاسل البايت (قائمة البايتات) والأعداد الصحيحة ذات 64 بت والأعداد العشرية ذات 32 بت. يتم تخزينها دائمًا كقوائم، وسيكون عنصر البيانات الفردي عبارة عن قائمة بحجم 1. يمكنك استخدام دوال المساعدة التالية لتخزين البيانات في TFRecords.

كتابة سلاسل البايت

# warning, the input is a list of byte strings, which are themselves lists of bytes
def _bytestring_feature(list_of_bytestrings):
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))

كتابة الأعداد الصحيحة

def _int_feature(list_of_ints): # int64
  return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))

الكتابة على اللوحات العائمة

def _float_feature(list_of_floats): # float32
  return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))

كتابة ملف TFRecord باستخدام أدوات المساعدة أعلاه

# input data in my_img_bytes, my_class, my_height, my_width, my_floats
with tf.python_io.TFRecordWriter(filename) as out_file:
  feature = {
    "image": _bytestring_feature([my_img_bytes]), # one image in the list
    "class": _int_feature([my_class]),            # one class in the list
    "size": _int_feature([my_height, my_width]),  # fixed length (2) list of ints
    "float_data": _float_feature(my_floats)       # variable length  list of floats
  }
  tf_record = tf.train.Example(features=tf.train.Features(feature=feature))
  out_file.write(tf_record.SerializeToString())

لقراءة البيانات من TFRecords، عليك أولاً تحديد تنسيق السجلات التي خزّنتها. في البيان، يمكنك الوصول إلى أي حقل مسمّى كقائمة ثابتة الطول أو قائمة متغيرة الطول:

القراءة من ملفات TFRecord

def read_tfrecord(data):
  features = {
    # tf.string = byte string (not text string)
    "image": tf.io.FixedLenFeature([], tf.string), # shape [] means scalar, here, a single byte string
    "class": tf.io.FixedLenFeature([], tf.int64),  # shape [] means scalar, i.e. a single item
    "size": tf.io.FixedLenFeature([2], tf.int64),  # two integers
    "float_data": tf.io.VarLenFeature(tf.float32)  # a variable number of floats
  }

  # decode the TFRecord
  tf_record = tf.io.parse_single_example(data, features)

  # FixedLenFeature fields are now ready to use
  sz = tf_record['size']

  # Typical code for decoding compressed images
  image = tf.io.decode_jpeg(tf_record['image'], channels=3)

  # VarLenFeature fields require additional sparse.to_dense decoding
  float_data = tf.sparse.to_dense(tf_record['float_data'])

  return image, sz, float_data

# decoding a tf.data.TFRecordDataset
dataset = dataset.map(read_tfrecord)
# now a dataset of triplets (image, sz, float_data)

مقتطفات الرموز البرمجية المفيدة:

قراءة عناصر بيانات فردية

tf.io.FixedLenFeature([], tf.string)   # for one byte string
tf.io.FixedLenFeature([], tf.int64)    # for one int
tf.io.FixedLenFeature([], tf.float32)  # for one float

قراءة قوائم العناصر ذات الحجم الثابت

tf.io.FixedLenFeature([N], tf.string)   # list of N byte strings
tf.io.FixedLenFeature([N], tf.int64)    # list of N ints
tf.io.FixedLenFeature([N], tf.float32)  # list of N floats

قراءة عدد متغيّر من عناصر البيانات

tf.io.VarLenFeature(tf.string)   # list of byte strings
tf.io.VarLenFeature(tf.int64)    # list of ints
tf.io.VarLenFeature(tf.float32)  # list of floats

تعرض VarLenFeature متّجهًا متناثرًا، ويجب اتّخاذ خطوة إضافية بعد فك ترميز TFRecord:

dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])

من الممكن أيضًا أن تتضمّن ملفات TFRecord حقولاً اختيارية. إذا حدّدت قيمة تلقائية عند قراءة حقل، سيتم عرض القيمة التلقائية بدلاً من رسالة خطأ في حال كان الحقل غير متوفّر.

tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional

المواضيع التي تناولناها

  • 🤔 تقسيم ملفات البيانات للوصول إليها بسرعة من GCS
  • 😓 كيفية كتابة TFRecords (هل نسيت البنية؟ لا بأس، يمكنك إضافة إشارة مرجعية إلى هذه الصفحة كمرجع سريع)
  • 🤔 تحميل مجموعة بيانات من TFRecords باستخدام TFRecordDataset

يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.

6. تهانينا!

يمكنك الآن تزويد وحدة معالجة الموتّرات بالبيانات. يُرجى الانتقال إلى الدرس التطبيقي التالي

وحدات معالجة الموتّرات في التطبيقات العملية

تتوفّر وحدات معالجة الموتّرات ووحدات معالجة الرسومات على منصة Cloud AI:

أخيرًا، يسرّنا تلقّي ملاحظاتك. يُرجى إعلامنا إذا لاحظت أي خطأ في هذا المختبر أو إذا كنت تعتقد أنّه يجب تحسينه. يمكن تقديم الملاحظات من خلال مشاكل GitHub [ رابط الملاحظات].

HR.png

Martin Görner ID small.jpg
المؤلف: مارتن غورنر
Twitter: @martin_gorner