Jedi-teknik til at reducere foldningsnetværk - beskæring

Jedi-teknik til at reducere foldningsnetværk - beskæring

Før du igen er opgaven med at opdage objekter. Prioriteten er driftshastighed med acceptabel nøjagtighed. Du tager YOLOv3-arkitekturen og træner den videre. Nøjagtighed (mAp75) er større end 0.95. Men løbsraten er stadig lav. Crap.

I dag vil vi omgå kvantisering. Og under snittet kigger vi Model beskæring — trimning af redundante dele af netværket for at fremskynde inferens uden tab af nøjagtighed. Det er tydeligt hvor, hvor meget og hvordan man skærer. Lad os finde ud af, hvordan du gør dette manuelt, og hvor du kan automatisere det. I slutningen er der et depot på keras.

Indledning

På mit tidligere arbejdssted, Macroscop i Perm, fik jeg én vane - altid at overvåge udførelsestiden for algoritmer. Og tjek altid netværkets køretid gennem et tilstrækkeligt filter. Normalt består state-of-the-art i produktionen ikke dette filter, hvilket førte mig til beskæring.

Beskæring er et gammelt emne, der blev diskuteret i Stanford foredrag i 2017. Hovedideen er at reducere størrelsen af ​​det trænede netværk uden at miste nøjagtigheden ved at fjerne forskellige noder. Det lyder fedt, men jeg hører sjældent om dets brug. Sandsynligvis er der ikke nok implementeringer, der er ingen russisksprogede artikler, eller bare alle betragter det som beskæring af knowhow og forbliver tavse.
Men lad os skille det ad

Et indblik i biologi

Jeg elsker det, når Deep Learning ser på ideer, der kommer fra biologi. De, ligesom evolution, kan man stole på (vidste du, at ReLU ligner meget funktion af neuronaktivering i hjernen?)

Modelbeskæringsprocessen er også tæt på biologi. Netværkets respons her kan sammenlignes med hjernens plasticitet. Der er et par interessante eksempler i bogen. Norman Doidge:

  1. Hjernen hos en kvinde, der blev født med kun den ene halvdel, har omprogrammeret sig selv til at udføre funktionerne i den manglende halvdel.
  2. Fyren skød den del af hans hjerne, der var ansvarlig for synet, af. Med tiden overtog andre dele af hjernen disse funktioner. (vi forsøger ikke at gentage)

Ligeledes kan du skære nogle af de svage viklinger ud fra din model. Som en sidste udvej vil de resterende bundter hjælpe med at erstatte de afskårne.

Elsker du Transfer Learning eller lærer du fra bunden?

Mulighed nummer et. Du bruger Transfer Learning på Yolov3. Retina, Mask-RCNN eller U-Net. Men det meste af tiden behøver vi ikke at genkende 80 objektklasser som i COCO. I min praksis er alt begrænset til 1-2 klassetrin. Man kan antage, at arkitekturen for 80 klasser er overflødig her. Det tyder på, at arkitekturen skal gøres mindre. Desuden vil jeg gerne gøre dette uden at miste de eksisterende fortrænede vægte.

Mulighed nummer to. Måske har du mange data- og computerressourcer, eller du har bare brug for en super-brugerdefineret arkitektur. Det betyder ikke noget. Men du lærer netværket fra bunden. Den sædvanlige procedure er at se på datastrukturen, vælge en arkitektur, der er OVERDRAGENDE i kraft, og skubbe frafald fra omskoling. Jeg så 0.6 frafald, Karl.

I begge tilfælde kan netværket reduceres. Motiveret. Lad os nu finde ud af, hvad slags omskæringsbeskæring er

Generel algoritme

Vi besluttede, at vi kunne fjerne bundterne. Det ser ret simpelt ud:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Fjernelse af enhver foldning er stressende for netværket, hvilket normalt fører til en vis stigning i fejl. På den ene side er denne stigning i fejl en indikator for, hvor korrekt vi fjerner foldninger (f.eks. indikerer en stor stigning, at vi gør noget forkert). Men en lille stigning er ganske acceptabel og elimineres ofte ved efterfølgende let ekstra træning med en lille LR. Tilføj et ekstra træningstrin:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Nu skal vi finde ud af, hvornår vi vil stoppe vores Learning<->Pruning loop. Der kan være eksotiske muligheder her, når vi skal reducere netværket til en vis størrelse og hastighed (for eksempel for mobile enheder). Den mest almindelige mulighed er dog at fortsætte cyklussen, indtil fejlen bliver højere end acceptabelt. Tilføj en betingelse:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Så algoritmen bliver klar. Det er tilbage at finde ud af, hvordan man bestemmer de slettede viklinger.

Søg efter slettede bundter

Vi er nødt til at fjerne nogle viklinger. At skynde sig frem og "skyde" nogen er en dårlig idé, selvom det vil virke. Men da du har et hoved, kan du tænke og prøve at vælge "svage" viklinger til fjernelse. Der er flere muligheder:

  1. Mindste L1-mål eller lav_magnitude_beskæring. Ideen om, at viklinger med små vægte ikke bidrager meget til den endelige beslutning
  2. Mindste L1-mål under hensyntagen til middelværdi og standardafvigelse. Vi supplerer med en vurdering af fordelingens karakter.
  3. Maskering af viklinger og udelukkelse af dem, der mindst påvirker den endelige nøjagtighed. Mere præcis bestemmelse af ubetydelige viklinger, men meget tidskrævende og ressourcekrævende.
  4. Andre

