页面树结构

2017-11-09 ApacheCN 开源组织,第二期邀请成员活动,一起走的更远 : http://www.apachecn.org/member/209.html


MachineLearning 优酷地址 : http://i.youku.com/apachecn

转至元数据结尾
转至元数据起始

以下介绍界面定义的操作 ComputationBuilder 语义。通常,这些操作将一对一映射到RPC接口中定义的操作xla_data.proto

关于术语的说明:XLA处理的广义数据类型是一个N维数组,它保持一些统一类型的元素(如32位浮点数)。在整个文档中,数组用于表示任意维数组。为方便起见,特殊情况下有更具体和熟悉的名称; 例如,向量是1维数组, 矩阵是2维数组。

 

Broadcast

参见 ComputationBuilder::Broadcast

通过复制数组中的数据将维度添加到数组。

Broadcast(operand, broadcast_sizes)

参数类型语义
operandComputationDataHandle要复制的数组
broadcast_sizesArraySlice<int64>新尺寸的尺寸

新的尺寸插入左侧,即如果broadcast_sizes有值{a0, ..., aN},并且操作数形状具有尺寸{b0, ..., bM},则输出的形状具有尺寸{a0, ..., aN, b0, ..., bM}

新维度索引到操作数的副本,即

output[i0, ..., iN, j0, ..., jM] = operand[j0, ..., jM]

例如,如果operandf32具有值的标量2.0f, broadcast_sizes则为{2, 3},则结果将是具有形状的数组,f32[2, 3]并且结果中的所有值将为2.0f

 

Call

参见 ComputationBuilder::Call

用给定的参数调用一个计算。

Call(computation, args...)

参数类型语义
computationComputation具有任意类型的N个参数的类型的计算T_0, T_1, ..., T_N -> S 
argsComputationDataHandles 序列任意类型的N个参数

 args必须匹配的参数的 arity和类型computation。允许没有args

 

Collapse

参见 ComputationBuilder::Collapse 和tf.reshape操作。

将阵列的尺寸折叠成一个维度。

Collapse(operand, dimensions)

参数类型语义
operandComputationDataHandleT型阵列
dimensionsint64 向量按顺序,T的尺寸的连续子集。

折叠将单个维度替换操作数维的给定子集。输入参数是T型的任意数组和维度索引的编译时常数向量。维度索引必须是按顺序(从低到高的维数),T的维度的连续子集。因此,{0,1,2},{0,1}或{1,2}都是有效的维集,但是{1,0}或{0,2}不是。它们被一个新的维度所替代,与维度序列中与它们所代替的尺寸顺序相同的位置,新尺寸大小等于原始尺寸大小的乘积。最小的维数dimensions是循环嵌套中最慢的变化维度(最主要的),这些维度会折叠这些维度,最高维数是最快的(最小的)。tf.reshape 

例如,令v为24个元素的数组:

let v = f32[4x2x3] { { {10, 11, 12},  {15, 16, 17}},
                    { {20, 21, 22},  {25, 26, 27}},
                    { {30, 31, 32},  {35, 36, 37}},
                    { {40, 41, 42},  {45, 46, 47}}};

// Collapse to a single dimension, leaving one dimension.
let v012 = Collapse(v, {0,1,2});
then v012 == f32[24] {10, 11, 12, 15, 16, 17,
                      20, 21, 22, 25, 26, 27,
                      30, 31, 32, 35, 36, 37,
                      40, 41, 42, 45, 46, 47};

// Collapse the two lower dimensions, leaving two dimensions.
let v01 = Collapse(v, {0,1});
then v01 == f32[4x6] { {10, 11, 12, 15, 16, 17},
                      {20, 21, 22, 25, 26, 27},
                      {30, 31, 32, 35, 36, 37},
                      {40, 41, 42, 45, 46, 47}};

// Collapse the two higher dimensions, leaving two dimensions.
let v12 = Collapse(v, {1,2});
then v12 == f32[8x3] { {10, 11, 12},
                      {15, 16, 17},
                      {20, 21, 22},
                      {25, 26, 27},
                      {30, 31, 32},
                      {35, 36, 37},
                      {40, 41, 42},
                      {45, 46, 47}};

Concatenate

参见 ComputationBuilder::ConcatInDim

串联组合由多个数组操作数组成。该数组具有与每个输入数组操作数(它们必须彼此相同的等级)的等级,并且按照它们被指定的顺序包含参数。

Concatenate(operands..., dimension)

参数类型语义
operandsN序列 ComputationDataHandle具有尺寸[L0,L1,...]的T型T阵列。需要N> = 1。
dimensionint64命名要连接的维度的间隔中的值。[0, N) operands 

除了dimension所有尺寸必须相同。这是因为XLA不支持“ragged”数组还要注意,rank-0值不能连接(因为不可能命名连接发生的维度)。

一维示例:

Concat({ {2, 3}, {4, 5}, {6, 7}}, 0)
>>> {2, 3, 4, 5, 6, 7}
二维示例:
let a = {
  {1, 2},
  {3, 4},
  {5, 6},
};
let b = {
  {7, 8},
};
Concat({a, b}, 0)
>>> {
  {1, 2},
  {3, 4},
  {5, 6},
  {7, 8},
} 
图:

ConvertElementType

参见 ComputationBuilder::ConvertElementType

