۱. مرور کلی
در این آزمایش، شما یاد خواهید گرفت که چگونه لایه کانولوشن را به یک مدل شبکه عصبی که میتواند گلها را تشخیص دهد، تبدیل کنید. این بار، خودتان مدل را از ابتدا خواهید ساخت و از قدرت TPU برای آموزش آن در عرض چند ثانیه و تکرار طراحی آن استفاده خواهید کرد.
این آزمایشگاه شامل توضیحات نظری لازم در مورد شبکههای عصبی کانولوشن است و نقطه شروع خوبی برای توسعهدهندگانی است که در مورد یادگیری عمیق یاد میگیرند.
این آزمایش بخش سوم از مجموعه «کرس روی TPU» است. میتوانید آنها را به ترتیب زیر یا به صورت مستقل انجام دهید.
- خطوط لوله داده با سرعت TPU: tf.data.Dataset و TFRecords
- اولین مدل Keras شما، با یادگیری انتقالی
- [این آزمایشگاه] شبکههای عصبی کانولوشن، با Keras و TPUها
- شبکههای عصبی مدرن، squeezenet، Xception، با Keras و TPUها

آنچه یاد خواهید گرفت
- ساخت یک طبقهبندیکننده تصویر کانولوشنی با استفاده از مدل ترتیبی Keras.
- برای آموزش مدل Keras خود روی TPU
- برای تنظیم دقیق مدل خود با انتخاب خوبی از لایههای کانولوشن.
بازخورد
اگر در این آزمایشگاه کد، نکتهی نادرستی میبینید، لطفاً به ما بگویید. میتوانید از طریق GitHub issues [ لینک بازخورد ] بازخورد خود را ارائه دهید.
۲. شروع سریع Google Colaboratory
این آزمایشگاه از Google Collaboratory استفاده میکند و نیازی به راهاندازی از طرف شما ندارد. Colaboratory یک پلتفرم دفترچه یادداشت آنلاین برای اهداف آموزشی است. این پلتفرم آموزش رایگان CPU، GPU و TPU را ارائه میدهد.

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

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

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

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

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

دسترسی به مخازن ذخیرهسازی ابری گوگل خصوصی شما برای Colab امکانپذیر است، مشروط بر اینکه با یک حساب کاربری مجاز احراز هویت شوید. قطعه کد بالا فرآیند احراز هویت را آغاز میکند.
۳. [اطلاعات] واحدهای پردازش تنسور (TPU) چیستند؟
به طور خلاصه

کد آموزش یک مدل روی 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ها برای ساخت و بهینهسازی یک طبقهبندیکننده گل با سرعتهای تعاملی (دقیقه در هر اجرای آموزشی) استفاده خواهیم کرد.

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

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

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

آموزش شبکه عصبی معمولاً در برابر نویز ناشی از کاهش دقت ممیز شناور مقاوم است. مواردی وجود دارد که نویز حتی به همگرایی بهینهساز کمک میکند. دقت ممیز شناور ۱۶ بیتی به طور سنتی برای تسریع محاسبات استفاده شده است، اما فرمتهای 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 پیادهسازی کند و این ضرب ماتریس را به صورت یکجا پردازش کند.

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

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

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

تصویر: همگامسازی گرادیانها در طول آموزش با استفاده از الگوریتم all-reduce در شبکه HPC مش چنبره دوبعدی Google TPU.
نرمافزار
آموزش در اندازه دستههای بزرگ
اندازه ایدهآل دسته برای TPUها، ۱۲۸ آیتم داده در هر هسته TPU است، اما سختافزار میتواند از ۸ آیتم داده در هر هسته TPU به خوبی استفاده کند. به یاد داشته باشید که یک Cloud TPU دارای ۸ هسته است.
در این آزمایشگاه کد، ما از API کرس استفاده خواهیم کرد. در کرس، دستهای که شما مشخص میکنید، اندازه دسته سراسری برای کل TPU است. دستههای شما به طور خودکار به ۸ قسمت تقسیم شده و روی ۸ هسته TPU اجرا میشوند.

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

