قبل از شما دوباره وظیفه شناسایی اشیاء است. اولویت سرعت عمل با دقت قابل قبول است. شما معماری YOLOv3 را انتخاب کرده و آن را بیشتر آموزش می دهید. دقت (mAp75) بیشتر از 0.95 است. اما نرخ اجرا هنوز پایین است. چرندیات.
امروز کوانتیزاسیون را دور خواهیم زد. و زیر برش را نگاه خواهیم کرد هرس مدل - برش بخش های اضافی شبکه برای سرعت بخشیدن به استنتاج بدون از دست دادن دقت. مشخص است که کجا، چقدر و چگونه باید برش داد. بیایید دریابیم که چگونه این کار را به صورت دستی انجام دهیم و کجا می توانید آن را خودکار کنید. در انتها یک مخزن در مورد کراس وجود دارد.
معرفی
در محل کار قبلی خود، Macroscop در پرم، یک عادت را به دست آوردم - همیشه نظارت بر زمان اجرای الگوریتم ها. و همیشه زمان اجرا شبکه را از طریق فیلتر کفایت بررسی کنید. معمولاً پیشرفته ترین در تولید از این فیلتر عبور نمی کند که من را به سمت هرس سوق داد.
هرس یک موضوع قدیمی است که در آن بحث شده است سخنرانی های استنفورد در سال 2017 ایده اصلی کاهش اندازه شبکه آموزش دیده بدون از دست دادن دقت با حذف گره های مختلف است. جالب به نظر می رسد، اما من به ندرت در مورد استفاده از آن می شنوم. احتمالاً پیادهسازی کافی وجود ندارد، مقالههای روسی زبان وجود ندارد یا به سادگی همه آن را دانش فنی میدانند و سکوت میکنند.
اما بیایید آن را جدا کنیم
نگاهی اجمالی به زیست شناسی
من دوست دارم Deep Learning به ایده هایی که از زیست شناسی می آیند نگاه می کند. آنها، مانند تکامل، قابل اعتماد هستند (آیا می دانستید که ReLU بسیار شبیه به عملکرد فعال شدن نورون در مغز?)
فرآیند هرس مدل نیز به زیست شناسی نزدیک است. پاسخ شبکه در اینجا را می توان با انعطاف پذیری مغز مقایسه کرد. چند مثال جالب در کتاب وجود دارد. نورمن دویج:
مغز زنی که تنها با یک نیمه به دنیا آمده است، خود را برای انجام وظایف نیمه گمشده از نو برنامه ریزی کرده است.
این مرد بخشی از مغز خود را که مسئول بینایی است، شلیک کرد. با گذشت زمان، بخشهای دیگر مغز این وظایف را بر عهده گرفتند. (ما سعی نمی کنیم تکرار کنیم)
به همین ترتیب، می توانید برخی از پیچش های ضعیف را از مدل خود حذف کنید. به عنوان آخرین راه حل، بسته های باقی مانده به جایگزینی بسته های بریده شده کمک می کنند.
آیا شما عاشق آموزش انتقالی هستید یا از صفر یاد می گیرید؟
گزینه شماره یک شما از Transfer Learning در Yolov3 استفاده می کنید. Retina، Mask-RCNN یا U-Net. اما اغلب اوقات ما نیازی به تشخیص 80 کلاس شی مانند COCO نداریم. در تمرین من، همه چیز محدود به نمرات 1-2 است. شاید بتوان تصور کرد که معماری 80 کلاس در اینجا اضافی است. این نشان می دهد که معماری باید کوچکتر شود. علاوه بر این، من می خواهم این کار را بدون از دست دادن وزنه های از قبل تمرین شده انجام دهم.
گزینه شماره دو شاید شما داده ها و منابع محاسباتی زیادی دارید یا فقط به یک معماری فوق العاده سفارشی نیاز دارید. مهم نیست اما شما در حال یادگیری شبکه از ابتدا هستید. روال معمول این است که به ساختار داده نگاه کنید، معماری را انتخاب کنید که از نظر قدرت بیش از حد باشد، و ترک تحصیل مجدد را کنار بگذارید. من 0.6 ترک تحصیل دیدم، کارل.
در هر دو مورد، شبکه را می توان کاهش داد. با انگیزه حالا بیایید بفهمیم که هرس ختنه چیست
الگوریتم عمومی
ما تصمیم گرفتیم که می توانیم بسته ها را حذف کنیم. خیلی ساده به نظر می رسد:
حذف هر پیچیدگی برای شبکه استرس زا است، که معمولاً منجر به افزایش خطا می شود. از یک طرف، این افزایش خطا نشان دهنده این است که چگونه پیچیدگی ها را به درستی حذف می کنیم (به عنوان مثال، افزایش زیاد نشان می دهد که ما کار اشتباهی انجام می دهیم). اما افزایش اندک کاملاً قابل قبول است و اغلب با تمرینات اضافی سبک بعدی با یک LR کوچک حذف می شود. یک مرحله آموزشی اضافی اضافه کنید:
اکنون باید بفهمیم که چه زمانی می خواهیم حلقه یادگیری<->Pruning خود را متوقف کنیم. زمانی که نیاز داریم شبکه را به اندازه و سرعت خاصی کاهش دهیم (مثلاً برای دستگاه های تلفن همراه) ممکن است گزینه های عجیب و غریبی در اینجا وجود داشته باشد. با این حال، رایج ترین گزینه این است که چرخه را تا زمانی که خطا بالاتر از حد قابل قبول شود، ادامه دهید. یک شرط اضافه کنید:
بنابراین، الگوریتم روشن می شود. باقی مانده است که چگونگی تعیین پیچیدگی های حذف شده را بفهمیم.
بسته های حذف شده را جستجو کنید
ما باید برخی از پیچیدگی ها را حذف کنیم. عجله به جلو و "تیراندازی" به هر کسی ایده بدی است، اگرچه کارساز خواهد بود. اما از آنجایی که سر دارید، می توانید فکر کنید و سعی کنید پیچش های "ضعیف" را برای حذف انتخاب کنید. چندین گزینه وجود دارد:
هر یک از گزینه ها حق حیات و ویژگی های اجرایی خاص خود را دارند. در اینجا گزینه ای را با کوچکترین L1-measure در نظر می گیریم
فرآیند دستی برای YOLOv3
معماری اصلی شامل بلوک های باقی مانده است. اما هر چقدر هم برای شبکه های عمیق باحال باشند، تا حدودی مانع ما می شوند. مشکل این است که شما نمی توانید تطبیق با شاخص های مختلف را در این لایه ها حذف کنید:
بنابراین، بیایید لایههایی را انتخاب کنیم که بتوانیم آزادانه آشتیها را حذف کنیم:
حالا بیایید یک چرخه کاری بسازیم:
در حال آپلود فعال سازی ها
فهمیدن اینکه چقدر باید برش داد
قطع
آموزش 10 دوره با LR=1e-4
آزمایش کردن
تخلیه کانولوشن ها برای تخمین مقدار بخشی که می توانیم در یک مرحله خاص حذف کنیم مفید است. نمونه های تخلیه:
می بینیم که تقریباً در همه جا 5 درصد کانولوشن ها دارای هنجار L1 بسیار پایین هستند و می توانیم آنها را حذف کنیم. در هر مرحله، این تخلیه تکرار میشد و ارزیابی میشد که کدام لایه و چند لایه را میتوان برش داد.
کل فرآیند در 4 مرحله تکمیل شد (اعداد در اینجا و همه جا برای RTX 2060 Super):
گام
mAp75
تعداد پارامتر، میلیون
اندازه شبکه، مگابایت
از ابتدایی، %
زمان اجرا، ms
شرایط ختنه
0
0.9656
60
241
100
180
-
1
0.9622
55
218
91
175
5 درصد از همه
2
0.9625
50
197
83
168
5 درصد از همه
3
0.9633
39
155
64
155
15٪ برای لایه های با بیش از 400 پیچش
4
0.9555
31
124
51
146
10٪ برای لایه های با بیش از 100 پیچش
یک اثر مثبت به مرحله 2 اضافه شد - اندازه دسته 4 در حافظه قرار می گیرد که روند آموزش اضافی را بسیار تسریع می کند.
در مرحله 4، روند متوقف شد زیرا حتی آموزش اضافی طولانی مدت mAp75 را به مقادیر قدیمی افزایش نداد.
در نتیجه، ما موفق شدیم استنتاج را با سرعت بیشتری انجام دهیم ٪۱۰۰، اندازه را کاهش دهید ٪۱۰۰ و دقیقا از دست نده
اتوماسیون برای معماری های ساده تر
برای معماریهای شبکه سادهتر (بدون بلوکهای اضافه شرطی، متصل و باقیمانده)، تمرکز بر پردازش تمام لایههای کانولوشن و خودکار کردن فرآیند برش کانولوشن کاملاً ممکن است.
من این گزینه را اجرا کردم اینجا.
ساده است: شما فقط به یک تابع ضرر، یک بهینه ساز و ژنراتورهای دسته ای نیاز دارید:
import pruning
from keras.optimizers import Adam
from keras.utils import Sequence
train_batch_generator = BatchGenerator...
score_batch_generator = BatchGenerator...
opt = Adam(lr=1e-4)
pruner = pruning.Pruner("config.json", "categorical_crossentropy", opt)
pruner.prune(train_batch, valid_batch)
در صورت لزوم، می توانید پارامترهای پیکربندی را تغییر دهید:
{
"input_model_path": "model.h5",
"output_model_path": "model_pruned.h5",
"finetuning_epochs": 10, # the number of epochs for train between pruning steps
"stop_loss": 0.1, # loss for stopping process
"pruning_percent_step": 0.05, # part of convs for delete on every pruning step
"pruning_standart_deviation_part": 0.2 # shift for limit pruning part
}
علاوه بر این، یک محدودیت بر اساس انحراف استاندارد اجرا شده است. هدف محدود کردن بخشی است که حذف میشود، به استثنای پیچیدگیهایی با معیارهای L1 «کافی» از قبل:
بنابراین، ما به شما این امکان را میدهیم که فقط پیچیدگیهای ضعیف را از توزیعهای مشابه با سمت راست حذف کنید و بر حذف از توزیعهای مشابه با توزیع چپ تأثیری نگذارید:
وقتی توزیع به نرمال نزدیک شد، ضریب pruning_standart_deviation_part را می توان از موارد زیر انتخاب کرد:
من یک فرض 2 سیگما را توصیه می کنم. یا می توانید این ویژگی را نادیده بگیرید و مقدار <1.0 را باقی بگذارید.
خروجی نمودار اندازه شبکه، از دست دادن و زمان اجرای شبکه برای کل آزمایش است که به 1.0 نرمال شده است. به عنوان مثال، در اینجا اندازه شبکه تقریباً 2 برابر بدون کاهش کیفیت کاهش یافت (شبکه کانولوشن کوچک با وزن 100k):
سرعت دویدن در معرض نوسانات عادی است و تقریباً بدون تغییر باقی می ماند. برای این توضیحی وجود دارد:
تعداد پیچش ها از مناسب (32، 64، 128) به راحت ترین برای کارت های ویدئویی - 27، 51 و غیره تغییر می کند. من ممکن است در اینجا اشتباه کنم، اما به احتمال زیاد تأثیر دارد.
معماری گسترده نیست، اما سازگار است. با کاهش عرض، روی عمق تاثیر نمی گذاریم. بنابراین، بار را کاهش می دهیم، اما سرعت را تغییر نمی دهیم.
بنابراین، بهبود در کاهش بار CUDA در طول اجرا به میزان 20-30٪ بیان شد، اما نه در کاهش در زمان اجرا.
نمایش نتایج: از
بیایید تأمل کنیم. ما 2 گزینه را برای هرس در نظر گرفتیم - برای YOLOv3 (زمانی که باید با دستان خود کار کنید) و برای شبکه هایی با معماری ساده تر. مشاهده می شود که در هر دو مورد می توان به کاهش اندازه شبکه و افزایش سرعت بدون از دست دادن دقت دست یافت. نتایج:
کاهش سایز
اجرا شتاب
کاهش بار CUDA
در نتیجه، سازگاری با محیط زیست (ما استفاده آینده از منابع محاسباتی را بهینه می کنیم. جایی که فرد خوشحال است گرتا تونبرگ)
ضمیمه
پس از مرحله هرس، می توانید کوانتیزاسیون را اضافه کنید (مثلاً با TensorRT)