TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)
Het doet alleen pijn de eerste keer!

Hallo iedereen! Beste vrienden, in dit artikel wil ik mijn ervaring delen met het gebruik van TensorRT, RetinaNet op basis van de repository github.com/aidonchuk/retinanet-examples (dit is een fork van de officiƫle repository van nvidia, wat het mogelijk maakt om geoptimaliseerde modellen snel in productie te gebruiken). Terwijl ik door berichten in de community-kanelen scrol, ods.ai, kom ik vaak vragen tegen over het gebruik van TensorRT, en de vragen herhalen zich in het algemeen, daarom heb ik besloten om een zo volledig mogelijk handleiding te schrijven voor het gebruik van snelle inferentie op basis van TensorRT, RetinaNet, Unet en docker.

Taakbeschrijving

Laten we de taak zo formuleren: we moeten een dataset labelen, een RetinaNet/Unet-netwerk trainen op Pytorch1.3+, de verkregen gewichten omzetten naar ONNX, vervolgens omzetten naar een TensorRT-engine en dit hele proces in docker uitvoeren, bij voorkeur op Ubuntu 18 en zeer bij voorkeur op ARM(Jetson)* architectuur, waarmee we handmatige installatie van de omgeving minimaliseren. Uiteindelijk krijgen we een container die niet alleen klaar is voor export en training van RetinaNet/Unet, maar ook voor volledige ontwikkeling en training van classificatie, segmentatie met alle benodigde omhulsels.

Stap 1. Voorbereiding van de omgeving

Hier is het belangrijk op te merken dat ik de laatste tijd volledig ben gestopt met het gebruik en de installatie van enige bibliotheken op een desktopmachine, evenals op een devbox. Het enige dat ik moet creƫren en installeren is een python virtual environment en cuda 10.2 (ik kan me beperken tot alleen de nvidia-driver) uit deb.

Laten we aannemen dat je een vers geïnstalleerde Ubuntu 18 hebt. Laten we cuda 10.2(deb) installeren, ik zal niet in detail treden over het installatieproces, de officiële documentatie is daarvoor voldoende.

Laten we nu docker installeren, je kunt gemakkelijk een installatiehandleiding voor docker vinden, hier is een voorbeeld www.digitalocean.com/community/tutorials/docker-ubuntu-18-04-1-nl, versie 19+ is al beschikbaar — laten we deze installeren. Vergeet niet docker zonder sudo te gebruiken, dat is handiger. Nadat alles is gelukt, doen we het als volgt:

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

Je kunt zelfs niet in de officiƫle repository kijken github.com/NVIDIA/nvidia-docker.

Laten we nu git clone doen github.com/aidonchuk/retinanet-examples.

Er is nog maar een klein beetje nodig voordat we Docker met het NVIDIA-image kunnen gebruiken; we moeten ons registreren in NGC Cloud en inloggen. Ga hierheen ngc.nvidia.com, registreer ons en zodra we binnen zijn in NGC Cloud, drukken we op SETUP in de linkerbovenhoek van het scherm of volgen deze link ngc.nvidia.com/setup/api-key. Druk op 'genereer sleutel'. Ik raad aan deze op te slaan, anders moet je hem opnieuw genereren bij een volgend bezoek en, bijgevolg, herhalen van deze stap bij een nieuwe machine.

Voer uit:

docker login nvcr.io
Gebruikersnaam: $oauthtoken
Wachtwoord:  - de gegenereerde sleutel

Kopieer gewoon de gebruikersnaam. Nou, daar hebben we het, de omgeving is opgezet!

Fase 2. Het bouwen van de Docker-container

In de tweede fase van ons werk gaan we Docker bouwen en kennismaken met de interne werking.
Laten we naar de hoofdmap van het project retina-examples gaan en voeren

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

We bouwen Docker door de huidige gebruiker door te geven — dit is erg handig als je iets schrijft op een gemounte VOLUME met de rechten van de huidige gebruiker, anders is het root en dat kan lastig zijn.

Terwijl Docker wordt gebouwd, laten we de Dockerfile bestuderen:

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"]

Zoals te zien is in de tekst, nemen we al onze favoriete bibliotheken, compileren we Retinanet, voegen we basisinstrumenten toe voor het werken met Ubuntu en configureren we de openssh-server. De eerste regel betreft het erven van het nvidia-image, waarvoor we in de NGC Cloud hebben ingelogd en dat Pytorch1.3, TensorRT6.x.x.x en nog veel meer bibliotheken bevat die het mogelijk maken om de cpp-bronbestanden van onze detector te compileren.

Stap 3. De container docker starten en debuggen

Laten we overgaan naar de belangrijkste use case van de container en de ontwikkelomgeving; laten we beginnen met het starten van nvidia docker. Voer uit:

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

Nu is de container beschikbaar via ssh @localhost. Na een succesvolle start openen we het project in PyCharm. Vervolgens openen we

Instellingen->Project Interpreter->Toevoegen->Ssh Interpreter

Stap 1
TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

Stap 2
TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

Stap 3
TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

Kies alles zoals op de screenshots,

Interpreter -> /opt/conda/bin/python

— dit zal een symlink zijn naar Python3.6 en

Synchroniseer map -> /workspace/retinanet

Klik op voltooien, wacht op indexering, en dat is het, de omgeving is klaar voor gebruik!

BELANGRIJK!!! Direct na indexering de gecompileerde bestanden voor Retinanet uit docker extraheren. In het contextmenu in de root van het project kiezen we de optie

Deployment->Download

Er verschijnt één bestand en twee mappen: build, retinanet.egg-info en _Д.so

TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

Als jouw project er zo uitziet, dan ziet de omgeving alle benodigde bestanden en zijn we klaar om RetinaNet te trainen.

Stap 4. We markeren de gegevens en trainen de detector

Voor het annoteren gebruik ik voornamelijk supervise.ly — een prettige en gebruiksvriendelijke tool, die onlangs veel bugs heeft opgelost en daardoor aanzienlijk beter functioneert.

Stel dat je de dataset hebt geannoteerd en deze hebt gedownload, maar je kunt het niet direct in onze RetinaNet stoppen, omdat het in zijn eigen formaat staat en we het moeten converteren naar COCO. De conversietool is te vinden in:

markup_utils/supervisly_to_coco.py

Houd er rekening mee dat de Category in het script een voorbeeld is en dat je jouw eigen moet invoeren (de categorie background hoeft niet toegevoegd te worden)

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

De auteurs van de originele repository besloten om te veronderstellen dat je niets anders dan COCO/VOC zult trainen voor detectie, dus ik moest het originele bestand een beetje bewerken

retinanet/dataset.py

Door hier mijn favoriete augmentaties toe te voegen albumentations.readthedocs.io/en/latest en verwijder stevige ingebouwde categorieƫn uit COCO. Er is ook de mogelijkheid om grote detectiegebieden bij te snijden als je naar kleine objecten zoekt op grote afbeeldingen, je hebt een kleine dataset =), en niets werkt, maar daarover later meer.

In het algemeen is de trainloop ook niet zo sterk, in eerste instantie slaagde hij de checkpoints niet op, gebruikte hij een vreselijke scheduler, enzovoort. Maar nu moet je alleen nog maar de backbone kiezen en uitvoeren.

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

met de volgende parameters:

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

In de console zie je:

Model aan het initialiseren...
     model: RetinaNet
  backbone: ResNet18FPN
   klassen: 2, ankers: 9
Geselecteerd optimalisatieniveau O0:  Pure FP32 training.

Standaarden voor dit optimalisatieniveau zijn:
effectief                : Waar
opt_niveau              : O0
cast_model_type        : torch.float32
patch_torch_functions  : Vals
keep_batchnorm_fp32    : Geen
master_weights         : Vals
loss_scale             : 1.0
Verwerken van gebruikersoverrides (extra kwargs die niet None zijn)...
Na het verwerken van overrides zijn de optimalisatie-opties:
effectief                : Waar
opt_niveau              : O0
cast_model_type        : torch.float32
patch_torch_functions  : Vals
keep_batchnorm_fp32    : Geen
master_weights         : Vals
loss_scale             : 128.0
Dataset aan het voorbereiden...
    loader: pytorch
    resize: [1024, 1280], max: 1280
    apparaat: 4 gpu's
    batch: 4, precisie: gemengd