تصویر: برای اجرا روی 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 پشتیبانی نمیشود.
۴. [اطلاعات] طبقهبندیکننده شبکه عصبی ۱۰۱
به طور خلاصه
اگر تمام اصطلاحات پررنگشده در پاراگراف بعدی را از قبل میدانید، میتوانید به تمرین بعدی بروید. اگر تازه یادگیری عمیق را شروع کردهاید، خوش آمدید و لطفاً ادامه مطلب را بخوانید.
برای مدلهایی که به صورت دنبالهای از لایهها ساخته شدهاند، Keras رابط برنامهنویسی کاربردی Sequential را ارائه میدهد. برای مثال، یک طبقهبندیکننده تصویر با استفاده از سه لایه متراکم را میتوان در Keras به صورت زیر نوشت:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
tf.keras.layers.Dense(500, activation="relu"),
tf.keras.layers.Dense(50, activation="relu"),
tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])
# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy']) # % of correct answers
# train the model
model.fit(dataset, ... )

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

شما میتوانید با تبدیل مقادیر RGB تمام پیکسلهای یک تصویر به یک بردار طولانی و استفاده از آن به عنوان ورودی، آن را به چنین شبکهای وارد کنید. این بهترین تکنیک برای تشخیص تصویر نیست، اما بعداً آن را بهبود خواهیم بخشید.
نورونها، فعالسازیها، RELU
یک «نورون» مجموع وزنی تمام ورودیهای خود را محاسبه میکند، مقداری به نام «بایاس» به آن اضافه میکند و نتیجه را از طریق چیزی به نام «تابع فعالسازی» ارسال میکند. وزنها و بایاس در ابتدا ناشناخته هستند. آنها به صورت تصادفی مقداردهی اولیه میشوند و با آموزش شبکه عصبی روی تعداد زیادی از دادههای شناخته شده، «یاد گرفته» میشوند.

محبوبترین تابع فعالسازی، RELU (Rectified Linear Unit) نام دارد. همانطور که در نمودار بالا میبینید، این تابع بسیار ساده است.
فعالسازی سافتمکس
شبکه فوق با یک لایه ۵ نورونی به پایان میرسد زیرا ما گلها را به ۵ دسته (رز، لاله، قاصدک، مینا، آفتابگردان) طبقهبندی میکنیم. نورونهای لایههای میانی با استفاده از تابع فعالسازی کلاسیک RELU فعال میشوند. با این حال، در لایه آخر، میخواهیم اعداد بین ۰ و ۱ را محاسبه کنیم که نشاندهنده احتمال این است که این گل رز، لاله و غیره باشد. برای این کار، از یک تابع فعالسازی به نام "softmax" استفاده خواهیم کرد.
اعمال softmax روی یک بردار با در نظر گرفتن تابع نمایی هر عنصر و سپس نرمالسازی بردار، معمولاً با استفاده از نرم L1 (مجموع قدرمطلقها) انجام میشود، به طوری که مجموع مقادیر برابر با ۱ شود و بتوان آنها را به عنوان احتمال تفسیر کرد.


اتلاف آنتروپی متقاطع
حالا که شبکه عصبی ما پیشبینیهایی از تصاویر ورودی تولید میکند، باید میزان دقت آنها را اندازهگیری کنیم، یعنی فاصله بین آنچه شبکه به ما میگوید و پاسخهای صحیح، که اغلب "برچسب" نامیده میشوند. به یاد داشته باشید که ما برای همه تصاویر موجود در مجموعه دادهها برچسبهای صحیح داریم.
هر فاصلهای جواب میدهد، اما برای مسائل طبقهبندی، فاصلهای که «فاصله آنتروپی متقاطع» نامیده میشود، مؤثرترین است. ما این را تابع خطا یا «زیان» مینامیم:

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

