
Bolestivé je to iba prvýkrát!
Ahojte všetci! Drahí priatelia, v tomto článku sa chcem podeliť so svojimi skúsenosťami s používaním TensorRT, RetinaNet na základe repozitára (toto je fork oficiálneho repozitára od , ktorý umožní začať používať optimalizované modely v produkčnom prostredí v čo najkratšom čase). Prechádzajúc správami v komunitných kanáloch , sa stretávam s otázkami ohľadom používania TensorRT a väčšinou sa otázky opakujú, preto som sa rozhodol napísať čo najúplnejší návod na používanie rýchlej inferencie založenej na TensorRT, RetinaNet, Unet a dockeri.
Opis úlohy
Navrhujem nastaviť úlohu takto: potrebujeme anotovať dataset, natrénovať na ňom sieť RetinaNet/Unet na Pytorch1.3+, previesť získané váhy do ONNX, potom ich skonvertovať do TensorRT engine a všetko spustiť v dockeri, ideálne na Ubuntu 18 a veľmi žiadúce na ARM(Jetson)* architektúre, čím minimalizujeme manuálne nasadenie prostredia. Nakoniec získame kontajner pripravený nielen na export a školenie RetinaNet/Unet, ale aj na plnohodnotný vývoj a školenie klasifikácie a segmentácie so všetkým potrebným zázemím.
Fáza 1. Príprava prostredia
Je dôležité si všimnúť, že v poslednej dobe som úplne prešiel na nepoužívanie a nasadzovanie akýchkoľvek knižníc na desktopovom stroji, rovnako ako aj na devboxe. Jediné, čo musím vytvoriť a nainštalovať — je python virtuálne prostredie a cuda 10.2 (možno sa obmedziť na jeden ovládač nvidia) z deb.
Predpokladajme, že máte čerstvo nainštalované Ubuntu 18. Nainštalujeme cuda 10.2 (deb), podrobnosti o procese inštalácie nebudem rozoberať, oficiálna dokumentácia je úplne dostatočná.
Teraz nainštalujeme docker, návod na inštaláciu dockera sa dá ľahko nájsť, tu je príklad , už je dostupná verzia 19+ — nainštalujeme ju. A nezabudnite umožniť používanie dockera bez sudo, takto to bude pohodlnejšie. Po úspešnej inštalácii to urobíme takto:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
A nemusíte ani nahliadať do oficiálneho repozitára .
Teraz urobíme git clone .
Zostáva už len málo, aby ste mohli začať používať docker s nvidia obrazom. Budeme sa musieť zaregistrovať v NGC Cloud a prihlásiť sa. Prejdite sem , zaregistrujeme sa a potom, čo sa dostaneme dovnútra NGC Cloud, klikneme na SETUP v ľavom hornom rohu obrazovky alebo prejdeme na tento odkaz . Kliknite na "vygenerovať kľúč". Odporúčam ho uložiť, inak ho pri ďalšej návšteve budete musieť generovať znova a, samozrejme, pri nasadzovaní na novom zariadení tento proces zopakovať.
Vykonáme:
docker login nvcr.io
Username: $oauthtoken
Password: - vygenerovaný kľúč
Username jednoducho skopírujeme. Tak, a máme hotové prostredie!
Krok 2. Sestavenie docker kontajnera
V druhom kroku našej práce zostavíme docker a oboznámime sa s jeho vnútornosťami.
Prejdeme do koreňového priečinka projektu retina-examples a vykonáme
docker build --build-arg USER=$USER --build-arg UID=$UID --build-arg GID=$GID --build-arg PW=alex -t retinanet:latest retinanet/
Zostavujeme docker s prenosom aktuálneho používateľa — to je veľmi užitočné, ak plánujete niečo písať na pripojenom VOLUME s právami aktuálneho používateľa, inak to bude root a problém.
Kým sa docker zostavuje, poďme preskúmať Dockerfile:
FROM nvcr.io/nvidia/pytorch:19.10-py3
ARG USER=alex
ARG UID=1000
ARG GID=1000
ARG PW=alex
RUN useradd -m ${USER} --uid=${UID} && echo "${USER}:${PW}" | chpasswd
RUN apt-get -y update && apt-get -y upgrade && apt-get -y install curl && apt-get -y install wget && apt-get -y install git && apt-get -y install automake && apt-get install -y sudo && adduser ${USER} sudo
RUN pip install git+https://github.com/bonlime/pytorch-tools.git@master
COPY . retinanet/
RUN pip install --no-cache-dir -e retinanet/
RUN pip install /workspace/retinanet/extras/tensorrt-6.0.1.5-cp36-none-linux_x86_64.whl
RUN pip install tensorboardx
RUN pip install albumentations
RUN pip install setproctitle
RUN pip install paramiko
RUN pip install flask
RUN pip install mem_top
RUN pip install arrow
RUN pip install pycuda
RUN pip install torchvision
RUN pip install pretrainedmodels
RUN pip install efficientnet-pytorch
RUN pip install git+https://github.com/qubvel/segmentation_models.pytorch
RUN pip install pytorch_toolbelt
RUN chown -R ${USER}:${USER} retinanet/
RUN cd /workspace/retinanet/extras/cppapi && mkdir build && cd build && cmake -DCMAKE_CUDA_FLAGS="--expt-extended-lambda -std=c++14" .. && make && cd /workspace
RUN apt-get install -y openssh-server && apt install -y tmux && apt-get -y install bison flex && apt-cache search pcre && apt-get -y install net-tools && apt-get -y install nmap
RUN apt-get -y install libpcre3 libpcre3-dev && apt-get -y install iputils-ping
RUN mkdir /var/run/sshd
RUN echo 'root:pass' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed 's@sessions*requireds*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
CMD ["/usr/sbin/sshd", "-D"]
Ako vidno z textu, vezmeme všetky naše obľúbené knižnice, skompilujeme retinanet, pridáme základné nástroje pre pohodlnú prácu s Ubuntu a nastavíme server openssh. Prvá veta sa zaoberá dedičstvom obrazu nvidia, pre ktorý sme sa prihlasovali do NGC Cloud a ktorý obsahuje Pytorch1.3, TensorRT6.x.x.x a množstvo ďalších knižníc, ktoré umožňujú skompilovať cpp zdrojové súbory nášho detektora.
Fáza 3. Spustenie a ladenie docker kontajnera
Prejdeme k hlavnému prípadu použitia kontajnera a vývojového prostredia, najprv spustíme nvidia docker. Vykonáme:
docker run --gpus all --net=host -v /home/:/workspace/mounted_vol -d -P --rm --ipc=host -it retinanet:latestTeraz je kontajner dostupný cez ssh @localhost. Po úspešnom spustení otvoríme projekt v PyCharme. Následne otvoríme
Nastavenia->Interpret Projekti->Pridať->Ssh Interpreter Krok 1

