خطوط لوله داده با سرعت TPU: tf.data.Dataset و TFRecords

۱. مرور کلی

TPU ها بسیار سریع هستند. جریان داده‌های آموزشی باید با سرعت آموزش آنها همگام باشد. در این آزمایش، نحوه بارگذاری داده‌ها از GCS با API tf.data.Dataset برای تغذیه TPU خود را خواهید آموخت.

این آزمایش بخش اول از مجموعه «کرس روی TPU» است. می‌توانید آنها را به ترتیب زیر یا به صورت مستقل انجام دهید.

ca8cc21f6838eccc.png

آنچه یاد خواهید گرفت

  • برای استفاده از API مربوط به tf.data.Dataset برای بارگذاری داده‌های آموزشی
  • استفاده از فرمت TFRecord برای بارگذاری کارآمد داده‌های آموزشی از GCS

بازخورد

اگر در این آزمایشگاه کد، نکته‌ی نادرستی می‌بینید، لطفاً به ما بگویید. بازخورد را می‌توانید از طریق GitHub issues [ لینک بازخورد ] ارائه دهید.

۲. شروع سریع Google Colaboratory

این آزمایشگاه از Google Collaboratory استفاده می‌کند و نیازی به راه‌اندازی از طرف شما ندارد. Colaboratory یک پلتفرم دفترچه یادداشت آنلاین برای اهداف آموزشی است. این پلتفرم آموزش رایگان CPU، GPU و TPU را ارائه می‌دهد.

688858c21e3beff2.png

می‌توانید این دفترچه نمونه را باز کنید و چند سلول را مرور کنید تا با Colaboratory آشنا شوید.

c3df49e90e5a654f.png Welcome to Colab.ipynb

یک پس زمینه TPU انتخاب کنید

۸۸۳۲c۶۲۰۸c۹۹۶۸۷d.png

در منوی Colab، Runtime > Change runtime type را انتخاب کنید و سپس TPU را انتخاب کنید. در این آزمایشگاه کد، از یک TPU (واحد پردازش تنسور) قدرتمند که برای آموزش شتاب‌دهی سخت‌افزاری پشتیبانی می‌شود، استفاده خواهید کرد. اتصال به محیط اجرا به طور خودکار در اولین اجرا اتفاق می‌افتد، یا می‌توانید از دکمه "اتصال" در گوشه بالا سمت راست استفاده کنید.

اجرای نوت بوک

76d05caa8b4db6da.png

با کلیک روی یک سلول و استفاده از Shift-ENTER، سلول‌ها را یکی‌یکی اجرا کنید. همچنین می‌توانید کل نوت‌بوک را با Runtime > Run all اجرا کنید.

فهرست مطالب

429f106990037ec4.png

همه دفترچه‌ها فهرست مطالب دارند. می‌توانید آن را با استفاده از فلش سیاه سمت چپ باز کنید.

سلول‌های پنهان

edc3dba45d26f12a.png

بعضی از سلول‌ها فقط عنوان خود را نشان می‌دهند. این یک ویژگی مخصوص دفترچه یادداشت Colab است. می‌توانید روی آنها دوبار کلیک کنید تا کد داخلشان را ببینید، اما معمولاً خیلی جالب نیست. معمولاً از توابع پشتیبانی یا تجسم‌سازی می‌کنند. برای تعریف توابع داخلشان، هنوز باید این سلول‌ها را اجرا کنید.

احراز هویت

cdd4b41413100543.png

دسترسی به مخازن ذخیره‌سازی ابری گوگل خصوصی شما برای Colab امکان‌پذیر است، مشروط بر اینکه با یک حساب کاربری مجاز احراز هویت شوید. قطعه کد بالا فرآیند احراز هویت را آغاز می‌کند.

۳. [اطلاعات] واحدهای پردازش تنسور (TPU) چیستند؟

به طور خلاصه

f88cf6facfc70166.png

