TensorFlow中的图层模块提供用于深度学习的更高层次封装的API,利用它我们可以轻松地构建模型,这一节我们就来看这个模块的API的具体用法。
概览
层模块的路径写法为tf.layers,这个模块定义在tensorflow / python / layers / layers.py,其官方文档地址为:
https
://www.tensorflow.org/api_docs/python/tf/layers,TensorFlow
版本为1.5。
这里面提供了多个类和方法以供使用,下面我们分别予以介绍。
方法
tf.layers模块提供的方法有:
-
Input(...):用于实例化一个输入张量,作为神经网络的输入。
-
average_pooling1d(...):一维平均池化层
-
average_pooling2d(...):二维平均池化层
-
average_pooling3d(...):三维平均池化层
-
batch_normalization(...):批量标准化层
-
conv1d(...):一维卷积层
-
conv2d(...):二维卷积层
-
conv2d_transpose(...):二维反卷积层
-
conv3d(...):三维卷积层
-
conv3d_transpose(...):三维反卷积层
-
密集(...):全连接层
-
辍学(...):辍学层
-
flatten(...):Flatten层,即把一个张量展平
-
max_pooling1d(...):一维最大池化层
-
max_pooling2d(...):二维最大池化层
-
max_pooling3d(...):三维最大池化层
-
separable_conv2d(...):二维深度可分离卷积层
输入
tf.layers.Input()这个方法是用于输入数据的方法,其实类似于tf.placeholder,相当于一个占位符的作用,当然也可以通过传入张量参数来进行赋值。
12345678Input( shape=None, batch_size=None, name=None, dtype=tf.float32, sparse=False, tensor=None)
参数说明如下:
-
形状:可选,默认无,是一个数字组成的组或列表,但是这个形状比较特殊,它不包含batch_size,比如传入的形为[32],那么它会将形状转化为[?,32 ],这里一定需要注意。
-
batch_size:任选,默认无,代表输入数据的批量大小,可以是数字或者无。
-
名称:可选,默认无,输入层的名称。
-
dtype:可选,默认tf.float32,元素的类型。
-
稀疏:可选,默认False,指定是否以稀疏矩阵的形式来创建占位符。
-
张量:任选,默认无,如果指定,那么创建的内容便不再是一个占位符,会用此张量初始化。
返回值:返回一个包含历史元数据的张量。
我们用一个实例来感受一下:
1234x = tf.layers.Input(shape=[32])print(x)y = tf.layers.dense(x, 16, activation=tf.nn.softmax)print(y)
首先我们用Input()方法初始化了一个占位符,这时我们没有传入张量参数,然后调用了dense()方法构建了一个全连接网络,激活函数使用softmax,然后将二者输出,结果如下:
12Tensor("input_layer_1:0", shape=(?, 32), dtype=float32)Tensor("dense/Softmax:0", shape=(?, 16), dtype=float32)
这时我们发现,shape它给我们做了转化,本来是[32],结果它给转化成了[?,32],即第一维代表batch_size,所以我们需要注意,在调用此方法的时候不需要去关心batch_size这一维。
如果我们在初始化的时候传入一个已有张量,例如:
123data = tf.constant([1, 2, 3])x = tf.layers.Input(tensor=data)print(x)
结果如下:
1Tensor("Const:0", shape=(3,), dtype=int32)
可以看到它可以自动计算出其形状和dtype。
batch_normalization
此方法是批量标准化的方法,经过处理之后可以加速训练速度,其定义在tensorflow / python / layers / normalization.py,论文可以参考:
http://arxiv.org/abs/1502.03167
“批量标准化:加速深度通过减少内部协变量来进行网络培训“。
1234567891011121314151617181920212223242526batch_normalization( inputs, axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer=tf.zeros_initializer(), gamma_initializer=tf.ones_initializer(), moving_mean_initializer=tf.zeros_initializer(), moving_variance_initializer=tf.ones_initializer(), beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None, training=False, trainable=True, name=None, reuse=None, renorm=False, renorm_clipping=None, renorm_momentum=0.99, fused=None, virtual_batch_size=None, adjustment=None)
参数说明如下:
-
输入:必需,即输入数据。
-
axis:任选,默认-1,即进行标注化操作时操作数据的哪个维度。
-
动力:可选,默认0.99,即动态均值的动量。
-
epsilon:可选,默认0.01,大于0的小浮点数,用于防止除0错误。
-
center:可选,默认True,若设为True,将会beta作为偏置加上去,否则忽略参数beta
-
scale:任意,默认True,若设为True,则会乘以gamma,否则不使用gamma。当下一层是线性的时,可以设False,因为scaling的操作将被下一层执行。
-
beta_initializer:任选,默认zeros_initializer,即beta权重的初始方法。
-
gamma_initializer:可选,默认ones_initializer,即gamma的初始化方法。
-
moving_mean_initializer:任选,默认zeros_initializer,即动态均值的初始化方法。
-
moving_variance_initializer:可选,默认ones_initializer,即动态方差的初始化方法。
-
beta_regularizer:可选,默认无,beta的正则化方法。
-
gamma_regularizer:可选,默认无,gamma的正则化方法。
-
beta_constraint:可选,默认无,加在beta上的约束项。
-
gamma_constraint:可选,默认无,加在gamma上的约束项。
-
训练:可选,默认False,返回结果是训练模式。
-
可训练:可选,默认为True,布尔类型,如果为True,则要变量添加GraphKeys.TRAINABLE_VARIABLES中。
-
名称:任选,默认无,层名称。
-
重用:可选,默认无,根据层名判断是否重复利用。
-
renorm:任选,默认False,是否要用Batch Renormalization(https://arxiv.org/abs/1702.03275)
-
renorm_clipping:可选,默认无,是否要使用rmax,rmin,dmax来标量张量。
-
renorm_momentum,可选,默认0.99,用来更新动态均值和标准差的Momentum值。
-
融合,可选,默认无,是否使用一个更快的,融合的实现方法。
-
virtual_batch_size,可选,默认无,是一个int数字,指定一个虚拟批量大小。
-
调整,任选,默认无,对标准化后的结果进行适当调整的方法。
最后的一些参数说明不够详尽,更详细的用法参考:
https
其用法很简单,在输入数据后面加一层batch_normalization()即可:
123x = tf.layers.Input(shape=[32])x = tf.layers.batch_normalization(x)y = tf.layers.dense(x, 20)
稠密
密集,即全连接网络,层模块提供了一个dense()方法来实现此操作,定义在tensorflow / python / layers / core.py中,下面我们来说明一下它的用法。
12345678910111213141516dense( 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)
参数说明如下:
-
输入:必需,即需要进行操作的输入数据。
-
单位:必须,即神经元的数量。
-
activation:可选,默认为None,如果为None则是线性激活。
-
use_bias:可选,默认为True,是否使用偏置。
-
kernel_initializer:可选,默认为None,即权重的初始化方法,如果为None,则使用默认的Xavier初始化方法。
-
bias_initializer:可选,默认为零值初始化,即偏置的初始化方法。
-
kernel_regularizer:可选,默认为None,施加在权重上的正则项。
-
bias_regularizer:可选,默认为None,施加在偏置上的正则项。
-
activity_regularizer:可选,默认为None,施加在输出上的正则项。
-
kernel_constraint,可选,默认为None,施加在权重上的约束项。
-
bias_constraint,可选,默认为None,施加在偏置上的约束项。
-
可训练:可选,默认为True,布尔类型,如果为True,则会将变量添加到GraphKeys.TRAINABLE_VARIABLES中。
-
name:可选,默认为None,卷积层的名称。
-
重用:可选,默认为无,布尔类型,如果为True,那么如果名称相同时,会重复利用。
返回值:全连接网络处理后的张量。
下面我们用一个实例来感受一下它的用法:
1
2
3
4
5
6
|
x = tf.layers.Input(shape=[32])
print(x)
y1 = tf.layers.dense(x, 16, activation=tf.nn.relu)
print(y1)
y2 = tf.layers.dense(y1, 5, activation=tf.nn.sigmoid)
print(y2)
|
首先我们用Input定义了[?,32]的输入数据,然后经过第一层全连接网络,此时指定了神经元个数为16,激活函数为relu,接着输出结果经过第二层全连接网络,此时指定了神经元个数为5,激活函数为sigmoid,最后输出,结果如下:
1
2
3
|
Tensor("input_layer_1:0", shape=(?, 32), dtype=float32)
Tensor("dense/Relu:0", shape=(?, 16), dtype=float32)
Tensor("dense_2/Sigmoid:0", shape=(?, 5), dtype=float32)
|
可以看到输出结果的最后一维度就等于神经元的个数,这是非常容易理解的。
卷积
(),conv2d(),conv3d(),分别代表一维,二维,三维卷积,另外还有conv2d_transpose(),conv3d_transpose(),这个提供了多卷积方法, ,分别代表二维和三维反卷积,还有separable_conv2d()方法代表二维深度可分离卷积。它们定义在tensorflow / python / layers / convolutional.py中,其用法都是类似的,在这里conv2d()方法为例进行说明。
123456789101112131415161718192021conv2d( 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)
参数说明如下:
-
输入:必需,即需要进行操作的输入数据。
-
filters:必需,是一个数字,代表了输出通道的个数,即output_channels。
-
kernel_size:必需,卷积核大小,必须是一个数字(高和宽都是此数字)或者长度为2的列表(分别代表高,宽)。
-
strides:可选,默认为(1,1),卷积步长,必须是一个数字(高和宽都是此数字)或者长度为2的列表(分别代表高,宽)。
-
padding:可选,默认为valid,padding的模式,有效和same两种,大小写不区分。
-
data_format:可选,默认channels_last,分为channels_last和channels_first两种模式,代表了怎么输入数据的维度类型,如果是channels_last,那么输入数据的形状为(batch,height,width,channels),如果是channels_first,那么输入数据的形状为(批次,通道,高度,宽度)。
-
dilation_rate:任选,默认为(1,1),卷积的扩张率,如当扩张率为2时,卷积核内部就会有边距,3×3的卷积核就会变成5× 5。
-
activation:可选,默认为None,如果为None则是线性激活。
-
use_bias:可选,默认为True,是否使用偏置。
-
kernel_initializer:可选,默认为None,即权重的初始化方法,如果为None,则使用默认的Xavier初始化方法。
-
bias_initializer:可选,默认为零值初始化,即偏置的初始化方法。
-
kernel_regularizer:可选,默认为None,施加在权重上的正则项。
-
bias_regularizer:可选,默认为None,施加在偏置上的正则项。
-
activity_regularizer:可选,默认为None,施加在输出上的正则项。
-
kernel_constraint,可选,默认为None,施加在权重上的约束项。
-
bias_constraint,可选,默认为None,施加在偏置上的约束项。
-
可训练:可选,默认为True,布尔类型,如果为True,则会将变量添加到GraphKeys.TRAINABLE_VARIABLES中。
-
name:可选,默认为None,卷积层的名称。
-
重用:可选,默认为无,布尔类型,如果为True,那么如果名称相同时,会重复利用。
返回值:卷积后的张量。
下面我们用实例感受一下它的用法:
123x = tf.layers.Input(shape=[20, 20, 3])y = tf.layers.conv2d(x, filters=6, kernel_size=2, padding='same')print(y)
这里我们首先声明了一个[?,20,20,3]的输入x,然后将其传给conv2d()方法,filters设定为6,即输出通道为6,kernel_size为2,即卷积核大小为2 x 2,padding方式设置为same,那么输出结果的宽高和原来一定是相同的,但是输出通道就变成了6,结果如下:
1Tensor("conv2d/BiasAdd:0", shape=(?, 20, 20, 6), dtype=float32)
但如果我们将padding方式不传入,使用默认的有效模式,代码改写如下:
1
2
3
|
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=2)
print(y)
|
结果如下:
1
|
Tensor("conv2d/BiasAdd:0", shape=(?, 19, 19, 6), dtype=float32)
|
结果就变成了[?,19,19,6],这是因为步长默认为1,卷积核大小为2 x 2,所以得到的结果的高宽即为(20 - (2 - 1) )×(20-(2-1))= 19×19。
当然卷积核我们也可以变换大小,传入一个列表形式:
1
2
3
|
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=[2, 3])
print(y)
|
这时我们的卷积核大小变成了2 x 3,即高为2,宽为3,结果就变成了[?,19,18,6],这是因为步长默认为1,核大小为2 x 2,所以得到的结果的高宽即为(20 - (2 - 1))x(20 - (3 - 1))= 19 x 18。
如果我们将步长也设置一下,也传入列表形式:
1
2
3
|
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=[2, 3], strides=[2, 2])
print(y)
|
这个卷积核大小变成了2 x 3,步长变成了2 x 2,所以结果的高宽为ceil(20 - (2 1))/ 2 x ceil(20 - (3 - 1) )/ 2 = 10 x 9,得到的结果即为[?,10,9,6]。
运行结果如下:
1
|
Tensor("conv2d_4/BiasAdd:0", shape=(?, 10, 9, 6), dtype=float32)
|
另外我们还可以传入激活函数,或者用于偏置等操作,实例如下:
1
2
3
|
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=2, activation=tf.nn.relu, use_bias=False)
print(y)
|
这样我们就将激活函数改成了relu,同时禁用了bias,运行结果如下:
1
|
Tensor("conv2d_5/Relu:0", shape=(?, 19, 19, 6), dtype=float32)
|
另外还有反卷积操作,反卷积顾名思义即卷积的反向操作,即输入卷积的结果,得到卷积前的结果,其参数用法是完全一样的,例如:
1
2
3
|
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d_transpose(x, filters=6, kernel_size=2, strides=2)
print(y)
|
例如此处输入的图像高宽为20 x 20,经过卷积核为2,步长为2的反卷积处理,得到的结果高宽就变为了40 x 40,结果如下:
1
|
Tensor("conv2d_transpose/BiasAdd:0", shape=(?, 40, 40, 6), dtype=float32)
|
池
pooling,即池化,layers模块提供了多个池化方法,这几个池化方法都是类似的,包括max_pooling1d(),max_pooling2d(),max_pooling3d(),average_pooling1d(),average_pooling2d(),average_pooling3d ),分别代表一维二维三维最大和平均池化方法,它们都定义在tensorflow / python / layers / pooling.py中,这里以max_pooling2d()方法为例进行介绍。
12345678max_pooling2d( inputs, pool_size, strides, padding='valid', data_format='channels_last', name=None)
参数说明如下:
-
输入:必需,即需要池化的输入对象,必须是4维的。
-
pool_size:必需,池化窗口大小,必须是一个数字(高和宽都是此数字)或者长度为2的列表(分别代表高,宽)。
-
strides:必需,池化步长,必须是一个数字(高和宽都是此数字)或者长度为2的列表(分别代表高,宽)。
-
padding:可选,默认valid,padding的方法,有效或者相同,大小写不区分。
-
data_format:可选,默认channels_last,分为channels_last和channels_first两种模式,代表了怎么输入数据的维度类型,如果是channels_last,那么输入数据的形状为(batch,height,width,channels),如果是channels_first,那么输入数据的形状为(批次,通道,高度,宽度)。
-
名称:可选,默认无,池化层的名称。
返回值:经过池化处理后的张量。
下面我们用一个实例来感受一下:
1
2
3
4
5
6
|
x = tf.layers.Input(shape=[20, 20, 3])
print(x)
y = tf.layers.conv2d(x, filters=6, kernel_size=3, padding='same')
print(y)
p = tf.layers.max_pooling2d(y, pool_size=2, strides=2)
print(p)
|
在这里我们首先指定了输入x,形为[20,20,3],然后对其进行了卷积计算,然后池化,最后得到池化后的结果。结果如下:
1
2
3
|
Tensor("input_layer_1:0", shape=(?, 20, 20, 3), dtype=float32)
Tensor("conv2d/BiasAdd:0", shape=(?, 20, 20, 6), dtype=float32)
Tensor("max_pooling2d/MaxPool:0", shape=(?, 10, 10, 6), dtype=float32)
|
可以看到这里池化窗口用的是2,步长也是2,所以原本卷积后形为[?,20,20,6]的结果就变成了[?,10,10,6]。
退出
dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃,可以用来防止过拟合,层模块中提供了dropout()方法来实现这一操作,定义在tensorflow / python / layers / core.py。下面我们来说明一下它的用法。
12345678dropout( inputs, rate=0.5, noise_shape=None, seed=None, training=False, name=None)
参数说明如下:
-
输入:必须,即输入数据。
-
rate:任选,默认为0.5,即丢失率,如设置为0.1,则意味着会丢弃10%的神经元。
-
noise_shape:可选,默认为None,int32类型的一维Tensor,它代表了丢弃mask的形状,dropout mask会与输入相乘对输入做转换,例如输入的形状为(batch_size,timesteps,features),但我们想要droput mask在所有timeteps都是相同的,我们可以设置noise_shape = [batch_size,1,features]。
-
seed:任选,默认为None,即产生随机熟的种子值。