Krok 2

Krok 3

Vyberieme všetko ako na snímkach obrazovky,
Interpret -> /opt/conda/bin/python— to bude ln na Python3.6 a
Sync folder -> /workspace/retinanetKlikneme na dokončiť, čakáme na indexovanie a všetko, prostredie je pripravené na použitie!
DÔLEŽITÉ!!! Ihneď po indexovaní vytiahnuť zo docker skompilované súbory pre Retinanet. V kontextovom menu v koreňovom projekte vyberieme položku
Nasadenie->StiahnuťObjaví sa jeden súbor a dve zložky build, retinanet.egg-info a _C.so

Ak váš projekt vyzerá takto, prostredie vidí všetky potrebné súbory a sme pripravení na výcvik RetinaNet.
Krok 4. Označujeme dáta a trénujeme detektor
Na označovanie väčšinou používam — príjemný a užívateľsky prívetivý nástroj, naposledy opravili množstvo chýb a stal sa podstatne stabilnejším.
Predpokladajme, že ste označili dataset a stiahli ho, ale ihneď ho vložiť do nášho RetinaNet nebude možné, pretože je vo vlastnom formáte a na to je potrebné ho konvertovať na COCO. Nástroj na konverziu sa nachádza v:
markup_utils/supervisly_to_coco.pyVšimnite si, že Category v skripte je príklad a je potrebné vložiť svoje (kategorii background pridávať netreba)
categories = [{'id': 1, 'name': '1'},
{'id': 2, 'name': '2'},
{'id': 3, 'name': '3'},
{'id': 4, 'name': '4'}] Autori originálneho repozitára akosi usúdili, že okrem COCO/VOC nebudete trénovať nič na detekciu, takže bolo potrebné trochu upraviť pôvodný súbor
retinanet/dataset.pyPridali tu vaše obľúbené augmentácie a odstrániť tvrdo zakódované kategórie z COCO. Tiež existuje možnosť orezať veľké oblasti detekcie, ak na veľkých obrázkoch hľadáte malé objekty a máte malý dataset =), a nič nefunguje, ale o tom inokedy.
Všeobecne je train loop tiež slabý, pôvodne neukladal checkpointy, používal nejaký hrozný plánovač atď. Ale teraz vám zostáva len vybrať backbone a vykonať
/opt/conda/bin/python retinanet/main.pys parametrami:
train retinanet_rn34fpn.pth
--backbone ResNet34FPN
--classes 12
--val-iters 10
--images /workspace/mounted_vol/dataset/train/images
--annotations /workspace/mounted_vol/dataset/train_12_class.json
--val-images /workspace/mounted_vol/dataset/test/images_small
--val-annotations /workspace/mounted_vol/dataset/val_10_class_cropped.json
--jitter 256 512
--max-size 512
--batch 32
V konzole uvidíte:
Inicializácia modelu...
model: RetinaNet
backbone: ResNet18FPN
triedy: 2, kotvy: 9
Vybraný optimalizačný level O0: Čisté FP32 tréning.
Predvolené nastavenia pre tento optimalizačný level sú:
enabled : True
opt_level : O0
cast_model_type : torch.float32
patch_torch_functions : False
keep_batchnorm_fp32 : None
master_weights : False
loss_scale : 1.0
Spracovanie užívateľských prepisov (ďalšie kwargs, ktoré nie sú None)...
Po spracovaní prepisov sú optimalizačné možnosti:
enabled : True
opt_level : O0
cast_model_type : torch.float32
patch_torch_functions : False
keep_batchnorm_fp32 : None
master_weights : False
loss_scale : 128.0
Príprava datasetu...
loader: pytorch
resize: [1024, 1280], max: 1280
device: 4 gpus
batch: 4, precision: mixed
Tréning modelu na 20000 iterácií...
[ 1/20000] fokális strata: 0.95619, strata krabice: 0.51584, 4.042s/4-batch (fw: 0.698s, bw: 0.459s), 1.0 im/s, lr: 0.0001
[ 12/20000] fokális strata: 0.76191, strata krabice: 0.31794, 0.187s/4-batch (fw: 0.055s, bw: 0.133s), 21.4 im/s, lr: 0.0001
[ 24/20000] fokális strata: 0.65036, strata krabice: 0.30269, 0.173s/4-batch (fw: 0.045s, bw: 0.128s), 23.1 im/s, lr: 0.0001
[ 36/20000] fokális strata: 0.46425, strata krabice: 0.23141, 0.178s/4-batch (fw: 0.047s, bw: 0.131s), 22.4 im/s, lr: 0.0001
[ 48/20000] fokális strata: 0.45115, strata krabice: 0.23505, 0.180s/4-batch (fw: 0.047s, bw: 0.133s), 22.2 im/s, lr: 0.0001
[ 59/20000] fokális strata: 0.38958, strata krabice: 0.25373, 0.184s/4-batch (fw: 0.049s, bw: 0.134s), 21.8 im/s, lr: 0.0001
[ 71/20000] fokális strata: 0.37733, strata krabice: 0.23988, 0.174s/4-batch (fw: 0.049s, bw: 0.125s), 22.9 im/s, lr: 0.0001
[ 83/20000] fokális strata: 0.39514, strata krabice: 0.23878, 0.181s/4-batch (fw: 0.048s, bw: 0.133s), 22.1 im/s, lr: 0.0001
[ 94/20000] fokális strata: 0.39947, strata krabice: 0.23817, 0.185s/4-batch (fw: 0.050s, bw: 0.134s), 21.6 im/s, lr: 0.0001
[ 105/20000] fokális strata: 0.37343, strata krabice: 0.20238, 0.182s/4-batch (fw: 0.048s, bw: 0.134s), 22.0 im/s, lr: 0.0001
[ 116/20000] fokális strata: 0.19689, strata krabice: 0.17371, 0.183s/4-batch (fw: 0.050s, bw: 0.132s), 21.8 im/s, lr: 0.0001
[ 128/20000] fokális strata: 0.20368, strata krabice: 0.16538, 0.178s/4-batch (fw: 0.046s, bw: 0.131s), 22.5 im/s, lr: 0.0001
[ 140/20000] fokális strata: 0.22763, strata krabice: 0.15772, 0.176s/4-batch (fw: 0.050s, bw: 0.126s), 22.7 im/s, lr: 0.0001
[ 148/20000] fokális strata: 0.21997, strata krabice: 0.18400, 0.585s/4-batch (fw: 0.047s, bw: 0.144s), 6.8 im/s, lr: 0.0001
Priemerná presnosť (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.52674
Priemerná presnosť (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.91450
Priemerná presnosť (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.35172
Priemerná presnosť (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.61881
Priemerná presnosť (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = -1.00000
Priemerná presnosť (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = -1.00000
Priemerné pripomínanie (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.58824
Priemerné pripomínanie (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.61765
Priemerné pripomínanie (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.61765
Priemerné pripomínanie (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.61765
Priemerné pripomínanie (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = -1.00000
Priemerné pripomínanie (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = -1.00000
Ukladanie modelu: 148Aby ste si prezreli celý súbor parametrov, pozrite sa
retinanet/main.pyVo všeobecnosti sú štandardné pre detekciu a majú popis. Spustite tréning a počkajte na výsledky. Príklad inferencie si môžete pozrieť na:
retinanet/infer_example.pyalebo vykonajte príkaz:
/opt/conda/bin/python retinanet/main.py infer retinanet_rn34fpn.pth
--images /workspace/mounted_vol/dataset/test/images
--annotations /workspace/mounted_vol/dataset/val.json
--output result.json
--resize 256
--max-size 512
--batch 32
V repozitári je už integrovaný Focal Loss a niekoľko backbone, ako aj jednoduché zapracovanie vlastných.
retinanet/backbones/*.pyV tabuľke autori uvádzajú niektoré charakteristiky:

Rovnaké je aj backbone ResNeXt50_32x4dFPN a ResNeXt101_32x8dFPN, ktoré sú prevzaté z torchvision.
Dúfam, že sme sa trochu vyznali v detekcii, ale určite stojí za to prečítať si oficiálnu dokumentáciu, aby sme pochopili režimy exportu a logovania..
Krok 5. Export a inferencia modelov Unet s enkóderom Resnet.
Ako ste si pravdepodobne všimli, v Dockerfile boli nainštalované knižnice na segmentáciu a konkrétne skvelá knižnica . V balíku unet nájdete príklady inferencie a exportu pytorch checkpointov do engine TensorRT.
Hlavný problém pri exporte modelov podobných Unet z ONNX do TensoRT spočíva v potrebe určiť pevný rozmer Upsample alebo použiť ConvTranspose2D:
import torch.onnx.symbolic_opset9 as onnx_symbolic
def upsample_nearest2d(g, input, output_size):
# V súčasnosti, TRT 5.1/6.0 ONNX Parser nepodporuje všetky ONNX operácie
# potrebné na podporu dynamického upsampling ONNX formátu
# Tu hardcodujeme scale=2 ako dočasné riešenie
scales = g.op("Constant", value_t=torch.tensor([1., 1., 2., 2.]))
return g.op("Upsample", input, scales, mode_s="nearest")
onnx_symbolic.upsample_nearest2d = upsample_nearest2d
Pomocou tejto transformácie je možné to urobiť automaticky pri exporte do ONNX, ale už v 7. verzii TensorRT tento problém vyriešili, a my sa nemusíme čakať dlho.
Záver
Keď som začal používať docker, mal som pochybnosti o jeho výkonnosti pre moje úlohy. V jednom z mojich agregátov je teraz dosť veľký sieťový prenos vytváraný niekoľkými kamerami.

Rôzne testy na internete hovorili o relatívne veľkom overheade na sieťovú interakciu a zápis na VOLUME, plus neznámy a strašidelný GIL, a pretože snímanie snímky, práca ovládača a prenos snímky po sieti sú atómové operácie v režime hard real-time, oneskorenia v sieti sú pre mňa veľmi kritické.
Ale všetko dopadlo dobre =)
P.S. Ostáva pridať váš obľúbený train loop pre segmentáciu a do produkcie!
Poďakovanie
Ďakujem komunite , bez nej nie je možné rásť! Obrovské ďakujem , ktorý ma namotivoval zaoberať sa DL, za jeho cenné rady a mimoriadnu profesionalitu!
Používajte v produkcii optimalizované modely!
Aurorai, llc
Zdroj: habr.com
