Ennen sinua taas on tehtävä havaita esineitä. Etusija on toiminnan nopeus hyväksyttävällä tarkkuudella. Otat YOLOv3-arkkitehtuurin ja harjoitat sitä edelleen. Tarkkuus (mAp75) on suurempi kuin 0.95. Mutta juoksunopeus on edelleen alhainen. Paska.
Tänään ohitamme kvantisoinnin. Ja leikkauksen alta katsomme Mallin karsiminen — verkon redundanttien osien leikkaaminen päättelyn nopeuttamiseksi tarkkuuden menettämättä. On selvää, missä, kuinka paljon ja miten leikataan. Selvitetään, kuinka tämä tehdään manuaalisesti ja missä voit automatisoida sen. Lopussa on arkisto kerasissa.
Esittely
Edellisessä työpaikassani, Macroscopissa Permissä, sain yhden tavan - seurata aina algoritmien suoritusaikaa. Ja tarkista aina verkon suoritusaika riittävyyssuodattimen kautta. Yleensä tuotannon uusimmat tekniikat eivät läpäise tätä suodatinta, mikä johti minut karsimiseen.
Leikkaaminen on vanha aihe, josta keskusteltiin Stanfordin luentoja vuonna 2017. Pääideana on pienentää koulutetun verkon kokoa tarkkuutta menettämättä poistamalla erilaisia solmuja. Kuulostaa hyvältä, mutta sen käytöstä kuulen harvoin. Todennäköisesti toteutuksia ei ole tarpeeksi, venäjänkielisiä artikkeleita ei ole tai yksinkertaisesti kaikki pitävät sitä tietotaidon karsimisena ja vaikenevat.
Mutta erotetaan se
Katsaus biologiaan
Rakastan sitä, kun Deep Learning tarkastelee ideoita, jotka tulevat biologiasta. Niihin, kuten evoluutioon, voidaan luottaa ( tiesitkö, että ReLU on hyvin samanlainen kuin neuronien aktivointitoiminto aivoissa?)
Mallin karsiminen on myös lähellä biologiaa. Verkoston vastetta tässä voidaan verrata aivojen plastisuuteen. Kirjassa on pari mielenkiintoista esimerkkiä. Norman Doidge:
Ainoastaan puolikkaan kanssa syntyneen naisen aivot ovat ohjelmoineet itsensä uudelleen suorittamaan puuttuvan puolikkaan toiminnot.
Kaveri ampui irti näöstä vastaavan osan aivoistaan. Ajan myötä muut aivojen osat ottivat nämä toiminnot haltuunsa. (emme yritä toistaa)
Samoin voit leikata joitakin heikkoja konvoluutioita mallistasi. Viimeisenä keinona jäljellä olevat niput auttavat korvaamaan leikatut niput.
Pidätkö Transfer Learningistä vai opitko tyhjästä?
Vaihtoehto numero yksi. Käytät Transfer Learning -ohjelmaa Yolov3:ssa. Retina, Mask-RCNN tai U-Net. Mutta useimmiten meidän ei tarvitse tunnistaa 80 objektiluokkaa, kuten COCO:ssa. Käytännössäni kaikki rajoittuu luokkiin 1-2. Voidaan olettaa, että 80 luokan arkkitehtuuri on tässä tarpeeton. Tämä viittaa siihen, että arkkitehtuuria on pienennettävä. Lisäksi haluaisin tehdä tämän menettämättä olemassa olevia esikoulutettuja painoja.
Vaihtoehto numero kaksi. Ehkä sinulla on paljon dataa ja laskentaresursseja tai tarvitset vain supermukautetun arkkitehtuurin. Ei väliä. Mutta opit verkkoa tyhjästä. Tavanomainen menettelytapa on tarkastella tietorakennetta, valita arkkitehtuuri, jonka teho on LIIKAA, ja ajaa keskeyttäneitä uudelleenkoulutuksesta. Näin 0.6 pudonnutta, Karl.
Molemmissa tapauksissa verkkoa voidaan pienentää. Motivoitunut. Nyt selvitetään, millainen ympärileikkausleikkaus on
Yleinen algoritmi
Päätimme, että voimme poistaa niput. Se näyttää melko yksinkertaiselta:
Konvoluution poistaminen on stressaavaa verkolle, mikä yleensä johtaa jonkin verran virheiden lisääntymiseen. Toisaalta tämä virhemäärän kasvu on osoitus siitä, kuinka oikein poistamme konvoluutioita (esimerkiksi suuri kasvu osoittaa, että teemme jotain väärin). Mutta pieni lisäys on melko hyväksyttävää, ja se eliminoituu usein seuraavalla kevyellä lisäharjoittelulla pienellä LR: llä. Lisää ylimääräinen koulutusvaihe:
Nyt meidän on selvitettävä, milloin haluamme lopettaa Learning<->Pruning-silmukamme. Tässä voi olla eksoottisia vaihtoehtoja, kun meidän on pienennettävä verkko tiettyyn kokoon ja nopeuteen (esimerkiksi mobiililaitteille). Yleisin vaihtoehto on kuitenkin jatkaa sykliä, kunnes virhe on hyväksyttävää suurempi. Lisää ehto:
Joten algoritmi tulee selväksi. On vielä selvitettävä, kuinka poistetut konvoluutit määritetään.
Etsi poistetut paketit
Meidän on poistettava joitain käänteitä. Kiirehtiminen eteenpäin ja kenenkään "ammuminen" on huono idea, vaikka se toimii. Mutta koska sinulla on pää, voit ajatella ja yrittää valita "heikkoja" käänteitä poistettavaksi. Vaihtoehtoja on useita:
Jokaisella vaihtoehdolla on oikeus elämään ja omat toteutuspiirteensä. Tässä tarkastellaan vaihtoehtoa pienimmällä L1-mitalla
Manuaalinen prosessi YOLOv3:lle
Alkuperäinen arkkitehtuuri sisältää jäännöslohkoja. Mutta riippumatta siitä, kuinka siistejä ne ovat syvälle verkoille, ne haittaavat meitä jonkin verran. Vaikeus on, että et voi poistaa täsmäytyksiä eri indekseillä näissä kerroksissa:
Siksi valitaan tasot, joista voimme vapaasti poistaa täsmäytykset:
Rakennetaan nyt työsykli:
Aktivointeja ladataan
Mieti kuinka paljon leikataan
Leikkaa pois
10 aikakauden oppiminen LR=1e-4
Testaus
Konvoluutioiden purkaminen on hyödyllistä arvioitaessa, kuinka paljon osaa voimme poistaa tietyssä vaiheessa. Esimerkkejä purkamisesta:
Näemme, että lähes kaikkialla 5 %:lla konvoluutioista on erittäin alhainen L1-normi ja voimme poistaa ne. Jokaisessa vaiheessa tämä purkaminen toistettiin ja arvioitiin, mitkä kerrokset ja kuinka monta voidaan leikata.
Koko prosessi suoritettiin 4 vaiheessa (numerot täällä ja kaikkialla RTX 2060 Superille):
vaihe
mAp75
Parametrien lukumäärä, milj
Verkon koko, mb
Alkuperäisestä, %
Ajoaika, ms
Ympärileikkaustila
0
0.9656
60
241
100
180
-
1
0.9622
55
218
91
175
5% kaikista
2
0.9625
50
197
83
168
5% kaikista
3
0.9633
39
155
64
155
15 % tasoille, joissa on yli 400 konvoluutiota
4
0.9555
31
124
51
146
10 % tasoille, joissa on yli 100 konvoluutiota
Vaiheeseen 2 lisättiin yksi positiivinen vaikutus - eräkoko 4 mahtui muistiin, mikä nopeutti huomattavasti lisäkoulutusprosessia.
Vaiheessa 4 prosessi pysäytettiin, koska edes pitkäaikainen lisäharjoittelu ei nostanut mAp75:tä vanhoihin arvoihin.
Tuloksena onnistuimme nopeuttamaan päättelyä 15%, pienennä kokoa 35% eikä häviä täsmälleen.
Automaatio yksinkertaisempiin arkkitehtuureihin
Yksinkertaisemmissa verkkoarkkitehtuureissa (ilman ehdollisia lisäyksiä, ketjutettuja ja jäännöslohkoja) on täysin mahdollista keskittyä kaikkien konvoluutiokerrosten käsittelyyn ja automatisoida konvoluutioiden leikkaaminen.
Otin tämän vaihtoehdon käyttöön täällä.
Se on yksinkertaista: tarvitset vain häviötoiminnon, optimoijan ja erägeneraattoreita:
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)
Tarvittaessa voit muuttaa konfigurointiparametreja:
{
"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
}
Lisäksi toteutetaan standardipoikkeamaan perustuva rajoitus. Tavoitteena on rajoittaa poistettavaa osaa, poissulkemalla konvoluutioita jo "riittävillä" L1-mitoilla:
Näin ollen sallimme sinun poistaa vain heikkoja konvoluutioita oikean jakauman kaltaisista jakaumista, emmekä vaikuta poistamiseen vasemmanpuoleista jakaumista:
Kun jakauma lähestyy normaalia, pruning_standart_deviation_part-kerroin voidaan valita seuraavista:
Suosittelen 2 sigman oletusta. Tai voit jättää tämän ominaisuuden huomioimatta jättäen arvon < 1.0.
Tulos on kaavio verkon koosta, häviöstä ja verkon käyttöajasta koko testille, normalisoituna arvoon 1.0. Esimerkiksi tässä verkon koko pieneni lähes 2 kertaa ilman laadun heikkenemistä (pieni konvoluutioverkko 100 XNUMX painolla):
Ajonopeus on alttiina normaaleille vaihteluille ja pysyy käytännössä ennallaan. Tälle on selitys:
Konvoluutioiden määrä muuttuu kätevästä (32, 64, 128) ei-kätevimpään näytönohjaimelle - 27, 51 jne. Voin olla väärässä, mutta todennäköisesti sillä on vaikutusta.
Arkkitehtuuri ei ole laaja, mutta johdonmukainen. Leveyttä pienentämällä emme vaikuta syvyyteen. Näin ollen vähennämme kuormaa, mutta emme muuta nopeutta.
Siksi parannus ilmaistui CUDA-kuorman pienentymisenä ajon aikana 20-30 %, mutta ei ajoajan lyhentymisenä.
Tulokset
Pohditaan. Harkitsemme kahta vaihtoehtoa karsimiseen - YOLOv2:lle (kun joudut työskentelemään käsin) ja verkoille, joilla on yksinkertaisempi arkkitehtuuri. Voidaan nähdä, että molemmissa tapauksissa on mahdollista saavuttaa verkon koon pienentäminen ja nopeuttaminen ilman tarkkuuden menetystä. Tulokset:
Kokoa pienennetään
Kiihdytysajo
CUDA-kuormituksen vähentäminen
Tuloksena ympäristöystävällisyys (Optimoimme laskentaresurssien käytön tulevaisuudessa. Jossain on onnellinen Greta Thunberg)
Liite
Karsimisen jälkeen voit lisätä kvantisoinnin (esimerkiksi TensorRT:llä)