مینی بچینگ و مومنتوم
شما میتوانید گرادیان خود را فقط روی یک تصویر نمونه محاسبه کنید و وزنها و بایاسها را فوراً بهروزرسانی کنید، اما انجام این کار روی یک دسته، مثلاً ۱۲۸ تصویر، گرادیانی را ارائه میدهد که محدودیتهای اعمال شده توسط تصاویر نمونه مختلف را بهتر نشان میدهد و بنابراین احتمالاً سریعتر به سمت راهحل همگرا میشود. اندازه مینی-دسته یک پارامتر قابل تنظیم است.
این تکنیک که گاهی اوقات «کاهش گرادیان تصادفی» نامیده میشود، یک مزیت عملیتر دیگر نیز دارد: کار با دستهها به معنای کار با ماتریسهای بزرگتر نیز هست و بهینهسازی این ماتریسها روی GPUها و TPUها معمولاً آسانتر است.
با این حال، همگرایی هنوز میتواند کمی آشوبناک باشد و حتی اگر بردار گرادیان همه صفر باشد، میتواند متوقف شود. آیا این بدان معناست که ما یک مینیمم پیدا کردهایم؟ نه همیشه. یک مؤلفه گرادیان میتواند روی یک مینیمم یا یک ماکزیمم صفر باشد. با یک بردار گرادیان با میلیونها عنصر، اگر همه آنها صفر باشند، احتمال اینکه هر صفر مربوط به یک مینیمم باشد و هیچ یک از آنها به یک نقطه ماکزیمم نرسد، بسیار کم است. در فضایی با ابعاد زیاد، نقاط زینی بسیار رایج هستند و ما نمیخواهیم در آنها متوقف شویم.

تصویر: یک نقطه زینی. گرادیان صفر است اما در همه جهات حداقل نیست. (منبع تصویر: ویکیمدیا: نوشته نیکوگوارو - اثر شخصی، CC BY 3.0 )
راه حل این است که مقداری مومنتوم به الگوریتم بهینهسازی اضافه کنیم تا بتواند بدون توقف از نقاط زینی عبور کند.
واژهنامه
دستهای یا مینی-دستهای : آموزش همیشه روی دستههایی از دادههای آموزشی و برچسبها انجام میشود. انجام این کار به همگرایی الگوریتم کمک میکند. بُعد «دستهای» معمولاً اولین بُعد از تانسورهای داده است. به عنوان مثال، یک تانسور شکل [100، 192، 192، 3] شامل 100 تصویر با ابعاد 192x192 پیکسل با سه مقدار در هر پیکسل (RGB) است.
تابع زیان آنتروپی متقاطع : یک تابع زیان ویژه که اغلب در طبقهبندیکنندهها استفاده میشود.
لایه متراکم : لایهای از نورونها که در آن هر نورون به تمام نورونهای لایه قبلی متصل است.
ویژگیها : ورودیهای یک شبکه عصبی گاهی اوقات «ویژگیها» نامیده میشوند. هنر تشخیص اینکه کدام بخشهای یک مجموعه داده (یا ترکیبی از بخشها) باید به یک شبکه عصبی داده شوند تا پیشبینیهای خوبی حاصل شود، «مهندسی ویژگی» نامیده میشود.
برچسبها : نام دیگری برای «کلاسها» یا پاسخهای صحیح در یک مسئله طبقهبندی نظارتشده
نرخ یادگیری : کسری از گرادیان که وزنها و بایاسها در هر تکرار حلقه آموزش بهروزرسانی میشوند.
لوجیتها : خروجیهای یک لایه از نورونها قبل از اعمال تابع فعالسازی، «لوجیت» نامیده میشوند. این اصطلاح از «تابع لجستیک» یا «تابع سیگموئید» گرفته شده است که قبلاً محبوبترین تابع فعالسازی بود. «خروجیهای نورون قبل از تابع لجستیک» به «لوجیتها» خلاصه شد.
تابع خطا (loss) : تابع خطایی که خروجیهای شبکه عصبی را با پاسخهای صحیح مقایسه میکند.
نورون : مجموع وزنی ورودیهایش را محاسبه میکند، یک بایاس اضافه میکند و نتیجه را از طریق یک تابع فعالسازی ارسال میکند.
کدگذاری وان-هات : کلاس ۳ از ۵ به صورت برداری با ۵ عنصر کدگذاری میشود که همه عناصر آن صفر هستند به جز عنصر سوم که ۱ است.
relu : واحد خطی یکسو شده. یک تابع فعالسازی محبوب برای نورونها.
سیگموئید : تابع فعالسازی دیگری که قبلاً محبوب بود و هنوز هم در موارد خاص مفید است.
softmax : یک تابع فعالسازی ویژه که روی یک بردار عمل میکند، تفاوت بین بزرگترین مؤلفه و سایر مؤلفهها را افزایش میدهد، و همچنین بردار را طوری نرمالسازی میکند که مجموع آن ۱ باشد تا بتوان آن را به عنوان برداری از احتمالات تفسیر کرد. به عنوان آخرین مرحله در طبقهبندیکنندهها استفاده میشود.
تانسور : یک "تانسور" مانند یک ماتریس است اما با تعداد دلخواهی از ابعاد. یک تانسور یک بعدی یک بردار است. یک تانسور دو بعدی یک ماتریس است. و سپس میتوانید تانسورهایی با ۳، ۴، ۵ یا بیشتر بعد داشته باشید.
۵. [اطلاعات جدید] شبکههای عصبی کانولوشن
به طور خلاصه
اگر تمام اصطلاحات پررنگشده در پاراگراف بعدی را از قبل میدانید، میتوانید به تمرین بعدی بروید. اگر تازه با شبکههای عصبی کانولوشن شروع کردهاید، لطفاً ادامه مطلب را بخوانید.