static_castC ++中的元素相似,执行从数据形状到目标形状的元素转换操作。尺寸必须匹配,转换是元素方面的; 例如s32元件成为 f32经由元件s32-到- f32转换例程。

ConvertElementType(operand, new_element_type)

参数类型语义
operandComputationDataHandle类型T的阵列与暗点D
new_element_typePrimitiveTypeU型

如果操作数和目标形状的尺寸不匹配,或者请求无效的转换(例如,从/从元组返回),则会产生错误。

如A转换T=s32U=f32将执行的归一化INT到浮子转换例程诸如舍入到最接近的偶数。

注意:精确的float到int和反向转换当前未指定,但可能会成为将来转换操作的附加参数。并非所有可能的转换都已经实现了所有目标。
let a: s32[3] = {0, 1, 2};
let b: f32[3] = convert(a, f32);
then b == f32[3]{0.0, 1.0, 2.0} 

Conv(卷积)

参见 ComputationBuilder::Conv

作为ConvWithGeneralPadding,但是填充以短的方式指定为“相同”或“有效”。SAME填充将输入(lhs)设为零,以使输出与不考虑时的输入形状相同。有效填充只是意味着没有填充。

 

ConvWithGeneralPadding(卷积)

参见 ComputationBuilder::ConvWithGeneralPadding

计算神经网络中使用的类型的卷积。这里,卷积可以被认为是在n维基础区域上移动的n维窗口,并且对窗口的每个可能的位置执行计算。

参数类型语义
lhsComputationDataHandle排列n + 2数组输入
rhsComputationDataHandle排列n + 2数组的内核权重
window_stridesArraySlice<int64>内核大步的数组
paddingArraySlice<pair<int64, int64>>(低,高)填充的nd数组
lhs_dilationArraySlice<int64>nd lhs扩张因子数组
rhs_dilationArraySlice<int64>nd rhs扩张因子阵列

令n为空间维数。所述lhs参数是一个等级n + 2阵列描述底部区域。这被称为输入,即使rhs当然也是输入。在神经网络中,这些是输入激活。n + 2维度按以下顺序:

  • batch:该维度中的每个坐标表示执行卷积的独立输入。
  • z/depth/features:基地区中的每个(y,x)位置都有一个与之相关的向量,进入这个维度。
  • spatial_dims:描述n定义窗口移动的基本区域的空间维度。

所述rhs参数是一个等级n + 2阵列描述卷积滤波器/内核/窗口。尺寸按以下顺序:

  • output-zz输出的尺寸。
  • input-z:此维度的大小应等于z lhs中维度的大小。
  • spatial_dims:描述n定义穿过基础区域移动的nd窗口的空间维度。

window_strides参数指定卷积窗口在空间维度上的步幅。例如,如果第一空间维度中的步幅为3,则窗口只能放置在第一个空间索引可被3整除的坐标处。

padding参数指定要应用于基本区域的零填充量。填充量可以为负 - 负填充的绝对值表示在进行卷积之前要从指定维中删除的元素数。padding[0]指定维的填充ypadding[1]指定维的填充x。每一对具有作为第一元素的低填充和作为第二元素的高填充。沿较低折射率的方向施加低填充,而沿较高折射率的方向施加高填充。例如,如果 padding[1]是,(2,3)则在左侧将存在2个零的填充,并且在第二个空间维度中将具有在右侧的3个零。lhs 

the lhs_dilationrhs_dilationarguments指定在每个空间维度上分别应用于lhs和rhs的扩张因子。如果在空间维度上的扩张因子是d,那么d-1个孔隐含地放置在该维度中的每个条目之间,增加了数组的大小。这些孔填充有无操作值,卷积表示零。

rhs的扩张也被称为atrous卷积。有关详细信息,请参阅 tf.nn.atrous_conv2d。lhs的扩张也被称为去卷积。

输出形状具有以下顺序:

  • batch:与batch输入(lhs)上的大小相同。
  • zoutput-z内核(rhs)的大小相同。
  • spatial_dims:卷积窗口的每个有效放置的一个值。

卷积窗口的有效位置由填充之后的基础区域的大小和大小确定。

来形容卷积确实,考虑二维卷积,并挑选一些固定的batchzyx坐标输出。然后(y,x)是窗口在基础区域的一个角落的位置(例如,左上角,取决于您如何解释空间尺寸)。我们现在有一个2d窗口,从基地区取出,每个2d点与1d矢量相关联,所以我们得到一个3d框。从卷积内核,由于我们修正了输出坐标z,我们也有一个3d框。两个框具有相同的尺寸,因此我们可以将两个框之间的元素产品的总和(类似于点积)。那就是输出值。

注意,如果output-z是例如5,则窗口的每个位置在输出中产生5个值到输出的z维度中。这些值在使用卷积内核的部分是不同的 - 每个output-z坐标都有一个单独的3d框值。所以你可以把它看作是5个单独的卷积,每一个都有一个不同的过滤器。

这里是一个二维卷积的伪代码,带有padding和striding:

for (b, oz, oy, ox) {  // output coordinates
  value = 0;
  for (iz, ky, kx) {  // kernel coordinates and input z
    iy = oy*stride_y + ky - pad_low_y;
    ix = ox*stride_x + kx - pad_low_x;
    if ((iy, ix) inside the base area considered without padding) {
      value += input(b, iz, iy, ix) * kernel(oz, iz, ky, kx);
    }
  }
  output(b, oz, oy, ox) = value;
} 

