📜  Caffe2-创建自己的网络

📅  最后修改于: 2020-12-11 04:49:02             🧑  作者: Mango


在本课程中,您将学习在Caffe2中定义一个单层神经网络(NN)并在随机生成的数据集上运行它。我们将编写代码以图形方式描述网络体系结构,打印输入,输出,权重和偏差值。要理解本课程,您必须熟悉神经网络架构及其中使用的术语数学方法。

网络架构

让我们考虑一下,我们想要构建一个单层NN,如下图所示:

网络架构

从数学上讲,此网络由以下Python代码表示-

Y = X * W^T + b

其中X,W,b是张量, Y是输出。我们将使用一些随机数据填充所有三个张量,运行网络并检查Y输出。为了定义网络和张量,Caffe2提供了几种操作员功能。

Caffe2运算子

在Caffe2中,运算符是计算的基本单位。 Caffe2运算符表示如下。

Caffe2运算子

Caffe2提供了详尽的运算符列表。对于当前正在设计的网络,我们将使用名为FC的运算符,该运算符将输入矢量X传递到具有二维权重矩阵W和一维偏差矢量b的完全连接的网络中的结果。换句话说,它计算以下数学方程式

Y = X * W^T + b

其中X的尺寸为(M xk),W的尺寸为(nxk)b(1 xn) 。输出Y的尺寸为(M xn) ,其中M为批次大小。

对于向量XW ,我们将使用GaussianFill运算符创建一些随机数据。为了生成偏差值b ,我们将使用ConstantFill运算符。

现在,我们将继续定义我们的网络。

建立网络

首先,导入所需的软件包-

from caffe2.python import core, workspace

接下来,通过调用core.Net定义网络,如下所示:

net = core.Net("SingleLayerFC")

网络的名称指定为SingleLayerFC 。至此,创建了称为net的网络对象。到目前为止,它不包含任何层。

创建张量

现在,我们将创建网络所需的三个向量。首先,我们将通过调用GaussianFill运算符来创建X张量,如下所示:

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

X向量的尺寸为2 x 3 ,平均数据值为0,0,标准差为1.0

同样,我们按如下方式创建W张量-

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

W向量的大小为5 x 3

最后,我们创建大小为5的偏差b矩阵。

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

现在,代码最重要的部分出现了,那就是定义网络本身。

定义网络

我们在以下Python语句中定义网络-

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

我们在输入数据X上调用FC运算符。权重以W表示,偏差以b表示。输出为Y。或者,您可以使用下面的Python语句(更详细)来创建网络。

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

至此,网络已创建完毕。在我们至少运行一次网络之前,它将不包含任何数据。在运行网络之前,我们将检查其体系结构。

印刷网络架构

Caffe2在JSON文件中定义了网络体系结构,可以通过在创建的net对象上调用Proto方法来对其进行检查。

print (net.Proto())

这产生以下输出-

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

从上面的清单中可以看到,它首先定义了运算符X,Wb 。让我们以W的定义为例。 W的类型指定为GausianFill平均值定义为float 0.0 ,标准偏差定义为float 1.0形状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
   }
   ...
}

为了自己的理解,请检查Xb的定义。最后,让我们看一下我们的单层网络的定义,在此复制

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

在此,网络类型为FC (完全连接),其中X,W,b为输入, Y为输出。该网络定义过于冗长,对于大型网络,检查其内容将变得很乏味。幸运的是,Caffe2为创建的网络提供了图形表示。

网络图形表示

要获取网络的图形表示,请运行以下代码段,该代码段实际上只是两行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)

运行代码时,您将看到以下输出-

图示

对于大型网络,图形表示对于可视化和调试网络定义错误非常有用。

最后,现在该运行网络了。

正在运行的网络

您可以通过在工作空间对象上调用RunNetOnce方法来运行网络-

workspace.RunNetOnce(net)

网络运行一次后,将创建我们随机生成的所有数据,并将其输入网络并创建输出。运行网络后创建的张量在Caffe2中称为Blob 。工作区由您创建并存储在内存中的Blob组成。这与Matlab非常相似。

运行网络后,您可以使用以下打印命令检查工作空间中包含的斑点

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

您将看到以下输出-

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

请注意,工作空间由三个输入Blob- X,Wb组成。它还包含名为Y的输出Blob。现在让我们检查这些blob的内容。

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

您将看到以下输出-

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

请注意,由于所有输入都是随机创建的,因此计算机上的数据或实际上在网络的每次运行中的数据都将有所不同。现在,您已经成功定义了网络并在计算机上运行它。