Come utilizzare TensorFlow Mobile nelle app Android

Con TensorFlow, uno dei framework di apprendimento automatico più diffusi oggi disponibili, è possibile creare e addestrare facilmente modelli profondi, noti anche come reti neurali feed-forward profonde, in grado di risolvere una serie di problemi complessi, come la classificazione delle immagini, l'oggetto rilevamento e comprensione del linguaggio naturale. TensorFlow Mobile è una libreria progettata per aiutarti a sfruttare questi modelli nelle tue app mobili.

In questo tutorial, ti mostrerò come utilizzare TensorFlow Mobile nei progetti Android Studio.

Prerequisiti

Per poter seguire questo tutorial, avrai bisogno di:

  • Android Studio 3.0 o versioni successive
  • TensorFlow 1.5.0 o successivo
  • un dispositivo Android con livello API 21 o successivo
  • e una conoscenza di base del framework TensorFlow

1. Creazione di un modello

Prima di iniziare a utilizzare TensorFlow Mobile, abbiamo bisogno di un modello TensorFlow addestrato. Creiamo uno ora.

Il nostro modello sarà molto semplice. Si comporterà come un gate XOR, prendendo due input, entrambi possono essere zero o uno, e produrre un output, che sarà zero se entrambi gli input sono identici e uno altrimenti. Inoltre, poiché sarà un modello profondo, avrà due livelli nascosti, uno con quattro neuroni e un altro con tre neuroni. Sei libero di cambiare il numero di livelli nascosti e il numero di neuroni che contengono.

Per mantenere questo tutorial breve, invece di utilizzare direttamente le API di basso livello di TensorFlow, utilizzeremo TFLearn, un popolare framework wrapper per TensorFlow che offre API più intuitive e concise. Se non lo hai già, usa il seguente comando per installarlo nell'ambiente virtuale TensorFlow:

pip installa tflearn

Per iniziare a creare il modello, creare uno script Python chiamato create_model.py, preferibilmente in una directory vuota, e aprilo con il tuo editor di testo preferito.

All'interno del file, la prima cosa che dobbiamo fare è importare le API di TFLearn.

importa tflearn

Successivamente, dobbiamo creare i dati di allenamento. Per il nostro modello semplice, ci saranno solo quattro possibili input e output, che assomigliano al contenuto della tabella di verità del gate XOR.

X = [[0, 0], [0, 1], [1, 0], [1, 1]] Y = [[0], # Uscita desiderata per gli ingressi 0, 0 [1], # Uscita desiderata per ingressi 0, 1 [1], # Uscita desiderata per gli ingressi 1, 0 [0] # Uscita desiderata per gli ingressi 1, 1]

Di solito è una buona idea usare valori casuali scelti da una distribuzione uniforme mentre si assegnano i pesi iniziali a tutti i neuroni nei livelli nascosti. Per generare i valori, utilizzare il uniforme() metodo.

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

A questo punto, possiamo iniziare a creare gli strati della nostra rete neurale. Per creare il livello di input, dobbiamo usare il dati in ingresso() metodo, che ci consente di specificare il numero di ingressi che la rete può accettare. Una volta che il livello di input è pronto, possiamo chiamare il fully_connected () metodo più volte per aggiungere più strati alla rete.

# Input layer net = tflearn.input_data (shape = [None, 2], name = 'my_input') # Strati nascosti net = tflearn.fully_connected (net, 4, activation = 'sigmoid', weights_init = weights) net = tflearn. fully_connected (net, 3, activation = 'sigmoid', weights_init = weights) # Output layer net = tflearn.fully_connected (net, 1, activation = 'sigmoid', weights_init = weights, name = 'my_output')

Si noti che nel codice precedente, abbiamo dato nomi significativi ai livelli di input e output. Fare ciò è importante perché ne avremo bisogno mentre usiamo la rete dalla nostra app per Android. Si noti inoltre che i livelli nascosto e di output stanno utilizzando il sigma funzione di attivazione. Sei libero di sperimentare con altre funzioni di attivazione, come SoftMaxtanh, e Relu.

Come ultimo livello della nostra rete, dobbiamo creare un livello di regressione usando il regressione() funzione, che prevede alcuni parametri ipertestuali come argomenti, come la frequenza di apprendimento della rete e le funzioni di ottimizzazione e perdita che dovrebbe utilizzare. Il seguente codice mostra come usare la discesa del gradiente stocastico, in breve SGD, come funzione di ottimizzazione e il quadrato medio come funzione di perdita:

net = tflearn.regression (net, learning_rate = 2, optimizer = 'sgd', loss = 'mean_square')

Successivamente, per far sapere al framework TFLearn che il nostro modello di rete è in realtà un modello di rete neurale profonda, dobbiamo chiamare il DNN () funzione.

model = tflearn.DNN (netto)

Il modello è ora pronto. Tutto ciò che dobbiamo fare ora è addestrarlo utilizzando i dati di allenamento che abbiamo creato in precedenza. Quindi chiama il in forma() metodo del modello e, insieme ai dati di allenamento, specificare il numero di epoche di allenamento da eseguire. Poiché i dati di addestramento sono molto piccoli, il nostro modello avrà bisogno di migliaia di epoche per raggiungere una ragionevole accuratezza.

model.fit (X, Y, 5000)

Una volta completato l'allenamento, possiamo chiamare il prevedere () metodo del modello per verificare se sta generando le uscite desiderate. Il codice seguente mostra come controllare le uscite per tutti gli input validi:

print ("1 XOR 0 =% f"% model.predict ([[1,0]]). item (0)) print ("1 XOR 1 =% f"% model.predict ([[1,1] ]). item (0)) print ("0 XOR 1 =% f"% model.predict ([[0,1]]). item (0)) print ("0 XOR 0 =% f"% modello. prevedere ([[0,0]]). item (0))

Se esegui lo script Python ora, dovresti vedere un output che assomiglia a questo:

Notare che le uscite non sono mai esattamente 0 o 1. Al contrario, sono numeri in virgola mobile che sono vicini a zero o vicini a uno. Pertanto, mentre si usano gli output, si potrebbe voler usare Python il giro() funzione.

A meno che non salviamo esplicitamente il modello dopo l'allenamento, lo perderemo non appena termina la sceneggiatura. Fortunatamente, con TFLearn, una semplice chiamata al salvare() metodo salva il modello. Tuttavia, per essere in grado di utilizzare il modello salvato con TensorFlow Mobile, prima di salvarlo, è necessario assicurarsi di rimuovere tutte le operazioni relative all'addestramento, che sono presenti nel tf.GraphKeys.TRAIN_OPS collezione, associata ad essa. Il seguente codice mostra come farlo:

# Rimuovi le operazioni di treno con net.graph.as_default (): del tf.get_collection_ref (tf.GraphKeys.TRAIN_OPS) [:] # Salva il modello model.save ('xor.tflearn')

Se esegui nuovamente lo script, vedrai che genera un file di checkpoint, un file di metadati, un file di indice e un file di dati, i quali, se usati insieme, possono ricreare rapidamente il nostro modello addestrato.

2. Congelamento del modello

Oltre a salvare il modello, è necessario bloccarlo prima di poterlo utilizzare con TensorFlow Mobile. Il processo di congelamento di un modello, come si potrebbe immaginare, implica la conversione di tutte le sue variabili in costanti. Inoltre, un modello congelato deve essere un singolo file binario conforme al formato di serializzazione dei buffer del protocollo di Google.

Crea un nuovo script Python chiamato freeze_model.py e aprirlo usando un editor di testo. Scriveremo tutto il codice per congelare il nostro modello all'interno di questo file.

Poiché TFLearn non ha alcuna funzione per il congelamento dei modelli, ora dovremo utilizzare direttamente le API di TensorFlow. Importali aggiungendo la seguente riga al file:

importare tensorflow come tf

In tutto lo script, useremo una singola sessione TensorFlow. Per creare la sessione, utilizzare il costruttore del file Sessione classe.

con tf.Session () come sessione: # Il resto del codice va qui

A questo punto, dobbiamo creare un risparmiatore oggetto chiamando il import_meta_graph () funzione e passando il nome del file di metadati del modello su di esso. Oltre a restituire a risparmiatore oggetto, il import_meta_graph () la funzione aggiunge automaticamente anche la definizione del grafico del modello alla definizione del grafico della sessione.

Una volta che il risparmiatore è stato creato, possiamo inizializzare tutte le variabili presenti nella definizione del grafico chiamando il ristabilire() metodo, che si aspetta il percorso della directory contenente l'ultimo file di checkpoint del modello.

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

A questo punto, possiamo chiamare il convert_variables_to_constants () funzione per creare una definizione di grafico congelata in cui tutte le variabili del modello vengono sostituite con costanti. Come input, la funzione prevede la sessione corrente, la definizione del grafico della sessione corrente e un elenco contenente i nomi dei livelli di output del modello.

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

Chiamando il SerializeToString () il metodo della definizione del grafico congelato ci fornisce una rappresentazione protobuf binaria del modello. Utilizzando le funzionalità di I / O di file di base di Python, ti suggerisco di salvarlo come un file chiamato frozen_model.pb.

con open ('frozen_model.pb', 'wb') come f: f.write (frozen_graph.SerializeToString ())

È possibile eseguire lo script ora per generare il modello congelato.

Ora abbiamo tutto ciò di cui abbiamo bisogno per iniziare a utilizzare TensorFlow Mobile.

3. Impostazione del progetto Android Studio

La libreria TensorFlow Mobile è disponibile su JCenter, quindi possiamo aggiungerla direttamente come implementazione dipendenza nel App modulo di build.gradle file.

implementazione 'org.tensorflow: tensorflow-android: 1.7.0'

Per aggiungere il modello congelato al progetto, posiziona il frozen_model.pb file nel progetto risorse cartella.

4. Inizializzazione dell'interfaccia TensorFlow

TensorFlow Mobile offre un'interfaccia semplice che possiamo usare per interagire con il nostro modello congelato. Per creare l'interfaccia, utilizzare il costruttore di TensorFlowInferenceInterface classe, che si aspetta un AssetManager istanza e il nome file del modello congelato.

thread val tfInterface = TensorFlowInferenceInterface (assets, "frozen_model.pb") // Altro codice qui

Nel codice precedente, puoi vedere che stiamo generando un nuovo thread. Si consiglia di farlo, anche se non sempre è necessario, per assicurarsi che l'interfaccia utente dell'app rimanga reattiva.

Per essere sicuri che TensorFlow Mobile sia riuscito a leggere correttamente il file del nostro modello, proviamo ora a stampare i nomi di tutte le operazioni presenti nel grafico del modello. Per ottenere un riferimento al grafico, possiamo usare il grafico() metodo dell'interfaccia e per ottenere tutte le operazioni, il operazioni () metodo del grafico. Il seguente codice mostra come:

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

Se esegui l'app ora, dovresti riuscire a visualizzare oltre una dozzina di nomi di operazioni stampati in Android Studio logcat finestra. Tra tutti questi nomi, se non ci fossero errori durante il congelamento del modello, sarete in grado di trovare i nomi dei livelli di input e output: my_input / X e my_output / Sigmoid.

5. Uso del modello

Per fare previsioni con il modello, dobbiamo mettere i dati nel suo livello di input e recuperare i dati dal suo livello di output. Per inserire i dati nel livello di input, utilizzare il alimentazione() metodo dell'interfaccia, che si aspetta il nome del livello, una matrice contenente gli input e le dimensioni dell'array. Il seguente codice mostra come inviare i numeri 0 e 1 al livello di input:

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

Dopo aver caricato i dati nel livello di input, dobbiamo eseguire un'operazione di inferenza usando il comando correre() metodo, che si aspetta il nome del livello di output. Una volta completata l'operazione, il livello di output conterrà la previsione del modello. Per caricare la previsione in un array Kotlin, possiamo usare il fetch () metodo. Il seguente codice mostra come farlo:

tfInterface.run (arrayOf ("my_output / Sigmoid")) val output = floatArrayOf (-1f) tfInterface.fetch ("my_output / Sigmoid", output)

Il modo in cui utilizzi la previsione è ovviamente a te. Per ora, ti suggerisco di stamparlo semplicemente.

println ("Output è $ output [0]")

Puoi ora eseguire l'app per verificare che la previsione del modello sia corretta.

Sentiti libero di cambiare i numeri che alimenti al livello di input per confermare che le previsioni del modello sono sempre corrette.

Conclusione

Ora sai come creare un semplice modello TensorFlow e utilizzarlo con TensorFlow Mobile nelle app Android. Non devi sempre limitarti ai tuoi modelli, però. Con le abilità che hai imparato oggi, non dovresti avere problemi a usare modelli più grandi, come MobileNet e Inception, disponibili nello zoo modello TensorFlow. Nota, tuttavia, che tali modelli porteranno a APK più grandi, il che potrebbe creare problemi per gli utenti con dispositivi di fascia bassa.

Per ulteriori informazioni su TensorFlow Mobile, fare riferimento alla documentazione ufficiale.