CrossReplicaSum

参见 ComputationBuilder::CrossReplicaSum

计算副本的总和。

CrossReplicaSum(operand)

参数类型语义
operandComputationDataHandle数组在复制品之间求和。

输出形状与输入形状相同。例如,如果有两个副本,并且操作数具有值(1.0, 2.5)(3.0, 5.1) 分别在两个副本上,则此op的输出值将 (4.0, 7.6)在两个副本上。

计算CrossReplicaSum的结果需要每个副本的一个输入,因此如果一个副本比另一个复制执行一个CrossReplicaSum节点,那么前一个副本将永远等待。由于复制品都运行相同的程序,所以没有很多方法可以实现,但是当一个while循环的条件取决于来自进给的数据并且被引用的数据导致while循环更多次迭代时,这是可能的在一个副本比另一个。

 

CustomCall

参见 ComputationBuilder::CustomCall

在计算中调用用户提供的函数。

CustomCall(target_name, args..., shape)

参数类型语义
target_namestring功能名称 将发出一个指向该符号名称的呼叫指令。
argsComputationDataHandles 序列N个任意类型的参数,将被传递给函数。
shapeShape输出形状的功能

函数签名是一样的,无论arity或args的类型如何:

extern "C" void target_name(void* out, void** in);
例如,如果使用CustomCall,则如下所示:
let x = f32[2] {1,2};
let y = f32[2x3] { {10, 20, 30}, {40, 50, 60}};

CustomCall("myfunc", {x, y}, f32[3x3])
以下是一个实现示例myfunc
extern "C" void myfunc(void* out, void** in) {
  float (&x)[2] = *static_cast<float(*)[2]>(in[0]);
  float (&y)[2][3] = *static_cast<float(*)[2][3]>(in[1]);
  EXPECT_EQ(1, x[0]);
  EXPECT_EQ(2, x[1]);
  EXPECT_EQ(10, y[0][0]);
  EXPECT_EQ(20, y[0][1]);
  EXPECT_EQ(30, y[0][2]);
  EXPECT_EQ(40, y[1][0]);
  EXPECT_EQ(50, y[1][1]);
  EXPECT_EQ(60, y[1][2]);
  float (&z)[3][3] = *static_cast<float(*)[3][3]>(out);
  z[0][0] = x[1] + y[1][0];
  // ...
} 
用户提供的函数不能有副作用,其执行必须是幂等的。
注意:用户提供的功能的不透明性限制了编译器的优化机会。尽量使用本地XLA操作来表达您的计算; 只能使用CustomCall作为最后的手段。

Dot

参见 ComputationBuilder::Dot

Dot(lhs, rhs)

参数类型语义
lhsComputationDataHandleT型阵列
rhsComputationDataHandleT型阵列

此操作的确切语义取决于操作数的等级:

输入产量语义
矢量[n] dot矢量[n]纯量矢量点产品
矩阵[mxk] dot矢量[k]矢量[m]矩阵向量乘法
矩阵[mxk] dot矩阵[kxn]矩阵[mxn]矩阵矩阵乘法

该操作执行最后维度lhs和最后一维之间的乘积总和rhs。这些是“承包”维度。的签约尺寸lhsrhs必须是相同的大小。实际上,它可以用于执行向量,向量/矩阵乘法或矩阵/矩阵乘法之间的点积。

 

元素二进制算术运算

参见 ComputationBuilder::Add

支持一组元素二进制算术运算。

Op(lhs, rhs)

其中Op是下列之一Add(加法), Sub(减法), Mul (乘), Div(除法), Rem(余数), Max(最大), Min (最小), LogicalAnd(逻辑AND),或LogicalOr(逻辑或)。

参数类型语义
lhsComputationDataHandle左侧操作数:T型数组
rhsComputationDataHandle右侧操作数:T型数组

参数的形状必须是相似的或兼容的。请参阅 广播文档,了解形状要兼容的含义。操作的结果具有广播两个输入阵列的结果的形状。在这个变型中,不同级别的阵列之间的操作支持,除非其中一个操作数是标量。

OpRem时,结果的符号从股利中取,结果的绝对值总是小于除数的绝对值。

对于这些操作,存在不同等级广播支持的替代变型:

Op(lhs, rhs, broadcast_dimensions)

哪里Op是与上面相同。该操作的变体应该用于不同等级的数组之间的算术运算(例如向一个向量添加一个矩阵)。

附加broadcast_dimensions操作数是用于将低级操作数的等级扩展到高级操作数的等级的整数的片。broadcast_dimensions将下排形状的尺寸映射到高级形状的尺寸。展开形状的未贴图尺寸填充尺寸为1的尺寸。然后,简化维度广播沿着这些简并维度广播形状以均衡两个操作数的形状。在广播页面中详细描述了 语义

 

元素比较操作

参见 ComputationBuilder::Eq

支持一组标准元素二进制比较操作。请注意,比较浮点类型时,应用标准IEEE 754浮点比较语义。

Op(lhs, rhs)

其中Op是的一个Eq(等于), Ne(不等于到), Ge (大于或-等于-比), Gt(大于), Le(少-或等于-比), Le (小于)。

参数类型语义
lhsComputationDataHandle左侧操作数:T型数组
rhsComputationDataHandle右侧操作数:T型数组

