Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Para jush përsëri është detyra e zbulimit të objekteve. Prioriteti është shpejtësia e funksionimit me saktësi të pranueshme. Ju merrni arkitekturën YOLOv3 dhe e trajnoni më tej. Saktësia (mAp75) është më e madhe se 0.95. Por shkalla e vrapimit është ende e ulët. Katrahurë.

Sot do të anashkalojmë kuantizimin. Dhe nën prerje ne do të shikojmë Krasitja e modelit — shkurtimi i pjesëve të tepërta të rrjetit për të shpejtuar përfundimin pa humbje të saktësisë. Është e qartë se ku, sa dhe si të pritet. Le të kuptojmë se si ta bëjmë këtë me dorë dhe ku mund ta automatizoni atë. Në fund ka një depo për keras.

Paraqitje

Në vendin tim të mëparshëm të punës, Macroscop në Perm, fitova një zakon - të monitoroja gjithmonë kohën e ekzekutimit të algoritmeve. Dhe gjithmonë kontrolloni kohën e funksionimit të rrjetit përmes një filtri të përshtatshmërisë. Zakonisht teknologjia moderne në prodhim nuk e kalon këtë filtër, gjë që më çoi në Krasitje.

Krasitja është një temë e vjetër që është diskutuar në Leksione në Stanford në vitin 2017. Ideja kryesore është zvogëlimi i madhësisë së rrjetit të trajnuar pa humbur saktësinë duke hequr nyjet e ndryshme. Tingëllon bukur, por rrallë dëgjoj për përdorimin e tij. Ndoshta, nuk ka zbatime të mjaftueshme, nuk ka artikuj në gjuhën ruse, ose thjesht të gjithë e konsiderojnë atë si ekspertizë dhe heshtin.
Por le ta ndajmë atë

Një vështrim në biologji

Më pëlqen kur Deep Learning shikon idetë që vijnë nga biologjia. Atyre, si evolucioni, mund t'u besohet (a e dini se ReLU është shumë e ngjashme me funksioni i aktivizimit të neuroneve në tru?)

Procesi i krasitjes model është gjithashtu i afërt me biologjinë. Përgjigja e rrjetit këtu mund të krahasohet me plasticitetin e trurit. Ka disa shembuj interesantë në libër. Norman Doidge:

  1. Truri i një gruaje që ka lindur vetëm me një gjysmë, është riprogramuar për të kryer funksionet e gjysmës që mungon.
  2. Djali qëlloi pjesën e trurit të tij përgjegjëse për shikimin. Me kalimin e kohës, pjesë të tjera të trurit morën përsipër këto funksione. (nuk po përpiqemi të përsërisim)

Po kështu, ju mund të hiqni disa nga konvolucionet e dobëta nga modeli juaj. Si mjet i fundit, tufat e mbetura do të ndihmojnë në zëvendësimin e atyre të prera.

A ju pëlqen Transfer Learning apo po mësoni nga e para?

Opsioni numër një. Ju përdorni Transfer Learning në Yolov3. Retina, Mask-RCNN ose U-Net. Por shumicën e kohës ne nuk kemi nevojë të njohim 80 klasa objektesh si në COCO. Në praktikën time, gjithçka është e kufizuar në klasat 1-2. Mund të supozohet se arkitektura për 80 klasa është e tepërt këtu. Kjo sugjeron që arkitektura duhet të bëhet më e vogël. Për më tepër, unë do të doja ta bëja këtë pa humbur peshat ekzistuese të para-stërvitura.

Opsioni numër dy. Ndoshta keni shumë të dhëna dhe burime kompjuterike, ose thjesht keni nevojë për një arkitekturë super të personalizuar. Nuk ka rëndësi. Por ju po mësoni rrjetin nga e para. Procedura e zakonshme është të shikoni strukturën e të dhënave, të zgjidhni një arkitekturë me fuqi të tepërt dhe të shtyni braktisjen nga rikualifikimi. Pashë 0.6 braktisje, Karl.

Në të dyja rastet, rrjeti mund të reduktohet. I motivuar. Tani le të kuptojmë se çfarë lloj krasitjeje rrethprerjeje është

Algoritmi i përgjithshëm