تصویر: فیلتر کردن یک تصویر با دو فیلتر متوالی که هر کدام از ۴x۴x۳=۴۸ وزن قابل یادگیری ساخته شدهاند.
یک شبکه عصبی کانولوشن ساده در Keras به این شکل است:
model = tf.keras.Sequential([
# input: images of size 192x192x3 pixels (the three stands for RGB channels)
tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
tf.keras.layers.Flatten(),
# classifying into 5 categories
tf.keras.layers.Dense(5, activation='softmax')
])
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy'])

شبکههای عصبی کانولوشنی ۱۰۱
در یک لایه از یک شبکه کانولوشن، یک "نورون" مجموع وزنی پیکسلهای درست بالای خود را، فقط در یک ناحیه کوچک از تصویر، انجام میدهد. این یک بایاس اضافه میکند و مجموع را از طریق یک تابع فعالسازی تغذیه میکند، درست همانطور که یک نورون در یک لایه متراکم معمولی انجام میدهد. سپس این عملیات در کل تصویر با استفاده از همان وزنها تکرار میشود. به یاد داشته باشید که در لایههای متراکم، هر نورون وزنهای خود را داشت. در اینجا، یک "وصله" از وزنها در هر دو جهت در تصویر میلغزد (یک "کانولوشن"). خروجی به تعداد پیکسلهای موجود در تصویر، مقادیر دارد (البته مقداری لایهگذاری در لبهها ضروری است). این یک عملیات فیلترینگ است که از یک فیلتر با وزنهای 4x4x3=48 استفاده میکند.
با این حال، ۴۸ وزن کافی نخواهد بود. برای اضافه کردن درجات آزادی بیشتر، همین عملیات را با مجموعهای جدید از وزنها تکرار میکنیم. این کار مجموعهای جدید از خروجیهای فیلتر را تولید میکند. بیایید آن را «کانال» خروجیها بنامیم، مشابه کانالهای R، G و B در تصویر ورودی.

دو (یا چند) مجموعه از وزنها را میتوان با اضافه کردن یک بُعد جدید به عنوان یک تانسور خلاصه کرد. این به ما شکل کلی تانسور وزنها را برای یک لایه کانولوشن میدهد. از آنجایی که تعداد کانالهای ورودی و خروجی پارامترها هستند، میتوانیم شروع به انباشت و زنجیرهسازی لایههای کانولوشن کنیم.

تصویر: یک شبکه عصبی کانولوشنی، «مکعبهای» داده را به «مکعبهای» داده دیگر تبدیل میکند.
کانولوشنهای گامبهگام، حداکثر تجمع
با انجام کانولوشنها با گام ۲ یا ۳، میتوانیم مکعب داده حاصل را در ابعاد افقی نیز کوچک کنیم. دو روش رایج برای انجام این کار وجود دارد:
- کانولوشن گامدار: یک فیلتر لغزشی مانند بالا اما با گام بزرگتر از ۱
- حداکثر ادغام: یک پنجره کشویی که عملیات MAX را اعمال میکند (معمولاً روی تکههای ۲x۲، که هر ۲ پیکسل تکرار میشود)

