Kako rasporediti modele TensorFlow u proizvodnju pomoću TF posluživanja

Uvod

Primena modela strojnog učenja (ML) u proizvodnju postala je popularna, stalna tema. Mnoge tvrtke i okviri nude različita rješenja kojima je cilj riješiti ovaj problem.

Da bi se pozabavio ovom zabrinutošću, Google je objavio TensorFlow (TF) koji služi u nadi da će riješiti problem uvođenja ML modela u proizvodnju.

Ovaj dio nudi praktični vodič o posluživanju unaprijed obučene konvolucijske mreže semantičke segmentacije. Na kraju ovog članka moći ćete koristiti TF Serving za postavljanje i upućivanje zahtjeva dubokom CNN-u obučenom za TF. Također ću predstaviti pregled glavnih blokova TF posluživanja i raspravit ću njegove API-je i kako sve to funkcionira.

Jedna stvar koju ćete odmah primijetiti je da je potrebno vrlo malo koda da bi stvarno služio TF modelu. Ako želite slijediti tutorial i pokrenuti primjer na svom stroju, slijedite ga kakav jest. Ali, ako želite znati samo o TensorFlow posluživanju, možete se usredotočiti na prva dva odjeljka.

Ovaj članak naglašava dio posla koji radimo ovdje u Daitan Group.

Knjižnice koje poslužuju TensorFlow - pregled

Uzmimo malo vremena da shvatimo kako TF posluživanje rješava puni životni ciklus posluživanja modela ML. Ovdje ćemo pregledati (na visokoj razini) svaki od glavnih blokova TF posluživanja. Cilj ovog odjeljka je pružiti lagani uvod u API-je za posluživanje TF. Detaljan pregled potražite na stranici dokumentacije za posluživanje TF.

TensorFlow posluživanje sastoji se od nekoliko apstrakcija. Ove apstrakcije implementiraju API-je za različite zadatke. Najvažniji su Servable, Loader, Source i Manager. Pređimo na njihovu interakciju.

Ukratko, životni ciklus posluživanja započinje kada TF Serving identificira model na disku. Za to se brine komponenta Source. Odgovorna je za prepoznavanje novih modela koje treba učitati. U praksi nadzire datotečni sustav kako bi prepoznao kada nova verzija modela stigne na disk. Kad vidi novu verziju, nastavlja se stvaranjem Loader-a za tu određenu verziju modela.

Ukratko, Loader zna gotovo sve o modelu. Uključuje kako ga učitati i kako procijeniti potrebne resurse modela, kao što su traženi RAM i GPU memorija. Loader ima pokazivač na model na disku, zajedno sa svim potrebnim meta-podacima za njegovo učitavanje. Ali ovdje postoji kvaka: Loader još uvijek ne smije učitati model.

Nakon stvaranja Loader-a, izvor ga šalje Manager-u kao željenu verziju.

Po primanju Aspired verzije modela, upravitelj nastavlja s postupkom posluživanja. Ovdje postoje dvije mogućnosti. Jedno je da je prva verzija modela primorana na implementaciju. U ovoj situaciji, upravitelj će se pobrinuti da su dostupni potrebni resursi. Jednom kad upravitelj dodeli Loaderu dopuštenje za učitavanje modela.

Drugo je da forsiramo novu verziju postojećeg modela. U ovom slučaju, upravitelj mora konzultirati dodatak za pravila o verzijama prije nego što krene dalje. Politika verzija određuje kako će se odvijati postupak učitavanja nove verzije modela.

Točnije, prilikom učitavanja nove verzije modela, možemo birati između očuvanja (1) dostupnosti ili (2) resursa. U prvom slučaju želimo biti sigurni da je naš sustav uvijek dostupan za dolazne zahtjeve klijenata. Znamo da upravitelj omogućuje Loaderu da instancira novi graf s novim težinama.

U ovom trenutku imamo istovremeno učitane dvije verzije modela. Ali Manager iskrcava stariju verziju tek nakon završetka učitavanja i sigurnog prebacivanja između modela.

S druge strane, ako želimo uštedjeti resurse bez dodatnog međuspremnika (za novu verziju), možemo odabrati da sačuvamo resurse. Moglo bi biti korisno da vrlo teški modeli imaju mali jaz u dostupnosti, u zamjenu za uštedu memorije.

Na kraju, kada klijent zatraži ručicu za model, upravitelj vraća ručicu u Servable.