کد آموزش یک مدل روی TPU در Keras (و در صورت عدم دسترسی به TPU، استفاده از GPU یا CPU):

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 ها؟

پردازنده‌های گرافیکی مدرن حول «هسته‌های» قابل برنامه‌ریزی سازماندهی شده‌اند، معماری بسیار انعطاف‌پذیری که به آنها امکان می‌دهد وظایف متنوعی مانند رندر سه‌بعدی، یادگیری عمیق، شبیه‌سازی‌های فیزیکی و غیره را انجام دهند. از سوی دیگر، TPUها یک پردازنده برداری کلاسیک را با یک واحد ضرب ماتریسی اختصاصی جفت می‌کنند و در هر کاری که در آن ضرب‌های ماتریسی بزرگ غالب هستند، مانند شبکه‌های عصبی، عالی عمل می‌کنند.

8eb3e718b8e2ed08.png

تصویر: یک لایه شبکه عصبی متراکم به عنوان یک ضرب ماتریسی، با دسته‌ای از هشت تصویر که به طور همزمان از طریق شبکه عصبی پردازش می‌شوند. لطفاً ضرب یک خط در ستون را اجرا کنید تا تأیید کنید که واقعاً مجموع وزنی تمام مقادیر پیکسل‌های یک تصویر را انجام می‌دهد. لایه‌های کانولوشن را می‌توان به عنوان ضرب ماتریسی نیز نمایش داد، اگرچه کمی پیچیده‌تر است ( توضیح در اینجا، در بخش 1 ).

سخت‌افزار

MXU و VPU

یک هسته TPU نسخه ۲ از یک واحد ضرب ماتریس (MXU) که ​​ضرب‌های ماتریسی را اجرا می‌کند و یک واحد پردازش برداری (VPU) برای سایر وظایف مانند فعال‌سازی‌ها، softmax و غیره ساخته شده است. VPU محاسبات float32 و int32 را مدیریت می‌کند. از سوی دیگر، MXU با فرمت ممیز شناور با دقت ترکیبی ۱۶ تا ۳۲ بیتی عمل می‌کند.

7d68944718f76b18.png

ممیز شناور با دقت ترکیبی و bfloat16

MXU ضرب ماتریس‌ها را با استفاده از ورودی‌های bfloat16 و خروجی‌های float32 محاسبه می‌کند. جمع‌های میانی با دقت float32 انجام می‌شوند.

19c5fc432840c714.png

آموزش شبکه عصبی معمولاً در برابر نویز ناشی از کاهش دقت ممیز شناور مقاوم است. مواردی وجود دارد که نویز حتی به همگرایی بهینه‌ساز کمک می‌کند. دقت ممیز شناور ۱۶ بیتی به طور سنتی برای تسریع محاسبات استفاده شده است، اما فرمت‌های float16 و float32 محدوده‌های بسیار متفاوتی دارند. کاهش دقت از float32 به float16 معمولاً منجر به سرریز و سرریز می‌شود. راه‌حل‌هایی وجود دارد، اما معمولاً برای کار کردن float16 به کار اضافی نیاز است.

به همین دلیل است که گوگل فرمت bfloat16 را در TPUها معرفی کرد. bfloat16 یک float32 کوتاه شده با دقیقاً همان بیت‌های توان و محدوده float32 است. این، علاوه بر این واقعیت که TPUها ضرب ماتریس‌ها را با دقت مختلط با ورودی‌های 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]

