TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)
Bolí to jen poprvé!

Ahoj všichni! Drazí přátelé, v tomto článku se chci podělit o své zkušenosti s používáním TensorRT, RetinaNet založeného na repozitáři github.com/aidonchuk/retinanet-examples (to je fork oficiální repozitáře od nvidia, který vám umožní začít používat optimalizované modely v production co nejrychleji). Při procházení zpráv v komunitních kanálech ods.ai, narážím na dotazy týkající se používání TensorRT, a většina otázek se opakuje, proto jsem se rozhodl napsat co nejúplnější příručku pro použití rychlého inferenčního systému založeného na TensorRT, RetinaNet, Unet a dockeru.

Popis úkolu

Navrhuji úkol formulovat takto: je třeba anotovat dataset, trénovat síť RetinaNet/Unet na Pytorch1.3+, převedeme získané váhy do ONNX, následně je převedeme do TensorRT engine a celé to spustíme v dockeru, ideálně na Ubuntu 18 a velmi doporučeno na architektuře ARM(Jetson)*, čímž minimalizujeme manuální nasazení prostředí. Nakonec dostaneme kontejner připravený nejen k exportu a trénování RetinaNet/Unet, ale také k plnohodnotnému vývoji a trénování klasifikace a segmentace se všemi potřebnými vazbami.

Krok 1. Příprava prostředí

Je důležité poznamenat, že v poslední době jsem úplně přestal používat a nasazovat jakékoli knihovny na desktopovém počítači, tak jako na devboxu. Jediné, co musím vytvářet a instalovat — je python virtuální prostředí a cuda 10.2 (můžete se omezit na jeden nvidia driver) z deb balíčku.

Předpokládejme, že máte čerstvě nainstalované Ubuntu 18. Nainstalujeme cuda 10.2 (deb), nebudu se podrobně zabývat procesem instalace, oficiální dokumentace je více než dostačující.

Nyní nainstalujeme docker, návod na instalaci dockera můžete snadno najít, zde je příklad www.digitalocean.com/community/tutorials/docker-ubuntu-18-04-1-cs, již je k dispozici verze 19+ — instalujeme ji. A nezapomeňte umožnit použití dockera bez sudo, tak bude pohodlnější. Po úspěšném dokončení to udělá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 můžete se ani nepodívat do oficiálního repozitáře github.com/NVIDIA/nvidia-docker.

Nyní uděláme git clone github.com/aidonchuk/retinanet-examples.

Zbývá jen málo, abychom mohli začít používat Docker s nvidia obrazem. Nejprve se musíme registrovat v NGC Cloud a přihlásit se. Jdeme sem ngc.nvidia.com, registrujeme se a poté, co se dostaneme do NGC Cloud, klikneme na SETUP v levém horním rohu obrazovky nebo přejdeme na tento odkaz ngc.nvidia.com/setup/api-key. Klikněte na „vygenerovat klíč“. Doporučuji ho uložit, jinak při příští návštěvě bude třeba ho vygenerovat znovu a při nastavování na novém zařízení tuto operaci zopakovat.

Provedeme:

docker login nvcr.io
Uživatelské jméno: $oauthtoken
Heslo:  - vygenerovaný klíč

Uživatelské jméno jednoduše zkopírujte. No a máme to, prostředí je připraveno!

Krok 2. Sestavení docker kontejneru

Ve druhém kroku naší práce poskládáme docker a seznámíme se s jeho vnitřnosti.
Přejdeme do kořenové složky vzhledem k projektu retina-examples a provedeme

docker build --build-arg USER=$USER --build-arg UID=$UID --build-arg GID=$GID --build-arg PW=alex -t retinanet:latest retinanet/

Sestavujeme docker a předáváme mu aktuálního uživatele — to je velmi užitečné, pokud budete něco psát na připojeném VOLUME s právy aktuálního uživatele, jinak to bude pod rootem a obtížné.

Zatímco se docker sestavuje, pojďme si prostudovat 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"]