参数的形状必须是相似的或兼容的。请参阅 广播文档,了解形状要兼容的含义。操作的结果是具有以元素类型广播两个输入阵列的结果的形状PRED。在这个变型中,不同级别的阵列之间的操作支持,除非其中一个操作数是标量。

对于这些操作,存在不同等级广播支持的替代变型:

Op(lhs, rhs, broadcast_dimensions)

哪里Op是与上面相同。该操作的变体应该用于不同等级的数组之间的比较操作(例如向一个向量添加一个矩阵)。

附加broadcast_dimensions操作数是一整整数,用于指定用于广播操作数的维度。在广播页面中详细描述了语义

 

元素一元函数

ComputationBuilder支持这些元素一元函数:

Abs(operand)元素方面的腹肌x -> |x|

Ceil(operand)元素方面的小区x -> ⌈x⌉

Exp(operand)元素自然指数x -> e^x

Floor(operand)元素层x -> ⌊x⌋

IsFinite(operand)测试每个元素是否operand是有限的,即不是正的或负的无穷大,而不是NaN。返回PRED与输入形状相同的值的数组,其中每个元素是true 且仅当对应的输入元素是有限的。

Log(operand)元素自然对数x -> ln(x)

LogicalNot(operand)元素方面的逻辑没有x -> !(x)

Neg(operand)元素否定x -> -x

Sign(operand)元素符号操作x -> sgn(x)在哪里

                    

使用元素类型的比较运算符operand

Tanh(operand)元素双曲正切x -> tanh(x)

参数类型语义
operandComputationDataHandle该功能的操作数

该函数应用于operand数组中的每个元素,导致具有相同形状的数组。它被允许为operand标量(等级0)。

 

GetTupleElement

参见 ComputationBuilder::GetTupleElement

索引到具有编译时常量值的元组。

该值必须是编译时常量,以便形状推理可以确定结果值的类型。

这类似于std::get<int N>(t)C ++。概念:

let v: f32[10] = f32[10]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let s: s32 = 5;
let t: (f32[10], s32) = tuple(v, s);
let element_1: s32 = gettupleelement(t, 1);  // Inferred shape matches s32.
参见tf.tuple

Infeed

参见 ComputationBuilder::Infeed

Infeed(shape)

论据类型语义
shapeShape从Infeed界面读取数据的形状。必须将形状的布局字段设置为与发送到设备的数据的布局相匹配; 否则其行为是未定义的。

从设备的隐式Infeed流式接口读取单个数据项,将数据解释为给定形状及其布局,并返回一个 ComputationDataHandle数据。在计算中允许多个进给操作,但是在进给操作中必须有一个完整的顺序。例如,下面的代码中的两个输入有一个总顺序,因为while循环之间有一个依赖关系。如果没有总订单,编译器会发出错误。

result1 = while (condition, init = init_value) {
  Infeed(shape)
}

result2 = while (condition, init = result1) {
  Infeed(shape)
}
不支持嵌套元组形状。对于空的元组形状,进给操作实际上是一个nop,并且不会从设备的进给中读取任何数据。
注意:我们计划允许多个进给操作,而不需要总计,在这种情况下,编译器将提供有关在编译程序中如何将“进给”操作序列化的信息。

Map

参见 ComputationBuilder::Map

Map(operands..., computation)

参数类型语义
operandsComputationDataHandles 序列N个类型的数组T_0..T_ {N-1}
computationComputation类型的计算 与类型T的N个参数和任意类型的M个T_0, T_1, ..., T_{N + M -1} -> S 
static_operands序列MComputationDataHandlesM个任意类型的数组

在给定的operands数组上应用标量函数,产生一个相同维数的数组,其中每个元素是映射函数的结果,该函数应用于输入数组中的相应元素,并static_operands 以额外的输入给出computation

映射函数是一个任意的计算,其限制是它具有标量类型的N个输入和类型T的单个输出S。输出具有与操作数相同的尺寸,但元素类型T被替换为S.

例如:在输入数组中的每个(多维)索引处Map(op1, op2, op3, computation, par1)映射elem_out <- computation(elem1, elem2, elem3, par1)以产生输出数组。

 

Pad

参见 ComputationBuilder::Pad

Pad(operand, padding_value, padding_config)

参数类型语义
operandComputationDataHandle类型数组 T
padding_valueComputationDataHandle类型的标量T填充添加的填充
padding_configPaddingConfig两个边缘(低,高)和每个维度的元素之间的填充量

 operand通过在数组周围的填充以及在给定的数组的元素之间扩展给定的数组padding_valuepadding_config 指定每个维度的边缘填充量和内部填充量。

PaddingConfig是的重复场PaddingConfigDimension,其包含用于每个维度的三个字段:edge_padding_lowedge_padding_high,和 interior_paddingedge_padding_lowedge_padding_high分别指定在每个维度的低端(索引0旁边)和高端(最高索引旁边)附加的填充量。边缘填充量可以为负 - 负填充的绝对值表示要从指定维度中删除的元素的数量。interior_padding指定在每个维度中的任何两个元素之间添加的填充量。内部填充在边缘填充之前逻辑地发生,因此在负边缘填充的情况下,元素从内部填充的操作数中移除。如果边缘填充对全为(0,0)且内部填充值全为0,则此操作为无操作。edge_padding interior_padding 

Reduce

参见 ComputationBuilder::Reduce

对数组应用还原函数。

Reduce(operand, init_value, computation, dimensions)

