Caffe2 - Guida rapida

Negli ultimi due anni, il Deep Learning è diventato una grande tendenza nel Machine Learning. È stato applicato con successo per risolvere problemi precedentemente irrisolvibili in Vision, Speech Recognition and Natural Language Processing(PNL). Ci sono molti altri domini in cui il Deep Learning viene applicato e ha dimostrato la sua utilità.

Caffe (Convolutional Architecture for Fast Feature Embedding) è un framework di apprendimento profondo sviluppato presso Berkeley Vision and Learning Center (BVLC). Il progetto Caffe è stato creato da Yangqing Jia durante il suo dottorato di ricerca. presso l'Università della California - Berkeley. Caffe offre un modo semplice per sperimentare con il deep learning. È scritto in C ++ e fornisce collegamenti perPython e Matlab.

Supporta molti diversi tipi di architetture di apprendimento profondo come CNN (Rete neurale convoluzionale), LSTM(Memoria a lungo termine) e FC (completamente connesso). Supporta GPU ed è quindi ideale per ambienti di produzione che coinvolgono reti neurali profonde. Supporta anche le librerie del kernel basate su CPU comeNVIDIA, Libreria CUDA Deep Neural Network (cuDNN) e Intel Math Kernel Library (Intel MKL).

Nell'aprile 2017, Facebook, la società di servizi di social networking con sede negli Stati Uniti, ha annunciato Caffe2, che ora include RNN (Recurrent Neural Networks) e nel marzo 2018 Caffe2 è stato fuso in PyTorch. I creatori di Caffe2 e i membri della comunità hanno creato modelli per risolvere vari problemi. Questi modelli sono disponibili al pubblico come modelli pre-addestrati. Caffe2 aiuta i creatori nell'utilizzo di questi modelli e nella creazione della propria rete per fare previsioni sul dataset.

Prima di entrare nei dettagli di Caffe2, cerchiamo di capire la differenza tra machine learning e deep learning. Ciò è necessario per capire come vengono creati e utilizzati i modelli in Caffe2.

Machine learning v / s deep learning

In qualsiasi algoritmo di machine learning, sia esso tradizionale o deep learning, la selezione delle funzionalità nel set di dati gioca un ruolo estremamente importante per ottenere la precisione di previsione desiderata. Nelle tradizionali tecniche di machine learning, ilfeature selectionè fatto principalmente dall'ispezione umana, dal giudizio e dalla profonda conoscenza del dominio. A volte, potresti chiedere aiuto ad alcuni algoritmi testati per la selezione delle funzionalità.

Il flusso di machine learning tradizionale è illustrato nella figura seguente:

Nell'apprendimento profondo, la selezione delle funzionalità è automatica e fa parte dell'algoritmo di apprendimento profondo stesso. Questo è mostrato nella figura sotto:

Negli algoritmi di deep learning, feature engineeringviene fatto automaticamente. In genere, la progettazione delle funzionalità richiede tempo e una buona esperienza nel dominio. Per implementare l'estrazione automatica delle caratteristiche, gli algoritmi di deep learning richiedono in genere enormi quantità di dati, quindi se hai solo migliaia e decine di migliaia di punti dati, la tecnica di deep learning potrebbe non riuscire a darti risultati soddisfacenti.

Con dati più grandi, gli algoritmi di deep learning producono risultati migliori rispetto agli algoritmi ML tradizionali con un ulteriore vantaggio di ingegnerizzazione delle funzionalità minore o nulla.

Dopo aver acquisito alcune informazioni sul deep learning, diamo una panoramica di cosa è Caffe.

Formazione di una CNN

Impariamo il processo per addestrare una CNN a classificare le immagini. Il processo consiste nei seguenti passaggi:

  • Data Preparation- In questo passaggio, ritagliamo al centro le immagini e le ridimensioniamo in modo che tutte le immagini per l'addestramento e il test abbiano le stesse dimensioni. Questo di solito viene fatto eseguendo un piccolo script Python sui dati dell'immagine.

  • Model Definition- In questa fase, definiamo un'architettura CNN. La configurazione viene salvata in.pb (protobuf)file. Una tipica architettura CNN è mostrata nella figura seguente.

  • Solver Definition- Definiamo il file di configurazione del solutore. Il risolutore esegue l'ottimizzazione del modello.

  • Model Training- Usiamo l'utility Caffe incorporata per addestrare il modello. La formazione può richiedere una notevole quantità di tempo e utilizzo della CPU. Al termine della formazione, Caffe memorizza il modello in un file, che può essere utilizzato successivamente sui dati di test e sulla distribuzione finale per le previsioni.

Novità di Caffe2

In Caffe2, troverai molti modelli pre-addestrati pronti per l'uso e potrai anche sfruttare i contributi della comunità di nuovi modelli e algoritmi abbastanza frequentemente. I modelli che crei possono essere facilmente ampliati utilizzando la potenza della GPU nel cloud e possono anche essere ridotti all'uso di masse su dispositivi mobili con le sue librerie multipiattaforma.

I miglioramenti apportati a Caffe2 rispetto a Caffe possono essere riassunti come segue:

  • Distribuzione mobile
  • Nuovo supporto hardware
  • Supporto per formazione distribuita su larga scala
  • Calcolo quantizzato
  • Stress testato su Facebook

Demo modello pre-addestrato

Il sito Berkeley Vision and Learning Center (BVLC) fornisce demo delle loro reti pre-addestrate. Una di queste reti per la classificazione delle immagini è disponibile sul collegamento qui indicatohttps://caffe2.ai/docs/learn-more#null__caffe-neural-network-for-image-classification ed è raffigurato nello screenshot qui sotto.

Nello screenshot, l'immagine di un cane è classificata ed etichettata con la sua precisione di previsione. Dice anche che ci sono voluti solo0.068 secondsper classificare l'immagine. Puoi provare un'immagine di tua scelta specificando l'URL dell'immagine o caricando l'immagine stessa nelle opzioni fornite nella parte inferiore dello schermo.

Ora che hai abbastanza informazioni sulle capacità di Caffe2, è ora di sperimentare Caffe2 da solo. Per utilizzare i modelli pre-addestrati o per sviluppare i tuoi modelli nel tuo codice Python, devi prima installare Caffe2 sulla tua macchina.

Nella pagina di installazione del sito Caffe2 che è disponibile al link https://caffe2.ai/docs/getting-started.html vedrai quanto segue per selezionare la tua piattaforma e il tipo di installazione.

Come puoi vedere nello screenshot qui sopra, Caffe2 supporta diverse piattaforme popolari comprese quelle mobili.

Ora, capiremo i passaggi per MacOS installation su cui vengono testati tutti i progetti di questo tutorial.

Installazione su MacOS

L'installazione può essere di quattro tipi come indicato di seguito:

  • Binari predefiniti
  • Build From Source
  • Immagini Docker
  • Cloud

A seconda delle tue preferenze, seleziona uno dei precedenti come tipo di installazione. Le istruzioni fornite qui si riferiscono al sito di installazione di Caffe2 perpre-built binaries. Usa Anaconda perJupyter environment. Esegui il seguente comando sul prompt della console

pip install torch_nightly -f 
https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html

Oltre a quanto sopra, avrai bisogno di alcune librerie di terze parti, che vengono installate utilizzando i seguenti comandi:

conda install -c anaconda setuptools
conda install -c conda-forge graphviz  
conda install -c conda-forge hypothesis
conda install -c conda-forge ipython
conda install -c conda-forge jupyter
conda install -c conda-forge matplotlib
conda install -c anaconda notebook
conda install -c anaconda pydot
conda install -c conda-forge python-nvd3
conda install -c anaconda pyyaml
conda install -c anaconda requests
conda install -c anaconda scikit-image
conda install -c anaconda scipy

Alcuni dei tutorial nel sito Web di Caffe2 richiedono anche l'installazione di zeromq, che viene installato utilizzando il seguente comando:

conda install -c anaconda zeromq

Installazione Windows / Linux

Esegui il seguente comando sul prompt della console:

conda install -c pytorch pytorch-nightly-cpu

Come avrai notato, avresti bisogno di Anaconda per utilizzare l'installazione di cui sopra. Sarà necessario installare i pacchetti aggiuntivi come specificato inMacOS installation.

Installazione di prova

Per testare la tua installazione, di seguito viene fornito un piccolo script Python, che puoi tagliare e incollare nel tuo progetto Juypter ed eseguire.

from caffe2.python import workspace
import numpy as np
print ("Creating random data")
data = np.random.rand(3, 2)
print(data)
print ("Adding data to workspace ...")
workspace.FeedBlob("mydata", data)
print ("Retrieving data from workspace")
mydata = workspace.FetchBlob("mydata")
print(mydata)

Quando esegui il codice sopra, dovresti vedere il seguente output:

Creating random data
[[0.06152718 0.86448082]
[0.36409966 0.52786113]
[0.65780886 0.67101053]]
Adding data to workspace ...
Retrieving data from workspace
[[0.06152718 0.86448082]
[0.36409966 0.52786113]
[0.65780886 0.67101053]]

Lo screenshot della pagina di test dell'installazione è mostrato qui come riferimento rapido -

Ora che hai installato Caffe2 sulla tua macchina, procedi con l'installazione delle applicazioni tutorial.

Installazione del tutorial

Scarica il codice sorgente dei tutorial utilizzando il seguente comando sulla tua console:

git clone --recursive https://github.com/caffe2/tutorials caffe2_tutorials

Al termine del download, troverai diversi progetti Python nel file caffe2_tutorialscartella nella directory di installazione. Lo screenshot di questa cartella viene fornito per una rapida lettura.

/Users/yourusername/caffe2_tutorials

Puoi aprire alcuni di questi tutorial per vedere cosa è il file Caffe2 codesembra. I prossimi due progetti descritti in questo tutorial sono in gran parte basati sugli esempi mostrati sopra.

È ora il momento di fare un po 'di codice Python da soli. Cerchiamo di capire come utilizzare un modello pre-addestrato da Caffe2. Successivamente, imparerai a creare la tua banale rete neurale per l'addestramento sul tuo set di dati.

Prima di imparare a utilizzare un modello pre-addestrato nella tua applicazione Python, verifica che i modelli siano installati sulla tua macchina e siano accessibili tramite il codice Python.

Quando installi Caffe2, i modelli pre-addestrati vengono copiati nella cartella di installazione. Sulla macchina con installazione Anaconda, questi modelli sono disponibili nella seguente cartella.

anaconda3/lib/python3.7/site-packages/caffe2/python/models

Controlla la cartella di installazione sulla tua macchina per la presenza di questi modelli. Puoi provare a caricare questi modelli dalla cartella di installazione con il seguente breve script Python:

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)

Quando lo script viene eseguito correttamente, vedrai il seguente output:

/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/init_net.pb
/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/predict_net.pb

Ciò conferma che il squeezenet è installato sulla tua macchina ed è accessibile al tuo codice.

Ora sei pronto per scrivere il tuo codice Python per la classificazione delle immagini utilizzando Caffe2 squeezenet modulo pre-addestrato.

In questa lezione imparerai a utilizzare un modello pre-addestrato per rilevare oggetti in una data immagine. Useraisqueezenet modulo pre-addestrato che rileva e classifica gli oggetti in una data immagine con grande precisione.

Apri un nuovo file Juypter notebook e segui i passaggi per sviluppare questa applicazione di classificazione delle immagini.

Importazione di librerie

Innanzitutto, importiamo i pacchetti richiesti utilizzando il codice seguente:

from caffe2.proto import caffe2_pb2
from caffe2.python import core, workspace, models
import numpy as np
import skimage.io
import skimage.transform
from matplotlib import pyplot
import os
import urllib.request as urllib2
import operator

Successivamente, ne abbiamo impostati alcuni variables -

INPUT_IMAGE_SIZE = 227
mean = 128

Le immagini utilizzate per l'allenamento saranno ovviamente di varie dimensioni. Tutte queste immagini devono essere convertite in una dimensione fissa per un addestramento accurato. Allo stesso modo, anche le immagini di prova e l'immagine che si desidera prevedere nell'ambiente di produzione devono essere convertite nella dimensione, uguale a quella utilizzata durante l'addestramento. Quindi, creiamo una variabile sopra chiamataINPUT_IMAGE_SIZE avere valore 227. Quindi, convertiremo tutte le nostre immagini nella dimensione227x227 prima di usarlo nel nostro classificatore.

Dichiariamo anche una variabile chiamata mean avere valore 128, che viene utilizzato successivamente per migliorare i risultati della classificazione.

Successivamente, svilupperemo due funzioni per l'elaborazione dell'immagine.

Elaborazione delle immagini

L'elaborazione dell'immagine consiste in due fasi. Il primo è ridimensionare l'immagine e il secondo è ritagliare centralmente l'immagine. Per questi due passaggi, scriveremo due funzioni per il ridimensionamento e il ritaglio.

Ridimensionamento dell'immagine

Per prima cosa, scriveremo una funzione per ridimensionare l'immagine. Come detto prima, ridimensioneremo l'immagine a227x227. Quindi definiamo la funzioneresize come segue -

def resize(img, input_height, input_width):

Otteniamo le proporzioni dell'immagine dividendo la larghezza per l'altezza.

original_aspect = img.shape[1]/float(img.shape[0])

Se il rapporto di aspetto è maggiore di 1, indica che l'immagine è ampia, vale a dire che è in modalità orizzontale. Ora regoliamo l'altezza dell'immagine e restituiamo l'immagine ridimensionata utilizzando il codice seguente:

if(original_aspect>1):
   new_height = int(original_aspect * input_height)
   return skimage.transform.resize(img, (input_width,
   new_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Se le proporzioni sono less than 1, indica il portrait mode. Ora regoliamo la larghezza utilizzando il seguente codice:

if(original_aspect<1):
   new_width = int(input_width/original_aspect)
   return skimage.transform.resize(img, (new_width,
   input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Se il rapporto di aspetto è uguale a 1, non effettuiamo alcuna regolazione di altezza / larghezza.

if(original_aspect == 1):
   return skimage.transform.resize(img, (input_width,
   input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Il codice funzione completo è fornito di seguito per una rapida consultazione:

def resize(img, input_height, input_width):
   original_aspect = img.shape[1]/float(img.shape[0])
   if(original_aspect>1):
      new_height = int(original_aspect * input_height)
      return skimage.transform.resize(img, (input_width,
	   new_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)
   if(original_aspect<1):
         new_width = int(input_width/original_aspect)
         return skimage.transform.resize(img, (new_width,
         input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)
   if(original_aspect == 1):
         return skimage.transform.resize(img, (input_width,
         input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Scriveremo ora una funzione per ritagliare l'immagine attorno al suo centro.

Ritaglio dell'immagine

Dichiariamo il crop_image funzionare come segue:

def crop_image(img,cropx,cropy):

Estraiamo le dimensioni dell'immagine usando la seguente dichiarazione:

y,x,c = img.shape

Creiamo un nuovo punto di partenza per l'immagine utilizzando le seguenti due righe di codice:

startx = x//2-(cropx//2)
starty = y//2-(cropy//2)

Infine, restituiamo l'immagine ritagliata creando un oggetto immagine con le nuove dimensioni -

return img[starty:starty+cropy,startx:startx+cropx]

Di seguito viene fornito l'intero codice funzione per una rapida consultazione:

def crop_image(img,cropx,cropy):
   y,x,c = img.shape
   startx = x//2-(cropx//2)
   starty = y//2-(cropy//2)
   return img[starty:starty+cropy,startx:startx+cropx]

Ora scriveremo il codice per testare queste funzioni.

Elaborazione dell'immagine

Innanzitutto, copia un file immagine in images sottocartella all'interno della directory del progetto. tree.jpgil file viene copiato nel progetto. Il seguente codice Python carica l'immagine e la visualizza sulla console:

img = skimage.img_as_float(skimage.io.imread("images/tree.jpg")).astype(np.float32)
print("Original Image Shape: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Original image')

L'output è il seguente:

Nota che la dimensione dell'immagine originale è 600 x 960. Dobbiamo ridimensionarlo alla nostra specifica di227 x 227. Chiamando il nostro definito in precedenzaresizela funzione fa questo lavoro.

img = resize(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after resizing: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Resized image')

L'output è come indicato di seguito:

Nota che ora la dimensione dell'immagine è 227 x 363. Dobbiamo ritagliarlo su227 x 227per il feed finale al nostro algoritmo. Chiamiamo la funzione crop precedentemente definita per questo scopo.

img = crop_image(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after cropping: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Center Cropped')

Di seguito è menzionato l'output del codice:

A questo punto, l'immagine è di dimensioni 227 x 227ed è pronto per ulteriori elaborazioni. Scambiamo ora gli assi dell'immagine per estrarre i tre colori in tre zone differenti.

img = img.swapaxes(1, 2).swapaxes(0, 1)
print("CHW Image Shape: " , img.shape)

Di seguito è riportato l'output:

CHW Image Shape: (3, 227, 227)

Notare che l'ultimo asse è ora diventato la prima dimensione dell'array. Tracciamo ora i tre canali utilizzando il seguente codice:

pyplot.figure()
for i in range(3):
   pyplot.subplot(1, 3, i+1)
   pyplot.imshow(img[i])
   pyplot.axis('off')
   pyplot.title('RGB channel %d' % (i+1))

L'output è indicato di seguito:

Infine, eseguiamo alcune elaborazioni aggiuntive sull'immagine come la conversione Red Green Blue per Blue Green Red (RGB to BGR), rimuovendo la media per ottenere risultati migliori e aggiungendo l'asse delle dimensioni del batch utilizzando le seguenti tre righe di codice:

# convert RGB --> BGR
img = img[(2, 1, 0), :, :]
# remove mean
img = img * 255 - mean
# add batch size axis
img = img[np.newaxis, :, :, :].astype(np.float32)

A questo punto, la tua immagine è in formato NCHW formated è pronto per essere inserito nella nostra rete. Successivamente, caricheremo i nostri file di modello pre-addestrati e inseriremo l'immagine sopra per la previsione.

Previsione di oggetti nell'immagine elaborata

Per prima cosa impostiamo i percorsi per init e predict reti definite nei modelli pre-addestrati di Caffe.

Impostazione dei percorsi dei file del modello

Ricorda dalla nostra discussione precedente, tutti i modelli pre-addestrati sono installati in modelscartella. Abbiamo impostato il percorso di questa cartella come segue:

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")

Abbiamo impostato il percorso per il file init_net protobuf file di squeezenet modello come segue -

INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')

Allo stesso modo, abbiamo impostato il percorso per il file predict_net protobuf come segue -

PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')

Stampiamo i due percorsi a scopo diagnostico:

print(INIT_NET)
print(PREDICT_NET)

Il codice sopra insieme all'output viene fornito qui come riferimento rapido -

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)

L'output è menzionato di seguito:

/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/init_net.pb
/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/predict_net.pb

Successivamente, creeremo un predittore.

Creazione del predittore

Leggiamo i file del modello utilizzando le seguenti due istruzioni:

with open(INIT_NET, "rb") as f:
   init_net = f.read()
with open(PREDICT_NET, "rb") as f:
   predict_net = f.read()

Il predittore viene creato passando i puntatori ai due file come parametri al file Predictor funzione.

p = workspace.Predictor(init_net, predict_net)

Il poggetto è il predittore, che viene utilizzato per prevedere gli oggetti in una data immagine. Nota che ogni immagine di input deve essere in formato NCHW come quello che abbiamo fatto in precedenza al nostrotree.jpg file.

Previsione di oggetti

Prevedere gli oggetti in una data immagine è banale: basta eseguire una singola riga di comando. Noi chiamiamorun metodo sul predictor oggetto per il rilevamento di un oggetto in una data immagine.

results = p.run({'data': img})

I risultati della previsione sono ora disponibili in results oggetto, che convertiamo in un array per la nostra leggibilità.

results = np.asarray(results)

Stampa le dimensioni dell'array per la tua comprensione utilizzando la seguente dichiarazione:

print("results shape: ", results.shape)

L'output è come mostrato di seguito:

results shape: (1, 1, 1000, 1, 1)

Ora rimuoveremo l'asse non necessario -

preds = np.squeeze(results)

La previsione più in alto può ora essere recuperata prendendo il file max valore in preds Vettore.

curr_pred, curr_conf = max(enumerate(preds), key=operator.itemgetter(1))
print("Prediction: ", curr_pred)
print("Confidence: ", curr_conf)

L'output è il seguente:

Prediction: 984
Confidence: 0.89235985

Come vedi il modello ha previsto un oggetto con un valore di indice 984 con 89%fiducia. L'indice di 984 non ha molto senso per noi per capire che tipo di oggetto viene rilevato. Dobbiamo ottenere il nome in stringa per l'oggetto usando il suo valore di indice. Il tipo di oggetti che il modello riconosce insieme ai valori di indice corrispondenti sono disponibili in un repository GitHub.

Ora vedremo come recuperare il nome per il nostro oggetto con valore di indice 984.

Risultato stringente

Creiamo un oggetto URL nel repository github come segue:

codes = "https://gist.githubusercontent.com/aaronmarkham/cd3a6b6ac0
71eca6f7b4a6e40e6038aa/raw/9edb4038a37da6b5a44c3b5bc52e448ff09bfe5b/alexnet_codes"

Leggiamo il contenuto dell'URL -

response = urllib2.urlopen(codes)

La risposta conterrà un elenco di tutti i codici e le relative descrizioni. Di seguito vengono mostrate alcune righe della risposta per la tua comprensione di ciò che contiene:

5: 'electric ray, crampfish, numbfish, torpedo',
6: 'stingray',
7: 'cock',
8: 'hen',
9: 'ostrich, Struthio camelus',
10: 'brambling, Fringilla montifringilla',

Ora iteriamo l'intero array per individuare il codice 984 desiderato utilizzando un file for loop come segue -

for line in response:
   mystring = line.decode('ascii')
   code, result = mystring.partition(":")[::2]
   code = code.strip()
   result = result.replace("'", "")
   if (code == str(curr_pred)):
      name = result.split(",")[0][1:]
      print("Model predicts", name, "with", curr_conf, "confidence")

Quando esegui il codice, vedrai il seguente output:

Model predicts rapeseed with 0.89235985 confidence

Ora puoi provare il modello su un'altra immagine.

Previsione di un'immagine diversa

Per prevedere un'altra immagine, copia semplicemente il file immagine nel file imagescartella della directory del progetto. Questa è la directory in cui il nostro precedentetree.jpgil file viene memorizzato. Cambia il nome del file immagine nel codice. È necessaria una sola modifica come mostrato di seguito

img = skimage.img_as_float(skimage.io.imread("images/pretzel.jpg")).astype(np.float32)

L'immagine originale e il risultato della previsione sono mostrati di seguito:

L'output è menzionato di seguito:

Model predicts pretzel with 0.99999976 confidence

Come puoi vedere, il modello pre-addestrato è in grado di rilevare gli oggetti in una data immagine con una grande precisione.

Fonte completa

La fonte completa per il codice precedente che utilizza un modello pre-addestrato per il rilevamento di oggetti in una determinata immagine è menzionata qui per una rapida consultazione -

def crop_image(img,cropx,cropy):
   y,x,c = img.shape
   startx = x//2-(cropx//2)
   starty = y//2-(cropy//2)
   return img[starty:starty+cropy,startx:startx+cropx]
img = skimage.img_as_float(skimage.io.imread("images/pretzel.jpg")).astype(np.float32)
print("Original Image Shape: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Original image')
img = resize(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after resizing: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Resized image')
img = crop_image(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after cropping: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Center Cropped')
img = img.swapaxes(1, 2).swapaxes(0, 1)
print("CHW Image Shape: " , img.shape)
pyplot.figure()
for i in range(3):
pyplot.subplot(1, 3, i+1)
pyplot.imshow(img[i])
pyplot.axis('off')
pyplot.title('RGB channel %d' % (i+1))
# convert RGB --> BGR
img = img[(2, 1, 0), :, :]
# remove mean
img = img * 255 - mean
# add batch size axis
img = img[np.newaxis, :, :, :].astype(np.float32)
CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)
with open(INIT_NET, "rb") as f:
   init_net = f.read()
with open(PREDICT_NET, "rb") as f:
   predict_net = f.read()
p = workspace.Predictor(init_net, predict_net)
results = p.run({'data': img})
results = np.asarray(results)
print("results shape: ", results.shape)
preds = np.squeeze(results)
curr_pred, curr_conf = max(enumerate(preds), key=operator.itemgetter(1))
print("Prediction: ", curr_pred)
print("Confidence: ", curr_conf)
codes = "https://gist.githubusercontent.com/aaronmarkham/cd3a6b6ac071eca6f7b4a6e40e6038aa/raw/9edb4038a37da6b5a44c3b5bc52e448ff09bfe5b/alexnet_codes"
response = urllib2.urlopen(codes)
for line in response:
   mystring = line.decode('ascii')
   code, result = mystring.partition(":")[::2]
   code = code.strip()
   result = result.replace("'", "")
   if (code == str(curr_pred)):
      name = result.split(",")[0][1:]
      print("Model predicts", name, "with", curr_conf, "confidence")

A questo punto, sai come utilizzare un modello pre-addestrato per eseguire le previsioni sul tuo set di dati.

Il passo successivo è imparare a definire il tuo neural network (NN) architetture in Caffe2e addestrali sul tuo set di dati. Ora impareremo come creare un banale NN a singolo strato.

In questa lezione imparerai a definire un file single layer neural network (NN)in Caffe2 ed eseguirlo su un set di dati generato casualmente. Scriveremo codice per rappresentare graficamente l'architettura di rete, input di stampa, output, pesi e valori di polarizzazione. Per capire questa lezione, devi avere familiarità conneural network architectures, suo terms e mathematics utilizzato in loro.

Architettura di rete

Consideriamo di voler costruire un NN a singolo strato come mostrato nella figura sotto -

Matematicamente, questa rete è rappresentata dal seguente codice Python:

Y = X * W^T + b

Dove X, W, b sono tensori e Yè l'output. Riempiremo tutti e tre i tensori con alcuni dati casuali, eseguiremo la rete ed esamineremo il fileYproduzione. Per definire la rete e i tensori, Caffe2 ne fornisce diversiOperator funzioni.

Operatori Caffe2

In Caffe2, Operatorè l'unità di calcolo di base. Il Caffe2Operator è rappresentato come segue.

Caffe2 fornisce un elenco esaustivo di operatori. Per la rete che stiamo progettando attualmente, utilizzeremo l'operatore chiamato FC, che calcola il risultato del passaggio di un vettore di inputX in una rete completamente connessa con una matrice di peso bidimensionale W e un vettore bias monodimensionale b. In altre parole, calcola la seguente equazione matematica

Y = X * W^T + b

Dove X ha dimensioni (M x k), W ha dimensioni (n x k) e b è (1 x n). Il risultatoY sarà di dimensione (M x n), dove M è la dimensione del batch.

Per i vettori X e W, useremo il GaussianFilloperatore per creare alcuni dati casuali. Per generare valori di biasb, noi useremo ConstantFill operatore.

Procederemo ora a definire la nostra rete.

Creazione di rete

Prima di tutto, importa i pacchetti richiesti -

from caffe2.python import core, workspace

Quindi, definire la rete chiamando core.Net come segue -

net = core.Net("SingleLayerFC")

Il nome della rete è specificato come SingleLayerFC. A questo punto, viene creato l'oggetto di rete denominato net. Finora non contiene alcun livello.

Creazione di tensori

Creeremo ora i tre vettori richiesti dalla nostra rete. Innanzitutto, creeremo il tensore X chiamandoGaussianFill operatore come segue -

X = net.GaussianFill([], ["X"], mean=0.0, std=1.0, shape=[2, 3], run_once=0)

Il X il vettore ha dimensioni 2 x 3 con il valore medio dei dati di 0,0 e la deviazione standard di 1.0.

Allo stesso modo, creiamo W tensore come segue -

W = net.GaussianFill([], ["W"], mean=0.0, std=1.0, shape=[5, 3], run_once=0)

Il W il vettore è di dimensioni 5 x 3.

Infine, creiamo pregiudizi b matrice di dimensione 5.

b = net.ConstantFill([], ["b"], shape=[5,], value=1.0, run_once=0)

Ora, arriva la parte più importante del codice e questa è la definizione della rete stessa.

Definizione di rete

Definiamo la rete nella seguente istruzione Python:

Y = X.FC([W, b], ["Y"])

Noi chiamiamo FC operatore sui dati di input X. I pesi sono specificati inWe bias in b. L'output èY. In alternativa, puoi creare la rete utilizzando la seguente istruzione Python, che è più dettagliata.

Y = net.FC([X, W, b], ["Y"])

A questo punto, la rete viene semplicemente creata. Fino a quando non eseguiremo la rete almeno una volta, non conterrà alcun dato. Prima di eseguire la rete, esamineremo la sua architettura.

Architettura di rete di stampa

Caffe2 definisce l'architettura di rete in un file JSON, che può essere esaminato chiamando il metodo Proto sul file net oggetto.

print (net.Proto())

Questo produce il seguente output:

name: "SingleLayerFC"
op {
   output: "X"
   name: ""
   type: "GaussianFill"
   arg {
      name: "mean"
      f: 0.0
   }
   arg {
      name: "std"
      f: 1.0
   }
   arg {
      name: "shape"
      ints: 2
      ints: 3
   }
   arg {
      name: "run_once"
      i: 0
   }
}
op {
   output: "W"
   name: ""
   type: "GaussianFill"
   arg {
      name: "mean"
      f: 0.0
   }
   arg {
      name: "std"
      f: 1.0
   }
   arg {
      name: "shape"
      ints: 5
      ints: 3
   }
   arg {
      name: "run_once"
      i: 0
   }
}
op {
   output: "b"
   name: ""
   type: "ConstantFill"
   arg {
      name: "shape"
      ints: 5
   }
   arg {
      name: "value"
      f: 1.0
   }
   arg {
      name: "run_once"
      i: 0
   }
}
op {
   input: "X"
   input: "W"
   input: "b"
   output: "Y"
   name: ""
   type: "FC"
}

Come puoi vedere nell'elenco sopra, definisce prima gli operatori X, W e b. Esaminiamo la definizione diWcome esempio. Il tipo diW è specificato come GausianFill. Ilmean è definito come float 0.0, la deviazione standard è definita float 1.0, e il shape è 5 x 3.

op {
   output: "W"
   name: "" type: "GaussianFill"
   arg {
      name: "mean" 
	   f: 0.0
   }
   arg { 
      name: "std" 
      f: 1.0
   }
   arg { 
      name: "shape" 
      ints: 5 
      ints: 3
   }
   ...
}

Esamina le definizioni di X e bper la tua comprensione. Infine, esaminiamo la definizione della nostra rete a strato singolo, che viene riprodotta qui

op {
   input: "X"
   input: "W"
   input: "b"
   output: "Y"
   name: ""
   type: "FC"
}

Qui, il tipo di rete è FC (Completamente connesso) con X, W, b come input e Yè l'output. Questa definizione di rete è troppo prolissa e per reti di grandi dimensioni diventerà noioso esaminarne il contenuto. Fortunatamente, Caffe2 fornisce una rappresentazione grafica delle reti create.

Rappresentazione grafica di rete

Per ottenere la rappresentazione grafica della rete, esegui il seguente frammento di codice, che è essenzialmente solo due righe di codice Python.

from caffe2.python import net_drawer
from IPython import display
graph = net_drawer.GetPydotGraph(net, rankdir="LR")
display.Image(graph.create_png(), width=800)

Quando esegui il codice, vedrai il seguente output:

Per reti di grandi dimensioni, la rappresentazione grafica diventa estremamente utile per visualizzare ed eseguire il debug degli errori di definizione della rete.

Infine, è ora il momento di eseguire la rete.

Rete in esecuzione

Gestisci la rete chiamando il RunNetOnce metodo sul workspace oggetto -

workspace.RunNetOnce(net)

Dopo che la rete è stata eseguita una volta, tutti i nostri dati generati a caso verranno creati, inseriti nella rete e verrà creato l'output. Vengono chiamati i tensori che vengono creati dopo aver eseguito la reteblobsin Caffe2. Lo spazio di lavoro è costituito dablobscreate e archiviate in memoria. Questo è abbastanza simile a Matlab.

Dopo aver eseguito la rete, puoi esaminare il file blobs che l'area di lavoro contiene utilizzando quanto segue print comando

print("Blobs in the workspace: {}".format(workspace.Blobs()))

Vedrai il seguente output:

Blobs in the workspace: ['W', 'X', 'Y', 'b']

Si noti che l'area di lavoro è composta da tre BLOB di input: X, W e b. Contiene anche il BLOB di output chiamatoY. Esaminiamo ora il contenuto di questi blob.

for name in workspace.Blobs():
   print("{}:\n{}".format(name, workspace.FetchBlob(name)))

Vedrai il seguente output:

W:
[[ 1.0426593 0.15479846 0.25635982]
[-2.2461145 1.4581774 0.16827184]
[-0.12009818 0.30771437 0.00791338]
[ 1.2274994 -0.903331 -0.68799865]
[ 0.30834186 -0.53060573 0.88776857]]
X:
[[ 1.6588869e+00 1.5279824e+00 1.1889904e+00]
[ 6.7048723e-01 -9.7490678e-04 2.5114202e-01]]
Y:
[[ 3.2709925 -0.297907 1.2803618 0.837985 1.7562964]
[ 1.7633215 -0.4651525 0.9211631 1.6511179 1.4302125]]
b:
[1. 1. 1. 1. 1.]

Nota che i dati sulla tua macchina o di fatto su ogni corsa della rete sarebbero diversi poiché tutti gli input sono creati in modo casuale. Ora hai definito con successo una rete ed eseguila sul tuo computer.

Nella lezione precedente, hai imparato a creare una rete banale e hai imparato come eseguirla ed esaminarne l'output. Il processo per creare reti complesse è simile al processo descritto sopra. Caffe2 fornisce una vasta gamma di operatori per la creazione di architetture complesse. Sei incoraggiato a esaminare la documentazione di Caffe2 per un elenco di operatori. Dopo aver studiato lo scopo dei vari operatori, saresti in grado di creare reti complesse e addestrarli. Per addestrare la rete, Caffe2 ne fornisce diversipredefined computation units- cioè gli operatori. Dovrai selezionare gli operatori appropriati per addestrare la tua rete al tipo di problema che stai cercando di risolvere.

Una volta che una rete è stata addestrata in modo soddisfacente, è possibile memorizzarla in un file di modello simile ai file di modello pre-addestrati utilizzati in precedenza. Questi modelli addestrati possono essere aggiunti al repository Caffe2 a vantaggio di altri utenti. Oppure puoi semplicemente mettere il modello addestrato per il tuo uso di produzione privato.

Sommario

Caffe2, che è un framework di apprendimento profondo, ti consente di sperimentare diversi tipi di reti neurali per prevedere i tuoi dati. Il sito Caffe2 fornisce molti modelli pre-addestrati. Hai imparato a utilizzare uno dei modelli pre-addestrati per classificare gli oggetti in una data immagine. Hai anche imparato a definire un'architettura di rete neurale di tua scelta. Tali reti personalizzate possono essere addestrate utilizzando molti operatori predefiniti in Caffe. Un modello addestrato viene memorizzato in un file che può essere portato in un ambiente di produzione.