Jak je vidět z textu, vezmeme všechny naše oblíbené knihovny, zkompilujeme retinanet, přidáme základní nástroje pro pohodlnou práci s Ubuntu a nastavíme server openssh. První řádek se týká dědění obrazu nvidia, pro který jsme se přihlásili do NGC Cloud a který obsahuje Pytorch1.3, TensorRT6.x.x.x a spoustu dalších knihoven, které umožňují zkompilovat cpp zdrojové kódy našeho detektoru.

Krok 3. Spuštění a ladění docker kontejneru

Přejdeme k hlavnímu případu použití kontejneru a vývojového prostředí, nejprve spustíme nvidia docker. Provedeme:

docker run --gpus all --net=host -v /home/:/workspace/mounted_vol -d -P --rm --ipc=host -it retinanet:latest

Nyní je kontejner dostupný přes ssh @localhost. Po úspěšném spuštění otevřeme projekt v PyCharm. Dále otevřeme

Nastavení->Interpret projektů->Přidat->Ssh interpreter

Krok 1
TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

Krok 2
TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

Krok 3
TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

Vybereme všechno jako na screenshotu,

Interpreter -> /opt/conda/bin/python

— to bude odkaz na Python3.6 a

Sync folder -> /workspace/retinanet

Klikneme na finish, čekáme na indexování a všechno, prostředí je připraveno k použití!

DŮLEŽITÉ!!! Ihned po indexaci stáhneme ze dockeru zkompilované soubory pro Retinanet. V kontextovém menu v kořenovém adresáři projektu vybereme položku

Nasazení->Stáhnout

Objeví se jeden soubor a dvě složky build, retinanet.egg-info a _С.so

TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

Pokud váš projekt vypadá takto, pak prostředí vidí všechny potřebné soubory a jsme připraveni na trénink RetinaNet.

Krok 4. Označujeme data a trénujeme detektor

Pro označování většinou používám supervise.ly — příjemný a uživatelsky přívětivý nástroj, v poslední době se opravilo spoustu chyb a začal se chovat mnohem lépe.

Předpokládejme, že jste dataset označili a stáhli jej, ale hned ho do našeho RetinaNet nedáte, protože je ve vlastním formátu a proto je třeba jej převést do COCO. Nástroj pro převod se nachází v:

markup_utils/supervisly_to_coco.py

Všimněte si, že kategorie ve skriptu je příklad a je třeba vložit vaše (kategorii pozadí přidávat nemusíte)

categories = [{'id': 1, 'name': '1'}, 
                  {'id': 2, 'name': '2'}, 
                  {'id': 3, 'name': '3'},
                  {'id': 4, 'name': '4'}] 

Autoři původního repozitáře se z nějakého důvodu domnívali, že nic jiného než COCO/VOC nebudete trénovat pro detekci, a proto bylo nutné mírně upravit původní soubor

retinanet/dataset.py

Přidáním zde oblíbených augmentací albumentations.readthedocs.io/en/latest a odstranit pevně zabudované kategorie z COCO. Také existuje možnost oříznout velké oblasti detekce, pokud hledáte malé objekty na velkých obrázcích a máte malý dataset =), a nic nefunguje, ale o tom jindy.

Celkově je tréninková smyčka také slabá, původně neukládala kontrolní body, používala nějaký hrozný plánovač atd. Ale teď už stačí jen vybrat backbone a provést to.

/opt/conda/bin/python retinanet/main.py

s parametry:

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:

Inicializace modelu...
     model: RetinaNet
  backbone: ResNet18FPN
   třídy: 2, kotvy: 9
Vybraná úroveň optimalizace O0:  Čisté FP32 trénování.

Výchozí hodnoty pro tuto úroveň optimalizace jsou:
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
Zpracování uživatelských přepsání (další parametry, které nejsou None)...
Po zpracování přepsání jsou možnosti optimalizace:
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
Příprava datové sady...
    loader: pytorch
    resize: [1024, 1280], max: 1280
    zařízení: 4 gpus
    dávka: 4, preciznost: smíšená
