Caffe2 - Créer votre propre réseau

Dans cette leçon, vous apprendrez à définir un single layer neural network (NN)dans Caffe2 et exécutez-le sur un ensemble de données généré aléatoirement. Nous allons écrire du code pour représenter graphiquement l'architecture du réseau, imprimer l'entrée, la sortie, les poids et les valeurs de biais. Pour comprendre cette leçon, vous devez être familiarisé avecneural network architectures, son terms et mathematics utilisé en eux.

Architecture de réseau

Considérons que nous voulons construire une seule couche NN comme le montre la figure ci-dessous -

Mathématiquement, ce réseau est représenté par le code Python suivant -

Y = X * W^T + b

X, W, b sont des tenseurs et Yest la sortie. Nous allons remplir les trois tenseurs avec des données aléatoires, exécuter le réseau et examiner leYproduction. Pour définir le réseau et les tenseurs, Caffe2 fournit plusieursOperator les fonctions.

Opérateurs Caffe2

Dans Caffe2, Operatorest l'unité de base du calcul. Le Caffe2Operator est représenté comme suit.

Caffe2 fournit une liste exhaustive d'opérateurs. Pour le réseau que nous concevons actuellement, nous utiliserons l'opérateur appelé FC, qui calcule le résultat du passage d'un vecteur d'entréeX dans un réseau entièrement connecté avec une matrice de poids bidimensionnelle W et un vecteur de biais unidimensionnel b. En d'autres termes, il calcule l'équation mathématique suivante

Y = X * W^T + b

X a des dimensions (M x k), W a des dimensions (n x k) et b est (1 x n). Le résultatY sera de dimension (M x n), où M est la taille du lot.

Pour les vecteurs X et W, nous utiliserons le GaussianFillopérateur pour créer des données aléatoires. Pour générer des valeurs de biaisb, nous utiliserons ConstantFill opérateur.

Nous allons maintenant procéder à la définition de notre réseau.

Créer un réseau

Tout d'abord, importez les packages requis -

from caffe2.python import core, workspace

Ensuite, définissez le réseau en appelant core.Net comme suit -

net = core.Net("SingleLayerFC")

Le nom du réseau est spécifié comme SingleLayerFC. À ce stade, l'objet réseau appelé net est créé. Il ne contient aucune couche pour le moment.

Création de tenseurs

Nous allons maintenant créer les trois vecteurs requis par notre réseau. Tout d'abord, nous allons créer un tenseur X en appelantGaussianFill opérateur comme suit -

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

le X le vecteur a des dimensions 2 x 3 avec la valeur moyenne des données de 0,0 et l'écart type de 1.0.

De même, nous créons W tenseur comme suit -

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

le W le vecteur est de taille 5 x 3.

Enfin, nous créons des biais b matrice de taille 5.

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

Maintenant, vient la partie la plus importante du code et qui définit le réseau lui-même.

Définition du réseau

Nous définissons le réseau dans l'instruction Python suivante -

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

Nous appelons FC opérateur sur les données d'entrée X. Les poids sont spécifiés dansWet biais en b. La sortie estY. Vous pouvez également créer le réseau à l'aide de l'instruction Python suivante, qui est plus détaillée.

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

À ce stade, le réseau est simplement créé. Tant que nous n'exécutons pas le réseau au moins une fois, il ne contiendra aucune donnée. Avant d'exécuter le réseau, nous examinerons son architecture.

Architecture de réseau d'impression

Caffe2 définit l'architecture réseau dans un fichier JSON, qui peut être examiné en appelant la méthode Proto sur le net objet.

print (net.Proto())

Cela produit la sortie suivante -

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"
}

Comme vous pouvez le voir dans la liste ci-dessus, il définit d'abord les opérateurs X, W et b. Examinons la définition deWpar exemple. Le type deW est spécifié comme GausianFill. lemean est défini comme float 0.0, l'écart type est défini comme flottant 1.0, et le shape est 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
   }
   ...
}

Examiner les définitions de X et bpour votre propre compréhension. Enfin, regardons la définition de notre réseau monocouche, qui est reproduite ici

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

Ici, le type de réseau est FC (Entièrement connecté) avec X, W, b comme entrées et Yest la sortie. Cette définition de réseau est trop verbeuse et pour les grands réseaux, il deviendra fastidieux d'examiner son contenu. Heureusement, Caffe2 fournit une représentation graphique des réseaux créés.

Représentation graphique du réseau

Pour obtenir la représentation graphique du réseau, exécutez l'extrait de code suivant, qui ne comprend essentiellement que deux lignes de code 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)

Lorsque vous exécutez le code, vous verrez la sortie suivante -

Pour les grands réseaux, la représentation graphique devient extrêmement utile pour visualiser et déboguer les erreurs de définition de réseau.

Enfin, il est maintenant temps de faire fonctionner le réseau.

Réseau en cours d'exécution

Vous exécutez le réseau en appelant le RunNetOnce méthode sur le workspace objet -

workspace.RunNetOnce(net)

Une fois le réseau exécuté une fois, toutes nos données générées au hasard seraient créées, introduites dans le réseau et la sortie sera créée. Les tenseurs créés après l'exécution du réseau sont appelésblobsdans Caffe2. L'espace de travail se compose dublobsvous créez et stockez en mémoire. Ceci est assez similaire à Matlab.

Après avoir exécuté le réseau, vous pouvez examiner le blobs que l'espace de travail contient en utilisant les éléments suivants print commander

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

Vous verrez la sortie suivante -

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

Notez que l'espace de travail se compose de trois objets blob d'entrée - X, W et b. Il contient également l'objet blob de sortie appeléY. Examinons maintenant le contenu de ces blobs.

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

Vous verrez la sortie suivante -

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.]

Notez que les données sur votre machine ou en fait sur chaque exécution du réseau seraient différentes car toutes les entrées sont créées au hasard. Vous avez maintenant défini avec succès un réseau et l'exécutez sur votre ordinateur.