参数类型语义
operandComputationDataHandle类型数组 T
init_valueComputationDataHandle类型的标量 T
computationComputation计算类型 T, T -> T
dimensionsint64 排列无序的维度数组减少

在概念上,该操作将输入阵列中的一个或多个维度减小为标量。结果数组的排名是rank(operand) - len(dimensions)。 init_value是用于每个减少的初始值,并且如果后端选择这样做,也可以在计算期间的任何地方插入。所以在大多数情况下init_value应该是减少函数的一个标识(例如,0的加法)。

缩减函数的评估顺序是任意的,可能是非确定性的。因此,减少功能不应该对重新关联过于敏感。

一些减少功能,如加法,并不是严格关联浮标。然而,如果数据范围有限,则浮点加法足够接近于大多数实际用途的关联。然而,可以设想一些完全非关联性的减少,并且这将在XLA减少中产生不正确或不可预测的结果。

例如,当通过减少函数f(这是computation)减少具有值[10,11,12,13]的1D阵列中的一个维度时,则可以计算为

f(10, f(11, f(12, f(init_value, 13)))

但也有许多其他的可能性,例如

f(init_value, f(f(10, f(init_value, 11)), f(f(init_value, 12), f(13, init_value))))

以下是使用求和作为初始值为0的缩减计算的粗略伪代码示例。

result_shape <- remove all dims in dimensions from operand_shape

# Iterate over all elements in result_shape. The number of r's here is equal
# to the rank of the result
for r0 in range(result_shape[0]), r1 in range(result_shape[1]), ...:
  # Initialize this result element
  result[r0, r1...] <- 0

  # Iterate over all the reduction dimensions
  for d0 in range(dimensions[0]), d1 in range(dimensions[1]), ...:
    # Increment the result element with the value of the operand's element.
    # The index of the operand's element is constructed from all ri's and di's
    # in the right order (by construction ri's and di's together index over the
    # whole operand shape).
    result[r0, r1...] += operand[ri... di]
这是一个减少二维数组(矩阵)的例子。形状有2级,尺寸为0,尺寸为2,尺寸1为3:

使用“添加”功能减小尺寸0或1的结果:

请注意,两个减少结果都是1D阵列。该图显示一列作为列,另一列作为行仅为视觉方便。

对于一个更复杂的例子,这里是一个3D阵列。其等级为3,尺寸为0,尺寸为4,尺寸为1,尺寸为2,尺寸为2,尺寸为3.为了简单起见,值1至6可跨越尺寸0进行复制。

与2D示例类似,我们可以减少一个维度。例如,如果我们减小维数0,我们得到一个2级数组,其中所有维度0的值都折叠成一个标量:

|  4   8  12 |
| 16  20  24 |
如果我们减小维数2,我们还会得到一个二级数组,其中所有维度二的值都折成标量:
| 6  15 |
| 6  15 |
| 6  15 |
| 6  15 |
请注意,输入中的剩余维数之间的相对顺序将保留在输出中,但某些维度可能会被分配新的数字(因为排名发生变化)。

我们也可以减少多个维度。加减法尺寸0和1产生1D阵列| 20 28 36 |

在所有尺寸上减少3D阵列产生标量84

 

ReduceWindow

参见 ComputationBuilder::ReduceWindow

对输入多维数组的每个窗口中的所有元素应用缩减函数,产生与窗口的有效位置数相同数量的元素的输出多维数组。池层可以表示为a ReduceWindow

ReduceWindow(operand, init_value, computation, window_dimensions, window_strides, padding)

参数类型语义
operandComputationDataHandle包含T型元素的N维阵列。这是放置窗口的基础区域。
init_valueComputationDataHandle起始价值的减少。有关详细信息,请参阅缩小
computationComputation减少功能的类型 ,适用于每个窗口中的所有元素T, T -> T 
window_dimensionsArraySlice<int64>窗口尺寸值的整数数组
window_stridesArraySlice<int64>窗口步幅值整数数组
paddingPadding窗口的填充类型(Padding \:\:kSame或Padding \:\:kValid)

下面的代码和图示出了使用的一个例子ReduceWindow。输入是一个大小为[4x6]的矩阵,window_dimensions和window_stride_dimensions都是[2x3]。

// Create a computation for the reduction (maximum).
Computation max;
{
  ComputationBuilder builder(client_, "max");
  auto y = builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "y");
  auto x = builder.Parameter(1, ShapeUtil::MakeShape(F32, {}), "x");
  builder.Max(y, x);
  max = builder.Build().ConsumeValueOrDie();
}

// Create a ReduceWindow computation with the max reduction computation.
ComputationBuilder builder(client_, "reduce_window_2x3");
auto shape = ShapeUtil::MakeShape(F32, {4, 6});
auto input = builder.Parameter(0, shape, "input");
builder.ReduceWindow(
    input, *max,
    /*init_val=*/builder.ConstantLiteral(LiteralUtil::MinValue(F32)),
    /*window_dimensions=*/{2, 3},
    /*window_stride_dimensions=*/{2, 3},
    Padding::kValid); 

尺寸为1的大小指定尺寸中的窗口的位置距离其相邻窗口为1个元素。为了指定没有窗口彼此重叠,window_stride_dimensions应该等于window_dimensions。下图说明了两个不同步幅值的使用。填充应用于输入的每个维度,并且计算与填充中具有的尺寸的输入相同。