Ovim pregledom postavljeni smo za ronjenje u stvarnu aplikaciju. U sljedećim odjeljcima opisujemo kako služiti konvolucijskoj neuronskoj mreži (CNN) koristeći TF posluživanje.

Izvoz modela za posluživanje

Prvi korak za opsluživanje ML modela ugrađenog u TensorFlow jest osiguravanje ispravnog formata. Da bi to postigao, TensorFlow nudi klasu SavedModel.

SavedModel je univerzalni format serializacije za modele TensorFlow. Ako ste upoznati s TF-om, vjerojatno ste koristili TensorFlow Saver kako biste zadržali varijable svog modela.

TensorFlow Saver nudi funkcionalnosti za spremanje / vraćanje datoteka kontrolnih točaka modela na / s diska. Zapravo, SavedModel obavija TensorFlow Saver i zamišljen je kao standardni način izvoza TF modela za posluživanje.

Objekt SavedModel ima nekoliko lijepih značajki.

Prvo, omogućuje vam spremanje više od jednog meta-grafa u jedan objekt SavedModel. Drugim riječima, omogućuje nam različite grafikone za različite zadatke.

Na primjer, pretpostavimo da ste upravo završili trening svog modela. U većini situacija, za izvođenje zaključaka, vaš graf ne treba neke operacije specifične za trening. Ovi operativni programi mogu uključivati ​​varijable optimizatora, tenzore zakazivanja stope učenja, dodatne operativne operacije pred obradu itd.

Štoviše, možda ćete htjeti poslužiti kvantiziranu verziju grafa za mobilnu implementaciju.

U tom kontekstu, SavedModel omogućuje vam spremanje grafova s ​​različitim konfiguracijama. U našem bismo primjeru imali tri različita grafikona s odgovarajućim oznakama kao što su "trening", "zaključivanje" i "mobilno". Također, ova tri grafikona dijele isti skup varijabli - što naglašava učinkovitost memorije.

Ne tako davno, kada smo željeli rasporediti TF modele na mobilne uređaje, morali smo znati imena ulaznih i izlaznih tenzora za hranjenje i preuzimanje podataka u / iz modela. To je natjeralo programere da traže tenzor koji im je potreban među svim tenzorima grafa. Da tenzori nisu pravilno imenovani, zadatak bi mogao biti vrlo naporan.

Da bi olakšao stvari, SavedModel nudi podršku za SignatureDefs. Ukratko, SignatureDefs definiraju potpis izračuna koji podržava TensorFlow. Određuje odgovarajuće ulazne i izlazne tenzore za računski graf. Jednostavno rečeno, ovim potpisima možete odrediti točne čvorove koji će se koristiti za ulaz i izlaz.

Da bi se koristili ugrađeni API-ji za posluživanje, TF Serving zahtijeva da modeli uključuju jedan ili više SignatureDefs.

Da bismo stvorili takve potpise, moramo dati definicije za ulaze, izlaze i željeni naziv metode. Ulazi i izlazi predstavljaju mapiranje iz niza u objekte TensorInfo (više o ovom potonjem). Ovdje definiramo zadane tenzore za hranjenje i primanje podataka na i s grafa. Parametar method_name cilja jedan od TF API-ja za posluživanje na visokoj razini.

Trenutno postoje tri API-ja za posluživanje: klasifikacija, predviđanje i regresija. Svaka definicija potpisa odgovara određenom RPC API-ju. Klasifikacija SegnatureDef koristi se za API klasificiranja RPC. Predict SegnatureDef koristi se za Predict RPC API i dalje.

Za klasifikacijski potpis mora postojati ulazni tenzor (za primanje podataka) i najmanje jedan od dva moguća izlazna tenzora: klase i / ili rezultati. Regresijski potpis potpis zahtijeva točno jedan tenzor za ulaz, a drugi za izlaz. I na kraju, predviđajući potpis omogućuje dinamički broj ulaznih i izlaznih tenzora.

Uz to, SavedModel podržava pohranu imovine za slučajeve kada inicijalizacija operativnog sustava ovisi o vanjskim datotekama. Također, ima mehanizme za brisanje uređaja prije stvaranja SavedModel-a.

Sada, da vidimo kako to možemo učiniti u praksi.

Postavljanje okoliša

Prije nego što započnemo, klonirajte ovu implementaciju TensorFlow DeepLab-v3 iz Githuba.

DeepLab je Googleova najbolja semantička segmentacija ConvNet. U osnovi, mreža uzima sliku kao ulaz i izbacuje sliku nalik maski koja odvaja određene objekte od pozadine.