Model trainen voor 20000 iteraties...
[    1/20000] focal loss: 0.95619, box loss: 0.51584, 4.042s/4-batch (fw: 0.698s, bw: 0.459s), 1.0 im/s, lr: 0.0001
[   12/20000] focal loss: 0.76191, box loss: 0.31794, 0.187s/4-batch (fw: 0.055s, bw: 0.133s), 21.4 im/s, lr: 0.0001
[   24/20000] focal loss: 0.65036, box loss: 0.30269, 0.173s/4-batch (fw: 0.045s, bw: 0.128s), 23.1 im/s, lr: 0.0001
[   36/20000] focal loss: 0.46425, box loss: 0.23141, 0.178s/4-batch (fw: 0.047s, bw: 0.131s), 22.4 im/s, lr: 0.0001
[   48/20000] focal loss: 0.45115, box loss: 0.23505, 0.180s/4-batch (fw: 0.047s, bw: 0.133s), 22.2 im/s, lr: 0.0001
[   59/20000] focal loss: 0.38958, box loss: 0.25373, 0.184s/4-batch (fw: 0.049s, bw: 0.134s), 21.8 im/s, lr: 0.0001
[   71/20000] focal loss: 0.37733, box loss: 0.23988, 0.174s/4-batch (fw: 0.049s, bw: 0.125s), 22.9 im/s, lr: 0.0001
[   83/20000] focal loss: 0.39514, box loss: 0.23878, 0.181s/4-batch (fw: 0.048s, bw: 0.133s), 22.1 im/s, lr: 0.0001
[   94/20000] focal loss: 0.39947, box loss: 0.23817, 0.185s/4-batch (fw: 0.050s, bw: 0.134s), 21.6 im/s, lr: 0.0001
[  105/20000] focal loss: 0.37343, box loss: 0.20238, 0.182s/4-batch (fw: 0.048s, bw: 0.134s), 22.0 im/s, lr: 0.0001
[  116/20000] focal loss: 0.19689, box loss: 0.17371, 0.183s/4-batch (fw: 0.050s, bw: 0.132s), 21.8 im/s, lr: 0.0001
[  128/20000] focal loss: 0.20368, box loss: 0.16538, 0.178s/4-batch (fw: 0.046s, bw: 0.131s), 22.5 im/s, lr: 0.0001
[  140/20000] focal loss: 0.22763, box loss: 0.15772, 0.176s/4-batch (fw: 0.050s, bw: 0.126s), 22.7 im/s, lr: 0.0001
[  148/20000] focal loss: 0.21997, box loss: 0.18400, 0.585s/4-batch (fw: 0.047s, bw: 0.144s), 6.8 im/s, lr: 0.0001
 Gemiddelde Precisie  (AP) @[ IoU=0.50:0.95 | gebied=   alle | maxDets=100 ] = 0.52674
 Gemiddelde Precisie  (AP) @[ IoU=0.50      | gebied=   alle | maxDets=100 ] = 0.91450
 Gemiddelde Precisie  (AP) @[ IoU=0.75      | gebied=   alle | maxDets=100 ] = 0.35172
 Gemiddelde Precisie  (AP) @[ IoU=0.50:0.95 | gebied= klein | maxDets=100 ] = 0.61881
 Gemiddelde Precisie  (AP) @[ IoU=0.50:0.95 | gebied=medium | maxDets=100 ] = -1.00000
 Gemiddelde Precisie  (AP) @[ IoU=0.50:0.95 | gebied= groot | maxDets=100 ] = -1.00000
 Gemiddelde Recall     (AR) @[ IoU=0.50:0.95 | gebied=   alle | maxDets=  1 ] = 0.58824
 Gemiddelde Recall     (AR) @[ IoU=0.50:0.95 | gebied=   alle | maxDets= 10 ] = 0.61765
 Gemiddelde Recall     (AR) @[ IoU=0.50:0.95 | gebied=   alle | maxDets=100 ] = 0.61765
 Gemiddelde Recall     (AR) @[ IoU=0.50:0.95 | gebied= klein | maxDets=100 ] = 0.61765
 Gemiddelde Recall     (AR) @[ IoU=0.50:0.95 | gebied=medium | maxDets=100 ] = -1.00000
 Gemiddelde Recall     (AR) @[ IoU=0.50:0.95 | gebied= groot | maxDets=100 ] = -1.00000