Trénování modelu po dobu 20000 iterací...
[    1/20000] ztráta ohniskové ztráty: 0.95619, ztráta boxu: 0.51584, 4.042s/4-dávka (vpřed: 0.698s, vzad: 0.459s), 1.0 snímků/s, lr: 0.0001
[   12/20000] ztráta ohniskové ztráty: 0.76191, ztráta boxu: 0.31794, 0.187s/4-dávka (vpřed: 0.055s, vzad: 0.133s), 21.4 snímků/s, lr: 0.0001
[   24/20000] ztráta ohniskové ztráty: 0.65036, ztráta boxu: 0.30269, 0.173s/4-dávka (vpřed: 0.045s, vzad: 0.128s), 23.1 snímků/s, lr: 0.0001
[   36/20000] ztráta ohniskové ztráty: 0.46425, ztráta boxu: 0.23141, 0.178s/4-dávka (vpřed: 0.047s, vzad: 0.131s), 22.4 snímků/s, lr: 0.0001
[   48/20000] ztráta ohniskové ztráty: 0.45115, ztráta boxu: 0.23505, 0.180s/4-dávka (vpřed: 0.047s, vzad: 0.133s), 22.2 snímků/s, lr: 0.0001
[   59/20000] ztráta ohniskové ztráty: 0.38958, ztráta boxu: 0.25373, 0.184s/4-dávka (vpřed: 0.049s, vzad: 0.134s), 21.8 snímků/s, lr: 0.0001
[   71/20000] ztráta ohniskové ztráty: 0.37733, ztráta boxu: 0.23988, 0.174s/4-dávka (vpřed: 0.049s, vzad: 0.125s), 22.9 snímků/s, lr: 0.0001
[   83/20000] ztráta ohniskové ztráty: 0.39514, ztráta boxu: 0.23878, 0.181s/4-dávka (vpřed: 0.048s, vzad: 0.133s), 22.1 snímků/s, lr: 0.0001
[   94/20000] ztráta ohniskové ztráty: 0.39947, ztráta boxu: 0.23817, 0.185s/4-dávka (vpřed: 0.050s, vzad: 0.134s), 21.6 snímků/s, lr: 0.0001
[  105/20000] ztráta ohniskové ztráty: 0.37343, ztráta boxu: 0.20238, 0.182s/4-dávka (vpřed: 0.048s, vzad: 0.134s), 22.0 snímků/s, lr: 0.0001
[  116/20000] ztráta ohniskové ztráty: 0.19689, ztráta boxu: 0.17371, 0.183s/4-dávka (vpřed: 0.050s, vzad: 0.132s), 21.8 snímků/s, lr: 0.0001
[  128/20000] ztráta ohniskové ztráty: 0.20368, ztráta boxu: 0.16538, 0.178s/4-dávka (vpřed: 0.046s, vzad: 0.131s), 22.5 snímků/s, lr: 0.0001
[  140/20000] ztráta ohniskové ztráty: 0.22763, ztráta boxu: 0.15772, 0.176s/4-dávka (vpřed: 0.050s, vzad: 0.126s), 22.7 snímků/s, lr: 0.0001
[  148/20000] ztráta ohniskové ztráty: 0.21997, ztráta boxu: 0.18400, 0.585s/4-dávka (vpřed: 0.047s, vzad: 0.144s), 6.8 snímků/s, lr: 0.0001
 Průměrná přesnost  (AP) @[ IoU=0.50:0.95 | oblast=   všechny | maxDets=100 ] = 0.52674
 Průměrná přesnost  (AP) @[ IoU=0.50      | oblast=   všechny | maxDets=100 ] = 0.91450
 Průměrná přesnost  (AP) @[ IoU=0.75      | oblast=   všechny | maxDets=100 ] = 0.35172
 Průměrná přesnost  (AP) @[ IoU=0.50:0.95 | oblast= malá | maxDets=100 ] = 0.61881
 Průměrná přesnost  (AP) @[ IoU=0.50:0.95 | oblast=střední | maxDets=100 ] = -1.00000
 Průměrná přesnost  (AP) @[ IoU=0.50:0.95 | oblast= veliká | maxDets=100 ] = -1.00000
 Průměrná návratnost     (AR) @[ IoU=0.50:0.95 | oblast=   všechny | maxDets=  1 ] = 0.58824
 Průměrná návratnost     (AR) @[ IoU=0.50:0.95 | oblast=   všechny | maxDets= 10 ] = 0.61765
 Průměrná návratnost     (AR) @[ IoU=0.50:0.95 | oblast=   všechny | maxDets=100 ] = 0.61765
 Průměrná návratnost     (AR) @[ IoU=0.50:0.95 | oblast= malá | maxDets=100 ] = 0.61765
 Průměrná návratnost     (AR) @[ IoU=0.50:0.95 | oblast=střední | maxDets=100 ] = -1.00000
 Průměrná návratnost     (AR) @[ IoU=0.50:0.95 | oblast= veliká | maxDets=100 ] = -1.00000