Ova je verzija osposobljena na podatkovnom skupu podataka za segmentaciju Pascal VOC. Dakle, može segmentirati i prepoznati do 20 klasa. Ako želite saznati više o semantičkoj segmentaciji i DeepLab-v3, pogledajte Ronjenje u duboke konvolucijske mreže semantičke segmentacije i Deeplab_V3.

Sve datoteke povezane s posluživanjem nalaze se u: ./deeplab_v3/serving/. Tamo ćete pronaći dvije važne datoteke: deeplab_saved_model.py i deeplab_client.ipynb

Prije nego što krenete dalje, obavezno preuzmite unaprijed obučeni model Deeplab-v3. Krenite u gore spremište GitHub, kliknite vezu kontrolnih točaka i preuzmite mapu pod nazivom 16645 / .

Na kraju, trebali biste imati mapu nazvanu tboard_logs / s mapom 16645 / koja je smještena unutar nje.

Sada moramo stvoriti dva Python virtualna okruženja. Jedan za Python 3 i drugi za Python 2. Za svaku env obavezno instalirajte potrebne ovisnosti. Možete ih pronaći u datotekama serve_requirements.txt i client_requirements.txt.

Trebaju nam dva Python env-a jer je naš model, DeepLab-v3, razvijen pod Pythonom 3. Međutim, TensorFlow Serving Python API objavljen je samo za Python 2. Stoga, za izvoz modela i pokretanje TF posluživanja koristimo Python 3 env . Za pokretanje klijentskog koda pomoću API-ja TF Serving python koristimo PIP paket (dostupan samo za Python 2).

Imajte na umu da se Python 2 env možete odreći pomoću API-ja za posluživanje iz bazel. Više pojedinosti potražite u Instalaciji posluživanja TF.

S tim korakom dovršimo, krenimo s onim što je stvarno važno.

Kako to učiniti

Da biste koristili SavedModel, TensorFlow nudi jednostavnu klasu korisnih programa visoke razine nazvanu SavedModelBuilder. Klasa SavedModelBuilder pruža funkcionalnosti za spremanje više meta grafova, pridruženih varijabli i imovine.

Prođimo kroz tekući primjer kako izvesti CNN model duboke segmentacije za posluživanje.

Kao što je gore spomenuto, za izvoz modela koristimo klasu SavedModelBuilder. Generirat će datoteku međuspremnika protokola SavedModel zajedno s varijablama i imovinom modela (ako je potrebno).

Idemo secirati kod.

SavedModelBuilder prima (kao ulaz) direktorij u koji će se spremiti podaci modela. Ovdje je varijabla export_path spajanje baze podataka_puta_izvoza i verzije_ modela . Kao rezultat toga, različite verzije modela bit će spremljene u zasebne direktorije unutar mape export_path_base .

Recimo da imamo osnovnu verziju našeg modela u proizvodnji, ali želimo primijeniti njegovu novu verziju. Poboljšali smo točnost našeg modela i želimo novu verziju ponuditi našim klijentima.

Da bismo izvezli drugu verziju istog grafa, možemo samo postaviti FLAGS.model_version na veću cijelu vrijednost. Tada će se unutar mape export_path_base stvoriti druga mapa (koja sadrži novu verziju našeg modela) .

Sada moramo odrediti ulazne i izlazne tenzore našeg modela. Da bismo to učinili, koristimo SignatureDefs. Potpisi definiraju koju vrstu modela želimo izvesti. Pruža mapiranje iz nizova (logička imena tenzora) u objekte TensorInfo. Ideja je da se, umjesto referenciranja stvarnih imena tenzora za ulaz / izlaz, klijenti mogu pozivati ​​na logička imena definirana potpisima.

Za posluživanje semantičke segmentacije CNN stvorit ćemo Predvidljivi potpis . Imajte na umu da funkcija build_signature_def () uzima mapiranje ulaznih i izlaznih tenzora, kao i željeni API.

SignatureDef zahtijeva specifikaciju: ulaza, izlaza i naziva metode. Imajte na umu da za ulaze očekujemo tri vrijednosti - sliku i još dva tenzora koja određuju njezine dimenzije (visinu i širinu). Za izlaze smo definirali samo jedan ishod - izlaznu masku segmentacije.

Imajte na umu da nizovi "slika", "visina", "širina" i "segmentacija_mapa" nisu tenzori. Umjesto toga, to su logična imena koja se odnose na stvarne tenzore input_tensor , image_height_tensor i image_width_tensor . Dakle, oni mogu biti bilo koji jedinstveni niz koji vam se sviđa.