Hver af mulighederne har ret til liv og sine egne implementeringsfunktioner. Her overvejer vi muligheden med det mindste L1-mål

Manuel proces til YOLOv3

Den originale arkitektur indeholder restblokke. Men uanset hvor seje de er til dybe netværk, vil de hindre os noget. Vanskeligheden er, at du ikke kan slette afstemninger med forskellige indekser i disse lag:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Lad os derfor vælge lag, hvorfra vi frit kan slette afstemninger:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Lad os nu bygge en arbejdscyklus:

  1. Uploader aktiveringer
  2. At finde ud af, hvor meget der skal skæres
  3. Lad være med det
  4. Læring 10 epoker med LR=1e-4
  5. Afprøvning

Aflæsning af foldninger er nyttigt til at vurdere, hvor meget del vi kan fjerne på et bestemt trin. Eksempler på aflæsning:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Vi ser, at næsten overalt 5% af viklingerne har en meget lav L1-norm, og vi kan fjerne dem. Ved hvert trin blev denne aflæsning gentaget, og der blev foretaget en vurdering af, hvilke lag og hvor mange der kunne skæres ud.

Hele processen blev gennemført i 4 trin (numre her og overalt for RTX 2060 Super):

trin mAp75 Antal parametre, mio Netværksstørrelse, mb Fra initial, % Køretid, frk Omskæringstilstand
0 0.9656 60 241 100 180
1 0.9622 55 218 91 175 5% af alle
2 0.9625 50 197 83 168 5% af alle
3 0.9633 39 155 64 155 15 % for lag med 400+ viklinger
4 0.9555 31 124 51 146 10 % for lag med 100+ viklinger

En positiv effekt blev tilføjet til trin 2 - batchstørrelse 4 passer ind i hukommelsen, hvilket i høj grad fremskyndede processen med yderligere træning.
Ved trin 4 blev processen stoppet pga selv langvarig ekstra træning hævede ikke mAp75 til gamle værdier.
Som et resultat formåede vi at fremskynde slutningen med 15 %, reducer størrelsen med 35 % og ikke tabe præcist.

Automatisering til enklere arkitekturer

For simplere netværksarkitekturer (uden betinget tilføjelse, sammenkædede og resterende blokke) er det ganske muligt at fokusere på at behandle alle foldningslag og automatisere processen med at skære foldninger ud.

Jeg implementerede denne mulighed her.
Det er enkelt: du behøver kun en tabsfunktion, en optimering og batchgeneratorer:

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)

Om nødvendigt kan du ændre konfigurationsparametrene:

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

Derudover implementeres en begrænsning baseret på standardafvigelsen. Målet er at begrænse den del, der fjernes, undtagen foldninger med allerede "tilstrækkelige" L1-mål:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Derfor tillader vi dig kun at fjerne svage foldninger fra distributioner, der ligner den højre, og ikke påvirke fjernelsen fra distributioner, der ligner den venstre:

Jedi-teknik til at reducere foldningsnetværk - beskæring

Når fordelingen nærmer sig normal, kan pruning_standart_deviation_part-koefficienten vælges fra:

Jedi-teknik til at reducere foldningsnetværk - beskæring
Jeg anbefaler en antagelse om 2 sigma. Eller du kan ignorere denne funktion og lade værdien være < 1.0.

Outputtet er en graf over netværksstørrelse, tab og netværkskørselstid for hele testen, normaliseret til 1.0. For eksempel, her blev netværksstørrelsen reduceret med næsten 2 gange uden tab af kvalitet (lille foldet netværk med 100k vægte):

Jedi-teknik til at reducere foldningsnetværk - beskæring

Kørehastigheden er underlagt normale udsving og forbliver stort set uændret. Der er en forklaring på dette:

  1. Antallet af foldninger ændres fra praktisk (32, 64, 128) til ikke det mest bekvemme for videokort - 27, 51 osv. Jeg kan tage fejl her, men højst sandsynligt har det en effekt.
  2. Arkitekturen er ikke bred, men konsekvent. Ved at reducere bredden påvirker vi ikke dybden. Dermed reducerer vi belastningen, men ændrer ikke hastigheden.

Derfor kom forbedringen til udtryk i en reduktion i CUDA-belastningen under kørslen med 20-30 %, men ikke i en reduktion af køretiden

Resultaterne af

Lad os reflektere. Vi overvejede 2 muligheder for beskæring - til YOLOv3 (når du skal arbejde med hænderne) og til netværk med enklere arkitekturer. Det kan ses, at det i begge tilfælde er muligt at opnå netværksstørrelsesreduktion og fremskyndelse uden tab af nøjagtighed. Resultater:

  • Reduktion af størrelsen
  • Accelerationsløb
  • Reduktion af CUDA-belastning
  • Som et resultat, miljøvenlighed (Vi optimerer den fremtidige brug af computerressourcer. Et eller andet sted er man glad Greta Thunberg)

Tillæg

  • Efter beskæringstrinnet kan du tilføje kvantisering (for eksempel med TensorRT)
  • Tensorflow giver muligheder for lav_magnitude_beskæring. Arbejder.
  • depot Jeg vil gerne udvikle mig og hjælper gerne

Kilde: www.habr.com

Tilføj en kommentar