Ne vendosëm që mund të hiqnim paketat. Duket mjaft e thjeshtë:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Heqja e çdo konvolucioni është stresuese për rrjetin, gjë që zakonisht çon në një rritje të gabimit. Nga njëra anë, kjo rritje e gabimit është një tregues se sa saktë i heqim konvolucionet (për shembull, një rritje e madhe tregon se po bëjmë diçka të gabuar). Por një rritje e vogël është mjaft e pranueshme dhe shpesh eliminohet nga trajnimi shtesë i lehtë pasues me një LR të vogël. Shtoni një hap shtesë trajnimi:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Tani duhet të kuptojmë se kur duam të ndalojmë ciklin tonë të të mësuarit<->Pruning. Mund të ketë opsione ekzotike këtu kur duhet të zvogëlojmë rrjetin në një madhësi dhe shpejtësi të caktuar (për shembull, për pajisjet celulare). Megjithatë, opsioni më i zakonshëm është të vazhdohet cikli derisa gabimi të bëhet më i lartë se i pranueshëm. Shtoni një kusht:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Pra, algoritmi bëhet i qartë. Mbetet për të kuptuar se si të përcaktohen konvolucionet e fshira.

Kërkoni për paketa të fshira

Duhet të heqim disa konvolucione. Të nxitosh përpara dhe "të qëllosh" këdo është një ide e keqe, megjithëse do të funksionojë. Por meqenëse keni një kokë, mund të mendoni dhe të përpiqeni të zgjidhni konvolucione "të dobëta" për heqje. Ka disa opsione:

  1. Krasitja më e vogël L1 ose me madhësi të ulët. Ideja që konvolucionet me pesha të vogla japin pak kontribut në vendimin përfundimtar
  2. L1-masa më e vogël duke marrë parasysh devijimin mesatar dhe standard. Ne plotësojmë me një vlerësim të natyrës së shpërndarjes.
  3. Maskimi i konvolucioneve dhe përjashtimi i atyre që ndikojnë më pak në saktësinë përfundimtare. Përcaktimi më i saktë i konvolucioneve të parëndësishme, por që kërkon shumë kohë dhe konsumon burime.
  4. Të tjerët

Secila prej opsioneve ka të drejtën e jetës dhe veçoritë e veta të zbatimit. Këtu shqyrtojmë opsionin me masën më të vogël L1

Procesi manual për YOLOv3

Arkitektura origjinale përmban blloqe të mbetura. Por sado të lezetshëm të jenë për rrjete të thella, do të na pengojnë disi. Vështirësia është se nuk mund të fshini rakordimet me indekse të ndryshme në këto shtresa:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Prandaj, le të zgjedhim shtresat nga të cilat mund të fshijmë lirisht rakordimet:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Tani le të ndërtojmë një cikël pune:

  1. Ngarkimi i aktivizimeve
  2. Duke kuptuar se sa për të prerë
  3. Prerë jashtë
  4. Mësimi i 10 epokave me LR=1e-4
  5. Duke testuar

Shkarkimi i konvolucioneve është i dobishëm për të vlerësuar se sa pjesë mund të heqim në një hap të caktuar. Shembuj të shkarkimit:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Ne shohim se pothuajse kudo 5% e konvolucioneve kanë një normë L1 shumë të ulët dhe ne mund t'i heqim ato. Në çdo hap, ky shkarkim përsëritej dhe bëhej një vlerësim se cilat shtresa dhe sa mund të priheshin.

I gjithë procesi u përfundua në 4 hapa (numrat këtu dhe kudo për RTX 2060 Super):

hap mAp75 Numri i parametrave, milion Madhësia e rrjetit, mb Nga fillimi, % Koha e ekzekutimit, ms Gjendja e synetisë
0 0.9656 60 241 100 180 -
1 0.9622 55 218 91 175 5% e të gjithëve
2 0.9625 50 197 83 168 5% e të gjithëve
3 0.9633 39 155 64 155 15% për shtresat me 400+ konvolucione
4 0.9555 31 124 51 146 10% për shtresat me 100+ konvolucione

