提交 3c5cb66f 编写于 作者: J jiangjiajun

add tensorflow2fluid docs

上级 c6d9546c
## 比较函数
在PaddlePaddle中使用运算符来对tensor之间进行`element-wise`方式的对比。其与TensorFlow相应接口关系如下表所示,
| TensorFlow接口 | PaddlePaddle接口 |
|--------------------------|-------------------------------------------------|
|[tf.math.less_equal](https://www.tensorflow.org/api_docs/python/tf/math/less_equal)|运算符`<=`|
|[tf.math.greater](https://www.tensorflow.org/api_docs/python/tf/math/greater)|运算符`>`|
|[tf.math.greater_equal](https://www.tensorflow.org/api_docs/python/tf/math/greater_equal)|运算符`>=`|
|[tf.math.equal](https://www.tensorflow.org/api_docs/python/tf/math/equal)|运算符`==`[paddle.fluid.layers.equal](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#permalink-7-equal) |
|[tf.math.less](https://www.tensorflow.org/api_docs/python/tf/math/less)|运算符`<`[paddle.fluid.layers.less_than](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#permalink-11-less_than) |
## tf.case
### [tf.case](https://www.tensorflow.org/api_docs/python/tf/case)
```python
tf.case(
pred_fn_pairs,
default=None,
exclusive=False,
strict=False,
name='case'
)
```
### [paddle.fluid.layers.While](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#while)
```python
class paddle.fluid.layers.Switch(
name=None
)
```
### 功能差异
#### 使用方式
TensorFlow:用户采用定义`条件-函数对`的方式,创建一个`case`操作;
PaddlePaddle:用户通过在`switch`代码块中,定义`case`分支方式,实现`switch`操作。与TensorFlow对比,在使用形式上更类似于传统的c/c++代码。
### 代码示例
```
# 如下代码展示进行学习率的调度,当global_step超过某个数值时,学习率减小
# 定义学习率tensor
lr = fluid.layers.tensor.create_global_var(
shape=[1],
value=0.0,
dtype='float32',
persistable=True,
name="learning_rate")
# 定义学习率常量
lr_0 = tensor.fill_constant(
shape=[1], dtype='float32', value=1.0)
lr_1 = tensor.fill_constant(
shape=[1], dtype='float32', value=0.1)
# 当global_step超过10000时,采用lr_1,否则采用lr_0
with fluid.layers.control_flow.Switch() as switch:
with switch.case(global_step > 10000):
fluid.layers.tensor.assign(input=lr_1, output=lr)
with switch.default():
fluid.layers.tensor.assign(input=lr_0, output=lr)
```
## tf.contrib.rnn.GRUCell
### [tf.contrib.rnn.GRUCell](https://www.tensorflow.org/api_docs/python/tf/nn/rnn_cell/GRUCell)
```python
tf.contrib.rnn.GRUCell(
num_units,
activation=None,
reuse=None,
kernel_initializer=None,
bias_initializer=None,
name=None,
dtype=None,
**kwargs
)
```
### [paddle.fluid.layers.gru_unit](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#gru-unit)
```python
paddle.fluid.layers.gru_unit(
input,
hidden,
size,
param_attr=None,
bias_attr=None,
activation='tanh',
gate_activation='sigmoid',
origin_mode=False
)
```
### 功能差异
#### 实现方式
TensorFlow:GRU的实现方式见论文[Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation](http://arxiv.org/abs/1406.1078)
PaddlePaddle:GRU有两种实现方式,当设置`origin_mode=False`时,与TensorFlow实现方式一致;当设置`origin_mode=True`时,实现方式则参考论文[Empirical Evaluation of
Gated Recurrent Neural Networks
on Sequence Modeling](https://arxiv.org/pdf/1412.3555.pdf)
#### 使用方式
TensorFlow:首先定义`GRUCell`对象,定义对象时只需要指定单元数`num_units`;由于`GRUCell`内部定义了`__call__`方法,因而其对象是可调用对象,直接使用`step_output, cur_state = cell(step_input, last_state)`的形式,可以计算得到当前步的输出与状态;
PaddlePaddle:提供op形式的调用接口,通常与[paddle.fluid.layers.DynamicRNN](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#dynamicrnn)配合使用,以获取序列中的单步输入。**注意,为了提高`gru_unit`的计算效率,用户在使用该接口时需要遵从如下约定:假设要指定的GRU单元数为`num_units`,则`size`以及`input.shape[-1]`必须为`3*num_units`,`hidden.shape[-1]`为`num_units`,见如下代码示例小节。**
#### 返回值
TensorFlow:返回一个二元组,分别是当前时刻的输出值与隐藏状态,实际上输出值与隐藏状态为相同的tensor;
PaddlePaddle:返回一个三元组,即`(hidden_value, reset_hidden_value, gate_value)`。后面两个元素为内部使用,用户可以只关注第一个元素。
### 代码示例
```
emb_size = 32
emb_vocab = 10000
num_unit_0 = 10
data = fluid.layers.data(name='input', shape=[1], dtype='int64', lod_level=1)
embedding = fluid.layers.embedding(input=data, size=[emb_vocab, emb_size],
is_sparse=False)
# 为了调用gru_unit,输入最后的维度必须为实际单元数的3倍
emb_fc = layers.fc(embedding, num_unit_0 * 3)
drnn = fluid.layers.DynamicRNN()
with drnn.block():
word = drnn.step_input(emb_fc)
# 指定上一时刻的隐状态,单元数为num_unit_0
prev_hid0 = drnn.memory(shape=[num_unit_0])
# 执行gru_unit计算,num_unit_0 为实际的单元数
cur_hid0, _, _ = layers.gru_unit(word, prev_hid0, num_unit_0 * 3)
# 更新隐状态
drnn.update_memory(prev_hid0, cur_hid0)
drnn.output(cur_hid0)
out = drnn()
last = fluid.layers.sequence_last_step(out)
```
## tf.expand_dims
### [tf.expand_dims](https://www.tensorflow.org/api_docs/python/tf/expand_dims)
``` python
tf.expand_dims(
input,
axis=None,
name=None,
dim=None
)
```
### [paddle.fluid.layers.unsqueeze](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#unsqueeze)
``` python
paddle.fluid.layers.unsqueeze(
input,
axes,
name=None)
```
### 功能差异
#### 参数类型
TensorFlow:`axis``int`类型或`0-D`tensor, 使用`axis`指定要增加维度的位置,支持负数进行索引;
PaddlePaddle:`axes``list`类型,表示要增加维度的位置列表,支持在多个位置同时增加维度,也支持负数进行索引。
### 代码示例
```python
# 输入 tensor t 的 shape 为[3, 4]
# 输出 tensor out 的 shape 为[1, 3, 4]
out = fluid.layers.unsqueeze(t, [0])
# 输出 tensor out 的 shape 为[3, 4, 1]
out = fluid.layers.unsqueeze(t, [-1])
# 输出 tensor out 的 shape 为[1, 1,3, 4]
out = fluid.layers.unsqueeze(t, [0, 1])
```
## tf.image.non_max_suppression
### [tf.image.non_max_suppression](https://www.tensorflow.org/api_docs/python/tf/image/non_max_suppression)
``` python
tf.image.non_max_suppression(
boxes,
scores,
max_output_size,
iou_threshold=0.5,
score_threshold=float('-inf'),
name=None
)
```
### [paddle.fluid.layers.multiclass_nms](http://paddlepaddle.org/documentation/docs/en/1.3/api/layers.html#permalink-245-multiclass_nms)
``` python
paddle.fluid.layers.multiclass_nms(
bboxes,
scores,
score_threshold,
nms_top_k,
keep_top_k,
nms_threshold=0.3,
normalized=True,
nms_eta=1.0,
background_label=0,
name=None)
```
### 功能差异
#### 输入格式
TensorFlow:`boxes`的shape为`[num_boxes, 4]``scores`的shape为`[num_boxes]`
PaddlePaddle:相对比Tensorflow,还支持batch和多类别,`bboxes`的shape为`[batch, num_boxes, 4]``scores`的shape为`[batch, num_classes, num_boxes]`
#### 输出格式
TensorFlow: 返回shape为`[N]`的tensor,表示为`boxes`中选取的index集合,长度为`N`
PaddlePaddle: 返回`[N, 6]`[LodTensor](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/fluid_cn.html#lodtensor),其中每行内容为`[lable, confidence, xmin, ymin, xmax, ymax]`
#### 参数差异
TensorFlow: 在所有boxes中,根据其它参数条件,最终选出的boxes数量不超过`max_output_size`
PaddlePaddle: 在`nms_top_k`个boxes中,根据其它参数条件,最终选出的boxes数量不超过`keep_top_k`
### 代码示例
```python
clip_boxes = fluid.layers.data(dtype='float32', shape=[5000, 4], name='boxes')
scores = fluid.layers.data(dtype='float32', shape=[1, 5000], name='scores')
# nms_top_k=-1,表示在输入的所有boxes中选取
selected_boxes = fluid.layers.multiclass_nms(
clip_boxes,
scores,
scrore_threshold=0.5,
nms_top_k=-1,
keep_top_k=300,
nms_threshold=0.7)
```
## tf.image.resize_images
### [tf.image.resize_images](https://www.tensorflow.org/api_docs/python/tf/image/resize_images)
``` python
tf.image.resize_images(
images,
size,
method=ResizeMethod.BILINEAR,
align_corners=False,
preserve_aspect_ratio=False
)
```
### [paddle.fluid.layers.image_resize](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#paddle.fluid.layers.image_resize)
``` python
paddle.fluid.layers.image_resize(
input,
out_shape=None,
scale=None,
name=None,
resample='BILINEAR',
actual_shape=None,
align_corners=True,
align_mode=1
)
```
### 功能差异
#### 参数种类
TensorFlow:支持`BILINEAR`,`NEAREST`,`BICUBIC`, `AREA`四种方式;
PaddlePaddle:支持`BILINEAR``NEAREST`两种方式, `align_mode``BILINEAR`的可选项,当为1的时候,与TensorFlow功能一致。
### 代码示例
```python
# 输入图像数据shape为[None, 3, 300, 300]
inputs = fluid.layers.data(dtype='float32', shape=[3, 300, 300], name='inputs')
# 输出shape为[3, 400, 500]
outputs = fluid.layers.image_reisze(inputs, [400, 500])
```
## tf.layers.conv2d
### [tf.layers.conv2d](https://www.tensorflow.org/api_docs/python/tf/layers/conv2d)
``` python
tf.layers.conv2d(
inputs,
filters,
kernel_size,
strides=(1, 1),
padding='valid',
data_format='channels_last',
dilation_rate=(1, 1),
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
```
### [paddle.fluid.layers.conv2d](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#paddle.fluid.layers.conv2d)
``` python
paddle.fluid.layers.conv2d(
input,
num_filters,
filter_size,
stride=1,
padding=0,
dilation=1,
groups=None,
param_attr=None,
bias_attr=None,
use_cudnn=True,
act=None,
name=None)
```
### 功能差异
#### 数据格式
TensorFlow: 默认输入数据格式为`NHWC`,表示`(batch,height, width, in_channels)`, 同时也将`data_format`参数设为`channels_first`,支持`NCHW`格式的数据输入。其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NHWC | (kernel_h, kernel_w, filters_num, in_channels)| (batch, out_h, out_w, filters_num)|
|NDHW | (kernel_h, kernel_w, filters_num, in_channels) | (batch, filters_num, out_h, out_w)|
PaddlePaddle:只支持输入数据格式为`NCHW`,且**卷积核格式**与TensorFlow不同,其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NCHW | (in_channels, filters_num, kernel_h, kernel_w) | (batch, filters_num, out_h, out_w)|
#### Padding机制
TensorFlow: `SAME``VALID`两种选项。当为`SAME`时,padding的计算方式如下所示,
```python
# 计算在width上的padding size
# height上的padding计算方式同理
ceil_size = ceil(input_width / stride_width)
pad_size = (ceil_size - 1) * stride_width + filter_width - input_width
pad_left = ceil(pad_size / 2)
pad_right = pad_size - pad_left
```
PaddlePaddle:`padding`参数表示在输入图像四周padding的size大小。
#### 参数差异
TensorFlow:深度可分离卷积使用[tf.layers.separable_conv2d](https://www.tensorflow.org/api_docs/python/tf/layers/separable_conv2d)接口;
PaddlePaddle: 使用`paddle.fluid.layers.conv2d`,可参考
[PaddlePaddle对卷积的说明文档](http://paddlepaddle.org/documentation/docs/zh/1.3/api_guides/low_level/layers/conv.html), 同时也可参考[tf.nn.separable_conv2d](tf.nn.separable_conv2d.md)中的代码示例。
### 代码示例
```python
# 结合pad2d,实现SAME方式的padding
# 输入Shape:(None, 3, 200, 200)
# 输出Shape:(None, 5, 67, 67)
# 卷积核Shape: (5, 3, 4, 4)
inputs = paddle.fluid.layers.data(dtype='float32', shape=[3, 200, 200], name='inputs)
pad_inputs = paddle.fluid.layers.pad2d(inputs, paddings=[1, 2, 1, 2])
outputs = paddle.fluid.layers.conv2d(pad_inputs, 5, [4, 4], (1, 1))
## tf.layers.dense
### [tf.layers.dense](https://www.tensorflow.org/api_docs/python/tf/layers/dense)
``` python
tf.layers.dense(
inputs,
units,
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
```
### [paddle.fluid.layers.fc](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#fc)
``` python
paddle.fluid.layers.fc(
input,
size,
num_flatten_dims=1,
param_attr=None,
bias_attr=None,
act=None,
is_test=False,
name=None
)
```
### 功能差异
#### 输入类型
TensorFlow:`inputs`为一个tensor;
PaddlePaddle:允许`input`是一个tensor或者是一个tensor 列表,如果是tensor列表的情况,该layer会声明多个kernel,个数与列表长度相同,在将列表中各个tensor与对应kernel做矩阵乘法之后,将各个结果相加。
#### kernel、bias初始化
TensorFlow:通过`kernel_initializer``bias_initializer``kernel``bias`进行初始化;
PaddlePaddle:通过设置`param_attr``bias_attr`为某种Attribute的方式,进行`kernel``bias`初始化。
#### 高维tensor处理
TensorFlow:对于rank大于2的输入tensor,将其看做是最内两个维度所组成矩阵的堆叠,dense操作将改变最后一个维度;
PaddlePaddle:对于rank大于2的输入tensor,可以从第`num_flatten_dims`维开始(维度下标从0开始,`num_flatten_dims`最小为1),将各维度拍平,例如`shape`为(2,3,4,5),当`num_flatten_dims`为2时,输入tensor将被reshape成(2,3,20)的tensor,输出tensor的shape为(2,3,size)。
### 代码示例
```python
# 输入 tensor t 的shape为[2, 3, 4, 5]
# size=6, 输出tensor 的shape为[2,6]
out = fluid.layers.fc(t, size=6)
# size=6, 设置kernel为均匀分布
out = fluid.layers.fc(t, size=6, \
param_attr=fluid.ParamAttr(initializer=fluid.initializer.Uniform(low=-0.5, high=0.5)))
# size=6, num_flatten_dims=2,输出tensor的shape为[2, 3, 6]
out = fluid.layers.fc(t, size=6, num_flatten_dims=2)
```
## tf.losses.sigmoid_cross_entropy
### [tf.losses.sigmoid_cross_entropy](https://www.tensorflow.org/api_docs/python/tf/losses/sigmoid_cross_entropy)
```python
tf.losses.sigmoid_cross_entropy(
multi_class_labels,
logits,
weights=1.0,
label_smoothing=0,
scope=None,
loss_collection=tf.GraphKeys.LOSSES,
reduction=Reduction.SUM_BY_NONZERO_WEIGHTS
)
```
### [paddle.fluid.layers.sigmoid_cross_entropy_with_logit](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#sigmoid_cross_entropy_with_logits)
```python
paddle.fluid.layers.sigmoid_cross_entropy_with_logits(
x,
label,
name=None
)
```
### 功能差异
#### 返回值类型
Tensorflow:通过控制`reduction`参数,返回结果可以是rank为0的tensor,也可以是shape与`logits`相同的tensor;
PaddlePaddle:固定返回shape与`x`相同的tensor,表示每个样本在每个标签上的损失。
#### 其他
Tensorflow:通过`weights`,可以设置不同样本、不同label的权重;通过`label_smoothing`,可以控制对label进行平滑;
PaddlePaddle:不支持调权与平滑功能。
### 代码示例
```
# x与label均是shape为[3,5]的tensor,表示三个样本,每个样本有5个类别
# out是shape为[3,5]的tensor,表示每个样本在每个类别上的loss
out = fluid.layers.sigmoid_cross_entropy_with_logits(x, label)
```
## tf.math.is_finite
### [tf.math.is_finite](https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/math/is_finite)
``` python
tf.math.is_finite(
x,
name=None
)
```
### [paddle.fluid.layers.isfinite](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#paddle.fluid.layers.isfinite)
``` python
paddle.fluid.layers.isfinite(x)
```
### 功能差异
#### 输出格式
TensorFlow: 返回elementwise检查的结果,即输出与输入shape一致;
PaddlePaddle: 返回结果仅包含一个boolean值,若输入数据中均为`infinite`,则返回True,否则返回False。
### 代码示例
```python
# TensorFlow示例
# 输入[2.1, 3.2, 4.5]
# 输出[True, True, True]
result = tf.is_finite(inputs)
# PaddlePaddle示例
# 输入[2.1, 3.2, 4.5]
# 输出True
result = fluid.layers.isfinite(inputs)
```
## tf.math.rsqrt
### [tf.math.rsqrt](https://www.tensorflow.org/api_docs/python/tf/math/rsqrt)
``` python
tf.math.rsqrt(
x,
name=None
)
```
### PaddlePaddle实现
PaddlePaddle中目前无对应接口,可使用如下代码实现
``` python
def rsqrt(x):
net_0 = fluid.layers.sqrt(x)
net_1 = fluid.layers.pow(net_0, factor=-1.0)
return net_1
```
### 代码示例
``` python
inputs = fluid.layers.data(dtype='float32', shape=[1000], name='inputs')
# 调用上述自定义函数
result = rsqrt(inputs)
```
## tf.matmul
### [tf.matmul](https://www.tensorflow.org/api_docs/python/tf/linalg/matmul)
``` python
tf.matmul(
a,
b,
transpose_a=False,
transpose_b=False,
adjoint_a=False,
adjoint_b=False,
a_is_sparse=False,
b_is_sparse=False,
name=None
)
```
### [paddle.fluid.layers.matmul](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#matmul)
``` python
paddle.fluid.layers.matmul(
x,
y,
transpose_x=False,
transpose_y=False,
alpha=1.0,
name=None
)
```
### 功能差异
#### 输入格式
TensorFlow:要求op的两个操作数具有相同的rank;
PaddlePaddle:允许两者具有不同的rank,具体说就是当任一操作数的rank大于2时,将其看做最里面两维度矩阵的堆叠,paddlepaddle将进行broadcast操作。
#### 其他
TensorFlow:使用`adjoint`参数可以实现快速的共轭操作;paddlepaddle中并不支持;
PaddlePaddle:额外支持对输出进行数乘操作。
### 代码示例
```python
# x: [M, K], y: [K, N]
fluid.layers.matmul(x, y) # out: [M, N]
# x: [B, ..., M, K], y: [B, ..., K, N]
fluid.layers.matmul(x, y) # out: [B, ..., M, N]
# x: [B, M, K], y: [B, K, N]
fluid.layers.matmul(x, y) # out: [B, M, N]
# x: [B, M, K], y: [K, N]
fluid.layers.matmul(x, y) # out: [B, M, N]
# x: [B, M, K], y: [K]
fluid.layers.matmul(x, y) # out: [B, M]
# x: [K], y: [K]
fluid.layers.matmul(x, y) # out: [1]
# x: [M], y: [N]
fluid.layers.matmul(x, y, True, True) # out: [M, N]
```
## tf.nn.avg_pool
### [tf.nn.avg_pool](https://www.tensorflow.org/versions/r1.10/api_docs/python/tf/nn/avg_pool)
``` python
tf.nn.avg_pool(
value,
ksize,
strides,
padding,
data_format='NHWC',
name=None
)
```
### [paddle.fluid.layers.pool2d](http://paddlepaddle.org/documentation/docs/en/1.3/api/layers.html#permalink-116-pool2d)
``` python
paddle.fluid.layers.pool2d(
input,
pool_size=-1,
pool_type='max',
pool_stride=1,
pool_padding=0,
global_pooling=False,
use_cudnn=True,
ceil_mode=False,
name=None,
exclusive=True)
```
### 功能差异
#### 输入格式
TensorFlow: 默认为`NHWC`的数据输入格式,同时也可通过修改`data_format`参数,支持`NCHW`的输入;
PaddlePaddle:只支持`NCHW`的数据输入格式。
#### Padding机制
Tensorflow: 存在`SAME``VALID`两种padding方式。当为`SAME`时,padding的size计算方式如下伪代码所示,需要注意的是,当计算得到的`pad_size`为奇数时,右侧与下方相对比左侧和上方会多1个size;
``` python
# 计算在width上的padding size
# height上的padding计算方式同理
ceil_size = ceil(input_width / stride_width)
pad_size = (ceil_size - 1) * stride_width + filter_width - input_width
pad_left = ceil(pad_size / 2)
pad_right = pad_size - pad_left
```
PaddlePaddle:在输入的上、下、左、右分别padding,size大小为`pool_padding`
### 代码示例
```
inputs = fluid.layers.data(dtype='float32', shape=[3, 300, 300], name='inputs')
# 计算得到输入的长、宽对应padding size为1
# 当Tensorflow中padding为SAME时,可能会两侧padding的size不同,可调用pad2d对齐
pad_res = fluid.layers.pad2d(inputs, paddings=[0, 1, 0, 1])
conv_res = fluid.layers.pool2d(pad_res, pool_size=3, pool_type='avg', padding=[1, 1], pool_stride=2)
```
## tf.nn.bidirectional_dynamic_rnn
### [tf.nn.bidirectional_dynamic_rnn](https://www.tensorflow.org/api_docs/python/tf/nn/bidirectional_dynamic_rnn)
```python
tf.nn.bidirectional_dynamic_rnn(
cell_fw,
cell_bw,
inputs,
sequence_length=None,
initial_state_fw=None,
initial_state_bw=None,
dtype=None,
parallel_iterations=None,
swap_memory=False,
time_major=False,
scope=None
)
```
### 功能差异
#### 使用方式
TensorFlow:用户通过定义正向与反向`cell`,可以实现一个双向RNN网络的功能;
PaddlePaddle:并没有提供一个对应的接口,用户可以使用`DynamicRNN`组合实现得到,详见如下代码示例。
### 代码示例
```
# 如下代码片段实现双向lstm网络,lstm单元数为16
num_unit_0 = 16
# 定义LoD输入
data = fluid.layers.data(name='input', shape=[1], dtype='int64', lod_level=1)
# 获得正向与反向embedding
embedding = fluid.layers.embedding(input=data, size=[emb_vocab, emb_size],
is_sparse=False)
rev_embedding = fluid.layers.sequence_reverse(embedding)
# 定义lstm网络
def rnn(in_tensor):
drnn = fluid.layers.DynamicRNN()
with drnn.block():
word = drnn.step_input(in_tensor)
prev_hid0 = drnn.memory(shape=[num_unit_0])
prev_cell0 = drnn.memory(shape=[num_unit_0])
cur_hid0, cur_cell0 = layers.lstm_unit(word, prev_hid0, prev_cell0)
drnn.update_memory(prev_hid0, cur_hid0)
drnn.update_memory(prev_cell0, cur_cell0)
drnn.output(cur_hid0)
out = drnn()
return out
# 计算正向lstm网络的输出
out = rnn(embedding)
# 计算反向lstm网络的输出
rev_out = rnn(rev_embedding)
# 再次反转使得rev_out每个时刻所处理的数据与out对应
rev_rev_out = fluid.layers.sequence_reverse(rev_out)
# 合并得到最后的输出,其shape为(-1, 32)
concat_out = layers.concat([out, rev_rev_out], axis=1)
```
## tf.nn.conv2d
### [tf.nn.conv2d](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d)
```python
tf.nn.conv2d(
input,
filter,
strides,
padding,
use_cudnn_on_gpu=True,
data_format='NHWC',
dilations=[1, 1, 1, 1],
name=None
)
```
### [paddle.fluid.layers.conv2d](http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#paddle.fluid.layers.conv2d)
```python
paddle.fluid.layers.conv2d(
input,
num_filters,
filter_size,
stride=1,
padding=0,
dilation=1,
groups=None,
param_attr=None,
bias_attr=None,
use_cudnn=True,
act=None,
name=None
)
```
### 功能差异
`tf.nn.conv2d`中的参数`filter`为具体的tensor,而`paddle.fluid.layers.conv2d`参数中则声明卷积核的`size`,函数内部创建卷积核tensor。也可通过如下代码示例,自行创建并复用卷积核
需要注意的是PaddlePaddle中的输入、输出以及卷积核的格式与tensorflow存在部分差异,可参考[tf.layers.conv2d](tf.layers.conv2d.md)
### 代码示例
```python
# 输入为NCHW格式
inputs = fluid.layers.data(dtype='float32', shape=[-1, 3, 300, 300], name='inputs')
create_kernel = fluid.layers.create_parameters(shape=[5, 3, 2, 2], dtype='float32', name='kernel')
# PaddlePaddle中可通过相同的参数命名引用同一个参数变量
# 通过指定卷积核参数名(param_attr)为'kernel',引用了create_kernel
result = fluid.layers.conv2d(inputs, 5, [2, 2], param_attr='kernel')
```
## tf.nn.conv2d_transpose
### [tf.nn.conv2d_transpose](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d_transpose)
``` python
tf.nn.conv2d_transpose(
value,
filter,
output_shape,
strides,
padding='SAME',
data_format='NHWC',
name=None
)
```
### [paddle.fluid.layers.conv2d_transpose](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#paddle.fluid.layers.conv2d_transpose)
``` python
paddle.fluid.layers.conv2d_transpose(
input,
num_filters,
output_size=None,
filter_size=None,
padding=0,
stride=1,
dilation=1,
groups=None,
param_attr=None,
bias_attr=None,
use_cudnn=True,
act=None,
name=None
)
```
### 功能差异
#### 数据格式
TensorFlow: 默认输入数据格式为`NHWC`,表示`(batch,height, width, in_channels)`, 同时也将`data_format`参数设为`channels_first`,支持`NCHW`格式的数据输入。其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NHWC | (kernel_h, kernel_w, filters_num, in_channels)| (batch, out_h, out_w, filters_num)|
|NDHW | (kernel_h, kernel_w, filters_num, in_channels) | (batch, filters_num, out_h, out_w)|
PaddlePaddle:只支持输入数据格式为`NCHW`,且**卷积核格式**与TensorFlow不同,其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NCHW | (in_channels, filters_num, kernel_h, kernel_w) | (batch, filters_num, out_h, out_w)|
#### Padding机制
TensorFlow: `SAME``VALID`两种选项。当为`SAME`时,padding的计算方式如下所示
```python
# 计算在width上的padding size
# height上的padding计算方式同理
ceil_size = ceil(input_width / stride_width)
pad_size = (ceil_size - 1) * stride_width + filter_width - input_width
pad_left = ceil(pad_size / 2)
pad_right = pad_size - pad_left
```
PaddlePaddle:`padding`参数表示在输入图像四周padding的size大小
#### 输出大小
TensorFlow:当padding为`SAME``VALID`两种情况下,输出大小计算方式如下所示
```python
if padding == 'SAME':
output_size = input_size * stride
elif padding == 'VALID':
output_size = input_size * stride + max(kernel_size - stride, 0)
```
PaddlePaddle: 输出大小计算公式如下,差异主要由于TensorFlow在`conv2d_transpose`的最后还存在**裁剪**步骤,因此可参考示例代码,调用`crop`解决
```python
output_size = (input_size - 1) * stride - 2 * padding + dilation * (kernel - 1) + 1
```
### 代码示例
```python
# TensorFlow使用conv2d_transpose
# 输入shape: [-1, 20, 20, 3]
inputs = tf.placeholder(dtype=tf.float32, shape=[None, 20, 20, 3])
filter = tf.random_uniform(shape=[5, 5, 3, 3], 0.0 1.0)
batch = tf.shape(inputs)[0]
# conv2d_transpose输出shape: [-1, 40, 40, 3]
result = tf.nn.conv2d_transpose(inputs, filter, output_shape=[batch, 40, 40, 3],
strides=[1, 2, 2, 1], padding='SAME')
#PaddlePaddle中使用conv2d_transpose
# 输入Shape:(None, 3, 20, 20)
inputs = fluid.layers.data(dtype='float32', shape=[3, 20, 20], name='inputs)
# conv2d_transpose输出shape:[-1, 3, 41, 41]
outputs = fluid.layers.conv2d_transpose(pad_inputs, 3, filter_size=[5, 5],
padding=[1, 1], stride=[2, 2], bias_attr=False)
# 裁剪后结果即为与TensorFlow一致
outputs = fluid.layers.crop(outputs, shape=[-1, 3, 40, 40])
## tf.nn.conv3d_transpose
### [tf.nn.conv3d_transpose](https://www.tensorflow.org/api_docs/python/tf/nn/conv3d_transpose)
``` python
tf.nn.conv3d_transpose(
value,
filter,
output_shape,
strides,
padding='SAME',
data_format='NDHWC',
name=None
)
```
### [paddle.fluid.layers.conv3d_transpose](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#permalink-48-conv3d_transpose)
``` python
paddle.fluid.layers.conv3d_transpose(
input,
num_filters,
output_size=None,
filter_size=None,
padding=0,
stride=1,
dilation=1,
groups=None,
param_attr=None,
bias_attr=None,
use_cudnn=True,
act=None,
name=None
)
```
### 功能差异
#### 数据格式
TensorFlow: 默认输入数据格式为`NDHWC`,表示`(batch,depth, height, width, in_channels)`, 同时也将`data_format`参数设为`channels_first`,支持`NCDHW`格式的数据输入。其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NDHWC | (kernel_d, kernel_h, kernel_w, filters_num, in_channels)| (batch, out_d, out_h, out_w, filters_num)|
|NCDHW | (kernel_d, kernel_h, kernel_w, filters_num, in_channels) | (batch, filters_num, out_d, out_h, out_w)|
PaddlePaddle: 只支持输入数据格式为`NCDHW`,且**卷积核格式**与TensorFlow不同,其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NCDHW | (in_channels, filters_num, kernel_d, kernel_h, kernel_w) | (batch, filters_num, out_d, out_h, out_w)|
#### Padding机制
TensorFlow: `SAME``VALID`两种选项。当为`SAME`时,padding的计算方式如下所示
```python
# 计算在width上的padding size
# height上的padding计算方式同理
ceil_size = ceil(input_width / stride_width)
pad_size = (ceil_size - 1) * stride_width + filter_width - input_width
pad_left = ceil(pad_size / 2)
pad_right = pad_size - pad_left
```
PaddlePaddle:`padding`参数表示在输入图像四周padding的size大小
#### 输出大小
TensorFlow:当padding为`SAME``VALID`两种情况下,输出大小计算方式如下所示
```python
if padding == 'SAME':
output_size = input_size * stride
elif padding == 'VALID':
output_size = input_size * stride + max(kernel_size - stride, 0)
```
PaddlePaddle: 输出大小计算公式如下,差异主要由于TensorFlow在`conv2d_transpose`的最后还存在**裁剪**步骤,因此可参考示例代码,调用`crop`解决
```python
output_size = (input_size - 1) * stride - 2 * padding + dilation * (kernel - 1) + 1
```
### 代码示例
```python
# TensorFlow使用conv3d_transpose
# 输入shape: [-1, 5, 20, 40, 3]
inputs = tf.placeholder(dtype=tf.float32, shape=[None, 5 20, 40, 3])
filter = tf.random_uniform(shape=[2, 4, 5, 7 3], 0.0 1.0)
batch = tf.shape(inputs)[0]
# conv2d_transpose输出shape: [-1, 5, 40, 80, 7]
result = tf.nn.conv2d_transpose(inputs, filter, output_shape=[batch, 5, 40, 80 7],
strides=(1, 2, 2), padding='SAME')
#PaddlePaddle中使用conv3d_transpose
# 输入Shape:(None, 3, 5, 20, 40)
inputs = fluid.layers.data(dtype='float32', shape=[3, 5, 20, 40], name='inputs)
# conv3d_transpose输出shape:[-1, 7, 6, 40, 81]
outputs = fluid.layers.conv3d(inputs, 7, filter_size=(2, 4, 5), stride=(1, 2, 2),
padding=(0, 1, 1), bias_attr=False)
# 裁剪后结果即为与TensorFlow一致
outputs = fluid.layers.crop(outputs, shape=[-1, 7, 5, 40, 80])
## tf.nn.depthwise_conv2d
### [tf.nn.depthwise_conv2d](https://www.tensorflow.org/api_docs/python/tf/nn/depthwise_conv2d)
```python
tf.nn.depthwise_conv2d(
input,
filter,
strides,
padding,
rate=None,
name=None,
data_format=None
)
```
### [paddle.fluid.layers.conv2d](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#paddle.fluid.layers.conv2d)
```python
paddle.fluid.layers.conv2d(
input,
num_filters,
filter_size,
stride=1,
padding=0,
dilation=1,
groups=None,
param_attr=None,
bias_attr=None,
use_cudnn=True,
act=None,
name=None
)
```
### 功能差异
#### 数据格式
TensorFlow:默认输入数据格式为`NHWC`,表示`(batch, height, width, in_channels)`, 同时也将`data_format`参数设为`channels_first`,支持`NCHW`格式的数据输入。其中输入、输出、卷积核对应关系如下表所示,
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NHWC | (kernel_h, kernel_w, in_channels, channel_multiplier)| (batch, out_h, out_w, in_channel*channel_multiplier)|
|NCHW | (kernel_h, kernel_w, in_channels, channel_multiplier) | (batch, in_channel*channel_multiplier, out_h, out_w)|
PaddlePaddle: 只支持输入数据格式为`NCHW`,且**卷积核格式**与TensorFlow不同,其中输入、输出、卷积核对应关系如下表所示,可以看到,需要设置`num_filters`参数与`in_channels`一致
| 输入 | 卷积核 | 输出 |
|--------------------|-------------------|------------------|
|NCHW | (num_filters, in_channels/groups, kernel_h, kernel_w) | (batch, num_filters, out_h, out_w)|
#### Padding机制
TensorFlow: `SAME``VALID`两种选项。当为`SAME`时,padding的计算方式如下所示
```python
# 计算在width上的padding size
# height上的padding计算方式同理
ceil_size = ceil(input_width / stride_width)
pad_size = (ceil_size - 1) * stride_width + filter_width - input_width
pad_left = ceil(pad_size / 2)
pad_right = pad_size - pad_left
```
PaddlePaddle:`padding`参数表示在输入图像四周padding的size大小
#### 参数差异
Tensorflow:普通2维卷积使用`tf.layers.conv2d`
PaddlePaddle:仍使用本接口,可参考在文档[tf.layers.conv2d](https://github.com/PaddlePaddle/X2Paddle/blob/doc/tensorflow2fluid/doc/tf.layers.conv2d.md)
### 代码示例
```python
# TensorFlow中使用depthwise_conv2d
# 输入shape: [-1, 20, 20, 3]
inputs = tf.placeholder(dtype=tf.float32, shape=[None, 20, 20, 3])
filter = tf.random_uniform(shape=[4, 4, 3, 1], 0.0 1.0)
# 输出shape: [-1, 20, 20, 3]
result = tf.nn.depthwise_conv2d(inputs, filter, strides=[1, 1, 1, 1], padding='SAME')
# PaddlePaddle中使用conv2d实现depthwise_conv2d
# 输入shape: [-1, 3, 20, 20]
inputs = fluid.layers.data(dtype='float32', shape=[3, 20, 20], name='inputs')
# 使用pad2d对齐TensorFlow的padding参数:SAME
inputs = fluid.layers.pad2d(inputs, paddings=[1, 2, 1, 2])
#输出shape:[-1, 3, 20, 20]
result = fluid.layers.conv2d(inputs, 3, filter_size=[4, 4], groups=3, bias_attr=False)
```
## tf.dropout
### [tf.nn.dropout](https://www.tensorflow.org/api_docs/python/tf/nn/dropout)
``` python
tf.nn.dropout(
x,
keep_prob=None,
noise_shape=None,
seed=None,
name=None,
rate=None
)
```
### [paddle.fluid.layers.dropout](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#cn-api-fluid-layers-dropout)
``` python
paddle.fluid.layers.dropout(
x,
dropout_prob,
is_test=False,
seed=None,
name=None,
dropout_implementation='downgrade_in_infer'
)
```
### 功能差异
#### 丢弃概率
TensorFlow:使用`keep_prob`表示保留单元输出的概率,等价于`1-rate`
PaddlePaddle:使用`dropout_prob`表示将单元输出设置为0的概率,即其丢弃概率;
#### dropout独立性
TensorFlow:通过设置一个可以广播到x的`noise_shape`,可以控制dropout的独立性;
PaddlePaddle:暂无此设置。
#### 实现方式
TensorFlow:在训练时,被保留的单元输出要乘上`1/keep_prob`的系数,而在测试时,直接关闭dropout。
PaddlePaddle:通过设置`dropout_implementation`有不同的实现。当设置为`downgrade_in_infer`时,在训练时,保留单元直接被输出,而测试时所有单元乘以`1-dropout_prob`的系数;当设置为`upgrade_in_train`时,则与tensorflow的实现一致。
### 代码示例
```python
# 输入 tensor t 为[[1,2],[3,4]]
# 第0维前面padding长度为0,后面padding长度为1;第1维前面padding长度为1,后面padding长度为2
out = fluid.layers.dropout(t, dropout_prob=0.2, dropout_implementation="upscale_in_train")
# inference 时关闭dropout
inference_program = fluid.default_main_program().clone(for_test=True)
```
## tf.nn.dynamic_rnn
### [tf.nn.dynamic_rnn](https://www.tensorflow.org/api_docs/python/tf/nn/dynamic_rnn)
``` python
tf.nn.dynamic_rnn(
cell,
inputs,
sequence_length=None,
initial_state=None,
dtype=None,
parallel_iterations=None,
swap_memory=False,
time_major=False,
scope=None
)
```
### [paddle.fluid.layers.DynamicRNN](http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/api_guides/low_level/layers/control_flow.html#dynamicrnn)
``` python
paddle.fluid.layers.DynamicRNN(name=None)
```
### 功能差异
#### 调用机制
Tensorflow: `tf.nn.dynamic_rnn`通常与`tf.nn.rnn_cell.LSTMCell``tf.nn.rnn_cell.GRUCell`等Cell结合使用
PaddlePaddle: 使用`paddle.fluid.layers.DynamicRNN`类实现类似功能 ,通过DynamicRNN提供的类方法,用户可以在`with block`中方便地自定义每个时间步的处理过程。
#### 输入格式
TensorFlow: `tf.nn.dynamic_rnn`输入为序列数据,批输入中的每个序列需要填充到相同的长度
PaddlePaddle: 使用
[LoDTensor](http://www.paddlepaddle.org/documentation/docs/zh/1.2/user_guides/howto/basic_concept/lod_tensor.html)表示一个批输入,用户在使用时不需要进行填充操作。
### 代码示例
```
# TensorFlow代码示例
# 创建 BasicRNNCell
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(hidden_size)
# 定义初始隐状态
initial_state = rnn_cell.zero_state(batch_size, dtype=tf.float32)
# 输出shape为(batch_size, max_time, cell_state_size)
# 最后时刻隐状态shape为(batch_size, cell_state_size)
outputs, state = tf.nn.dynamic_rnn(rnn_cell, input_data,
initial_state=initial_state,
dtype=tf.float32)
# PaddlePaddle代码示例
# 创建一个DynamicRNN对象
drnn = fluid.layers.DynamicRNN()
# 定义一个类似BasicRNNCell的处理过程
with drnn.block():
# 设置drnn的序列输入,并取得当前步的输入
cur_input = drnn.step_input(input_data)
# 设置memory变量,并取得上一时刻(或初始)隐状态
last_hidden_state = drnn.memory(shape=[hidden_size], value=0.0)
# 计算当前时刻隐状态
cur_hidden_state = fluid.layers.fc(input=[cur_input, last_hidden_state], size=hidden_size, act='relu')
# 更新隐状态
drnn.update_memory(last_hidden_state, cur_hidden_state)
# 记录本时刻的输出(BasicRNNCell中当前时刻的输出与当前时刻隐状态一致)
drnn.output(hidden)
# 获取输出LoDTensor,其shape为(-1, hidden_size)
outputs = drnn()
# 获取各序列最后时刻的隐状态,其shape为(batch_size, hidden_size)
state = fluid.layers.sequence_last_step(outputs)
```
### 其他
为了简化用户定义动态RNN的过程,paddle有如下op可供选择:
- [paddle.fluid.layers.dynamic_lstm](http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#dynamic-lstm):相当于 `tf.nn.dynamic_rnn`结合`tf.nn.rnn_cell.LSTMCell`
- [paddle.fluid.layers.dynamic_gru](http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#dynamic-gru):相当于`tf.nn.dynamic_rnn`结合`tf.nn.rnn_cell.GRUCell`
## tf.nn.l2_normalize
### [tf.nn.l2_normalize](https://www.tensorflow.org/api_docs/python/tf/math/l2_normalize)
```python
tf.math.l2_normalize(
x,
axis=None,
epsilon=1e-12,
name=None,
dim=None
)
```
### [paddle.fluid.layers.l2_normalize](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#l2-normalize)
```python
paddle.fluid.layers.l2_normalize(
x,
axis,
epsilon=1e-12,
name=None
)
```
### 功能差异
#### 计算方式
TensorFlow:计算方式为`output = x / sqrt(max(sum(x^2), epsilon))`;
PaddlePaddle:计算方式为`output = x / sqrt(sum(x^2) + epsilon))`
### 代码示例
```
# x是shape为[3,2]的张量
# out同样是shape[3,2]的张量,axis设置为1,表示将x中每个行向量做归一化
out = fluid.layers.l2_normalize(x, axis=1)
```
## tf.nn.max_pool
### [tf.nn.max_pool](https://www.tensorflow.org/api_docs/python/tf/nn/max_pool)
``` python
tf.nn.max_pool(
value,
ksize,
strides,
padding,
data_format='NHWC',
name=None
)
```
### [paddle.fluid.layers.pool2d](http://paddlepaddle.org/documentation/docs/en/1.3/api/layers.html#permalink-116-pool2d)
``` python
paddle.fluid.layers.pool2d(
input,
pool_size=-1,
pool_type='max',
pool_stride=1,
pool_padding=0,
global_pooling=False,
use_cudnn=True,
ceil_mode=False,
name=None,
exclusive=True)
```
### 功能差异
#### 输入格式
TensorFlow: 默认为`NHWC`的数据输入格式,同时也可通过修改`data_format`参数,支持`NCHW`的输入;
PaddlePaddle:只支持`NCHW`的数据输入格式。
#### Padding机制
Tensorflow: 存在`SAME``VALID`两种padding方式。当为`SAME`时,padding的size计算方式如下,仅在最右和最下进行padding;
```
ceil_size = ceil(input_size / stride)
pad_size = (ceil_size - 1) * stride + filter_size - input_size
```
PaddlePaddle:在输入的上、下、左、右分别padding,size大小为`pool_padding`,通过示例代码,可实现与Tensorflow中`max_pool``SAME`方式。
### 代码示例
```
inputs = fluid.layers.data(dtype='float32', shape=[3, 300, 300], name='inputs')
# 计算得到输入的长、宽对应padding size为1
# 在最右、最下进行padding
pad_res = fluid.layers.pad2d(inputs, padding=[0, 1, 0, 1])
conv_res = fluid.layers.pool2d(pad_res, pool_size=3, pool_type='max', pool_stride=2)
```
## tf.math.reduce_logsumexp
### [tf.math.reduce_logsumexp](https://www.tensorflow.org/api_docs/python/tf/math/reduce_logsumexp)
``` python
tf.math.log_softmax(
logits,
axis=None,
name=None,
dim=None
)
```
### PaddlePaddle实现
PaddlePaddle中目前无对应接口,可使用如下代码实现
``` python
def reduce_logsumexp(inputs, axis=None, keepdims=None):
net_0 = fluid.layers.exp(inputs)
net_1 = fluid.layers.reduce_sum(net_0, dim=axis, keep_dim=keepdims)
net_2 = fluid.layers.log(net_1)
return net_2
```
### 代码示例
``` python
inputs = fluid.layers.data(dtype='float32', shape=[1000], name='inputs')
# 调用上述自定义函数
result = reduce_logsumexp(inputs)
```
## tf.nn.rnn_cell.LSTMCell
### [tf.nn.rnn_cell.LSTMCell](https://www.tensorflow.org/api_docs/python/tf/nn/rnn_cell/LSTMCell)
```python
tf.nn.rnn_cell.LSTMCell(
num_units,
use_peepholes=False,
cell_clip=None,
initializer=None,
num_proj=None,
proj_clip=None,
num_unit_shards=None,
num_proj_shards=None,
forget_bias=1.0,
state_is_tuple=True,
activation=None,
reuse=None,
name=None,
dtype=None,
**kwargs
)
```
### [paddle.fluid.layers.lstm_unit](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#lstm-unit)
```python
paddle.fluid.layers.lstm_unit(
x_t,
hidden_t_prev,
cell_t_prev,
forget_bias=0.0,
param_attr=None,
bias_attr=None,
name=None
)
```
### 功能差异
#### 使用方式
TensorFlow:首先定义`LSTMCell`对象,定义对象时只需要指定单元数`num_units`;由于`LSTMCell`内部定义了`__call__`方法,因而其对象是可调用对象,直接使用`step_output, cur_state = cell(step_input, last_state)`的形式,可以计算得到当前步的输出与状态;
PaddlePaddle:提供op形式的调用接口,通常与[paddle.fluid.layers.DynamicRNN](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#dynamicrnn)配合使用,以获取序列中的单步输入。**注意,`lstm_unit`通过`cell_t_prev`最后一个维度来确定lstm的单元数,同时要求`hidden_t_prev`与`cell_t_prev`最后的维度相同。**
#### 窥孔连接
TensorFlow:通过设置`use_peepholes`选择LSTM的实现是否进行窥孔连接;
PaddlePaddle:只提供非窥孔连接的LSTM实现。
#### 输出变换
TensorFlow:第一个返回值为`step_output`。当`num_proj`非空时,由`hidden_state`经过`fc`变换后得到`step_output`;而当`num_proj`为空时,则直接返回`hidden_step`作为`step_output`
PaddlePaddle:第一个返回值为`hidden_state`,不涉及输出变换。
#### cell_state
TensorFlow:第二个返回值为`cell_state``cell_state`由真实的`cell_state``hidden_state`一起构成:当`state_id_tuple``True`时,返回真实的`cell_state``hidden_state`组成的`tuple`;反之,则返回`concat([cell_state, hidden_state], axis=1)`
PaddlePaddle:第二个返回值为真实的`cell_state`
### 代码示例
```
# embedding 是一个rank为2,lod_level为1的LoDTensor
num_unit_0 = 32
drnn = fluid.layers.DynamicRNN()
with drnn.block():
word = drnn.step_input(embedding)
# 记录hidden_state与cell_state,初始状态使用零向量
prev_hid0 = drnn.memory(shape=[num_unit_0])
prev_cell0 = drnn.memory(shape=[num_unit_0])
# 执行lstm计算
cur_hid0, cur_cell0 = layers.lstm_unit(word, prev_hid0, prev_cell0)
# 更新hidden_state与cell_state
drnn.update_memory(prev_hid0, cur_hid0)
drnn.update_memory(prev_cell0, cur_cell0)
# 输出每个时刻的hidden_state
drnn.output(cur_hid0)
# 获取每个时刻的输出
out = drnn()
# 获取最后时刻的输出
last = fluid.layers.sequence_last(out)
```
## tf.nn.rnn_cell.MultiRNNCell
### [tf.nn.rnn_cell.MultiRNNCell](https://www.tensorflow.org/api_docs/python/tf/nn/rnn_cell/MultiRNNCell)
```python
tf.nn.rnn_cell.MultiRNNCell(
cells,
state_is_tuple=True
)
```
### PaddlePaddle实现
在Tensorflow中,用户通过定义多个单独的`RNNCell`生成一个`cell`列表,进而调用`MultiRNNCell`,可以实现一个多层RNN网络的功能。PaddlePaddle并没有提供一个对应的接口,用户可以在`DynamicRNN`的block中,通过组合多个RNN相关的`unit`实现类似的功能,可参考代码示例。
### 代码示例
```
# 如下代码片段实现两层lstm网络,第一层单元数为32,第二层单元数为16
num_unit_0 = 32
num_unit_1 = 16
emb_size = 12
emb_vocab = 10000
data = fluid.layers.data(name='input', shape=[1], dtype='int64', lod_level=1)
embedding = fluid.layers.embedding(input=data, size=[emb_vocab, emb_size])
drnn = fluid.layers.DynamicRNN()
with drnn.block():
# 定义单步输入
word = drnn.step_input(embedding)
# 定义第一层lstm的hidden_state, cell_state
prev_hid0 = drnn.memory(shape=[num_unit_0])
prev_cell0 = drnn.memory(shape=[num_unit_0])
# 定义第二层lstm的hidden_state, cell_state
prev_hid1 = drnn.memory(shape=[num_unit_1])
prev_cell1 = drnn.memory(shape=[num_unit_1])
# 执行两层lstm运算
cur_hid0, cur_cell0 = layers.lstm_unit(word, prev_hid0, prev_cell0)
cur_hid1, cur_cell1 = layers.lstm_unit(cur_hid0, prev_hid1, prev_cell1)
# 更新第一层lstm的hidden_state, cell_state
drnn.update_memory(prev_hid0, cur_hid0)
drnn.update_memory(prev_cell0, cur_cell0)
# 更新第二层lstm的hidden_state, cell_state
drnn.update_memory(prev_hid1, cur_hid1)
drnn.update_memory(prev_cell1, cur_cell1)
drnn.output(cur_hid1)
out = drnn()
last = fluid.layers.sequence_last_step(out)
```
## tf.nn.separable_conv2d
### [tf.nn.separable_conv2d](https://www.tensorflow.org/api_docs/python/tf/nn/separable_conv2d)
``` python
tf.nn.separable_conv2d(
input,
depthwise_filter,
pointwise_filter,
strides,
padding,
rate=None,
name=None,
data_format=None
)
```
### PaddlePaddle实现
PaddlePaddle中目前无对应接口,可使用如下代码实现,在如下代码中只考虑了基本的`strides`参数,其它参数如`padding`在PaddlePaddle中使用机制
以及输入输出和卷积核格式与TensorFlow存在差异,可参考文档[tf.layers.conv2d](tf.layers.conv2d.md)[tf.nn.depthwise_conv2d](tf.nn.depthwise_conv2d.md)中的说明。
``` python
# TensorFlow中separable_conv2d的使用
depthwise_filter = tf.random_uniform([4, 4, 3, 1], 0.0, 1.0)
pointwise_filter = tf.random_uniform([1, 1, 3, 5], 0.0, 1.0)
result = tf.nn.separable_conv2d(input, depthwise_filter, pointwise_filter,
strides=[1, 1, 1, 1], padding='VALID')
# PaddlePaddle中对应如上代码实现separable_conv2d
depthwise_result = fluid.layers.conv2d(input, 3, filter_size=[4, 4],
stride=[1, 1], groups=3, bias_attr=False)
pointwise_result = fluid.layers.conv2d(depthwise_result, filter_size=[1, 1],
stride=[1, 1], bias_attr=False)
```
## tf.nn.softmax_cross_entropy_with_logits
### [tf.nn.rnn_cell.MultiRNNCell](https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits)
```python
tf.nn.softmax_cross_entropy_with_logits(
_sentinel=None,
labels=None,
logits=None,
dim=-1,
name=None
)
```
### [paddle.fluid.layers.softmax_with_cross_entropy](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#softmax-with-cross-entropy)
```python
paddle.fluid.layers.softmax_with_cross_entropy(
logits,
label,
soft_label=False,
ignore_index=-100,
numeric_stable_mode=False,
return_softmax=False
)
```
### 功能差异
#### 标签类型
TensorFlow:`labels`只能使用软标签,其`shape``[batch, num_classes]`,表示样本在各个类别上的概率分布;
PaddlePaddle:通过设置`soft_label`,可以选择软标签或者硬标签。当使用硬标签时,`label``shape``[batch, 1]``dtype``int64`;当使用软标签时,其`shape``[batch, num_classes]``dtype``int64`
#### 返回值
TensorFlow:返回`batch`中各个样本的log loss;
PaddlePaddle:当`return_softmax``False`时,返回`batch`中各个样本的log loss;当`return_softmax``True`时,再额外返回`logtis`的归一化值。
### 代码示例
```
# logits的shape为[32, 10], dtype为float32; label的shape为[32, 1], dtype为int64
# loss的shape为[32, 1], dtype为float32
loss = fluid.layers.softmax_with_cross_entropy(logits, label, soft_label=False)
```
## tf.nn.top_k
### [tf.nn.top_k](https://www.tensorflow.org/api_docs/python/tf/nn/top_k)
``` python
tf.math.top_k(
input,
k=1,
sorted=True,
name=None
)
```
### [paddle.fluid.layers.topk](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#topk)
``` python
paddle.fluid.layers.topk(
input,
k,
name=None
)
```
### 功能差异
#### 参数差异
TensorFlow: 通过设置`sorted`参数,对返回的值与下标设置是否进行降序排序;`k`默认为1。
PaddlePaddle: 对返回的`top-k` tensor进行降序排序;`k`没有默认值,必须设置。
### 代码示例
```python
# 输入 tensor t 为[[2,6,3],[3,0,8]]
# 当k=2时,输出 tensor out 为[[6,3], [8,3]],index为[[1,2],[2,0]]
out, index = fluid.layers.topk(t, k=1)
```
## tf.one_hot
### [tf.one_hot](https://www.tensorflow.org/api_docs/python/tf/one_hot)
``` python
tf.one_hot(
indices,
depth,
on_value=None,
off_value=None,
axis=None,
dtype=None,
name=None
)
```
### [paddle.fluid.layers.one_hot](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#one-hot)
``` python
layers.one_hot(;
input,
depth
)
```
### 功能差异
#### 输入格式
TensorFlow:indices shape 没有限定;支持设置on与off的值;
PaddlePaddle:input限定为2-D tensor,shape为(batch, 1)。
#### 参数种类
TensorFlow:可以配置`on_value``off_value`,默认为`1``0`
PaddlePaddle:无对应配置选项,即为默认的`1``0`
### 代码示例
```python
# 输入 tensor t 为[[1],[2]]
# depth 为3时,输出 tensor out 为[[0, 1, 0], [0, 0, 1]]
out = fluid.layers.one_hot(t, 3)
```
## tf.pad
### [tf.pad](https://www.tensorflow.org/api_docs/python/tf/pad)
``` python
tf.pad(
tensor,
paddings,
mode='CONSTANT',
name=None,
constant_values=0
)
```
### [paddle.fluid.layers.pad](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#cn-api-fluid-layers-pad)
``` python
paddle.fluid.layers.pad(
x,
paddings,
pad_value=0.0,
name=None
)
```
### 功能差异
#### padding方式
TensorFlow:支持采用三种模式进行padding,不同padding模式决定pad的值是什么,包括constant、symmetric和reflect。padding的shape为(rank, 2),表示每一维前后padding的长度
PaddlePaddle:目前仅支持采用常量进行padding;指定padding长度时,采用一个一维列表表示,其长度为输入rank的两倍,连续的两个值表示某维度上前、后进行padding的长度
### 代码示例
```python
# 输入 tensor t 为[[1,2],[3,4]]
# 第0维前面padding长度为0,后面padding长度为1;第1维前面padding长度为1,后面padding长度为2
out = fluid.layers.pad(t, paddings=[0,1,1,2])
```
## tf.placeholder
### [tf.placeholder](https://www.tensorflow.org/api_docs/python/tf/placeholder)
``` python
tf.placeholder(
dtype,
shape=None,
name=None
)
```
### [paddle.fluid.layers.data](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#cn-api-fluid-layers-data)
``` python
paddle.fluid.layers.data(
name,
shape,
append_batch_size=True,
dtype='float32',
lod_level=0,
type=VarType.LOD_TENSOR,
stop_gradient=True)
```
### 功能差异
#### Batch维度处理
TensorFlow: 对于shape中的batch维度,需要用户使用`None`指定;
PaddlePaddle: 将第1维设置为`-1`表示batch维度;如若第1维为正数,则会默认在最前面插入batch维度,如若要避免batch维,可将参数`append_batch_size`设为`False`
### 代码示例
```python
# 创建输入型tensor out,其shape为[-1, 3, 4], 数据类型为float32
out = fluid.layers.data('out', shape=[3, 4], dtype='float32')
# 创建输入型tensor out,其shape为[3, -1, 4], 数据类型为float32
out = fluid.layers.data('out', shape=[3, -1, 4], append_batch_size=False, dtype='float32')
```
## tf.print
### [tf.print](https://www.tensorflow.org/api_docs/python/tf/print)
```python
tf.print(
*inputs,
**kwargs
)
```
### [paddle.fluid.layers.Print](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#print)
```python
paddle.fluid.layers.Print(
input,
first_n=-1,
message=None,
summarize=-1,
print_tensor_name=True,
print_tensor_type=True,
print_tensor_shape=True,
print_tensor_lod=True,
print_phase='both'
)
```
### 功能差异
#### 使用方式
TensorFlow:在`graph`模式下,该op的运行决定于是否直接被运行,或者作为直接运行的其他op的依赖;在`eager`模式下,该op在被调用后会自动运行;
PaddlePaddle:在被调用后,该op被添加到代码块,之后执行到代码块时将自动运行。
#### input类型
TensorFlow:可以是python primitives,也可以是tensor或其与python primitives的组合;
PaddlePaddle:只可以是tensor。
#### 梯度打印
TensorFlow:不支持;
PaddlePaddle:通过设置`print_phase`,可以控制是否打印`input`的梯度。
### 代码示例
```
# input 是任意paddle tensor
# 打印input的内容,如果有梯度的话也将打印梯度
print(input, message="content of input")
```
## tf.reshape
### [tf.reshape](https://www.tensorflow.org/api_docs/python/tf/reshape)
``` python
tf.reshape(
tensor,
shape,
name=None
)
```
### [paddle.fluid.layers.reshape](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#cn-api-fluid-layers-reshape)
``` python
paddle.fluid.layers.reshape(
x,
shape,
actual_shape=None,
act=None,
inplace=False,
name=None)
```
### 功能差异:
#### shape标记差别
TensorFlow: shape 中可以使用单独一个-1,表示待推断的维度;
PaddlePaddle: shape 中除了可以使用单独一个-1表示待推断维度外,还能使用0,表示在输入tensor原来的shape中对应位置的维度。注意,0的下标不能超过原来tensor的rank。
## 代码示例
```python
# 输入 tensor t 的 shape 为[3, 4]
# 输出 tensor out 的 shape 为[2,6]
out = fluid.layers.reshape(t, [-1, 6])
# 输出 tensor out 的 shape 为[3, 2, 2]
out = fluid.layers.reshape(t, [0, 2, 2])
```
## tf.reverse_sequence
### [tf.reverse_sequence](https://www.tensorflow.org/api_docs/python/tf/reverse_sequence)
```python
tf.reverse_sequence(
input,
seq_lengths,
seq_axis=None,
batch_axis=None,
name=None,
seq_dim=None,
batch_dim=None
)
```
### [paddle.fluid.layers.sequence_reverse](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#sequence_reverse)
```python
paddle.fluid.layers.sequence_reverse(
x,
name=None
)
```
### 功能差异
#### 输入格式
Tensorflow:`reverse_sequence`中,`input`是一个带padding的tensor,每个序列都会被填充到相同长度;
PaddlePaddle:`sequence_reverse`中,`x`是一个[LoDTensor](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/fluid_cn.html#lodtensor)
不需要进行填充;
#### 参数类型
Tensorflow:通过`seq_axis``batch_axis`指定序列维度与batch维度;同时使用`seq_lengths`来表示每个序列的长度,属于序列的部分会被翻转,padding部分则被保留;
PaddlePaddle:由于`LoDTensor`本身已经携带序列信息,因而不需要用户提供除了输入tensor外的额外参数;
### 代码示例
```
# x是shape为[5, 6]的LoDTensor,其LoD信息为{0, 2, 5},表示两个序列,长度分别是2和3
# out同样也是shape为[5, 6]的LoDTensor,LoD信息为{0, 2, 5},表示两个序列
# out[0:2, 6] = x[2:0:-1, 6]
# out[2:5, 6] = x[5:2:-1, 6]
out = fluid.layers.sequence_reverse(x)
```
## tf.scatter_update
### [tf.scatter_update](https://www.tensorflow.org/api_docs/python/tf/scatter_update)
```python
tf.scatter_update(
ref,
indices,
updates,
use_locking=True,
name=None
)
```
### [paddle.fluid.layers.scatter](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#scatter)
```python
paddle.fluid.layers.scatter(
input,
index,
updates,
name=None
)
```
### 功能差异
#### 参数类型
Tensorflow:`indices`支持任意维度,可以是变量,也可以是常量;
PaddlePaddle:`index`只支持1-d Variable。
#### 其他
Tensorflow:`updates`支持numpy-style broadcasting;
PaddlePaddle:`updates`要求其rank与`input`相同,同时`updates.shape[0]`等于`index.shape[0]`
### 代码示例
```
# x是dtype为float32, shape为[3,9,5]的张量
# 将x[1:,:,:]置为1,并返回更新后的张量
out = layers.scatter(x,
index=layers.assign(np.array([1,2], dtype='int32')),
updates=layers.assign(np.ones((2,9,5), dtype='float32')))
```
## tf.slice
### [tf.slice](https://www.tensorflow.org/api_docs/python/tf/slice)
``` python
tf.slice(
input_,
begin,
size,
name=None
)
```
### [paddle.fluid.layers.slice](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#cn-api-fluid-layers-slice)
``` python
paddle.fluid.layers.slice(
input,
axes,
starts,
ends
)
```
### 功能差异
#### 参数类型
TensorFlow:`begin/size`可以是python list,也可以是变量类型;
PaddlePaddle:`axes/starts/ends`只能是python list。
#### 参数种类
TensorFlow:使用`begin`指定要开始截取tensor的位置,使用`size`指定截取长度,必须描述所有的轴;
PaddlePaddle:采用`axes`指定要操作的轴,未指定的轴默认全部截取,使用`starts``ends`分别指定截取tensor的开始与结束位置,注意采用的是先闭后开[start, end)的写法。
### 代码示例
```python
# 输入 tensor t 为[[0,1,2,3],[4,5,6,7],[8,9,10,11]]
# 输出 tensor out 为[[1,2],[5,6]]
out = fluid.layers.slice(t, axes=[0,1], starts=[0,1], ends=[2,3])
# 输出 tensor out 为[[1,2],[5,6],[9,10]]
out = fluid.layers.slice(t, axes=[1], starts=[1], ends=[3])
```
## tf.split
### [tf.split](https://www.tensorflow.org/api_docs/python/tf/split)
```python
tf.split(
value,
num_or_size_splits,
axis=0,
num=None,
name='split'
)
```
### [paddle.fluid.layers.split](http://paddlepaddle.org/documentation/docs/zh/1.2/api_cn/layers_cn.html#split)
```python
paddle.fluid.layers.split(
input,
num_or_sections,
dim=-1,
name=None
)
```
### 功能差异
#### 返回值类型
TensorFlow:`split`函数返回的结果均保存在一个tensor类型的值中;
PaddlePaddle:`split`返回`list`类型结果,长度为`num_or_sections`
### 代码示例
```
# x是shape为[3,9,5]的张量:
x0, x1, x2 = fluid.layers.split(x, num_or_sections=3, dim=1)
x0.shape # [3, 3, 5]
x1.shape # [3, 3, 5]
x2.shape # [3, 3, 5]
```
## tf.squared_difference
### [tf.squared_diffenrece](https://www.tensorflow.org/api_docs/python/tf/math/squared_difference)
``` python
tf.math.squared_difference(
x,
y,
name=None
)
```
### PaddlePaddle实现
PaddlePaddle中目前无对应接口,可使用如下代码实现
``` python
def squared_difference(x, y):
net_0 = fluid.layers.elementwise_sub(x, y)
net_1 = fluid.layers.elementwise_mul(net_0, net_0)
return net_1
```
### 代码示例
``` python
input_x = fluid.layers.data(dtype='float32', shape=[1000], name='input_x')
input_y = fluid.layers.data(dtype='float32', shape=[1000], name='input_y')
# 调用上述自定义函数
result = squared_difference(input_x, input_y)
```
## tf.stop_gradient
### [tf.stop_gradient](https://www.tensorflow.org/api_docs/python/tf/stop_gradient)
``` python
tf.stop_gradient(
input,
name=None
)
```
### PaddlePaddle实现
TensorFlow中,使用`stop_gradient`表示该tensor不需要进行bp。而在PaddlePaddle中,每个tensor具有`stop_gradient`的属性,用户可以将该属性直接设置成`True`/`False`
## 代码示例
```python
# 将tensor t设置成不需要bp
t.stop_gradient = True
## tf.while_loop
### [tf.while_loop](https://www.tensorflow.org/api_docs/python/tf/while_loop)
```python
tf.while_loop(
cond,
body,
loop_vars,
shape_invariants=None,
parallel_iterations=10,
back_prop=True,
swap_memory=False,
name=None,
maximum_iterations=None,
return_same_structure=False
)
```
### [paddle.fluid.layers.While](http://paddlepaddle.org/documentation/docs/zh/1.3/api_cn/layers_cn.html#while)
```python
paddle.fluid.layers.While(
cond,
is_test=False,
name=None
)
```
### 功能差异
#### 使用方式
TensorFlow:用户通过函数的方式定义`cond``body`,在循环体中操纵的是循环变量`loop_vars`,返回值为`tensor`或其`list`;
PaddlePaddle:用户通过op的方式定义`cond`,然后在`block`中实现循环体。*注意,在循环体中用户需要更新`cond`,具体可参数代码示例*
#### 其他
TensorFlow:支持设置最大迭代次数`maximum_iterations`及并行迭代`parallel_iterations`;
PaddlePaddle:不涉及最大迭代次数及并行。
### 代码示例
```
# 如下代码片段实现从0到5循环叠加i
i = fluid.layers.fill_constant(shape=[1], dtype='int64', value=0)
limit = fluid.layers.fill_constant(shape=[1], dtype='int64', value=5)
# 定义条件
cond = layers.less_than(x=i, y=limit)
while_op = layers.While(cond=cond)
# 定义循环体
with while_op.block():
# 更新i
i = layers.increment(x=i, in_place=True)
# 更新条件状态
layers.less_than(x=i, y=limit, cond=cond)
```
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册