Također, mapiranje u SignatureDefs odnosi se na TensorInfo protobuf objekte, a ne na stvarne tenzore. Za stvaranje objekata TensorInfo koristimo uslužnu funkciju: tf.saved_model.utils.build_tensor_info (tensor) .

To je to. Sada pozivamo funkciju add_meta_graph_and_variables () za izgradnju objekta međuspremnika protokola SavedModel. Zatim pokrećemo metodu save () i ona će zadržati snimku našeg modela na disku koji sadrži varijable i sredstva modela.

Sada možemo pokrenuti deeplab_saved_model.py za izvoz našeg modela.

Ako je sve prošlo u redu, vidjet ćete mapu ./serving/versions/1 . Imajte na umu da '1' predstavlja trenutnu verziju modela. Unutar svakog poddirektora verzije vidjet ćete sljedeće datoteke:

  • spremljeni_model.pb ili spremljeni_model.pbtxt. Ovo je serijalizirana datoteka SavedModel. Uključuje jednu ili više definicija grafikona modela, kao i definicije potpisa.
  • Varijable. Ova mapa sadrži serializirane varijable grafikona.

Sada smo spremni za pokretanje našeg poslužitelja modela. Da biste to učinili, pokrenite:

$ tensorflow_model_server --port=9000 --model_name=deeplab --model_base_path=

Model_base_path odnosi na kojem je spremljena izvezena modela. Također, na putu ne navodimo mapu verzije. Upravljanjem verzijama modela upravlja TF Serving.

Generiranje zahtjeva klijenta

Klijentski kod je vrlo jednostavan. Pogledajte ga na: deeplab_client.ipynb.

Prvo čitamo sliku koju želimo poslati poslužitelju i pretvaramo je u pravi format.

Dalje, kreiramo gRPC stub. Stub nam omogućuje pozivanje metoda udaljenog poslužitelja. Da bismo to učinili, instanciramo klasu beta_create_PredictionService_stub modula prediction_service_pb2 . U ovom trenutku klip sadrži potrebnu logiku za pozivanje udaljenih procedura (s poslužitelja) kao da su lokalne.

Sada moramo stvoriti i postaviti objekt zahtjeva. Budući da naš poslužitelj implementira TensorFlow Predict API, moramo analizirati zahtjev za predviđanjem. Da bismo izdali zahtjev za predviđanjem, prvo instanciramo klasu PredictRequest iz modula predict_pb2 . Također moramo navesti parametre model_spec.name i model_spec.signature_name . Ime param je „uređaj MODEL_NAME” argument da smo definirali kada smo pokrenuli poslužitelj. A signature_name odnosi na logički naziv dodijeljen signature_def_map () parametra add_meta_graph () rutinu.

Dalje, moramo dostaviti ulazne podatke kako je definirano u potpisu poslužitelja. Imajte na umu da smo na poslužitelju definirali API za predviđanje da očekuje sliku kao i dva skalara (visinu i širinu slike). Za hranjenje ulaznih podataka u objekt zahtjeva, TensorFlow pruža uslužni program tf.make_tensor_proto () . Ova metoda stvara objekt TensorProto od objekta numpy / Python. Možemo ga koristiti za hranjenje slike i njezinih dimenzija na objekt zahtjeva.

Izgleda da smo spremni nazvati poslužitelj. Da bismo to učinili, pozivamo metodu Predict () (koristeći klizač) i prosljeđujemo objekt zahtjeva kao argument.

Za zahtjeve koji vraćaju jedan odgovor, gRPC podržava i sinkrone i asinkrone pozive. Stoga, ako želite obaviti neki posao dok se zahtjev obrađuje, mogli bismo nazvati Predict.future () umjesto Predict () .

Sada možemo dohvatiti i uživati ​​u rezultatima.

Nadam se da vam se svidio ovaj članak. Hvala na čitanju!

Ako želite još, pogledajte:

Kako istrenirati vlastiti FaceID ConvNet koristeći TensorFlow Eager izvršenje

Lica su posvuda - od fotografija i videozapisa na web lokacijama društvenih medija, do aplikacija za sigurnost potrošača poput… medium.freecodecamp.org Uronjavanje u duboke konvolucijske mreže semantičke segmentacije i Deeplab_V3

Duboke konvolucijske neuronske mreže (DCNN) postigle su izuzetan uspjeh u raznim programima Computer Vision ... medium.freecodecamp.org