Machine Learning as a Service med TensorFlow

Forestil dig dette: Du er kommet ombord på AI Hype Train og besluttede at udvikle en app, der analyserer effektiviteten af ​​forskellige spisepinde-typer. For at tjene penge på denne imponerende AI-applikation og imponere VC'er bliver vi nødt til at åbne den for verden. Og det er bedre at skalere, da alle vil bruge det.

Som udgangspunkt vil vi bruge dette datasæt, som indeholder målinger af madklemningseffektiviteten hos forskellige individer med spisepinde af forskellig længde.

Arkitektur

Da vi ikke kun er dataforskere, men også ansvarlige softwareingeniører, udarbejder vi først vores arkitektur. Først skal vi beslutte, hvordan vi får adgang til vores implementerede model for at komme med forudsigelser. For TensorFlow ville et naivt valg være at bruge TensorFlow-servering. Denne ramme giver dig mulighed for at implementere uddannede TensorFlow-modeller, understøtter modelversionering og bruger gRPC under emhætten.

Det vigtigste forbehold for gRPC er, at det ikke er særlig offentligt venligt sammenlignet med for eksempel REST-tjenester. Enhver med minimal værktøj kan ringe til en REST-tjeneste og hurtigt få et resultat tilbage. Men når du bruger gRPC, skal du først generere klientkode fra proto-filer ved hjælp af specielle hjælpeprogrammer og derefter skrive klienten på dit foretrukne programmeringssprog.

TensorFlow Serving forenkler mange ting i denne pipeline, men det er stadig ikke den nemmeste ramme til forbrug af API på klientsiden. Overvej TF-servering, hvis du har brug for lynhurtig, pålidelig, strengt skrevet API, der vil blive brugt inde i din applikation (for eksempel som en backend-service til en web- eller mobilapp).

Vi bliver også nødt til at opfylde ikke-funktionelle krav til vores system. Hvis mange brugere måske vil vide deres chopstick-effektivitetsniveau, skal vi bruge systemet til at være fejltolerant og skalerbart. UI-teamet skal også installere deres chopstick'o'meter webapp et eller andet sted. Og vi har brug for ressourcer til at prototype nye maskinlæringsmodeller, muligvis i et Jupyter Lab med masser af computerkraft bag sig. Et af de bedste svar på disse spørgsmål er at bruge Kubernetes.

Kubernetes er et open source-system til automatisering af implementering, skalering og styring af containeriserede applikationer.

Med Kubernetes på plads, givet viden og lidt tid, kan vi skabe en skalerbar ina-cloud PaaS-løsning, der giver infrastruktur og software til fuldcyklusudvikling af datavidenskabsprojekter. Hvis du ikke er bekendt med Kubernetes, foreslår jeg, at du ser dette:

Kubernetes kører oven på Docker-teknologi, så hvis du ikke er bekendt med det, kan det være godt at læse den officielle tutorial først.

Alt i alt er dette et meget rigt emne, der fortjener flere bøger at dække helt, så her vil vi fokusere på en enkelt del: flytning af maskinlæringsmodeller til produktion.

Overvejelser

Ja, dette datasæt er lille. Og ja, anvendelse af dyb læring er måske ikke den bedste idé her. Bare husk at vi er her for at lære, og dette datasæt er bestemt sjovt. Modelleringsdelen af ​​denne tutorial mangler kvalitet, da hovedfokus er på modelimplementeringsprocessen.

Vi er også nødt til at imponere vores VC'er, så dyb læring er et must! :)

Kode

Alle kode- og konfigurationsfiler, der bruges i dette indlæg, er tilgængelige i et ledsagende GitHub-lager.

Træning Deep Chopstick klassificering

Først skal vi vælge en maskinlæringsramme, der skal bruges. Da denne artikel er beregnet til at demonstrere TensorFlow-serveringsfunktioner, vælger vi TensorFlow.

