
Valus ainult esimesel korral!
Tere kõigile! Kallid sõbrad, selles artiklis tahan jagada oma kogemust TensorRT ja RetinaNet kasutamisel, mis põhineb repol (see on ametliku repositooriumi fork , mis võimaldab alustada optimeeritud mudelite kasutamist tootmises lühikese aja jooksul). Kerides läbi ühisuse kanali sõnumeid , kohtan küsimusi TensorRT kasutamise kohta, ja enamik küsimusi kordub, seega otsustasin kirjutada nii täieliku juhendi kiire infereerimise kohta TensorRT, RetinaNet, Unet ja docker põhjal.
Ülesande kirjeldus
Pakun, et seadistame ülesande järgmiselt: meil on vaja andmestik märgistada, õpetada RetinaNet/Unet võrku Pytorch1.3+ peal, konverteerida saadud kaalud ONNX-iks, seejärel konverteerida need TensorRT engine'iks ja kogu see asi käivitada dockeris, soovitavalt Ubuntu 18 peal ja äärmiselt soovitavalt ARM(Jetson)* arhitektuuril, vähendades seeläbi käsitsi keskkonna seadistamist. Lõppude lõpuks saame konteineri, mis on valmis mitte ainult RetinaNet/Unet eksportimiseks ja õpetamiseks, vaid ka täielikuks arendamiseks ja klassifitseerimise, segmentimise õpetamiseks kogu vajaliku abivahendiga.
Etapp 1. Keskkonna ettevalmistamine
Siin on oluline märkida, et viimasel ajal olen täielikult loobunud igasuguste teekide kasutamisest ja seadistamisest laua- või devbox masinal. Ainus, mida tuleb luua ja installida, on python virtual environment ja cuda 10.2 (võib piirduda ainult nvidia draiveriga) deb-pakendist.
Eeldame, et teil on uusim Ubuntu 18. Paigaldame cuda 10.2 (deb), detailse paigaldusprotsessi üle ei peatu, ametlikku dokumentatsiooni on piisavalt.
Nüüd installime dockeri, dockeri paigaldusjuhendi leiab hõlpsasti, siin on näide , uus 19+ versioon on juba saadaval — installime selle. Ja ärge unustage muuta dockerit sudo-vaba kasutamiseks, nii on mugavam. Kui kõik on korda saanud, teeme järgmist:
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
Ja isegi ei pea ametlikku repositooriumisse vaatama .
Nüüd teeme git clone .
Kohal on peaaegu kõik valmis, et alustada dockeriga nvidia-pildiga. Peame registreerima NGC Cloudis ja sisse logima. Minge siia , registreerige end ja pärast seda, kui oleme NGC Cloudi sisse logitud, vajutage ekraani vasakus ülanurgas SETUP või minge sellel lingil . Vajutage "genereeri võti". Soovitan selle salvestada, vastasel juhul tuleb see järgmisel külastusel uuesti genereerida ja vastavalt uue masina seadistamisel korrata seda protseduuri.
Teeme:
docker login nvcr.io
Kasutajanimi: $oauthtoken
Parool: - genereeritud võti
Kasutajanime kopeerime lihtsalt. Nii et, arvestage, et keskkond on loodud!
Etapp 2. Docker konteineri koostamine
Teises etapis koostame docker ja tutvume selle sisemusega.
Liigume projekti retina-examples juurkausta ja täidame
docker build --build-arg USER=$USER --build-arg UID=$UID --build-arg GID=$GID --build-arg PW=alex -t retinanet:latest retinanet/
Kogume dockerit, edastades talle aktiivse kasutaja — see on väga kasulik, kui kavatsete midagi kirjutada monteeritud VOLUMEs kasutada praeguse kasutaja õigusi, vastasel juhul on see root ja häda.
Kui docker vormistatakse, uurime Dockerfile'i:
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"]
Kuidas näha, kasutame kõiki oma lemmikke, kompileerime retinaneti, lisame baasseadmed Ubuntu mugavuse tagamiseks ja seadistame openssh serveri. Esimene rida käsitleb nvidia pildi pärimist, mille jaoks tegime sisselogimise NGC Cloudi ja mis sisaldab Pytorch1.3, TensorRT6.x.x.x ja veel hulk teeke, mis võimaldavad kompileerida meie detektori cpp allikaid.
Etapp 3. Docker-konteineri käivitamine ja silumine
Liigume edasi konteineri ja arenduskeskkonna peamise kasutusjuhtumi juurde, alustuseks käivitame nvidia dockeri. Täidame:
docker run --gpus all --net=host -v /home/:/workspace/mounted_vol -d -P --rm --ipc=host -it retinanet:latestNüüd on konteiner доступен ssh @localhost. Pärast eduka käivitamise lõpetamist avame projekti PyCharmis. Jätkame avades
Settings->Project Interpreter->Add->Ssh Interpreter Samm 1