در یک پردازنده گرافیکی (GPU)، می‌توان این ضرب نقطه‌ای را در یک "هسته" پردازنده گرافیکی (GPU) برنامه‌ریزی کرد و سپس آن را روی هر تعداد "هسته" که به صورت موازی در دسترس هستند اجرا کرد تا سعی شود هر مقدار ماتریس حاصل را به طور همزمان محاسبه کرد. اگر ماتریس حاصل 128x128 بزرگ باشد، برای محاسبه همزمان هر مقدار ماتریس حاصل، به 128x128 = 16K "هسته" نیاز است که معمولاً امکان‌پذیر نیست. بزرگترین پردازنده‌های گرافیکی (GPU) حدود 4000 هسته دارند. از سوی دیگر، یک TPU از حداقل سخت‌افزار برای واحدهای محاسباتی در MXU استفاده می‌کند: فقط bfloat16 x bfloat16 => float32 multibulators، نه چیز دیگری. اینها آنقدر کوچک هستند که یک TPU می‌تواند 16K از آنها را در یک MXU 128x128 پیاده‌سازی کند و این ضرب ماتریس را به صورت یکجا پردازش کند.

f1b283fc45966717.gif

تصویر: آرایه سیستولیک MXU. عناصر محاسباتی، ضرب-انباشتگر هستند. مقادیر یک ماتریس در آرایه بارگذاری می‌شوند (نقاط قرمز). مقادیر ماتریس دیگر در آرایه جریان می‌یابند (نقاط خاکستری). خطوط عمودی مقادیر را به سمت بالا منتشر می‌کنند. خطوط افقی جمع‌های جزئی را منتشر می‌کنند. به عنوان یک تمرین، به کاربر واگذار می‌شود تا تأیید کند که با جریان داده‌ها در آرایه، نتیجه ضرب ماتریس از سمت راست خارج می‌شود.

علاوه بر این، در حالی که ضرب‌های نقطه‌ای در یک MXU محاسبه می‌شوند، جمع‌های میانی به سادگی بین واحدهای محاسباتی مجاور جریان می‌یابند. آنها نیازی به ذخیره و بازیابی به/از حافظه یا حتی یک فایل رجیستر ندارند. نتیجه نهایی این است که معماری آرایه سیستولیک TPU هنگام محاسبه ضرب‌های ماتریسی، از نظر چگالی و قدرت و همچنین از نظر سرعت نسبت به GPU برتری قابل توجهی دارد که قابل چشم‌پوشی نیست.

TPU ابری

وقتی شما یک " Cloud TPU نسخه ۲" را در پلتفرم ابری گوگل درخواست می‌کنید، یک ماشین مجازی (VM) دریافت می‌کنید که دارای یک برد TPU متصل به PCI است. برد TPU دارای چهار تراشه TPU دو هسته‌ای است. هر هسته TPU دارای یک VPU (واحد پردازش برداری) و یک MXU (واحد ضرب MatriX) با ابعاد ۱۲۸x۱۲۸ است. این "Cloud TPU" معمولاً از طریق شبکه به ماشین مجازی که آن را درخواست کرده است متصل می‌شود. بنابراین تصویر کامل به این شکل است:

dfce5522ed644ece.png

تصویر: ماشین مجازی شما با یک شتاب‌دهنده "Cloud TPU" متصل به شبکه. خود "Cloud TPU" از یک ماشین مجازی با یک برد TPU متصل به PCI با چهار تراشه TPU دو هسته‌ای روی آن ساخته شده است.

غلاف‌های TPU

در مراکز داده گوگل، TPU ها به یک اتصال داخلی محاسبات با کارایی بالا (HPC) متصل هستند که می‌تواند آنها را به عنوان یک شتاب‌دهنده بسیار بزرگ نشان دهد. گوگل آنها را پاد می‌نامد و می‌توانند تا ۵۱۲ هسته TPU v2 یا ۲۰۴۸ هسته TPU v3 را در خود جای دهند.

2ec1e0d341e7fc34.jpeg

تصویر: یک غلاف TPU نسخه ۳. بردها و رک‌های TPU از طریق اتصال HPC به هم متصل شده‌اند.

در طول آموزش، گرادیان‌ها با استفاده از الگوریتم all-reduce بین هسته‌های TPU رد و بدل می‌شوند ( توضیح خوبی در مورد all-reduce در اینجا آمده است ). مدلی که آموزش داده می‌شود می‌تواند با آموزش در اندازه‌های دسته‌ای بزرگ، از سخت‌افزار بهره ببرد.

d97b9cc5d40fdb1d.gif

تصویر: همگام‌سازی گرادیان‌ها در طول آموزش با استفاده از الگوریتم all-reduce در شبکه HPC مش چنبره دوبعدی Google TPU.

نرم‌افزار

آموزش در اندازه دسته‌های بزرگ

اندازه ایده‌آل دسته برای TPUها، ۱۲۸ آیتم داده در هر هسته TPU است، اما سخت‌افزار می‌تواند از ۸ آیتم داده در هر هسته TPU به خوبی استفاده کند. به یاد داشته باشید که یک Cloud TPU دارای ۸ هسته است.

در این آزمایشگاه کد، ما از API کرس استفاده خواهیم کرد. در کرس، دسته‌ای که شما مشخص می‌کنید، اندازه دسته سراسری برای کل TPU است. دسته‌های شما به طور خودکار به ۸ قسمت تقسیم شده و روی ۸ هسته TPU اجرا می‌شوند.

da534407825f01e3.png

برای نکات بیشتر در مورد عملکرد، به راهنمای عملکرد TPU مراجعه کنید. برای اندازه‌های دسته‌ای بسیار بزرگ، ممکن است در برخی مدل‌ها مراقبت‌های ویژه‌ای لازم باشد، برای جزئیات بیشتر به LARSOptimizer مراجعه کنید.

زیر کاپوت: XLA

برنامه‌های Tensorflow نمودارهای محاسباتی را تعریف می‌کنند. TPU مستقیماً کد پایتون را اجرا نمی‌کند، بلکه نمودار محاسباتی تعریف شده توسط برنامه Tensorflow شما را اجرا می‌کند. در پشت صحنه، کامپایلری به نام XLA (کامپایلر جبر خطی شتاب‌یافته) نمودار گره‌های محاسباتی Tensorflow را به کد ماشین TPU تبدیل می‌کند. این کامپایلر همچنین بهینه‌سازی‌های پیشرفته زیادی را روی کد و طرح‌بندی حافظه شما انجام می‌دهد. کامپایل به طور خودکار با ارسال کار به TPU انجام می‌شود. لازم نیست XLA را به طور صریح در زنجیره ساخت خود بگنجانید.

edce61112cd57972.png

تصویر: برای اجرا روی TPU، نمودار محاسباتی تعریف شده توسط برنامه Tensorflow شما ابتدا به یک نمایش XLA (کامپایلر جبر خطی شتاب یافته) ترجمه می‌شود، سپس توسط XLA به کد ماشین TPU کامپایل می‌شود.

استفاده از TPU در Keras

TPU ها از طریق رابط برنامه‌نویسی کاربردی Keras از Tensorflow 2.1 پشتیبانی می‌شوند. پشتیبانی Keras روی TPU ها و TPU pod ها کار می‌کند. در اینجا مثالی آورده شده است که روی TPU، GPU(ها) و CPU کار می‌کند:

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() واحد پردازش مرکزی (TPU) را در شبکه پیدا می‌کند. این تابع در اکثر سیستم‌های ابری گوگل (مشاغل پلتفرم هوش مصنوعی، Colaboratory، Kubeflow، ماشین‌های مجازی یادگیری عمیق که از طریق ابزار 'ctpu up' ایجاد شده‌اند) بدون پارامتر کار می‌کند. این سیستم‌ها به لطف متغیر محیطی TPU_NAME می‌دانند که TPU آنها کجاست. اگر یک TPU را به صورت دستی ایجاد می‌کنید، یا متغیر محیطی TPU_NAME را روی ماشین مجازی که از آن استفاده می‌کنید تنظیم کنید، یا TPUClusterResolver را با پارامترهای صریح فراخوانی کنید: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy بخشی است که توزیع و الگوریتم همگام‌سازی گرادیان «تماماً کاهشی» را پیاده‌سازی می‌کند.
  • استراتژی از طریق یک محدوده اعمال می‌شود. مدل باید در محدوده ()strike تعریف شود.
  • تابع tpu_model.fit برای آموزش TPU، یک شیء tf.data.Dataset را به عنوان ورودی دریافت می‌کند.

