Introduksjon til Tensorflow for Java

1. Oversikt

TensorFlow er en open source-bibliotek for dataflytprogrammering. Dette ble opprinnelig utviklet av Google og er tilgjengelig for et bredt spekter av plattformer. Selv om TensorFlow kan fungere på en enkelt kjerne, kan det som dra fordel av flere tilgjengelige CPUer, GPUer eller TPU-er.

I denne opplæringen vil vi gå gjennom det grunnleggende om TensorFlow og hvordan du bruker det i Java. Vær oppmerksom på at TensorFlow Java API er en eksperimentell API og følgelig ikke dekket av noen stabilitetsgaranti. Vi vil dekke senere i opplæringen mulige brukssaker for bruk av TensorFlow Java API.

2. Grunnleggende

TensorFlow-beregning dreier seg i utgangspunktet to grunnleggende begreper: Graf og økt. La oss gå gjennom dem raskt for å få den bakgrunnen som trengs for å gå gjennom resten av opplæringen.

2.1. TensorFlow-graf

Til å begynne med, la oss forstå de grunnleggende byggesteinene i TensorFlow-programmene. Beregninger er representert som grafer i TensorFlow. En graf er vanligvis en rettet asyklisk graf over operasjoner og data, for eksempel:

Ovenstående bilde representerer beregningsgrafen for følgende ligning:

f (x, y) = z = a * x + b * y

En beregningsgrafikk for TensorFlow består av to elementer:

  1. Tensor: Dette er kjernenheten for data i TensorFlow. De er representert som kantene i en beregningsgraf, som viser datastrømmen gjennom grafen. En tensor kan ha en form med et hvilket som helst antall dimensjoner. Antall dimensjoner i en tensor blir vanligvis referert til som dens rang. Så en skalar er en rang 0 tensor, en vektor er en rang en tensor, en matrise er en rang 2 tensor, og så videre og så videre.
  2. Drift: Dette er nodene i en beregningsgraf. De refererer til et bredt utvalg av beregninger som kan skje på tensorene som mates inn i operasjonen. De resulterer ofte også i tensorer som kommer fra operasjonen i en beregningsgraf.

2.2. TensorFlow-økt

Nå er en TensorFlow-graf bare en skjematisk oversikt over beregningen som faktisk ikke har noen verdier. Slik en graf må kjøres inne i det som kalles en TensorFlow-økt for at tensorene i grafen skal evalueres. Økten kan ta en haug med tensorer å evaluere fra en graf som inndataparametere. Deretter går den bakover i grafen og kjører alle nodene som er nødvendige for å evaluere disse tensorene.

Med denne kunnskapen er vi nå klare til å ta dette og bruke det på Java API!

3. Maven-oppsett

Vi setter opp et raskt Maven-prosjekt for å lage og kjøre en TensorFlow-graf i Java. Vi trenger bare tensorflow avhengighet:

 org.tensorflow tensorflow 1.12.0 

4. Lage grafen

La oss nå prøve å bygge grafen vi diskuterte i forrige avsnitt ved hjelp av TensorFlow Java API. Mer presist, for denne opplæringen bruker vi TensorFlow Java API for å løse funksjonen representert ved følgende ligning:

z = 3 * x + 2 * y

Det første trinnet er å erklære og initialisere en graf:

Grafgraf = ny graf ()

Nå må vi definere alle nødvendige operasjoner. Husk at operasjoner i TensorFlow forbruker og produserer null eller flere tensorer. Videre er hver node i grafen en operasjon inkludert konstanter og plassholdere. Dette kan virke kontraintuitivt, men bær det med et øyeblikk!

Klassen Kurve har en generisk funksjon som kalles opBuilder () å bygge alle slags operasjoner på TensorFlow.

4.1. Definere konstanter

Til å begynne med, la oss definere konstante operasjoner i grafen vår ovenfor. Merk at a konstant drift vil trenge en tensor for verdien:

Operasjon a = graph.opBuilder ("Const", "a") .setAttr ("dtype", DataType.fromClass (Double.class)) .setAttr ("value", Tensor.create (3.0, Double.class)). bygge(); Operasjon b = graph.opBuilder ("Const", "b") .setAttr ("dtype", DataType.fromClass (Double.class)) .setAttr ("value", Tensor.create (2.0, Double.class)). bygge();

Her har vi definert en Operasjon av konstant type, fôring i Tensor med Dobbelt verdier 2.0 og 3.0. Det kan virke lite overveldende til å begynne med, men det er akkurat slik det er i Java API for nå. Disse konstruksjonene er mye mer konsise på språk som Python.

4.2. Definere plassholdere

Mens vi trenger å gi verdier til konstantene våre, plassholdere trenger ikke en verdi på definisjonstidspunktet. Verdiene til plassholdere må oppgis når grafen kjøres inne i en økt. Vi vil gå gjennom den delen senere i opplæringen.

For nå, la oss se hvordan vi kan definere våre plassholdere:

Operasjon x = graph.opBuilder ("Placeholder", "x") .setAttr ("dtype", DataType.fromClass (Double.class)) .build (); Operasjon y = graph.opBuilder ("Placeholder", "y") .setAttr ("dtype", DataType.fromClass (Double.class)) .build ();

Merk at vi ikke trengte å gi noen verdi for våre plassholdere. Disse verdiene vil bli matet som Tensorer når du kjører.

4.3. Definere funksjoner

Til slutt må vi definere de matematiske operasjonene i ligningen vår, nemlig multiplikasjon og tillegg for å få resultatet.

Dette er igjen ingenting annet enn Operasjons i TensorFlow og Graph.opBuilder () er praktisk nok en gang:

Operasjon ax = graph.opBuilder ("Mul", "ax") .addInput (a.output (0)) .addInput (x.output (0)) .build (); Operasjon av = graph.opBuilder ("Mul", "av") .addInput (b.output (0)) .addInput (y.output (0)) .build (); Operasjon z = graph.opBuilder ("Legg til", "z") .addInput (ax.output (0)) .addInput (by.output (0)) .build ();

Her har vi definert der Operasjon, to for å multiplisere våre innspill og den siste for å oppsummere de mellomliggende resultatene. Merk at operasjoner her mottar tensorer som ikke er noe annet enn resultatet av våre tidligere operasjoner.

Vær oppmerksom på at vi får utdataene Tensor fra Operasjon ved hjelp av indeksen ‘0’. Som vi diskuterte tidligere, en Operasjon kan resultere i en eller flere Tensor og derfor, mens vi henter et håndtak for det, må vi nevne indeksen. Siden vi vet at virksomheten vår bare returnerer en Tensor, ‘0’ fungerer helt fint!

5. Visualisere grafen

Det er vanskelig å holde en fane i grafen ettersom den vokser i størrelse. Dette gjør det viktig å visualisere det på en eller annen måte. Vi kan alltid lage en håndtegning som den lille grafen vi opprettet tidligere, men det er ikke praktisk for større grafer. TensorFlow tilbyr et verktøy som heter TensorBoard for å lette dette.

Dessverre har Java API ikke muligheten til å generere en hendelsesfil som forbrukes av TensorBoard. Men ved hjelp av APIer i Python kan vi generere en hendelsesfil som:

forfatter = tf.summary.FileWriter ('.') ...... forfatter.add_graph (tf.get_default_graph ()) forfatter.flush ()

Vennligst ikke bry deg hvis dette ikke gir mening i sammenheng med Java, dette er lagt til her bare for fullstendighetens skyld og ikke nødvendig for å fortsette resten av opplæringen.

Vi kan nå laste inn og visualisere hendelsesfilen i TensorBoard som:

tensorboard --logdir.

TensorBoard kommer som en del av TensorFlow-installasjonen.

Legg merke til likheten mellom dette og den manuelt tegnede grafen tidligere!

6. Arbeide med økt

Vi har nå laget en beregningsgraf for vår enkle ligning i TensorFlow Java API. Men hvordan kjører vi det? Før vi tar for oss det, la oss se hva som er tilstanden til Kurve vi har nettopp opprettet på dette punktet. Hvis vi prøver å skrive ut resultatet av finalen vår Operasjon “Z”:

System.out.println (z.output (0));

Dette vil resultere i noe som:

Dette var ikke det vi forventet! Men hvis vi husker det vi diskuterte tidligere, er dette faktisk fornuftig. De Kurve vi nettopp har definert, har ikke blitt kjørt ennå, så tensorene der inne har faktisk ingen faktisk verdi. Utgangen ovenfor sier bare at dette vil være en Tensor av typen Dobbelt.

La oss nå definere en Økt å kjøre vår Kurve:

Øktessess = ny økt (graf)

Endelig er vi nå klare til å kjøre grafen vår og få utdataene vi har forventet:

Tensor tensor = sess.runner (). Hente ("z"). Feed ("x", Tensor.create (3.0, Double.class)). Feed ("y", Tensor.create (6.0, Double.class) ) .run (). get (0) .expect (Double.class); System.out.println (tensor.doubleValue ());

Så hva gjør vi her? Det skal være ganske intuitivt:

  • Få en Løper fra Økt
  • Definer Operasjon å hente med navnet “z”
  • Gi tensorer til våre plassholdere "x" og "y"
  • Kjør Kurve i Økt

Og nå ser vi skalareffekten:

21.0

Dette var det vi forventet, er det ikke!

7. Use Case for Java API

På dette tidspunktet kan TensorFlow høres ut som for mye for å utføre grunnleggende operasjoner. Men selvfølgelig, TensorFlow er ment å kjøre grafer mye mye større enn dette.

I tillegg tensorene den håndterer i virkelige modeller er mye større i størrelse og rang. Dette er de faktiske maskinlæringsmodellene der TensorFlow finner sin reelle bruk.

Det er ikke vanskelig å se at det å jobbe med kjernen API i TensorFlow kan bli veldig tungvint ettersom størrelsen på grafen øker. For dette formål TensorFlow tilbyr API-er på høyt nivå som Keras for å jobbe med komplekse modeller. Dessverre er det liten eller ingen offisiell støtte for Keras på Java ennå.

Imidlertid kan vi bruke Python til å definere og trene komplekse modeller enten direkte i TensorFlow eller ved å bruke APIer på høyt nivå som Keras. Deretter kan vi eksporter en trent modell og bruk den i Java ved hjelp av TensorFlow Java API.

Nå, hvorfor skulle vi ønske å gjøre noe sånt? Dette er spesielt nyttig i situasjoner der vi ønsker å bruke maskinlæringsfunksjoner i eksisterende klienter som kjører på Java. For eksempel å anbefale billedtekst for brukerbilder på en Android-enhet. Likevel er det flere tilfeller der vi er interessert i produksjonen av en maskinlæringsmodell, men ikke nødvendigvis vil lage og trene den modellen i Java.

Dette er hvor TensorFlow Java API finner mesteparten av bruken. Vi vil gå gjennom hvordan dette kan oppnås i neste avsnitt.

8. Bruke lagrede modeller

Vi vil nå forstå hvordan vi kan lagre en modell i TensorFlow til filsystemet og laste den tilbake muligens på et helt annet språk og plattform. TensorFlow tilbyr API-er for å generere modellfiler i en språk- og plattformnøytral struktur kalt Protocol Buffer.

8.1. Lagre modeller i filsystemet

Vi begynner med å definere den samme grafen vi opprettet tidligere i Python og lagre den i filsystemet.

La oss se at vi kan gjøre dette i Python:

importer tensorflow som tf-graf = tf.Graph () builder = tf.saved_model.builder.SavedModelBuilder ('./ model') med graph.as_default (): a = tf.constant (2, name = "a") b = tf.constant (3, name = "b") x = tf.placeholder (tf.int32, name = "x") y = tf.placeholder (tf.int32, name = "y") z = tf.math. legg til (a * x, b * y, name = "z") sess = tf.Session () sess.run (z, feed_dict = {x: 2, y: 3}) builder.add_meta_graph_and_variables (sess, [tf. saved_model.tag_constants.SERVING]) builder.save ()

Som fokus for denne opplæringen i Java, la oss ikke ta særlig hensyn til detaljene i denne koden i Python, bortsett fra at den genererer en fil som heter “saved_model.pb”. Vær oppmerksom på å passere kortheten ved å definere en lignende graf sammenlignet med Java!

8.2. Laster inn modeller fra filsystemet

Vi laster nå “saved_model.pb” inn i Java. Java TensorFlow API har SavedModelBundle å jobbe med lagrede modeller:

SavedModelBundle model = SavedModelBundle.load ("./ model", "serve"); Tensor tensor = modell.session (). Runner (). Hente ("z"). Feed ("x", Tensor.create (3, Integer.class)). Feed ("y", Tensor.create (3, Integer.class)) .run (). Get (0) .expect (Integer.class); System.out.println (tensor.intValue ());

Det skal nå være ganske intuitivt å forstå hva ovennevnte kode gjør. Den laster ganske enkelt modellgrafen fra protokollbufferen og gjør økten der tilgjengelig. Derfra og fremover kan vi stort sett gjøre hva som helst med denne grafen, slik vi ville ha gjort for en lokalt definert graf.

9. Konklusjon

For å oppsummere gikk vi i denne opplæringen gjennom de grunnleggende konseptene relatert til beregningsgrafen TensorFlow. Vi så hvordan du bruker TensorFlow Java API for å lage og kjøre en slik graf. Så snakket vi om brukstilfellene for Java API med hensyn til TensorFlow.

I prosessen forsto vi også hvordan vi kunne visualisere grafen ved hjelp av TensorBoard, og lagre og laste en modell på nytt ved hjelp av Protocol Buffer.

Som alltid er koden for eksemplene tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found