caffe2 operator的官方文档
一些常用的operator及简要说明
-
Append
将两个tensor在第一个维度上拼接,将第一个维度视作batch的维度,要求:in-place output ,输出的blob和输入的第一个blob一致。
input1: a1xbxc
input2: a2xbxc
output:(input1) (a1+a2)xbxc
该op好像不支持在gpu下的反向 -
BatchGather 沿bs按索引取值
按照给定的行号/列号/channel号,获取batch中每个样本的tensor的部分feature,默认第一个维度是batch size。
BatchGather([data, index]). 如:index为[[2:4],[5:7]],那么将返回data[:,2:4,5:7]的特征。 -
BooleanMask 按照bool型的掩膜取值
给定掩膜(mask),在data_tensor中按照mask中为True的位置,取出相应数据。
该op好像不支持在gpu下的反向 -
Reshape
input:data1, data2
output: shaped_data, original_shape
arguments: shape(当第一个input不存在时,自动使用shape参数)
功能:按照data2的shape,对data1进行reshape,data2可以不输入,不输入时,按照参数shape确定形状。
看到的代码中调用Reshape都是model.Reshape(xxx),其余函数都是model.net.function(xx),具体什么区别还没看。 -
Tile 在某一维度复制整个tensor
input: data:等待被复制的数据
arguments: tiles: 复制的倍数。 axis: 拼接的维度
例如:
data size 3x4x5
tiles: 7
axis: 1
output: 3x(4x7)x5
注意该函数往往需要配合Reshape使用,caffe2是否有将数据复制后直接新增一个维度的函数?
注意该函数的后项传播看起来不正确,应避免使用。 -
DiagonalFill 初始化一个对角阵
input: []
argument: value: 对角线的值。shape: 对角阵的size,此处注意如果高于2维,需要各个维度相等。dtype:对角阵的数据类型,如果不输入,缺省与value保持一致。 -
ConstantFill 初始化一个常量矩阵,每个元素的值相同。
input: []
argument: value: 矩阵中元素的值(所有元素的值相同),可以用来构建全1矩阵;shape;dtype:数据类型,dtype为1表示float, 2int, 具体见c++实现。 -
Scale 对tensor中的每一个元素做放缩
input: data
argument: scale: 放缩的倍数 -
BatchMatMul 带有bs维度的两个tensor做矩阵乘法
input: data1 :bsxd1xd2. data2: bsxd2xd3
output: bsxd1xd3
argument: trans_a: 将data1的最后两个维度转制;trans_b同理;broadcast: 自动对某一维度broadcast,但是加上该参数的话,不支持后向。
注:该函数如果不使用broadcast,那么需要两个乘数都带有bs维度。 -
Mul 各个元素点乘
input: data1 bsxd1xd2x…xdn. data2: bsxd1xd2x…xdn
output: bsxd1xd2x…xdn
argument: broadcast;axis。
支持沿着axis做broadcast,支持gpu的后向。 -
ReduceSum 将某维度所有元素相加
input: data
arguments: axes在该维度上所有元素相加; keepdimensions是否保持input的dimension,default=1.
例如 data bsxd1xd2xd3xd4. axes=(2,3) output:bsxd1x1xd4 -
Range 生成等差数列
input: [start, stop, step]
数列起点start,终点step,等差step
注意生成的数列中,不含stop,最后一项不是stop。 -
Sqrt 元素级的平方根
-
Copy 数据复制
将一个数据拷贝给另一个,相当于实现blob1==>blob2,目前不清楚如果直接用blob1=blob2究竟是属于引用,还是新开辟了一个空间使用过程中相当于开辟了一个新空间。类似的有Alias,赋值过程相当于引用。 -
Alias
引用blob,新blob与原blob只是名字不同,二者底层数据为同一个物理存储。 -
Concat 沿某一维度拼接
input: [data1, data2, …, data3]
arguments: axis
一些注意事项:
-
在网络搭建的过程中,operator中的input必须为blob_reference类型,比如RangeFill中的input:stop,虽然是一个标量,但是也需要是blob_reference,不可以直接把数值输进去。
-
caffe2的后项,默认情况下,为了节约显存,会将一些不需要更新的变量,在计算梯度并回传给前一层后,被覆盖掉。所以在最后rennet之后的工作空间中看不到该梯度。为了便于调试,可以修改MOMENGER为true。
-
caffe2的自动求后项在一些情况下会出问题,比如在实际的网络中:x --> y1=sqrt(x); x–> y2(x). 对于x这一路有两个分支,理论上应该把这两路返回的梯度求和。在caffe2的自动后项过程中,首先对sqrt一路求梯度: t 1 = ∂ l ∂ y 1 ⋅ 1 2 , t 2 = t 1 ⋅ 1 x \ t_{1}=\frac{\partial l}{\partial y_1}\cdot \frac{1}{2},t_{2}=t_{1} \cdot \frac{1}{\sqrt{x}} t1=∂y1∂l⋅21,t2=t1⋅x1, t 3 = ∂ l ∂ y 2 ⋅ ∂ y 2 x \ t_{3}=\frac{\partial l}{\partial y_2} \cdot \frac{\partial y_2}{x} t3=∂y2∂l⋅x∂y2. 正确的梯度应该为 ∂ l ∂ x = t 2 + t 3 \frac{\partial l}{\partial x} =t_2+t_3 ∂x∂l=t2+t3,但在caffe2的后项中,它计算的梯度是 ∂ l ∂ x = t 1 + t 2 + t 3 \frac{\partial l}{\partial x} =t_1+t_2+t_3 ∂x∂l=t1+t2+t3
-
对于一些数值计算类的operator,caffe2的后项目前没有发现问题,但是对于非数值计算类的op,例如Tile, 后项是错误的。在利用caffe2的自动后项时,应该非常小心的验证其后项。
一些仍然不清楚的问题:
- 如何利用operator自己写后项
- 如何约束某一层的学习率
- 直觉上应该有一个沿着某一维度复制的op,但是没有找到。目前是借助ones * matrix ==> reshape实现的。