وظایف رایج پورت کردن TPU

  • در حالی که روش‌های زیادی برای بارگذاری داده‌ها در یک مدل Tensorflow وجود دارد، برای TPUها، استفاده از API tf.data.Dataset الزامی است.
  • TPUها بسیار سریع هستند و دریافت داده‌ها اغلب هنگام اجرا روی آنها به یک گلوگاه تبدیل می‌شود. ابزارهایی وجود دارد که می‌توانید برای تشخیص گلوگاه‌های داده و سایر نکات مربوط به عملکرد در راهنمای عملکرد TPU از آنها استفاده کنید.
  • اعداد int8 یا int16 به عنوان int32 در نظر گرفته می‌شوند. TPU سخت‌افزار عدد صحیحی که روی کمتر از ۳۲ بیت کار کند، ندارد.
  • برخی از عملیات Tensorflow پشتیبانی نمی‌شوند. لیست آنها اینجاست . خبر خوب این است که این محدودیت فقط برای کد آموزشی، یعنی عبور رو به جلو و عقب از مدل شما اعمال می‌شود. شما همچنان می‌توانید از تمام عملیات Tensorflow در خط لوله ورودی داده خود استفاده کنید زیرا روی CPU اجرا خواهد شد.
  • tf.py_func در TPU پشتیبانی نمی‌شود.

۴. بارگذاری داده‌ها

c0ecb860e4cad0a9.jpegcc4781a7739c49ae.jpeg۸۱۲۳۶b00f8bbf39e.jpeg۹۶۱e۲۲۲۸۹۷۴۰۷۶bb.jpeg7517dc163bdffcd5.jpeg۹۶۳۹۲df4767f566d.png

ما با یک مجموعه داده از تصاویر گل کار خواهیم کرد. هدف این است که یاد بگیریم آنها را به 5 نوع گل دسته بندی کنیم. بارگذاری داده ها با استفاده از API tf.data.Dataset انجام می شود. ابتدا، بیایید با API آشنا شویم.

عملی

لطفاً دفترچه یادداشت زیر را باز کنید، سلول‌ها را اجرا کنید (Shift-ENTER) و هر جا که برچسب «کار لازم است» را دیدید، دستورالعمل‌ها را دنبال کنید.

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

اطلاعات تکمیلی

درباره مجموعه داده "گل‌ها"

مجموعه داده‌ها در ۵ پوشه سازماندهی شده است. هر پوشه شامل گل‌هایی از یک نوع است. پوشه‌ها به نام‌های گل آفتابگردان، گل مینا، قاصدک، لاله و رز نامگذاری شده‌اند. داده‌ها در یک مخزن عمومی در فضای ذخیره‌سازی ابری گوگل میزبانی می‌شوند. گزیده‌ای از:

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ها را می‌پذیرند. پس از بارگذاری داده‌ها در یک Dataset، API تمام قابلیت‌های رایجی را که برای داده‌های آموزش شبکه عصبی مفید هستند، ارائه می‌دهد:

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())

نتیجه‌گیری: بارگذاری تصاویر تک تک کند است!

با تکرار این مجموعه داده، خواهید دید که می‌توانید چیزی حدود ۱-۲ تصویر در ثانیه بارگذاری کنید. این خیلی کند است! شتاب‌دهنده‌های سخت‌افزاری که ما برای آموزش استفاده خواهیم کرد می‌توانند چندین برابر این سرعت را تحمل کنند. برای دیدن نحوه دستیابی به این هدف، به بخش بعدی بروید.

راه حل

این دفترچه‌ی حل مسئله است. اگر به مشکلی برخوردید، می‌توانید از آن استفاده کنید.

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

