在一个学习讨论组里被提问到:使用tensorflow创建网络模型时采用 tf.keras 和 tf.layers 哪种比较好?二话没说直接上代码。
把tensorflow官方的MNIST例子直接拿过来比较:
1、tf.layers
def model_fn(features, labels, mode, config):
"""
用tf.layers创建网络模型
:param features: 特征数据
:param labels: 标签
:param mode: 模式:tf.estimator.ModeKeys:TRAIN、EVAL、PREDICT
:param config
:return:
"""
# 批次为-1 宽高为28x28 通道为1
batch_size = -1
image_width = 28
image_height = 28
channels = 1
class_num = 10
learning_rate = 1e-4
input_height = image_height
input_width = image_width
# 输入层:
input_layer = tf.reshape(features['x'], [batch_size, image_height, image_width, channels])
# 卷积层1: 32个 5x5 过滤器 + ReLU激活函数
conv1 = tf.layers.conv2d(inputs=input_layer,
filters=32,
kernel_size=[5, 5],
padding='same',
activation=tf.nn.relu)
# 池化层1: 2x2 过滤器 + 步长为2
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
input_height = input_height // 2
input_width = input_width // 2
# 卷积层2: 64个 5x5 过滤器 + ReLU激活函数
conv2 = tf.layers.conv2d(inputs=pool1,
filters=64,
kernel_size=[5, 5],
padding='same',
activation=tf.nn.relu)
# 池化层2
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
input_height = int(input_height // 2)
input_width = int(input_width // 2)
pool2_flat = tf.reshape(pool2, [-1, input_height * input_width * 64])
# 密集层: 1024个神经元 + 丢弃正则化率为0.4
dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
dropout = tf.layers.dropout(inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
# 对数层: 10个神经元即分类类别0-9
logits = tf.layers.dense(inputs=dropout, units=class_num)
2、tf.keras
def create_model(data_format):
"""
用Keras创建网络模型
:param data_format:
:return:
"""
image_width = 28
image_height = 28
channels = 1
class_num = 10
if data_format == 'channels_first':
# (batch, channels, height, width) default
input_shape = [channels, image_height, image_width]
else:
# (batch, height, width, channels)
assert data_format == 'channels_last'
input_shape = [image_height, image_width, channels]
layer = tf.keras.layers
# 池化层: pool_size=(2,2) strides=(2,2)
max_pool = layer.MaxPool2D((2, 2), (2, 2), padding='same', data_format=data_format)
return tf.keras.Sequential([
layer.Reshape(target_shape=input_shape,
input_shape=(image_height * image_width,)),
layer.Conv2D(filters=32,
kernel_size=5,
padding='same',
data_format=data_format,
activation=tf.nn.relu),
max_pool,
layer.Conv2D(filters=64,
kernel_size=5,
padding='same',
data_format=data_format,
activation=tf.nn.relu),
max_pool,
layer.Flatten(),
layer.Dense(1024, activation=tf.nn.relu),
layer.Dropout(0.4),
layer.Dense(class_num)
])
从上面两段代码中可见,tf.layers代码稍多,需要手动计算flat层的shape;而tf.keras就比较简洁,类似流式的网络构建方式将模型的网络展示的简单明了。
tensorflow1.11.0发布时就已经对keras增强了支持,可以发现tensorflow已经有意向将keras升级为一级网络操作API,毕竟keras和tensorflow都是google的,进行合理的资源整合提升tensorflow的生态布局很有必要。其实采用哪种都可以,根据自己喜欢即可,个人比较喜欢keras的API风格。