Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Antaŭ vi denove estas la tasko detekti objektojn. La prioritato estas rapideco de operacio kun akceptebla precizeco. Vi prenas la arkitekturon YOLOv3 kaj plu trejnas ĝin. Precizeco (mAp75) estas pli granda ol 0.95. Sed la kurofteco estas ankoraŭ malalta. Crap.

Hodiaŭ ni preteriros kvantigon. Kaj sub la tranĉo ni rigardos Modelo Pritondado — tondado de redundaj partoj de la reto por akceli Inferencon sen perdo de precizeco. Estas klare kie, kiom kaj kiel tranĉi. Ni eltrovu kiel fari tion permane kaj kie vi povas aŭtomatigi ĝin. Fine estas deponejo pri keras.

Enkonduko

Ĉe mia antaŭa laborloko, Macroscop en Perm, mi akiris unu kutimon - ĉiam kontroli la ekzekuttempon de algoritmoj. Kaj ĉiam kontrolu la retan rultempon per taŭgeca filtrilo. Kutime pintnivela en produktado ne pasas ĉi tiun filtrilon, kiu kondukis min al Tondado.

Pritondado estas malnova temo pri kiu oni diskutis Stanfordaj prelegoj en 2017. La ĉefa ideo estas redukti la grandecon de la trejnita reto sen perdi precizecon forigante diversajn nodojn. Ĝi sonas mojosa, sed mi malofte aŭdas pri ĝia uzo. Verŝajne, ne estas sufiĉe da efektivigoj, mankas ruslingvaj artikoloj, aŭ simple ĉiuj konsideras ĝin pritondi scipovon kaj silentas.
Sed ni disigu ĝin

Ekrigardo en biologion

Mi amas ĝin kiam Deep Learning rigardas ideojn kiuj venas de biologio. Ili, kiel evolucio, estas fidindaj (ĉu vi sciis, ke ReLU tre similas al funkcio de neŭrona aktivigo en la cerbo?)

La Modela Pruning-procezo ankaŭ estas proksima al biologio. La respondo de la reto ĉi tie povas esti komparita kun la plastikeco de la cerbo. Estas kelkaj interesaj ekzemploj en la libro. Norman Doidge:

  1. La cerbo de virino, kiu naskiĝis kun nur unu duono, reprogramis sin por plenumi la funkciojn de la mankanta duono.
  2. La ulo pafis la parton de sia cerbo respondeca por vizio. Kun la tempo, aliaj partoj de la cerbo transprenis ĉi tiujn funkciojn. (ni ne provas ripeti)

Same, vi povas eltranĉi kelkajn el la malfortaj cirkloj el via modelo. Kiel lasta rimedo, la ceteraj pakaĵoj helpos anstataŭigi la tranĉitajn.

Ĉu vi amas Transfer Learning aŭ ĉu vi lernas de nulo?

Opcio numero unu. Vi uzas Transfer Learning sur Yolov3. Retino, Mask-RCNN aŭ U-Net. Sed plejofte ni ne bezonas rekoni 80 objektoklasojn kiel en COCO. En mia praktiko, ĉio estas limigita al klasoj 1-2. Oni povus supozi, ke la arkitekturo por 80 klasoj estas superflua ĉi tie. Ĉi tio sugestas, ke la arkitekturo devas fariĝi pli malgranda. Plie, mi ŝatus fari ĉi tion sen perdi la ekzistantajn antaŭtrejnitajn pezojn.

Opcio numero du. Eble vi havas multajn datumojn kaj komputikajn rimedojn, aŭ nur bezonas superpersonan arkitekturon. Ne gravas. Sed vi lernas la reton de nulo. La kutima proceduro estas rigardi la datumstrukturon, elekti arkitekturon kiu estas TROA en potenco, kaj puŝi ĉesulojn de retrejnado. Mi vidis 0.6 ĉesintojn, Karl.

En ambaŭ kazoj, la reto povas esti reduktita. Motivigita. Nun ni iru eltrovi kia cirkumcida pritondado estas

Ĝenerala algoritmo

