
Yenidən obyektləri aşkar etmə məsələsi ilə qarşı-qarşıyasınız. Prioritet — qəbul edilən dəqiqlikdə işin sürətidir. YOLOv3 arxitekturasını götürüb əlavə öyrənirsiniz. Dəqiqlik (mAp75) 0.95-dən yüksəkdir. Amma icra sürəti hələ də aşağıdır. Lənət olsun.
Bugün kvantlaşdırmanı kənara qoyacağıq. Və aşağıda baxacağıq Model Pruning — dəqiqlik itirmədən çıxarılması mümkün olan şəbəkənin artıq hissələrinin kəsilməsi. Nizamlayacaq — haradan, nə qədər və necə kəsmək olar. Bunu əl ilə necə etmək lazım olduğunu və harada avtomatlaşdıra biləcəyimizi müzakirə edəcəyik. Sonda — keras üçün repositoriya.
Giriş
Son iş yerimdə, Permdəki Macroscop-da, bir vərdiş qazandım — həmişə alqoritmlərin iş vaxtını izləmək. Və şəbəkələrin icra vaxtını həmişə adekvatlıq filtri ilə yoxlayıram. Adətən, state-of-the-art istehsalda bu filtrdən keçmir, bu da məni Pruning-ə gətirdi.
Pruning — köhnə bir mövzudur, 2017-ci ildə izah edilmişdir. Əsas ideya — müxtəlif düyünləri silməklə öyrənilmiş şəbəkənin ölçüsünü itirmədən kiçiltməkdir. Bu, gözəl səslənir, amma onun tətbiqlərini nadirən eşidirəm. Yəqin ki, tətbiqlər çatışmır, rusdilli məqalələr yoxdur, ya da insanlar pruning-i no-hau hesab edib susurlar.
Amma gəlin baxaq
Biologiyaya baxış
Dərin öyrənmə sahəsinə bioloji fikirlərin daxil olduğunu sevirəm. Onlara da, təkamülə də, inanmaq olar (bilmirdin ki, ReLU ağlın neyronlarının aktivasiya funksiyasına bənzəyir ?)
Model Pruning prosesi də biologiyaya yaxındır. Şəbəkənin reaksiyasını burada beynin plastikliyi ilə müqayisə etmək olar. Maraqlı nümunələr "Norman Doidge"-ın kitabında var. :
- Doğuşdan yalnız bir yarısı olan qadının beyni özünü itkin yarının funksiyalarını yerinə yetirmək üçün yenidən proqramlaşdırdı.
- Bir oğlan görmə üçün cavabdeh beyin hissəsini götürdü. Zaman keçdikcə, beyin digər hissələri bu funksiyaları öz üzərinə götürdü. (təkrarlamamağı çalışırıq)
Beləliklə, sizin modelinizdən zəif konvolyusiyaların bir hissəsini kəsə bilərsiniz. Ən pis halda, qalan konvolyusiyalar çıxarılanları əvəz etməyə kömək edəcək.
Transfer Öyrənməni sevirsən, yoxsa sıfırdan öyrənirsən?
Birinci variant. Yolov3-də Transfer Öyrənməsindən istifadə edirsən. Retina, Mask-RCNN və ya U-Net. Amma əksər hallarda 80 obyekt sinfini tanımağa ehtiyacımız olmur, COCO-da olduğu kimi. Mənim təcrübəmdə, bu, 1-2 siniflə məhdudlaşır. 80 sinif üçün arxitekturanın burada çox olduğunu düşünə bilərik. Arxitekturanı kiç ildirmək lazım olduğu fikri yaranır. Həmçinin, bunu var olan öncədən öyrənilmiş ağırlıqları itirmədən etmək istəyirəm.
İkinci variant. Bəlkə də çox məlumatın və hesablama resurslarınız var ya da sadəcə super fərdi bir arxitektura lazımdır. Hər nə isə. Amma siz şəbəkəni sıfırdan öyrənirsiniz. Adi ardıcıllıq — məlumatın strukturuna baxırıq, güc baxımından İZBƏTİF arxitektura seçirik və yerinə yetirmə üzrə dəyərləri artırırıq. Mən 0.6 dəyərində dəyərlər görmüşəm, Karl.
Hər iki halda şəbəkəni azaltmaq mümkündür. Motivasiya verdik. İndi gəlin, pruning haqqında aydınlaşdıraq.
Ümumi alqoritm
Biz qərara gəldik ki, konvolyusiyaları silə bilərik. Bu, olduqca sadə görünür:

Hər hansı bir konvolyusiyanı silmək şəbəkə üçün stressdir, bu da adətən müəyyən bir xətanın artımını təsir edir. Bir tərəfdən, bu xəta artımı, konvolyusiyaları nə qədər doğru silməyimizi göstərir (məsələn, böyük artım, bununla bağlı bir şeyin səhv olduğunu bildirir). Ancaq kiçik artım tamamilə qəbul ediləndir və bəzən sonrakı yüngül yenidən öyrənmə ilə aradan qaldırılır. Yenidən öyrənmə mərhələsini əlavə edirik:

İndi isə, LearningPruning dövrümüzü nə zaman dayandırmaq istədiyimizi başa düşməliyik. Burada hər hansı bir eksotik variant ola bilər, məsələn, bir şəbəkəni müəyyən ölçü və sürətə salmaq (məsələn, mobil cihazlar üçün). Ancaq ən tez-tez rast gəlinən variant, xətanın icazə verilən səviyyədən yuxarıya çıxması üçün dövrün davam etməsidir. Şərti əlavə edirik:

Beləliklə, alqoritm aydın olur. Silinəcək konvolyusiyaların necə müəyyən ediləcəyini müzakirə etməliyik.
Silinəcək konvolyusiyaların axtarışı
Bəzi konvolyusiyaları silməliyik. İstənilən konvolyusiyanı çıxarmaq pis ideyadır, baxmayaraq ki, işləyəcək. Ancaq düşünmək lazımdır və silinməsi üçün "zəif" konvolyusiyaları seçməyə çalışmalıyıq. Bir neçə variant var:
- . Kiçik ağırlıqlara sahib konvolyusiyaların qərar qəbul etməyə az təsir etdiyi ideyası.
- Orta və standart sapmanı nəzərə alan minimum L1 ölçüsü. Paylanma xarakterinin qiymətləndirilməsi ilə tamamlayırıq.
- . Kiçik əhəmiyyətli konvolyusiyaların daha dəqiq müəyyən edilməsi, lakin vaxt və resurslar baxımından xeyli sərf edir.
- Digərlər
Hər bir variantın həyata keçirilməyə haqqı var və öz xüsusiyyətləri var. Burada minimum L1 ölçüsü olan variantı müzakirə edəcəyik.
YOLOv3 üçün əl ilə proses
Orijinal arxitektura qalıq blokları ehtiva edir. Ancaq onlar dərin şəbəkələr üçün nə qədər cool olsa da, bizə bir az mane olacaq. Problemin mahiyyəti budur ki, bu qatlarda fərqli indeksli konvolyusiyaları silmək olmaz:

Buna görə, konvolyusiyaları sərbəst şəkildə silə biləcəyimiz qatları ayırırıq:

İndi iş dövrünü quraq:
- Aktivləşdirmələri yükləyirik.
- Nə qədər kəsəcəyimizi qiymətləndiririk.
- Kəsirik.
- LR=1e-4 ilə 10 epox öyrədirik.
- Test edirik.
Konvolyusiyaları yükləmək faydalıdır ki, müəyyən bir addımda nə qədərini silə biləcəyimizi qiymətləndirək. Yükləmə nümunələri:

Görürük ki, demək olar ki, hər yerdə 5%-lik konvolyusiyalar olduqca aşağı L1 normasına sahibdir və biz onları silə bilərik. Hər addımda belə yükləmə təkrarlanırdı və hansı qatlardan nə qədərinin silinə biləcəyi evalyasiya olunurdu.
Bütün proses 4 addıma sığdı (burada və hər yerdə 2060 Super RTX üçün sayılar):
| Addım | mAp75 | Parametr sayı, mln | Şəbəkə ölçüsü, mb | İlkin dəyərdən, % | İnterval müddəti, ms | Kəsmə şərti |
|---|---|---|---|---|---|---|
| 0 | 0.9656 | 60 | 241 | 100 | 180 | — |
| 1 | 0.9622 | 55 | 218 | 91 | 175 | Hər 5% nəfərdən |
| 2 | 0.9625 | 50 | 197 | 83 | 168 | Hər 5% nəfərdən |
| 3 | 0.9633 | 39 | 155 | 64 | 155 | Hər 15% 400+ konvolyusiya layları üçün |
| 4 | 0.9555 | 31 | 124 | 51 | 146 | Hər 10% 100+ konvolyusiya layları üçün |
2-ci addıma əlavə olaraq müsbət bir təsir yarandı - yaddaşda 4-lük batç ölçüsü, təqdimatı sürətləndirdi.
4-cü addımda proses dayandırıldı, çünki uzun müddət öyrənmə mAP75-i əvvəlki dəyərlərə yüksəltmədi.
Nəticədə infirens sürətini artırmaq mümkün oldu 15%, ölçünü azaltmaq 35% və dəqiqlikdə itki olmadan.
Sadə arxitekturalar üçün avtomatlaşdırma
Sadə şəbəkə arxitekturaları (şərti add, birləşdir və qalıq blokları olmadan) üçün bütün konvolyusiya laylarının emalını istiqamətləndirmək və konvolyusiyaların kəsilmə prosesini avtomatlaşdırmaq tamamilə mümkündür.
Bu variantı həyata keçirdim .
Sadədir: sizdən təkcə itki funksiyası, optimizator və batç yaradanlar tələb olunur:
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)Lazım gələrsə, konfiqurasiya parametrlərini dəyişə bilərsiniz:
{
"input_model_path": "model.h5",
"output_model_path": "model_pruned.h5",
"finetuning_epochs": 10, # kəsilmə mərhələləri arasında öyrənmək üçün epoxların sayı
"stop_loss": 0.1, # prosesi dayandırmaq üçün itki
"pruning_percent_step": 0.05, # hər kəsilmə mərhələsində silinən konvolyusiyaların nisbəti
"pruning_standart_deviation_part": 0.2 # kəsilmə hissəsini məhdudlaşdırmaq üçün dəyişiklik
}Əlavə olaraq standart sapma əsasında bir məhdudiyyət tətbiq edilmişdir. Məqsəd odur ki, silinən hissəni məhdudlaşdıraq, artıq "yetərli" L1 ölçmələri olan konvolyusiyaları istisna edək:

Beləliklə, yalnız zəif konvolyusiyaların sağ tərəfdə oxşar paylamalardan silinməsinə icazə verilir və sol tərəfdə oxşar paylamalara heç bir təsir etmir:

Paylama normal paylamağa yaxınlaşdıqca pruning_standart_deviation_part koeffisientini aşağıdakı dəyərlərdən seçmək olar:

Mən 2 sigma qəbulunu tövsiyə edirəm. Ya da bu xüsusiyyətə əsaslanmadan < 1.0 dəyərini saxlaya bilərsiniz.
Nəticədə, bütün test boyunca şəbəkə boyu, itki və işləmə müddətinin normalaşdırıldığı qrafik əldə edilir, 1.0-ə nisbətən. Məsələn, burada şəbəkənin ölçüsü keyfiyyət itirmədən demək olar ki, 2 dəfə azaldı (100k ağırlıqlı kiçik konvolyusiya şəbəkəsi):

İşləmə sürəti normal dalğalanmalara məruz qalır və demək olar ki, dəyişməz qaldı. Bunun izahı var:
- Konvolyusiyaların sayı, rahat (32, 64, 128) olanlardan, videokartlar üçün çox rahat olmayanlara - 27, 51 və s. çevrilir. Burada səhv edə bilərəm, amma bunun təsir etdiyini düşünürəm.
- Arxitektura geniş deyil, ancaq ardıcıldır. Genişliyi azaldarkən, dərinliklə oynayamırıq. Beləliklə, yükü azaldırıq, amma sürəti dəyişmirik.
Buna görə də inkişaf, işləmə zamanı CUDA yükünün 20-30% azaldılması ilə ifadə olunur, amma işləmə müddətinin azaldılması ilə deyil.
Yekunlar
Refleksiyaya vaxt ayıraq. YOLOv3 üçün iki pruning variantını araşdırdıq (əllərlə işləmək lazım olduğunda) və daha sadə arxitekturalara malik şəbəkələr üçün. Hər iki halda da, şəbəkənin ölçüsünü azaltmaq və sürətini artırmaq mümkün olduğu görünür, dəqiqliyi itirmədən. Nəticələr:
- Ölçünün azaldılması
- İcra sürətinin artırılması
- CUDA yükünün azaldılması
- Nəticə etibarilə, ekoloji cəhətdən (hesablama resurslarının gələcəkdən istifadəsini optimallaşdırırıq. Harada ki, biri sevindiyinə görə )
Yeni komponenti toplanmaya daxil etmək üçün, onun təsvirini bigtop.bom və .\/bigtop-packages faylına əlavə etmək lazımdır. Bu, mövcud komponentlərlə analoji olaraq edilməyə çalışıla bilər. Başlamaq üçün cəhd edin. İlk baxışda düşündüyünüz qədər çətin deyil.
- Pruning mərhələsindən sonra kvantizasiya (məsələn, TensorRT ilə) ilə də məşğul ola bilərik
- Tensorflow . İşləyir.
- inkişaf etdirmək istəyirəm və köməyə şadam
Mənbə: habr.com
