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) |