Ukládání modelu: 148

Pokud chcete prozkoumat všechny parametry, podívejte se na

retinanet/main.py

Obecně jsou standardní pro detekci a mají popis. Spusťte školení a vyčkejte na výsledky. Příklad inference naleznete v:

retinanet/infer_example.py

nebo zadejte následující pří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áři je již zabudován Focal Loss a několik backbone, a také se snadno implementují vlastní.

retinanet/backbones/*.py

V tabulce autoři uvádějí některé charakteristiky:

TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

Také existuje backbone ResNeXt50_32x4dFPN a ResNeXt101_32x8dFPN, převzatý z torchvision.
Doufám, že jsme si s detekcí trochu objasnili, ale je nutné přečíst oficiální dokumentaci, aby se pochopily režimy exportu a logování..

Krok 5. Export a inferenční modely Unet s enkodérem Resnet.

Jak jste si pravděpodobně všimli, v Dockerfile byly nainstalovány knihovny pro segmentaci a zejména úžasná knihovna github.com/qubvel/segmentation_models.pytorch. V balíčku Unet lze najít příklady inferencí a exportu pytorch checkpointů do motoru TensorRT.

Hlavní problém při exportu modelů podobných Unet z ONNX do TensorRT je potřeba stanovit pevnou velikost Upsample nebo použít ConvTranspose2D:

import torch.onnx.symbolic_opset9 as onnx_symbolic
        def upsample_nearest2d(g, input, output_size):
            # Momentálně TRT 5.1/6.0 ONNX Parser nepodporuje všechny ONNX operace
            # potřebné k podpoře dynamického upsampling ONNX formulace
            # Zde tvrdě kódujeme scale=2 jako dočasné řešení
            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

Pomocí této transformace je možné to udělat automaticky při exportu do ONNX, ale s 7 verzí TensorRT byl tento problém vyřešen, a my musíme čekat už jen chvíli.

Závěr

Když jsem začal používat Docker, měl jsem pochybnosti o jeho výkonu pro mé úkoly. V jednom z mých agregátorů je nyní docela velký síťový provoz generovaný několika kamerami.

TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation)

Různé testy na internetu mluvily o relativně velkém overheadu na síťovou interakci a zápis na VOLUME, navíc neznámý a děsivý GIL, a protože snímání snímku, práce ovladače a přenos snímku po síti jsou atomární operace v režimu hard real-time, zpoždění v síti je pro mne velmi kritické.

Ale všechno se to zvládlo =)

P.S. Zůstává přidat váš oblíbený tréninkový cyklus pro segmentaci a do produkce!

Poděkování

Děkuji komunitě ods.ai, bez ní není možné se rozvíjet! Obrovské díky n01z3, který mě přiměl zabývat se DL, za jeho cenné rady a mimořádný profesionalismus!

Používejte v produkci optimalizované modely!

TensorRT 6.x.x.x — vysoce výkonný inference pro modely hlubokého učení (Object Detection a Segmentation) Aurorai, llc

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster