Så här använder du TensorFlow Mobile i Android Apps

Med TensorFlow, en av de mest populära maskinlärningsramarna som finns tillgängliga idag, kan du enkelt skapa och träna djupa modeller - också vanligen refererade till som djupa feed-forward neurala nätverk - som kan lösa en mängd olika komplexa problem, såsom bildklassificering, objekt upptäckt och naturligt språkförståelse. TensorFlow Mobile är ett bibliotek som är utformat för att hjälpa dig att utnyttja dessa modeller i dina mobilappar.

I den här handledningen visar jag dig hur du använder TensorFlow Mobile i Android Studio-projekt.

förutsättningar

För att kunna följa denna handledning behöver du:

  • Android Studio 3.0 eller senare
  • TensorFlow 1.5.0 eller högre
  • en Android-enhet som kör API-nivå 21 eller högre
  • och en grundläggande förståelse för TensorFlow-ramverket

1. Skapa en modell

Innan vi börjar använda TensorFlow Mobile behöver vi en utbildad TensorFlow-modell. Låt oss skapa en nu.

Vår modell kommer att bli väldigt grundläggande. Det kommer att beter sig som en XOR-port, med två ingångar, vilka båda kan vara antingen noll eller en och producera en utgång, som kommer att vara noll om båda ingångarna är identiska och en annan. Dessutom, eftersom det kommer att bli en djup modell, kommer den att ha två dolda lager, en med fyra neuroner och en annan med tre neuroner. Du är fri att ändra antalet dolda lager och antalet neuroner som de innehåller.

För att hålla denna handledning kort, istället för att använda de låga TensorFlow-API: erna direkt, använder vi TFLearn, ett populärt inramningsramverk för TensorFlow som erbjuder mer intuitiva och koncisa API. Om du inte redan har det, använd följande kommando för att installera det i din virtuella TensorFlow-miljö:

pip installera tflearn

För att börja skapa modellen, skapa ett Python-skript som heter create_model.py, helst i en tom katalog och öppna den med din favorit textredigerare.

Inuti filen är det första vi behöver göra att importera API: erna TFLearn.

import tflearn

Därefter måste vi skapa träningsdata. För vår enkla modell kommer det bara att finnas fyra möjliga ingångar och utgångar som kommer att likna innehållet i XOR-portens sanningstabell.

X = [[0, 0], [0, 1], [1, 0], [1, 1]] Y = [[0], # Önskad utgång för ingångar 0, 0 [1], # Önskad utgång för ingångar 0, 1 [1], # Önskad utgång för ingångar 1, 0 [0] # Önskad utgång för ingångar 1, 1]

Det är vanligtvis en bra idé att använda slumpmässiga värden plockade från en enhetlig fördelning samtidigt som initialvikt tilldelas alla neuroner i de dolda skikten. För att generera värdena, använd enhetlig() metod.

vikter = tflearn.initializations.uniform (minval = -1, maxval = 1)

Vid denna tidpunkt kan vi börja skapa lagren i vårt neurala nätverk. För att skapa inmatningsskiktet måste vi använda indata() metod som tillåter oss att ange hur många inmatningar nätverket kan acceptera. När inmatningsskiktet är klart kan vi ringa fully_connected () Metod flera gånger för att lägga till flera lager i nätverket.

# Inmatningsskikt net = tflearn.input_data (form = [None, 2], name = 'my_input') # Dolda lag net = tflearn.fully_connected (net, 4, activation = 'sigmoid', weights_init = vikter) net = tflearn. full_connected (net, 3, activation = 'sigmoid', weights_init = vikter) # Utmatningslager net = tflearn.fully_connected (net, 1, activation = 'sigmoid', weights_init = vikter, namn = 'my_output')

Observera att i ovanstående kod har vi givit meningsfulla namn till inmatnings- och utgångslagen. Att göra det är viktigt eftersom vi behöver dem när du använder nätverket från vår Android-app. Observera också att de dolda och utgående lagren använder sigmoid aktiveringsfunktion. Du kan experimentera med andra aktiveringsfunktioner, till exempel Softmaxtanh, och Relu.

Som det sista laget i vårt nätverk måste vi skapa ett regressionslager med hjälp av regression () funktion, vilket förväntar sig några hyperparametrar som dess argument, såsom nätets lärandeprocent och optimerings- och förlustfunktionerna som ska användas. Följande kod visar hur du använder stokastisk gradient nedstigning, SGD för kort, som optimeringsfunktionen och medelvärdet som förlustfunktionen:

net = tflearn.regression (net, learning_rate = 2, optimizer = 'sgd', förlust = 'mean_square')

För att låta TFLearn-ramarna veta att vår nätverksmodell faktiskt är en djup neural nätverksmodell, måste vi ringa DNN () fungera.

modell = tflearn.DNN (netto)

Modellen är nu klar. Allt vi behöver göra nu är att träna det med träningsdata som vi skapade tidigare. Så ringa passa() modellens metod och, tillsammans med träningsdata, ange antalet träningsperioder som ska köras. Eftersom träningsdata är mycket små behöver vår modell tusentals epoker för att uppnå rimlig noggrannhet.

model.fit (X, Y, 5000)

När träningen är klar kan vi ringa förutspå() Metod för modellen för att kontrollera om det genererar önskade utgångar. Följande kod visar hur du kontrollerar utgångarna för alla giltiga ingångar:

print ("1 XOR 1 =% f"% model.predict ([[1,1] ] (0) Skriv ut ("0 XOR 1 =% f"% model.predict ([[0,1]]). Objekt (0)) Skriv ut ("0 XOR 0 =% f"% modell. förutsäga ([[0,0]]). punkt (0))

Om du kör Python-skriptet nu ska du se produktionen som ser ut så här:

Observera att utsignalerna aldrig är exakt 0 eller 1. I stället är de flytande punktnummer som är antingen nära noll eller nära en. Därför kan du använda Python när du använder utgångarna runda() fungera.

Om vi ​​inte uttryckligen sparar modellen efter träning det kommer vi att förlora det så snart skriptet slutar. Lyckligtvis, med TFLearn, ett enkelt samtal till spara() Metod sparar modellen. För att kunna använda den sparade modellen med TensorFlow Mobile, innan vi sparar den, måste vi dock se till att vi tar bort alla träningsrelaterade operationer som finns i tf.GraphKeys.TRAIN_OPS samling, associerad med den. Följande kod visar hur du gör det:

# Ta bort tåg ops med net.graph.as_default (): del tf.get_collection_ref (tf.GraphKeys.TRAIN_OPS) [:] # Spara modellmodellen.save ('xor.tflearn')

Om du kör skriptet igen ser du att det genererar en kontrollpostfil, en metadatafil, en indexfil och en datafil som alla som används tillsammans snabbt kan återskapa vår utbildade modell.

2. Frysning av modellen

Förutom att spara modellen måste vi frysa den innan vi kan använda den med TensorFlow Mobile. Processen att frysa en modell, som du kanske har gissat, innebär att omvandla alla dess variabler till konstanter. Dessutom måste en frusen modell vara en enda binärfil som överensstämmer med serialiseringsformatet för Google Protocol Buffers.

Skapa ett nytt Python-skript som heter freeze_model.py och öppna den med hjälp av en textredigerare. Vi skriver alla koden för att frysa vår modell i den här filen.

Eftersom TFLearn inte har några funktioner för frysning av modeller måste vi använda TensorFlow API direkt nu. Importera dem genom att lägga till följande rad i filen:

importera tensorflöde som tf

Under hela skriptet använder vi en enda TensorFlow-session. För att skapa sessionen, använd konstruktören för Session klass.

med tf.Session () som session: # Resten av koden går här

Vid denna tidpunkt måste vi skapa en Sparare objekt genom att ringa import_meta_graph () funktion och passera namnet på modellens metadatafil till den. Förutom att returnera a Sparare objekt, den import_meta_graph () funktionen lägger också automatiskt till grafdefinitionen för modellen till grafdefinitionen för sessionen.

När spararen är skapad kan vi initiera alla variabler som finns i grafdefinitionen genom att ringa återställa() metod som förväntar sig sökvägen till katalogen som innehåller modellens senaste kontrollpunktsfil.

my_saver = tf.train.import_meta_graph ('xor.tflearn.meta') my_saver.restore (session, tf.train.latest_checkpoint ('.'))

Vid denna tidpunkt kan vi ringa convert_variables_to_constants () funktion för att skapa en frusen grafdefinition där alla variabler av modellen ersätts med konstanter. Som ingångar förväntar sig funktionen den aktuella sessionen, den aktuella sessionens grafdefinition och en lista som innehåller namnen på modellens utgångslager.

frozen_graph = tf.graph_util.convert_variables_to_constants (session, session.graph_def, ['my_output / Sigmoid'])

Ringer till SerializeToString () Metoden för den frusna grafdefinitionen ger oss en binär protobuf-representation av modellen. Genom att använda Pythons grundläggande I / O-anläggningar, föreslår jag att du sparar den som en fil som heter frozen_model.pb.

med öppen ('frozen_model.pb', 'wb') som f: f.write (frozen_graph.SerializeToString ())

Du kan köra skriptet nu för att generera den frusna modellen.

Vi har nu allt vi behöver för att börja använda TensorFlow Mobile.

3. Android Studio Project Setup

TensorFlow Mobile-biblioteket är tillgängligt på JCenter, så vi kan direkt lägga till det som en genomförande beroendet i app modulens build.gradle fil.

implementation "org.tensorflow: tensorflow-android: 1.7.0 '

För att lägga till den frusna modellen till projektet, placera frozen_model.pb filen i projektets tillgångar mapp.

4. Initialisering av TensorFlow-gränssnittet

TensorFlow Mobile erbjuder ett enkelt gränssnitt som vi kan använda för att interagera med vår frusna modell. För att skapa gränssnittet, använd konstruktören för TensorFlowInferenceInterface klass, som förväntar sig en AssetManager instans och filnamn för den frusna modellen.

tråd val tfInterface = TensorFlowInferenceInterface (tillgångar, "frozen_model.pb") // Mer kod här

I ovanstående kod kan du se att vi gyter en ny tråd. Att göra det, men inte alltid nödvändigt, rekommenderas för att försäkra sig om att appens användargränssnitt fortsätter att vara mottagligt.

För att vara säker på att TensorFlow Mobile har lyckats läsa modellens fil korrekt, låt oss nu försöka skriva ut namnen på alla operationer som finns i modellens graf. För att få en referens till grafen kan vi använda Graf() metod för gränssnittet, och för att få alla operationer, operationer() metoden i diagrammet. Följande kod visar hur:

valgraf = tfInterface.graph () graph.operations () .forEach println (it.name ())

Om du kör appen nu bör du kunna se över ett dussin operationsnamn som skrivs ut i Android Studio logcat fönster. Bland alla dessa namn, om det inte fanns några fel under frysning av modellen, kan du hitta namnen på inmatnings- och utgångslagen: my_input / X och my_output / Sigmoid.

5. Använda modellen

För att göra förutsägelser med modellen måste vi sätta data i sitt ingående lager och hämta data från dess utmatningslager. För att sätta data i inmatningsskiktet använder du utfodra() metod för gränssnittet, vilket förväntar sig namnet på lagret, en matris som innehåller ingångarna och dimensionerna av matrisen. Följande kod visar hur du skickar numren 0 och 1 till inmatningsskiktet:

tfInterface.feed ("my_input / X", floatArrayOf (0f, 1f), 1, 2)

Efter att ha laddat in data i inmatningsskiktet måste vi köra en inferensoperation med hjälp av springa() metod som förväntar sig namnet på utmatningsskiktet. När operationen är klar kommer utmatningsskiktet att innehålla modellens förutsägelse. För att ladda prediktionen till en Kotlin-array kan vi använda hämta() metod. Följande kod visar hur du gör det:

tfInterface.run (arrayOf ("my_output / Sigmoid")) valutmatning = floatArrayOf (-1f) tfInterface.fetch ("my_output / Sigmoid", utgång)

Hur du använder förutsägelsen är självklart upp till dig. För närvarande föreslår jag att du bara skriver ut det.

println ("Output är $ output [0]")

Du kan köra appen nu för att se att modellens förutsägelse är korrekt.

Gärna ändra numren du matar till inmatningsskiktet för att bekräfta att modellens förutsägelser alltid är korrekta.

Slutsats

Du vet nu hur man skapar en enkel TensorFlow-modell och använder den med TensorFlow Mobile i Android-appar. Du behöver inte alltid begränsa dig själv till dina egna modeller. Med de färdigheter du lärde dig idag borde du inte ha några problem med att använda större modeller, till exempel MobileNet och Inception, som finns i TensorFlow-modellens zoo. Observera dock att sådana modeller leder till större APK, vilket kan skapa problem för användare med low-end-enheter.

För mer information om TensorFlow Mobile, se den officiella dokumentationen.