Një efekt pozitiv iu shtua hapit 2 - madhësia e grupit 4 përshtatet në kujtesë, gjë që përshpejtoi shumë procesin e trajnimit shtesë.
Në hapin 4, procesi u ndërpre sepse edhe trajnimi shtesë afatgjatë nuk e ngriti mAp75 në vlerat e vjetra.
Si rezultat, ne arritëm të përshpejtonim përfundimin me 15%, zvogëloni madhësinë me 35% dhe të mos humbasë saktësisht.

Automatizimi për arkitektura më të thjeshta

Për arkitekturat më të thjeshta të rrjetit (pa blloqe shtesë të kushtëzuara, të lidhura dhe të mbetura), është mjaft e mundur të përqendroheni në përpunimin e të gjitha shtresave konvolucionale dhe të automatizoni procesin e prerjes së konvolucioneve.

Unë e zbatova këtë opsion këtu.
Është e thjeshtë: ju nevojitet vetëm një funksion humbjeje, një optimizues dhe gjeneratorë të grupeve:

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)

Nëse është e nevojshme, mund të ndryshoni parametrat e konfigurimit:

{
    "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
}

Për më tepër, zbatohet një kufizim i bazuar në devijimin standard. Qëllimi është të kufizohet pjesa që hiqet, duke përjashtuar konvolucionet me masa tashmë "të mjaftueshme" L1:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Kështu, ne ju lejojmë të hiqni vetëm konvolucione të dobëta nga shpërndarjet e ngjashme me atë të djathtën dhe të mos ndikoni në heqjen nga shpërndarjet e ngjashme me atë të majtë:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Kur shpërndarja i afrohet normales, koeficienti pruning_standart_deviation_part mund të zgjidhet nga:

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje
Unë rekomandoj një supozim prej 2 sigma. Ose mund ta shpërfillni këtë veçori, duke lënë vlerën < 1.0.

Dalja është një grafik i madhësisë së rrjetit, humbjes dhe kohës së funksionimit të rrjetit për të gjithë testin, i normalizuar në 1.0. Për shembull, këtu madhësia e rrjetit u zvogëlua pothuajse 2 herë pa humbje të cilësisë (rrjet i vogël konvolucional me 100k pesha):

Teknika Jedi për reduktimin e rrjeteve konvolucionale - krasitje

Shpejtësia e drejtimit është subjekt i luhatjeve normale dhe mbetet praktikisht e pandryshuar. Ka një shpjegim për këtë:

  1. Numri i konvolucioneve ndryshon nga i përshtatshëm (32, 64, 128) në jo më të përshtatshëm për kartat video - 27, 51, etj. Mund të jem i gabuar këtu, por ka shumë të ngjarë që ka një efekt.
  2. Arkitektura nuk është e gjerë, por konsistente. Duke ulur gjerësinë, ne nuk ndikojmë në thellësi. Kështu, ne zvogëlojmë ngarkesën, por nuk e ndryshojmë shpejtësinë.

Prandaj, përmirësimi u shpreh në një ulje të ngarkesës CUDA gjatë drejtimit me 20-30%, por jo në një ulje të kohës së funksionimit.

Rezultatet e

Le të reflektojmë. Ne shqyrtuam 2 opsione për krasitjen - për YOLOv3 (kur duhet të punoni me duart tuaja) dhe për rrjetet me arkitektura më të thjeshta. Mund të shihet se në të dyja rastet është e mundur të arrihet zvogëlimi dhe shpejtësia e madhësisë së rrjetit pa humbje të saktësisë. Rezultatet:

  • Reduktimi i madhësisë
  • Vrapimi i përshpejtimit
  • Reduktimi i ngarkesës CUDA
  • Si rezultat, mirëdashësi mjedisore (Ne optimizojmë përdorimin e ardhshëm të burimeve kompjuterike. Diku dikush është i lumtur Greta Thunberg)

Shtojcë

  • Pas hapit të krasitjes, mund të shtoni kuantizimin (për shembull, me TensorRT)
  • Tensorflow ofron aftësi për krasitje me madhësi të ulët. Punimet.
  • depo Unë dua të zhvillohem dhe do të jem i lumtur të ndihmoj

Burimi: www.habr.com

Shto një koment