Samm 2

Samm 3

Valime kõik nagu ekraanipiltidel,
Interpreter -> /opt/conda/bin/python— see on sümboolne link Python3.6-le ja
Sync folder -> /workspace/retinanetVajutame lõpetamiseks, ootame indekseerimist ja kõik, keskkond on kasutamiseks valmis!
OLULINE!!! Vahetult pärast indekseerimist tõmmake dockerist kokku kompileeritud failid Retinanet'ile. Projekti juuremenüüs valige punkt
Deployment->DownloadIlmuvad üks fail ja kaks kausta build, retinanet.egg-info ja _C.so

Kui teie projekt näeb välja selline, siis keskkond näeb kõiki vajalikke faile ja oleme valmis RetinaNet'i koolitamiseks.
Etapp 4. Andmete märgistamine ja detektori koolitamine
Andmete märgistamiseks kasutan peamiselt — meeldiv ja mugav tööriist, viimasel ajal on palju vigu parandatud ja see on hakanud oluliselt paremini toimima.
Oletame, et olete märgistanud andmestiku ja alla laadinud selle, kuid otse meie RetinaNet'i seda panna ei saa, kuna see on oma formaadis ja selleks peame selle COCO-ks muutma. Muutmistööriist asub:
markup_utils/supervisly_to_coco.pyPange tähele, et skripti Category on näide ja peate oma sisestama (taustakategooriat ei tohi lisada)
categories = [{'id': 1, 'name': '1'},
{'id': 2, 'name': '2'},
{'id': 3, 'name': '3'},
{'id': 4, 'name': '4'}] Originaalvara autorid otsustasid kummalisel kombel, et te ei koolita detekteerimiseks midagi muud kui COCO/VOC, nii et pidin algfaili natuke toimetama
retinanet/dataset.pyLisades siin meie lemmikaugmenteerimised ja eemaldada kõvasti sisestatud kategooriad COCO-st. Samuti on võimalus kärpida suuri tuvastusala, kui otsite suurte piltide pealt väikeseid objekte ja teil on väike andmestik =), ja mitte midagi ei tööta, aga sellest räägime teinekord.
Üldiselt on treeningu tsükkel ka nõrk, algselt ei salvestanud see kontrollpunkte, kasutas mingit kohutavat scheduler'i jne. Kuid nüüd on teil jäänud ainult valida selgroog ja teostada.
/opt/conda/bin/python retinanet/main.pyparameetritega:
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
Kaasas näete:
Mudeli algmine...
mudel: RetinaNet
seljaosa: ResNet18FPN
klassid: 2, ankurd: 9
Valitud optimeerimistasand O0: puhas FP32 treening.
Selle optimeerimistasandi standardsed seaded on:
enustatud : Tõsi
opt_tase : O0
muuda_mudeli_tüüp : torch.float32
patch_torch_functions : Vale
hoia_batchnorm_fp32 : Puudub
master_weights : Vale
kahjumiskaal : 1.0
Kasutaja ülekaalude töötlemine (täiendavad kwargs, mis pole None)...
Pärast ülekaalude töötlemist on optimeerimise valikud:
enustatud : Tõsi
opt_tase : O0
muuda_mudeli_tüüp : torch.float32
patch_torch_functions : Vale
hoia_batchnorm_fp32 : Puudub
master_weights : Vale
kahjumiskaal : 128.0
Andmestiku ettevalmistamine...
laadija: pytorch
suuruse muutmine: [1024, 1280], max: 1280
seade: 4 gpu
partii: 4, täpsus: segatud
Koolitame mudelit 20000 iteratsiooni jooksul...
[ 1/20000] fookuse kadu: 0.95619, kastikadu: 0.51584, 4-partii 4.042s (esimene: 0.698s, tagumine: 0.459s), 1.0 im/s, lr: 0.0001
[ 12/20000] fookuse kadu: 0.76191, kastikadu: 0.31794, 0.187s/4-partii (esimene: 0.055s, tagumine: 0.133s), 21.4 im/s, lr: 0.0001
[ 24/20000] fookuse kadu: 0.65036, kastikadu: 0.30269, 0.173s/4-partii (esimene: 0.045s, tagumine: 0.128s), 23.1 im/s, lr: 0.0001
[ 36/20000] fookuse kadu: 0.46425, kastikadu: 0.23141, 0.178s/4-partii (esimene: 0.047s, tagumine: 0.131s), 22.4 im/s, lr: 0.0001
[ 48/20000] fookuse kadu: 0.45115, kastikadu: 0.23505, 0.180s/4-partii (esimene: 0.047s, tagumine: 0.133s), 22.2 im/s, lr: 0.0001
[ 59/20000] fookuse kadu: 0.38958, kastikadu: 0.25373, 0.184s/4-partii (esimene: 0.049s, tagumine: 0.134s), 21.8 im/s, lr: 0.0001
[ 71/20000] fookuse kadu: 0.37733, kastikadu: 0.23988, 0.174s/4-partii (esimene: 0.049s, tagumine: 0.125s), 22.9 im/s, lr: 0.0001
[ 83/20000] fookuse kadu: 0.39514, kastikadu: 0.23878, 0.181s/4-partii (esimene: 0.048s, tagumine: 0.133s), 22.1 im/s, lr: 0.0001
[ 94/20000] fookuse kadu: 0.39947, kastikadu: 0.23817, 0.185s/4-partii (esimene: 0.050s, tagumine: 0.134s), 21.6 im/s, lr: 0.0001
[ 105/20000] fookuse kadu: 0.37343, kastikadu: 0.20238, 0.182s/4-partii (esimene: 0.048s, tagumine: 0.134s), 22.0 im/s, lr: 0.0001
[ 116/20000] fookuse kadu: 0.19689, kastikadu: 0.17371, 0.183s/4-partii (esimene: 0.050s, tagumine: 0.132s), 21.8 im/s, lr: 0.0001
[ 128/20000] fookuse kadu: 0.20368, kastikadu: 0.16538, 0.178s/4-partii (esimene: 0.046s, tagumine: 0.131s), 22.5 im/s, lr: 0.0001
[ 140/20000] fookuse kadu: 0.22763, kastikadu: 0.15772, 0.176s/4-partii (esimene: 0.050s, tagumine: 0.126s), 22.7 im/s, lr: 0.0001
[ 148/20000] fookuse kadu: 0.21997, kastikadu: 0.18400, 0.585s/4-partii (esimene: 0.047s, tagumine: 0.144s), 6.8 im/s, lr: 0.0001
Keskmine täpsus (AP) @[ IoU=0.50:0.95 | ala= kõik | maxDets=100 ] = 0.52674
Keskmine täpsus (AP) @[ IoU=0.50 | ala= kõik | maxDets=100 ] = 0.91450
Keskmine täpsus (AP) @[ IoU=0.75 | ala= kõik | maxDets=100 ] = 0.35172
Keskmine täpsus (AP) @[ IoU=0.50:0.95 | ala= väike | maxDets=100 ] = 0.61881
Keskmine täpsus (AP) @[ IoU=0.50:0.95 | ala=keskmine | maxDets=100 ] = -1.00000
Keskmine täpsus (AP) @[ IoU=0.50:0.95 | ala= suur | maxDets=100 ] = -1.00000
Keskmine kõlblus (AR) @[ IoU=0.50:0.95 | ala= kõik | maxDets= 1 ] = 0.58824
Keskmine kõlblus (AR) @[ IoU=0.50:0.95 | ala= kõik | maxDets= 10 ] = 0.61765
Keskmine kõlblus (AR) @[ IoU=0.50:0.95 | ala= kõik | maxDets=100 ] = 0.61765
Keskmine kõlblus (AR) @[ IoU=0.50:0.95 | ala= väike | maxDets=100 ] = 0.61765
Keskmine kõlblus (AR) @[ IoU=0.50:0.95 | ala=keskmine | maxDets=100 ] = -1.00000
Keskmine kõlblus (AR) @[ IoU=0.50:0.95 | ala= suur | maxDets=100 ] = -1.00000
Mudeli salvestamine: 148Kogu parameetrikogumi uurimiseks vaadake
retinanet/main.pyÜldiselt on need standardid detekteerimiseks ja neil on kirjeldus. Käivitage treening ja oodake tulemusi. Infereerimise näidet saab vaadata aadressil:
retinanet/infer_example.pyvõi käivitage käsk:
/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
Repooris on juba sisseehitatud Focal Loss ja mitmed backbone'id, samuti on kerge lisada omasid.
retinanet/backbones/*.pyTabelis toovad autorid välja mõned omadused:

Samuti on olemas backbone ResNeXt50_32x4dFPN ja ResNeXt101_32x8dFPN, mis on võetud torchvision'ist.
Loodan, et olete natuke aru saanud tuvastamisest, kuid kindlasti tuleks lugeda ametlikku dokumentatsiooni, et mõista eksportimise ja logimise režiime..
Etapp 5. Unet mudelite eksport ja infereerimine Resneti kodeerijaga.
Kuidas te ilmselt tähele panite, olid Dockerfile'is paigaldatud segmenteerimise raamatukogud, sealhulgas suurepärane teek . Paketis unet võib leida näiteid PyTorch checkpointide infereerimiseks ja eksportimiseks TensorRT'sse.
Peamine probleem Unet-tüüpi mudelite eksportimisel ONNX-ist TensorRT-sse on see, et tuleb määrata fikseeritud suurus Upsample või kasutada ConvTranspose2D:
import torch.onnx.symbolic_opset9 as onnx_symbolic
def upsample_nearest2d(g, input, output_size):
# Praegu ei toeta TRT 5.1/6.0 ONNX parser kõiki ONNX op'e
# mis on vajalikud dünaamilise suurendamise ONNX vormingu toetamiseks
# Siin kõvuti kindlustame scale=2 ajutise lahendusena
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
Selle konversiooni abil saab seda automaatselt teha ONNX-i eksportimise ajal, kuid kui me oleme jõudnud TensorRT versioonini 7, siis see probleem lahendati ja me peame ootama veel natuke.
Kokkuvõte
Kui hakkasin Dockerit kasutama, kahtlesin selle sooritusvõimes oma ülesannete jaoks. Ühes minu agregaatidest genereeritakse praegu üsna suurt võrguliiklust mitme kaamera abil.

Erinevad testid internetis rääkisid suhteliselt suurtest ülekoormustest võrgus suhtlemisel ja kirjutamisel VOLUME'ile, pluss veel tundmatu ja hirmutav GIL, ning kuna kaadri pildistamine, draiveri töö ja kaadri edastamine üle võrgu on aatomilised operatsioonid režiimis hard real-time, võrgu latentsus on minu jaoks väga kriitiline.
Aga kõik läks hästi =)
P.S. Tuleb lisada teie lemmik treeningutsükkel segmenteerimise jaoks ja produktiivsusele!
Tänud
Aitäh kogukonnale , ilma milleta ei oleks võimalik areneda! Suur aitäh , kes julgustas mind tegelema DL-iga, tema hindamatute nõuannete ja erakordse professionaalsuse eest!
Kasutage tootmises optimeeritud mudeleid!
Aurorai, llc
Allikas: habr.com