Som du måske ved, er der to måder, hvorpå vi kan træne vores klassifikator: ved hjælp af TensorFlow og brug af TensorFlow Estimator API. Estimator API er et forsøg på at præsentere en samlet grænseflade til modeller for dyb læring på en måde scikit-learning gør det for et sæt klassiske ML-modeller. Til denne opgave kan vi bruge tf.estimator.LinearClassifiertil hurtigt at implementere Logistisk regression og eksportere modellen, når træningen er afsluttet.

Den anden måde, vi kan gøre det på, er at bruge almindelig TensorFlow til at træne og eksportere en klassifikator:

Opsætning af TensorFlow-servering

Så du har en fantastisk dyb læringsmodel med TensorFlow og er ivrig efter at sætte den i produktion? Nu er det tid til at få fat i TensorFlow-servering.

TensorFlow Serving er baseret på gRPC - et hurtigt opkaldsbibliotek til fjernprocedurer, der bruger et andet Google-projekt under emhætten - Protocol Buffers.

Protokolbuffere er en serialiseringsramme, der giver dig mulighed for at omdanne objekter fra hukommelsen til et effektivt binært format, der er egnet til transmission over netværket.

For at opsummere er gRPC en ramme, der muliggør fjernfunktionsopkald over netværket. Det bruger protokolbuffere til at serialisere og deserialisere data.

Hovedkomponenterne i TensorFlow-servering er:

  • Servable - dette er dybest set en version af din uddannede model, der eksporteres i et format, der passer til TF-servering til indlæsning
  • Loader - TF-serveringskomponent, der ved en tilfældighed indlæser servables i hukommelsen
  • Manager - implementerer servables livscyklusoperationer. Det styrer tjenerens fødsel (lastning), lang levetid (servering) og død (losning)
  • Kerne - får alle komponenter til at arbejde sammen (den officielle dokumentation er lidt vag om, hvad kernen faktisk er, men du kan altid se på kildekoden for at få fat på, hvad den gør)

Du kan læse en mere detaljeret oversigt over TF Serving-arkitektur i den officielle dokumentation.

For at få en TF Serving-baseret tjeneste i gang skal du:

  1. Eksporter modellen til et format, der er kompatibelt med TensorFlow-servering. Med andre ord, opret en serverbar.
  2. Installer eller kompiler TensorFlow-servering
  3. Kør TensorFlow Serving og indlæs den nyeste version af den eksporterede model (serverbar)

Opsætning af TernsorFlow-servering kan udføres på flere måder:

  • Bygning fra kilde. Dette kræver, at du installerer Bazel og gennemfører en lang kompileringsproces
  • Brug af en forudbygget binær pakke. TF-servering fås som en deb-pakke.

To automate this process and simplify subsequent installation to Kubernetes, we created a simple Dockerfile for you. Please clone the article’s repository and follow the instructions in the README.md file to build TensorFlow Serving Docker image:

➜ make build_image

This image has TensorFlow Serving and all dependencies preinstalled. By default, it loads models from the /models directory inside the docker container.

Running a prediction service

To run our service inside the freshly built and ready to use TF Serving image, be sure to first train and export the model (or if you’re using a companion repository, just run the make train_classifier command).

After the classifier is trained and exported, you can run the serving container by using the shortcut make run_server or by using the following command:

➜ docker run -p8500:8500 -d --rm -v /path/to/exported/model:/models tfserve_bin
  • -p maps ports from the container to the local machine
  • -d runs the container in daemon (background) mode
  • --rm removes the container after it has stopped
  • -v maps the local directory to a directory inside the running container. This way we pass our exported models to the TF Serving instance running inside the container

Calling model services from the client side

To call our services, we will use grpctensorflow-serving-api Python packages. Please notice that this package is currently only available for Python 2, so you should have a separate virtual environment for the TF Serving client.

To use this API with Python 3, you’ll either need to use an unofficial package from here then download and unzip the package manually, or build TensorFlow Serving from the source (see the documentation). Example clients for both Estimator API and plain TensorFlow are below:

Going into production with Kubernetes