Model opslaan: 148

Om de volledige set parameters te bekijken, kijk naar

retinanet/main.py

Over het algemeen zijn ze standaard voor detectie en hebben ze een beschrijving. Start de training en wacht op de resultaten. Een voorbeeld van inferentie kan worden bekeken in:

retinanet/infer_example.py

of voer de opdracht uit:

/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

In de repository is Focal Loss al ingebouwd, samen met verschillende backbones, en je kunt eenvoudig je eigen toevoegen.

retinanet/backbones/*.py

In de tabel geven de auteurs enkele kenmerken aan:

TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

Er is ook de backbone ResNeXt50_32x4dFPN en ResNeXt101_32x8dFPN, afkomstig van torchvision.
Ik hoop dat we de detectie een beetje hebben verduidelijkt, maar het is absoluut noodzakelijk om de officiƫle documentatie te lezen om de export- en loggingsmodi te begrijpen..

Stap 5. Export en inferentie van Unet-modellen met de Resnet-encoder.

Zoals je misschien hebt opgemerkt, zijn in de Dockerfile bibliotheken geĆÆnstalleerd voor segmentatie en in het bijzonder een geweldige library. github.com/qubvel/segmentation_models.pytorch. In het Unet-pakket vind je voorbeelden van inferentie en export van pytorch-checkpoints naar de TensorRT-engine.

Het belangrijkste probleem bij het exporteren van Unet-achtige modellen van ONNX naar TensorRT is de noodzaak om een vaste grootte voor Upsample in te stellen of gebruik te maken van ConvTranspose2D:

import torch.onnx.symbolic_opset9 as onnx_symbolic
        def upsample_nearest2d(g, input, output_size):
            # Momenteel ondersteunt de TRT 5.1/6.0 ONNX-parser niet alle ONNX-ops
            # die nodig zijn om dynamische upsampling ONNX-formulering te ondersteunen.
            # Hier hebben we scale=2 als tijdelijke oplossing hardcoded.
            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

Met deze transformatie kan dit automatisch worden gedaan bij de export naar ONNX, maar al in versie 7 van TensorRT is dit probleem opgelost en hoeven we niet veel langer te wachten.

Conclusie

Toen ik begon met het gebruik van docker had ik twijfels over de prestaties voor mijn taken. In een van mijn aggregaten is er momenteel behoorlijk veel netwerkverkeer vanwege verschillende camera's.

TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie)

Diverse tests op het internet wezen op een relatief grote overhead bij netwerkcommunicatie en schrijven naar VOLUME, plus de onbekende en angstaanjagende GIL, en aangezien het opnemen van een frame, het functioneren van de driver en de overdracht van een frame over het netwerk atomische handelingen zijn in de modus hard real-time, zijn netwerkvertragingen voor mij zeer kritiek.

Maar alles is goed gekomen =)

P.S. Vergeet niet je favoriete trainloop voor segmentatie toe te voegen en naar productie te brengen!

Dankbetuigingen

Bedankt aan de gemeenschap ods.ai, zonder hen is groei onmogelijk! Enorm bedankt n01z3, die me heeft aangespoord om me met DL bezig te houden, voor zijn onschatbare adviezen en uitzonderlijke professionaliteit!

Gebruik geoptimaliseerde modellen in productie!

TensorRT 6.x.x.x - hoogperformante inferentie voor modellen van diepe leren (Objectdetectie en Segmentatie) Aurorai, llc

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster