Caffe2 - Criando sua própria rede

Nesta lição, você aprenderá a definir um single layer neural network (NN)no Caffe2 e execute-o em um conjunto de dados gerado aleatoriamente. Escreveremos código para representar graficamente a arquitetura da rede, imprimir a entrada, a saída, os pesos e os valores de polarização. Para entender esta lição, você deve estar familiarizado comneural network architectures, Está terms e mathematics usado neles.

Arquitetura de rede

Vamos considerar que queremos construir uma única camada NN como mostrado na figura abaixo -

Matematicamente, esta rede é representada pelo seguinte código Python -

Y = X * W^T + b

Onde X, W, b são tensores e Yé a saída. Vamos preencher todos os três tensores com alguns dados aleatórios, executar a rede e examinar oYresultado. Para definir a rede e os tensores, Caffe2 fornece váriosOperator funções.

Operadores Caffe2

No Caffe2, Operatoré a unidade básica de computação. The Caffe2Operator é representado da seguinte forma.

Caffe2 fornece uma lista exaustiva de operadores. Para a rede que estamos projetando atualmente, usaremos o operador chamado FC, que calcula o resultado da passagem de um vetor de entradaX em uma rede totalmente conectada com uma matriz de peso bidimensional W e um vetor de polarização unidimensional b. Em outras palavras, ele calcula a seguinte equação matemática

Y = X * W^T + b

Onde X tem dimensões (M x k), W tem dimensões (n x k) e b é (1 x n). A saídaY será de dimensão (M x n), Onde M é o tamanho do lote.

Para os vetores X e W, vamos usar o GaussianFilloperador para criar alguns dados aleatórios. Para gerar valores de polarizaçãob, nós vamos usar ConstantFill operador.

Vamos agora definir nossa rede.

Criando Rede

Em primeiro lugar, importe os pacotes necessários -

from caffe2.python import core, workspace

Em seguida, defina a rede chamando core.Net como segue -

net = core.Net("SingleLayerFC")

O nome da rede é especificado como SingleLayerFC. Nesse ponto, o objeto de rede denominado net é criado. Ele não contém nenhuma camada até o momento.

Criação de tensores

Vamos agora criar os três vetores exigidos por nossa rede. Primeiro, criaremos o tensor X chamandoGaussianFill operador da seguinte forma -

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

o X vetor tem dimensões 2 x 3 com o valor médio dos dados de 0,0 e desvio padrão de 1.0.

Da mesma forma, nós criamos W tensor da seguinte forma -

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

o W vetor é do tamanho 5 x 3.

Finalmente, criamos viés b matriz de tamanho 5.

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

Agora, vem a parte mais importante do código, que é definir a própria rede.

Definindo Rede

Definimos a rede na seguinte instrução Python -

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

Nós chamamos FC operador nos dados de entrada X. Os pesos são especificados emWe viés em b. A saída éY. Como alternativa, você pode criar a rede usando a seguinte instrução Python, que é mais detalhada.

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

Nesse ponto, a rede é simplesmente criada. Até que executemos a rede pelo menos uma vez, ela não conterá nenhum dado. Antes de executar a rede, examinaremos sua arquitetura.

Arquitetura de rede de impressão

Caffe2 define a arquitetura de rede em um arquivo JSON, que pode ser examinado chamando o método Proto no net objeto.

print (net.Proto())

Isso produz a seguinte saída -

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

Como você pode ver na lista acima, primeiro define os operadores X, W e b. Vamos examinar a definição deWcomo um exemplo. O tipo deW é especificado como GausianFill. omean é definido como flutuante 0.0, o desvio padrão é definido como flutuante 1.0, e as 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
   }
   ...
}

Examine as definições de X e bpara seu próprio entendimento. Finalmente, vamos dar uma olhada na definição de nossa rede de camada única, que é reproduzida aqui

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

Aqui, o tipo de rede é FC (Totalmente conectado) com X, W, b como entradas e Yé a saída. Essa definição de rede é muito detalhada e, para redes grandes, será tedioso examinar seu conteúdo. Felizmente, Caffe2 fornece uma representação gráfica para as redes criadas.

Representação Gráfica da Rede

Para obter a representação gráfica da rede, execute o seguinte trecho de código, que é essencialmente apenas duas linhas de código 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)

Ao executar o código, você verá a seguinte saída -

Para grandes redes, a representação gráfica torna-se extremamente útil na visualização e depuração de erros de definição de rede.

Finalmente, é hora de operar a rede.

Rede em execução

Você administra a rede chamando o RunNetOnce método no workspace objeto -

workspace.RunNetOnce(net)

Depois que a rede é executada uma vez, todos os nossos dados que são gerados aleatoriamente seriam criados, alimentados na rede e a saída seria criada. Os tensores que são criados após a execução da rede são chamadosblobsem Caffe2. O espaço de trabalho consiste noblobsvocê cria e armazena na memória. Isso é bastante semelhante ao Matlab.

Depois de executar a rede, você pode examinar o blobs que o espaço de trabalho contém usando o seguinte print comando

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

Você verá a seguinte saída -

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

Observe que o espaço de trabalho consiste em três blobs de entrada - X, W e b. Ele também contém o blob de saída chamadoY. Vamos agora examinar o conteúdo desses blobs.

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

Você verá a seguinte saída -

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

Observe que os dados em sua máquina ou na verdade em cada execução da rede seriam diferentes, pois todas as entradas são criadas aleatoriamente. Agora você definiu com êxito uma rede e a executou em seu computador.