تصویر: جابجایی پنجره محاسبات به اندازه ۳ پیکسل منجر به مقادیر خروجی کمتری میشود. کانولوشنهای گامدار یا حداکثر تجمع (حداکثر در یک پنجره ۲x۲ که با گام ۲ جابجا میشود) راهی برای کوچک کردن مکعب داده در ابعاد افقی هستند.
طبقهبندیکنندهی تکاملی C
در نهایت، با مسطح کردن آخرین مکعب داده و عبور آن از یک لایه متراکم و فعالشده با softmax، یک هد طبقهبندی متصل میکنیم. یک طبقهبندیکننده کانولوشنی معمولی میتواند به شکل زیر باشد:

تصویر: یک طبقهبندیکننده تصویر با استفاده از لایههای کانولوشن و softmax. این طبقهبندیکننده از فیلترهای ۳x۳ و ۱x۱ استفاده میکند. لایههای maxpool حداکثر گروههای نقاط داده ۲x۲ را میگیرند. سر طبقهبندیکننده با یک لایه متراکم با فعالسازی softmax پیادهسازی شده است.
در کراس
پشته کانولوشنی نشان داده شده در بالا را میتوان در Keras به صورت زیر نوشت:
model = tf.keras.Sequential([
# input: images of size 192x192x3 pixels (the three stands for RGB channels)
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
tf.keras.layers.Flatten(),
# classifying into 5 categories
tf.keras.layers.Dense(5, activation='softmax')
])
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy'])
۶. کانوِنت سفارشی شما
عملی
بیایید یک شبکه عصبی کانولوشن را از ابتدا بسازیم و آموزش دهیم. استفاده از TPU به ما امکان میدهد خیلی سریع تکرار کنیم. لطفاً دفترچه یادداشت زیر را باز کنید، سلولها را اجرا کنید (Shift-ENTER) و هر جا که برچسب "WORK REQUIRED" را دیدید، دستورالعملها را دنبال کنید.
Keras_Flowers_TPU (playground).ipynb
هدف، غلبه بر دقت ۷۵ درصدی مدل یادگیری انتقالی است. آن مدل یک مزیت داشت، آن هم این بود که روی مجموعه دادهای متشکل از میلیونها تصویر از قبل آموزش دیده بود، در حالی که ما اینجا فقط ۳۶۷۰ تصویر داریم. آیا میتوانید حداقل با آن برابری کنید؟
اطلاعات تکمیلی
چند لایه، چقدر بزرگ؟
انتخاب اندازه لایهها بیشتر یک هنر است تا یک علم. شما باید تعادل مناسبی بین داشتن پارامترهای خیلی کم و خیلی زیاد (وزنها و بایاسها) پیدا کنید. با وزنهای خیلی کم، شبکه عصبی نمیتواند پیچیدگی شکلهای گل را نشان دهد. با وزنهای خیلی زیاد، میتواند مستعد "بیشبرازش" باشد، یعنی در تصاویر آموزشی تخصص پیدا میکند و قادر به تعمیم نیست. با پارامترهای زیاد، مدل نیز در آموزش کند خواهد بود. در Keras، تابع model.summary() ساختار و تعداد پارامترهای مدل شما را نمایش میدهد:
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 192, 192, 16) 448
_________________________________________________________________
conv2d_1 (Conv2D) (None, 192, 192, 30) 4350
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 96, 96, 60) 16260
_________________________________________________________________
...
_________________________________________________________________
global_average_pooling2d (Gl (None, 130) 0
_________________________________________________________________
dense (Dense) (None, 90) 11790
_________________________________________________________________
dense_1 (Dense) (None, 5) 455
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________
چند نکته:
- داشتن چندین لایه چیزی است که شبکههای عصبی «عمیق» را مؤثر میکند. برای این مسئله ساده تشخیص گل، ۵ تا ۱۰ لایه منطقی است.
- از فیلترهای کوچک استفاده کنید. معمولاً فیلترهای ۳x۳ در همه جا خوب هستند.
- فیلترهای ۱x۱ هم میتوانند استفاده شوند و ارزان هستند. آنها واقعاً چیزی را «فیلتر» نمیکنند، بلکه ترکیبهای خطی کانالها را محاسبه میکنند. آنها را با فیلترهای واقعی جایگزین کنید. (در بخش بعدی درباره «کانولوشنهای ۱x۱» بیشتر توضیح داده خواهد شد.)
- برای یک مسئله طبقهبندی مانند این، مرتباً با لایههای max-pooling (یا کانولوشنهایی با stride >1) نمونهبرداری کاهشی انجام دهید. برای شما مهم نیست گل کجا باشد، فقط مهم این است که گل رز باشد یا قاصدک، بنابراین از دست دادن اطلاعات x و y مهم نیست و فیلتر کردن نواحی کوچکتر ارزانتر است.
- تعداد فیلترها معمولاً مشابه تعداد کلاسها در انتهای شبکه میشود (چرا؟ به ترفند «میانگین جهانی ادغام» در زیر مراجعه کنید). اگر دادهها را به صدها کلاس طبقهبندی میکنید، تعداد فیلترها را به تدریج در لایههای متوالی افزایش دهید. برای مجموعه داده گل با ۵ کلاس، فیلتر کردن فقط با ۵ فیلتر کافی نخواهد بود. میتوانید در اکثر لایهها از تعداد فیلتر یکسانی استفاده کنید، مثلاً ۳۲ و هر چه به انتها نزدیکتر میشوید، آن را کاهش دهید.
- لایه(های) متراکم نهایی گران/گران هستند. این لایه/لایهها میتوانند وزنهای بیشتری نسبت به مجموع تمام لایههای کانولوشن داشته باشند. برای مثال، حتی با یک خروجی بسیار معقول از آخرین مکعب داده شامل ۲۴x۲۴x۱۰ نقطه داده، یک لایه متراکم ۱۰۰ نورونی هزینهای معادل ۲۴x۲۴x۱۰x۱۰۰=۵۷۶۰۰۰ وزن خواهد داشت!!! سعی کنید با فکر عمل کنید، یا از روش میانگینگیری سراسری (global average pooling) استفاده کنید (به پایین مراجعه کنید).
میانگین جهانی تجمیع
به جای استفاده از یک لایه متراکم و پرهزینه در انتهای یک شبکه عصبی کانولوشن، میتوانید «مکعب» دادههای ورودی را به تعداد کلاسهایی که دارید به بخشهای مختلف تقسیم کنید، مقادیر آنها را میانگین بگیرید و اینها را از طریق یک تابع فعالسازی softmax تغذیه کنید. این روش ساخت رأس طبقهبندی، هیچ وزنی ندارد. در Keras، سینتکس آن tf.keras.layers.GlobalAveragePooling2D().

راه حل
این دفترچهی حل مسئله است. اگر به مشکلی برخوردید، میتوانید از آن استفاده کنید.
Keras_Flowers_TPU (solution).ipynb
آنچه ما پوشش دادهایم
- 🤔 با لایههای کانولوشنی بازی شده است
- 🤓 با حداکثر تجمع، گامها، تجمع میانگین جهانی و ... آزمایش کردم.
- 😀 به سرعت روی یک مدل دنیای واقعی، روی TPU، تکرار شد
لطفا چند لحظه وقت بگذارید و این چک لیست را در ذهن خود مرور کنید.
۷. تبریک میگویم!
شما اولین شبکه عصبی کانولوشن مدرن خود را ساختهاید و آن را با دقت بیش از ۸۰٪ آموزش دادهاید و به لطف TPUها، معماری آن را تنها در عرض چند دقیقه تکرار کردهاید. لطفاً برای آشنایی با معماریهای کانولوشن مدرن، به آزمایشگاه بعدی بروید:
- خطوط لوله داده با سرعت TPU: tf.data.Dataset و TFRecords
- اولین مدل Keras شما، با یادگیری انتقالی
- [THIS LAB] Convolutional neural networks, with Keras and TPUs
- Modern convnets, squeezenet, Xception, with Keras and TPUs
TPUs in practice
TPUs and GPUs are available on Cloud AI Platform :
- On Deep Learning VMs
- In AI Platform Notebooks
- In AI Platform Training jobs
Finally, we love feedback. Please tell us if you see something amiss in this lab or if you think it should be improved. Feedback can be provided through GitHub issues [ feedback link ].

|