Ni decidis, ke ni povus forigi la pakaĵojn. Ĝi aspektas sufiĉe simpla:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Forigi ajnan konvolucion estas streĉa por la reto, kiu kutime kondukas al ioma pliiĝo de eraro. Unuflanke, ĉi tiu pliigo de eraro estas indikilo de kiom ĝuste ni forigas cirklaciojn (ekzemple, granda pliiĝo indikas, ke ni faras ion malbone). Sed malgranda pliiĝo estas sufiĉe akceptebla kaj ofte estas forigita per posta malpeza kroma trejnado kun malgranda LR. Aldonu plian trejnan paŝon:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Nun ni devas eltrovi kiam ni volas ĉesigi nian Lernadon<->Eltondan buklon. Eble ekzistas ekzotikaj opcioj ĉi tie kiam ni bezonas redukti la reton al certa grandeco kaj rapideco (ekzemple, por porteblaj aparatoj). Tamen, la plej ofta opcio estas daŭrigi la ciklon ĝis la eraro iĝas pli alta ol akceptebla. Aldonu kondiĉon:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Do, la algoritmo iĝas klara. Restas eltrovi kiel determini la forigitajn cirkvitojn.

Serĉu forigitajn pakaĵojn

Ni devas forigi iujn cirkvitojn. Rapidi antaŭen kaj "pafi" iun ajn estas malbona ideo, kvankam ĝi funkcios. Sed ĉar vi havas kapon, vi povas pensi kaj provi elekti "malfortajn" cirkvitojn por forigo. Estas pluraj ebloj:

  1. Plej malgranda L1-mezuro aŭ malalt_granda_tondado. La ideo, ke cirkvitoj kun malgrandaj pezoj faras malmulte da kontribuo al la fina decido
  2. Plej malgranda L1-mezuro konsiderante mezan kaj norman devion. Ni kompletigas per takso de la naturo de la distribuo.
  3. Maskante cirkvitojn kaj ekskludante tiujn, kiuj malplej influas la finan precizecon. Pli preciza determino de sensignifaj cirkloj, sed tre temporaba kaj rimedo-konsumanta.
  4. Aliaj

Ĉiu el la opcioj havas la rajton al vivo kaj siajn proprajn efektivigajn funkciojn. Ĉi tie ni konsideras la opcion kun la plej malgranda L1-mezuro

Mana procezo por YOLOv3

La origina arkitekturo enhavas restajn blokojn. Sed kiom ajn bonegaj ili estas por profundaj retoj, ili iom malhelpos nin. La malfacilaĵo estas, ke vi ne povas forigi repaciĝon kun malsamaj indeksoj en ĉi tiuj tavoloj:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Sekve, ni elektu tavolojn el kiuj ni povas libere forigi repaciĝon:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Nun ni konstruu laborciklon:

  1. Alŝutante aktivigojn
  2. Eltrovi kiom tranĉi
  3. Eltranĉu ĝin
  4. Lernado de 10 epokoj kun LR=1e-4
  5. Testado

Malŝarĝo de cirkloj estas utila por taksi kiom da parto ni povas forigi je certa paŝo. Malŝarĝaj ekzemploj:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Ni vidas, ke preskaŭ ĉie 5% de konvolucioj havas tre malaltan L1-normon kaj ni povas forigi ilin. Je ĉiu paŝo, ĉi tiu malŝarĝo estis ripetita kaj oni taksis kiuj tavoloj kaj kiom oni povus eltranĉi.

La tuta procezo estis kompletigita en 4 paŝoj (nombroj ĉi tie kaj ĉie por la RTX 2060 Super):

Paŝo mapo75 Nombro de parametroj, miliono Reta grandeco, mb De komenca, % Runtempo, ms Kondiĉo de cirkumcido
0 0.9656 60 241 100 180 -
1 0.9622 55 218 91 175 5% de ĉiuj
2 0.9625 50 197 83 168 5% de ĉiuj
3 0.9633 39 155 64 155 15% por tavoloj kun pli ol 400 cirkvitoj
4 0.9555 31 124 51 146 10% por tavoloj kun pli ol 100 cirkvitoj