缩减函数的评估顺序是任意的,可能是非确定性的。因此,减少功能不应该对重新关联过于敏感。有关Reduce更多细节,请参阅关于关联性的讨论。

 

Reshape

参见 ComputationBuilder::Reshape 和Collapse操作。

将阵列的尺寸重新整形为新配置。

Reshape(operand, new_sizes) Reshape(operand, dimensions, new_sizes)

参数类型语义
operandComputationDataHandleT型阵列
dimensionsint64 向量尺寸折叠的顺序
new_sizesint64 向量新尺寸的矢量

在概念上,重塑首先将数组平坦化为数据值的一维向量,然后将该向量细化为新形状。输入参数是类型T的任意数组,维度索引的编译时常数向量,以及结果的维度大小的编译时常数向量。dimension如果给定,向量中的值必须是T的所有维的排列; 默认如果没有给出{0, ..., rank - 1}。维度的顺序dimensions是从循环嵌套中最慢变化的维度(最主要的)到最快的维度(最小的),将输入数组折叠成一个维度。所述new_sizes矢量确定输出数组的大小。索引为new_sizes0时的值为维度0的大小,索引1处的值为维度1的大小,依此类推。new_size尺寸的乘积必须等于操作数尺寸的乘积。将折叠后的阵列细化为由多维数组定义的多维数组new_sizes,其尺寸new_sizes从最慢变化(最主要)到最快变化(最小)排序。

例如,令v为24个元素的数组:

let v = f32[4x2x3] { { {10, 11, 12}, {15, 16, 17}},
                    { {20, 21, 22}, {25, 26, 27}},
                    { {30, 31, 32}, {35, 36, 37}},
                    { {40, 41, 42}, {45, 46, 47}}};

In-order collapse:
let v012_24 = Reshape(v, {0,1,2}, {24});
then v012_24 == f32[24] {10, 11, 12, 15, 16, 17, 20, 21, 22, 25, 26, 27,
                         30, 31, 32, 35, 36, 37, 40, 41, 42, 45, 46, 47};

let v012_83 = Reshape(v, {0,1,2}, {8,3});
then v012_83 == f32[8x3] { {10, 11, 12}, {15, 16, 17},
                          {20, 21, 22}, {25, 26, 27},
                          {30, 31, 32}, {35, 36, 37},
                          {40, 41, 42}, {45, 46, 47}};

Out-of-order collapse:
let v021_24 = Reshape(v, {1,2,0}, {24});
then v012_24 == f32[24]  {10, 20, 30, 40, 11, 21, 31, 41, 12, 22, 32, 42,
                          15, 25, 35, 45, 16, 26, 36, 46, 17, 27, 37, 47};

let v021_83 = Reshape(v, {1,2,0}, {8,3});
then v021_83 == f32[8x3] { {10, 20, 30}, {40, 11, 21},
                          {31, 41, 12}, {22, 32, 42},
                          {15, 25, 35}, {45, 16, 26},
                          {36, 46, 17}, {27, 37, 47}};

let v021_262 = Reshape(v, {1,2,0}, {2,6,2});
then v021_262 == f32[2x6x2] { { {10, 20}, {30, 40},
                              {11, 21}, {31, 41},
                              {12, 22}, {32, 42}},
                             { {15, 25}, {35, 45},
                              {16, 26}, {36, 46},
                              {17, 27}, {37, 47}}};
特殊情况下,重塑可以将单元素数组转换为标量,反之亦然。例如,
Reshape(f32[1x1] { {5}}, {0,1}, {}) == 5;
Reshape(5, {}, {1,1}) == f32[1x1] { {5}}; 

Rev (reverse)

参见 ComputationBuilder::Rev

Rev(operand, dimensions)

参数类型语义
operandComputationDataHandleT型阵列
dimensionsArraySlice<int64>尺寸要反转

 operand沿着指定的方向反转数组 中元素的顺序dimensions,生成相同形状的输出数组。多维索引处的操作数阵列的每个元素都以变换的索引存储到输出数组中。通过反转每个维度中的指数来反转多维指数(即,如果尺寸N的尺寸是反向维度之一,则其索引i被转换为N-1-i)。

用于该Rev操作的一个用途是在神经网络中的梯度计算期间沿着两个窗口维度逆转卷积权重阵列。

 

RngBernoulli

参见 ComputationBuilder::RngBernoulli

构造一个给定形状的输出,随机数在伯努利分布之后生成。该参数需要是一个标量值的F32操作数,而输出形状需要具有元素类型U32。

RngBernoulli(mean, shape)

参数类型语义
meanComputationDataHandleF32类型的标量指定生成数字的平均值
shapeShapeU32型输出形状

RngNormal

参见 ComputationBuilder::RngNormal

构造给定形状的输出,随后生成随机数

该 
正态分布。参数musigma,和输出形状必须具有元素类型F32。参数还必须是标量值。 

RngNormal(mean, sigma, shape)

参数类型语义
muComputationDataHandleF32类型的标量指定生成数字的平均值
sigmaComputationDataHandleF32类型的标量指定生成数字的标准偏差
shapeShapeF32型输出形状

RngUniform

参见 ComputationBuilder::RngUniform

构造给定形状的输出,随后生成随机数,间隔时间均匀分布 [a, b)

参数和输出形状可能是F32,S32或U32,但类型必须一致。

此外,参数需要是标量值。如果 b<= a
结果是实现定义的。

RngUniform(a, b, shape)