If you have no Kubernetes cluster available, you may create one for local experiments using minikube, or you can easily deploy a real cluster using kubeadm.

We’ll go with the minikube option in this post. Once you have installed it (brew cask install minikube on Mac) we may start a local cluster and share its Docker environment with our machine:

➜ minikube start...➜ eval $(minikube docker-env)

After that, we’ll be able to build our image and put it inside the cluster using

➜ make build_image

A more mature option would be to use the internal docker registry and push the locally built image there, but we’ll leave this out of scope to be more concise.

After having our image built and available to the Minikube instance, we need to deploy our model server. To leverage Kubernetes’ load balancing and high-availability features, we will create a Deployment that will auto-scale our model server to three instances and will also keep them monitored and running. You can read more about Kubernetes deployments here.

All Kubernetes objects can be configured in various text formats and then passed to kubectl apply -f file_name command to (meh) apply our configuration to the cluster. Here is our chopstick server deployment config:

Let’s apply this deployment using the kubectl apply -f chopstick_deployment.yml command. After a while, you’ll see all components running:

➜ kubectl get allNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEdeploy/chopstick-classifier 3 3 3 3 1d
NAME DESIRED CURRENT READY AGErs/chopstick-classifier-745cbdf8cd 3 3 3 1d
NAME AGEdeploy/chopstick-classifier 1d
NAME AGErs/chopstick-classifier-745cbdf8cd 1d
NAME READY STATUS RESTARTS AGEpo/chopstick-classifier-745cbdf8cd-5gx2g 1/1 Running 0 1dpo/chopstick-classifier-745cbdf8cd-dxq7g 1/1 Running 0 1dpo/chopstick-classifier-745cbdf8cd-pktzr 1/1 Running 0 1d

Notice that based on the Deployment config, Kubernetes created for us:

  • Deployment
  • Replica Set
  • Three pods running our chopstick-classifier image

Now we want to call our new shiny service. To make this happen, first we need to expose it to the outside world. In Kubernetes, this can be done by defining Services. Here is the Service definition for our model:

As always, we can install it using kubectl apply -f chopstick_service.yml. Kubernetes will assign an external port to our LoadBalancer, and we can see it by running

➜ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEchopstick-classifier LoadBalancer 10.104.213.253  8500:32372/TCP 1dkubernetes ClusterIP 10.96.0.1  443/TCP 1d

As you can see, our chopstick-classifier is available via port 32372 in my case. It may be different in your machine, so don’t forget to check it out. A convenient way to get the IP and port for any Service when using Minikube is running the following command:

➜ minikube service chopstick-classifier --url//192.168.99.100:32372

Inference

Finally, we are able to call our service!

python tf_api/client.py 192.168.99.100:32372 1010.0Sending requestoutputs { key: "classes_prob" value { dtype: DT_FLOAT tensor_shape { dim { size: 1 } dim { size: 3 } } float_val: 3.98174306027e-11 float_val: 1.0 float_val: 1.83699980923e-18 }}

Before going to real production

As this post is meant mainly for educational purposes and has some simplifications for the sake of clarity, there are several important points to consider before going to production:

  • Use a service mesh like linkerd.io. Accessing services from randomly generated node ports is not recommended in production. As a plus, linkerd will add much more value to your production infrastructure: monitoring, service discovery, high speed load balancing, and more
  • Use Python 3 everywhere, as there is really no reason to use Python 2 now
  • Anvend dyb læring klogt. Selvom det er en meget generel, spektakulær og bredt anvendelig ramme, er dyb læring ikke det eneste værktøj, som en dataloger har til rådighed. Det er heller ikke en sølvkugle, der løser ethvert problem. Maskinindlæring har meget mere at tilbyde. Hvis du har relationelle / tabeldata, små datasæt, strenge begrænsninger for beregningsressourcer eller træningstid eller modelfortolkning, skal du overveje at bruge andre algoritmer og tilgange.
  • Kontakt os, hvis du har brug for hjælp til at løse maskinindlæringsudfordringer: [email protected]