Unu pozitiva efiko estis aldonita al paŝo 2 - aro grandeco 4 taŭgas en memoro, kiu multe akcelis la procezon de plia trejnado.
Je paŝo 4, la procezo estis ĉesigita ĉar eĉ longdaŭra plia trejnado ne altigis mAp75 al malnovaj valoroj.
Kiel rezulto, ni sukcesis akceli la inferencon per 15%, redukti la grandecon per 35% kaj ne perdi precize.

Aŭtomatigo por pli simplaj arkitekturoj

Por pli simplaj retaj arkitekturoj (sen kondiĉaj aldonaj, kunigitaj kaj restaj blokoj), estas tute eble koncentriĝi pri prilaborado de ĉiuj konvoluciaj tavoloj kaj aŭtomatigi la procezon de eltranĉado de konvolucioj.

Mi efektivigis ĉi tiun opcion tie.
Ĝi estas simpla: vi bezonas nur perdan funkcion, optimumigilon kaj batajn generatorojn:

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)

Se necese, vi povas ŝanĝi la agordajn parametrojn:

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

Aldone, limigo bazita sur la norma devio estas efektivigita. La celo estas limigi la forigitan parton, ekskludante cirkonfluojn kun jam "sufiĉaj" L1-mezuroj:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Tiel, ni permesas al vi forigi nur malfortajn konvoluciojn de distribuoj similaj al la dekstra kaj ne influi la forigon de distribuoj similaj al la maldekstra:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

Kiam la distribuo proksimiĝas al normalo, la koeficiento pruning_standart_deviation_part povas esti elektita el:

Jedi-tekniko por redukti konvoluciajn retojn - pritondado
Mi rekomendas supozon de 2 sigma. Aŭ vi povas ignori ĉi tiun funkcion, lasante la valoron < 1.0.

La eligo estas grafeo de retgrandeco, perdo kaj retrultempo por la tuta testo, normaligita al 1.0. Ekzemple, ĉi tie la retograndeco estis reduktita preskaŭ 2 fojojn sen perdo de kvalito (malgranda konvolucia reto kun 100k pezoj):

Jedi-tekniko por redukti konvoluciajn retojn - pritondado

La kura rapideco estas kondiĉigita de normalaj fluktuoj kaj restas preskaŭ senŝanĝa. Estas klarigo por ĉi tio:

  1. La nombro da konvolucioj ŝanĝiĝas de oportuna (32, 64, 128) al ne la plej oportuna por vidkartoj - 27, 51, ktp. Mi povus erari ĉi tie, sed plej verŝajne ĝi efikas.
  2. La arkitekturo ne estas larĝa, sed konsekvenca. Reduktante la larĝon, ni ne influas la profundon. Tiel, ni reduktas la ŝarĝon, sed ne ŝanĝas la rapidon.

Sekve, la plibonigo estis esprimita en redukto de la CUDA-ŝarĝo dum la kuro je 20-30%, sed ne en redukto de la rultempo.

Rezultoj

Ni pripensu. Ni pripensis 2 eblojn por pritondado - por YOLOv3 (kiam vi devas labori per viaj manoj) kaj por retoj kun pli simplaj arkitekturoj. Videblas, ke en ambaŭ kazoj eblas atingi retan grandeco-redukton kaj plirapidigon sen perdo de precizeco. Rezulto:

  • Reduktante la grandecon
  • Akcela kurado
  • Reduktante CUDA-Ŝarĝon
  • Rezulte, media amikeco (Ni optimumigas la estontan uzon de komputikaj rimedoj. Ie oni estas feliĉa Greta Thunberg)

apendico

  • Post la tonda paŝo, vi povas aldoni kvantigon (ekzemple kun TensorRT)
  • Tensorflow provizas kapablojn por malalt_granda_tondado. Verkoj.
  • deponejo Mi volas disvolviĝi kaj volonte helpos

fonto: www.habr.com

Aldoni komenton