参数类型语义
aComputationDataHandle类型T的标量指定间隔的下限
bComputationDataHandle类型T的标量指定间隔的上限
shapeShape

输出形状为T型

SelectAndScatter

参见 ComputationBuilder::SelectAndScatter

该操作可以被认为是一个复合操作,它首先ReduceWindowoperand阵列上计算 从每个窗口中选择一个元素,然后将该source数组分散到所选元素的索引,以构造与操作数数组相同形状的输出数组。二进制 select函数用于通过在每个窗口中应用来选择每个窗口中的元素,并且使用第一个参数的索引向量在词典上小于第二个参数的索引向量的属性进行调用。该select函数返回true如果选择了所述第一参数和返回false如果第二参数被选择,并且该函数必须保持传递性(即,如果select(a, b)select(b, c)是 trueselect(a, c) true 

该函数scatter应用于输出数组中每个选定的索引。它需要两个标量参数:

  1. 输出数组中所选索引的当前值
  2. 其中的散点值source适用于所选索引

它结合了两个参数,并返回一个标量值,用于更新输出数组中所选索引处的值。最初,输出数组的所有索引都设置为init_value

输出阵列具有相同的形状的operand阵列和source 阵列必须具有相同的形状施加的结果ReduceWindow 的上操作operand阵列。SelectAndScatter可用于反向传播神经网络中的池层的梯度值。

SelectAndScatter(operand, select, window_dimensions, window_strides, padding, source, init_value, scatter)

参数类型语义
operandComputationDataHandle类型T的数组,窗口滑过
selectComputation二进制计算类型 ,适用于每个窗口中的所有元素; 返回如果选择并返回所述第一参数如果选择了所述第二参数T, T -> PRED true false 
window_dimensionsArraySlice<int64>窗口尺寸值的整数数组
window_stridesArraySlice<int64>窗口步幅值整数数组
paddingPadding窗口的填充类型(Padding \:\:kSame或Padding \:\:kValid)
sourceComputationDataHandle类型为T的数组,其值将散布
init_valueComputationDataHandle类型T的标量值作为输出数组的初始值
scatterComputation二进制计算的类型 ,以将每个散射源元素与其目标元素进行应用T, T -> T 

下图显示了使用 函数的示例SelectAndScatter,其中select函数计算其参数中的最大值。注意,当窗口重叠时,如下面的图(2)所示,operand可以通过不同的窗口多次选择阵列的索引。在图中,由两个顶部窗口(蓝色和红色)选择值为9的元素,二进制加法scatter函数产生值为8(2 + 6)的输出元素。

 scatter函数的评估顺序是任意的,可能是非确定性的。因此,这个scatter功能不应该对重新关联过于敏感。有关Reduce更多细节,请参阅关于关联性的讨论。

 

Select

参见 ComputationBuilder::Select

根据谓词数组的值,从两个输入数组的元素构造一个输出数组。

Select(pred, on_true, on_false)

参数类型语义
predComputationDataHandlePRED类型的数组
on_trueComputationDataHandleT型阵列
on_falseComputationDataHandleT型阵列

阵列on_trueon_false必须具有相同的形状。这也是输出数组的形状。所述阵列pred必须具有相同的维数 on_trueon_false,与PRED元件的类型。

对于每个元素Ppred,输出阵列的相应元素取自on_true如果值Ptrue,并且从on_false若的值Pfalse。由于受限制的形式广播 ,pred可以是类型的标量PRED。在这种情况下,输出阵列从全取on_true如果predtrue,并且从 on_false如果predfalse

非标量示例pred

let pred: PRED[4] = {true, false, false, true};
let v1: s32[4] = {1, 2, 3, 4};
let v2: s32[4] = {100, 200, 300, 400};
==>
Select(pred, v1, v2) = s32[4]{1, 200, 300, 4};
标量示例pred
let pred: PRED = true;
let v1: s32[4] = {1, 2, 3, 4};
let v2: s32[4] = {100, 200, 300, 400};
==>
Select(pred, v1, v2) = s32[4]{1, 2, 3, 4};
支持元组之间的选择。为此,元组被认为是标量类型。如果on_trueon_false是元组(必须具有相同的形状!),那么pred必须是类型的标量PRED

Slice

参见 ComputationBuilder::Slice

切片从输入数组中提取一个子数组。子数组与输入的等级相同,并且包含输入数组中边界框内的值,其中边界框的维和索引作为切片操作的参数。

Slice(operand, start_indices, limit_indices)

参数类型语义
operandComputationDataHandleT型的N维数组
start_indicesArraySlice<int64>包含每个维度的切片的起始索引的N个整数的列表。值必须大于或等于零。
limit_indicesArraySlice<int64>包含每个维的切片的结尾索引(独占)的N个整数的列表。每个值必须严格大于尺寸的相应start_indices值,并且小于或等于尺寸的大小。

一维示例:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
Slice(a, {2}, {4}) produces:
  {2.0, 3.0}
二维示例:
let b =
 { {0.0,  1.0,  2.0},
   {3.0,  4.0,  5.0},
   {6.0,  7.0,  8.0},
   {9.0, 10.0, 11.0} }

Slice(b, {2, 1}, {4, 3}) produces:
  { { 7.0,  8.0},
    {10.0, 11.0} }

DynamicSlice

参见 ComputationBuilder::DynamicSlice

DynamicSlice以动态方式从输入数组中提取一个子数组 start_indices。每个维度中切片的大小都被传入size_indices,它指定了每个维度中独占切片间隔的终点:[start,start + size]。形状start_indices必须为Rank == 1,尺寸大小等于等级operand。注意:处理限制外切片索引(由“start_indices”的不正确的运行时计算产生)目前是实现定义的。目前,切片索引被计算为模输入尺寸大小以防止外界数组访问,但是这种行为在将来的实现中可能改变。

DynamicSlice(operand, start_indices, size_indices)

参数类型语义
operandComputationDataHandleT型的N维数组
start_indicesComputationDataHandle包含每个维度的切片的起始索引的N个整数的1个数组。值必须大于或等于零。
size_indicesArraySlice<int64>包含每个维度的切片大小的N个整数的列表。每个值必须严格大于零,并且起始+大小必须小于或等于维度的大小,以避免缠绕尺寸尺寸。

一维示例:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
let s = {2}

DynamicSlice(a, s, {2}) produces:
  {2.0, 3.0} 
二维示例:
let b =
 { {0.0,  1.0,  2.0},
   {3.0,  4.0,  5.0},
   {6.0,  7.0,  8.0},
   {9.0, 10.0, 11.0} }
let s = {2, 1}

DynamicSlice(b, s, {2, 2}) produces:
  { { 7.0,  8.0},
    {10.0, 11.0} }

DynamicUpdateSlice

参见 ComputationBuilder::DynamicUpdateSlice

DynamicUpdateSlice生成一个结果,该结果是输入数组的值 operand,并update覆盖了一个切片start_indices。形状决定update更新结果的子阵列的形状。形状start_indices必须为Rank == 1,尺寸大小等于等级operand。注意:处理限制外切片索引(由“start_indices”的不正确的运行时计算产生)目前是实现定义的。目前,切片索引被计算为模更新维度大小,以防止外界数组访问,但是这种行为在将来的实现中可能会改变。

DynamicUpdateSlice(operand, update, start_indices)

参数类型语义
operandComputationDataHandleT型的N维数组
updateComputationDataHandle包含切片更新的T型N维数组。更新形状的每个维度必须严格大于零,并且启动+更新必须小于每个维度的操作数大小,以避免生成超出范围的更新索引。
start_indicesComputationDataHandle包含每个维度的切片的起始索引的N个整数的1个数组。值必须大于或等于零。

一维示例:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
let u = {5.0, 6.0}
let s = {2}

DynamicUpdateSlice(a, u, s) produces:
  {0.0, 1.0, 5.0, 6.0, 4.0}
二维示例:
let b =
 { {0.0,  1.0,  2.0},
   {3.0,  4.0,  5.0},
   {6.0,  7.0,  8.0},
   {9.0, 10.0, 11.0} }
let u =
 { {12.0,  13.0},
   {14.0,  15.0},
   {16.0,  17.0} }

let s = {1, 1}

DynamicUpdateSlice(b, u, s) produces:
 { {0.0,  1.0,  2.0},
   {3.0, 12.0, 13.0},
   {6.0, 14.0, 15.0},
   {9.0, 16.0, 17.0} } 

Sort

参见 ComputationBuilder::Sort

对操作数中的元素进行排序。

Sort(operand)

参数类型语义
operandComputationDataHandle操作数排序

Transpose

另见tf.reshape操作。

Transpose(operand)

参数类型语义
operandComputationDataHandle转置操作数。
permutationArraySlice<int64>如何排列尺寸。

允许使用给定的排列操作数维度,所以 ∀ i . 0 ≤ i < rank ⇒ input_dimensions[permutation[i]] = output_dimensions[i]

这与Reshape(operand,permutation,Permute(permutation,operand.shape.dimensions))相同)。

 

Tuple

参见 ComputationBuilder::Tuple

一个包含可变数量的数据句柄的元组,每个数据句柄都有自己的形状。

这类似于std::tupleC ++。概念:

let v: f32[10] = f32[10]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let s: s32 = 5;
let t: (f32[10], s32) = tuple(v, s); 
元组可以通过操作进行解构(访问)GetTupleElement 。

 

While

参见 ComputationBuilder::While

While(condition, body, init)

参数类型语义
conditionComputation T -> PRED定义循环终止条件的类型的计算。
bodyComputation T -> T定义循环体的类型的计算。
initT对的参数初始值condition 和body

按顺序执行,body直到condition失败。这类似于许多其他语言的典型while循环,除了以下列出的差异和限制。

  • 一个While节点返回一个类型的值T,它是最后一次执行的结果body
  • 类型的形状T是静态确定的,并且在所有迭代中必须相同。
  • While节点不允许嵌套。(此限制可能会在将来取消某些目标。)

计算的T参数用init第一次迭代中的值初始化,并body 在每个后续迭代中自动更新为新结果。

 While节点的一个主要用途是实现神经网络中重复执行训练。简化的伪代码如下图所示,表示计算。代码可以在中找到while_test.cc。类型T在本例中是一个Tuple由以下组成的int32用于迭代计数和一个vector[10]为累加器。对于1000次迭代,循环继续向累加器添加常量向量。

// Pseudocode for the computation.
init = {0, zero_vector[10]} // Tuple of int32 and float[10].
result = init;
while (result(0) < 1000) {
  iteration = result(0) + 1;
  new_vector = result(1) + constant_vector[10];
  result = {iteration, new_vector};
} 

  • 无标签