آنچه ما پوشش داده‌ایم

  • 🤔 tf.data.Dataset.list_files
  • 🤔 tf.data.Dataset.map
  • 🤔 مجموعه داده‌های تاپل‌ها
  • 😀 تکرار در مجموعه داده‌ها

لطفا چند لحظه وقت بگذارید و این چک لیست را در ذهن خود مرور کنید.

۵. بارگذاری سریع داده‌ها

شتاب‌دهنده‌های سخت‌افزاری واحد پردازش تنسور (TPU) که ​​در این آزمایشگاه استفاده خواهیم کرد، بسیار سریع هستند. چالش اغلب این است که داده‌ها را به اندازه‌ای سریع به آنها بدهیم که مشغول بمانند. فضای ذخیره‌سازی ابری گوگل (GCS) قادر به حفظ توان عملیاتی بسیار بالا است، اما مانند همه سیستم‌های ذخیره‌سازی ابری، شروع یک اتصال هزینه رفت و برگشت شبکه را دارد. بنابراین، ذخیره داده‌های ما به صورت هزاران فایل جداگانه ایده‌آل نیست. ما قصد داریم آنها را در تعداد کمتری فایل دسته‌بندی کنیم و از قدرت tf.data.Dataset برای خواندن از چندین فایل به صورت موازی استفاده کنیم.

خواندنی

کدی که فایل‌های تصویر را بارگذاری می‌کند، اندازه آنها را به یک اندازه معمول تغییر می‌دهد و سپس آنها را در ۱۶ فایل 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 ذخیره کرد: رشته‌های بایتی (لیستی از بایت‌ها)، اعداد صحیح ۶۴ بیتی و اعداد اعشاری ۳۲ بیتی. آن‌ها همیشه به صورت لیست ذخیره می‌شوند، یک عنصر داده واحد، لیستی با اندازه ۱ خواهد بود. می‌توانید از توابع کمکی زیر برای ذخیره داده‌ها در 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، ابتدا باید طرح‌بندی رکوردهایی را که ذخیره کرده‌اید، تعریف کنید. در تعریف، می‌توانید به هر فیلد نامگذاری شده به عنوان یک لیست با طول ثابت یا یک لیست با طول متغیر دسترسی داشته باشید:

خواندن از TFRecords

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'])

همچنین می‌توان فیلدهای اختیاری در TFRecords داشت. اگر هنگام خواندن یک فیلد، مقدار پیش‌فرض را مشخص کنید، در صورت عدم وجود فیلد، مقدار پیش‌فرض به جای خطا بازگردانده می‌شود.

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

آنچه ما پوشش داده‌ایم

  • 🤔 تقسیم‌بندی فایل‌های داده برای دسترسی سریع از GCS
  • 😓 نحوه نوشتن TFRecords. (نحوه نوشتن را فراموش کرده‌اید؟ اشکالی ندارد، این صفحه را به عنوان برگه تقلب بوکمارک کنید)
  • 🤔 بارگذاری یک مجموعه داده از TFRecords با استفاده از TFRecordDataset

لطفا چند لحظه وقت بگذارید و این چک لیست را در ذهن خود مرور کنید.

۶. تبریک می‌گویم!

اکنون می‌توانید TPU را با داده تغذیه کنید. لطفاً به آزمایش بعدی بروید.

TPU ها در عمل

TPUها و GPUها در پلتفرم هوش مصنوعی ابری موجود هستند:

در نهایت، ما عاشق بازخورد هستیم. لطفاً اگر در این آزمایشگاه نکته‌ی اشتباهی می‌بینید یا فکر می‌کنید باید بهبود یابد، به ما بگویید. بازخورد را می‌توانید از طریق GitHub issues [ لینک بازخورد ] ارائه دهید.

منابع انسانی.png

کارت شناسایی مارتین گورنر کوچک.jpg
نویسنده: مارتین گورنر
توییتر: @martin_gorner