tf.layers是一种较为高级的TensorFlow API封装,可以在一个函数内实现神经网络一层的完整功能。对于已经理解了基本原理、使用已有的网络、追求高效率开发的人来说,tf.layers是一个不错的选择。
  虽然tf.layers简单好用,但是理解底层原理和学会使用底层API也同样有必要,因为当提出一个新的想法,或一篇新发表的论文需要用代码实现的时候,往往还没有高级的API,这时候底层的API就发挥出它的作用了。
  下面介绍tf.layers的如下几个(常用)函数:
Contents
tf.layers函数
| 函数 | 作用 | 
|---|---|
| tf.layers.dense | 全连接层 | 
| tf.layers.dropout | Droupout层 | 
| tf.layers.flatten | 把一个Tensor展平 | 
| tf.layers.conv2d | 二维卷积层 | 
| tf.layers.conv2d_transpose | 二维反卷积层 | 
| tf.layers.max_pooling2d | 二维最大池化层 | 
| tf.layers.average_pooling2d | 二维平均池化层 | 
| tf.layers.batch_normalization | 批量标准化层 | 
tf.layers.dense 全连接层
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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 ) """     Args:         inputs: 输入的Tensor         units: 整数,表示输出的神经元的数量         activation: 激活函数,可以选tf.nn.relu、tf.sigmoid等,也可以使用自己定义的函数         use_bias: 是否使用偏移,默认为True         kernel_initializer: 权重的初始化方法,如果为None,则使用默认的 Xavier 初始化方法         bias_initializer: 偏移的初始化方法,默认为零值初始化         kernel_regularizer: 施加在权重上的正则项         bias_regularizer: 施加在偏移上的正则项         activity_regularizer: 施加在输出上的正则项         kernel_constraint: 施加在权重上的约束项         bias_constraint: 施加在偏移上的约束项         trainable: 是否可训练,默认为True         name: 给这一层起个名字         reuse: 是否可重复利用,默认为None """ | 
tf.layers.dropout Dropout 层
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | tf.layers.dropout(     inputs,     rate=0.5,     noise_shape=None,     seed=None,     training=False,     name=None) """     Args:         inputs: 输入Tensor         rate=0.5: Dropout的比例,如果rate=0.1,会丢弃10%的输入神经元         noise_shape: dropout mask的shape,例如inputs的shape为(batch_size, timesteps, features),但我们想要droput mask              在所有timesteps都是相同的,我们可以设置 noise_shape=[batch_size, 1, features]。         seed: 产生随机数的种子值 """ | 
tf.layers.flatten 把一个Tensor展平(保留batch维,即第0维)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | tf.layers.flatten(inputs, name=None, data_format='channels_last') """     Args:         inputs: 输入张量         name: 名字         data_format: 一个字符串,指出channel的位置。             如果为'channels_last',则表示(batch, height, width, channels)             如果为'channels_first',则表示(batch, channels, height, width)     Examples:         x = tf.placeholder(shape=(None, 4, 4), dtype='float32')         y = flatten(x)         # flatten后`y`的形状变为了`(None, 16)` """ | 
tf.layers.conv2d 二维卷积层
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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=init_ops.zeros_initializer(),     kernel_regularizer=None,     bias_regularizer=None,     activity_regularizer=None,     kernel_constraint=None,     bias_constraint=None,     trainable=True,     name=None,     reuse=None) """     Args:         inputs: 输入Tensor         filters: 整数,过滤器的个数(即输出通道个数output_channels)         kernel_size: 一个整数(表示高和宽都是这个数)或一个列表[高, 宽],表示卷积核大小         strides=(1, 1): 一个整数(表示高和宽都是这个数)或一个列表[高, 宽],表示filter移动的步长         padding='valid': 一个字符串,'SAME'或'VALID',不区分大小写         data_format='channels_last': 一个字符串,表示channel的先后位置,与上面tf.layers.flatten意义相同         dilation_rate=(1, 1): 一个整数(表示高和宽都是这个数)或一个列表[高, 宽],表示卷积核的扩张率         activation=None: 激活函数 """ | 
tf.layers.conv2d_transpose 二维反卷积层
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | tf.layers.conv2d_transpose(     inputs,     filters,     kernel_size,     strides=(1, 1),     padding='valid',     data_format='channels_last',     activation=None,     use_bias=True,     kernel_initializer=None,     bias_initializer=init_ops.zeros_initializer(),     kernel_regularizer=None,     bias_regularizer=None,     activity_regularizer=None,     kernel_constraint=None,     bias_constraint=None,     trainable=True,     name=None,     reuse=None) """     Args:         参数与tf.layers.conv2d相同 """ | 
tf.layers.max_pooling2d 二维最大池化
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | tf.layers.max_pooling2d(     inputs,     pool_size,     strides,     padding='valid',     data_format='channels_last',     name=None) """     Args:         inputs: 输入Tensor         pool_size: 一个整数(表示高和宽都是这个数)或一个列表[高, 宽],表示pooling窗口大小         strides: 一个整数(表示高和宽都是这个数)或一个列表[高, 宽],表示pooling窗口移动的步长         padding='valid': 一个字符串,表示padding的方式,有'SAME'和'VALID'         data_format='channels_last':         name=None """ | 
tf.layers.average_pooling2d 二维平均池化
参数与二维最大池化相同
tf.layers.batch_normalization 批量标准化
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | tf.layers.batch_normalization(     inputs,     axis=-1,     momentum=0.99,     epsilon=1e-3,     center=True,     scale=True,     beta_initializer=init_ops.zeros_initializer(),     gamma_initializer=init_ops.ones_initializer(),     moving_mean_initializer=init_ops.zeros_initializer(),     moving_variance_initializer=init_ops.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) """     Args:         inputs: 输入Tensor         axis=-1:         momentum=0.99: 滑动平均的Momentum         epsilon=1e-3: 大于0的小浮点数,用于防止除0错误。         center=True: 如果为True,则将beta作为偏置加上去         scale=True: 若为True,则会乘以gamma         beta_initializer=init_ops.zeros_initializer(): beta权重的初始方法         gamma_initializer=init_ops.ones_initializer(): gamma权重的初始方法         moving_mean_initializer=init_ops.zeros_initializer(): 动态均值的初始化方法         moving_variance_initializer=init_ops.ones_initializer(): 动态方差的初始化方法         beta_regularizer=None: beta的正则化方法         gamma_regularizer=None: gamma的正则化方法         beta_constraint=None: 加在beta上的约束项         gamma_constraint=None: 加在gamma上的约束项         training=False: 布尔类型值或者布尔类型的Tensor(例如placeholder).是以训练的方式还是接口的方式返回输出         trainable=True: 是否可训练         name=None: 起个名字         reuse=None: 是否重用         renorm=False: 是否要用Batch Renormalization(https://arxiv.org/abs/1702.03275)         renorm_clipping=None: 是否要用 rmax、rmin、dmax 来 scalar Tensor         renorm_momentum=0.99: 用来更新动态均值和标准差的Momentum值         fused=None: 是否使用一个更快的、融合的实现方法         virtual_batch_size=None: 整数,指定一个虚拟batch size         adjustment=None: 对标准化后的结果进行适当调整的方法 """ | 
使用tf.layers简化代码
之前的文章TensorFlow – 卷积神经网络(CNN)与代码实现中的代码可以用tf.layers简化为:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | # encoding=utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('MNIST_data/', one_hot=True) """     输入 """ with tf.name_scope('input'):     x = tf.placeholder(tf.float32, [None, 784])     x_reshape = tf.reshape(x, [-1, 28, 28, 1]) with tf.name_scope('labels'):     y_ = tf.placeholder(tf.float32, [None, 10]) """     第一层卷积层 """ with tf.name_scope('conv_1'):     '''     w_c1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1), name='w_c1')     b_c1 = tf.Variable(tf.constant(0.1, shape=[32]), name='b_c1')     conv1 = tf.nn.conv2d(x_reshape, w_c1, strides=[1, 1, 1, 1], padding='SAME', name='conv1')     conv1 = tf.nn.relu(conv1 + b_c1, name='relu1')  # 使用relu激活函数     '''     conv1 = tf.layers.conv2d(x_reshape, 32, 5, padding='SAME', activation=tf.nn.relu)     # conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool1')     conv1 = tf.layers.max_pooling2d(conv1, 2, 2, padding='SAME') with tf.name_scope('conv_2'):     '''     w_c2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1), name='w_c2')     b_c2 = tf.Variable(tf.constant(0.1, shape=[64]), name='b_c2')     conv2 = tf.nn.conv2d(conv1, w_c2, strides=[1, 1, 1, 1], padding='SAME', name='conv2')     conv2 = tf.nn.relu(conv2 + b_c2, name='relu2')  # 使用relu激活函数     '''     conv2 = tf.layers.conv2d(conv1, 64, 5, padding='SAME', activation=tf.nn.relu)     # conv2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool2')     conv2 = tf.layers.max_pooling2d(conv2, 2, 2, padding='SAME') """     全连接层 """ with tf.name_scope('fc'):     # dense = tf.reshape(conv2, [-1, 7 * 7 * 64])     dense = tf.layers.flatten(conv2)     '''     w_d = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1), name='w_d')     b_d = tf.Variable(tf.constant(0.1, shape=[1024]), name='b_d')     dense = tf.matmul(dense, w_d)     dense = tf.nn.relu(dense + b_d, name='relu_d')     '''     dense = tf.layers.dense(dense, 1024, activation=tf.nn.relu)     # 使用Dropout, keep_prob是一个占位符, 训练时为0.5, 测试时为1     keep_prob = tf.placeholder(tf.float32)     dense = tf.nn.dropout(dense, keep_prob) """     输出层 """ with tf.name_scope('output'):     '''     w_out = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1), name='w_out')     b_out = tf.Variable(tf.constant(0.1, shape=[10]), name='b_out')     y = tf.matmul(dense, w_out) + b_out     '''     y = tf.layers.dense(dense, 10) loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)) optimizer = tf.train.AdamOptimizer(1e-4).minimize(loss) correct = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct, tf.float32)) with tf.Session() as sess:     sess.run(tf.global_variables_initializer())     tf.summary.FileWriter('logs/', sess.graph)     for i in range(20000):         batch = mnist.train.next_batch(50)         if i % 10 == 0:             # 每100次输出一次准确率             acc = sess.run(accuracy, feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.})             print('step %d, accuracy:%g' % (i, acc))         # 训练         sess.run(optimizer, feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})     acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.})     print('training completed, test accuracy:%g' % acc) | 
