使用的是矩池云+Pycharm进行测试,镜像内容为:
在官方给定的文档中,模型的预置参数如下
tf.keras.applications.vgg16.VGG16(
include_top=True,
weights='imagenet',
input_tensor=None,
input_shape=None,
pooling=None,
classes=1000,
classifier_activation='softmax'
)
(1) 导入包
import tensorflow as tf
(2) 加载数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
(3) 处理数据集的形状,参考如何用VGG16训练MNIST数据集?
这里测试了一下,不可以忽略该步骤,因为网络要求最小的size是32 × 32 × 3
现在,我们需要28×28 填充为32×32(当然也可以填充为48×48,它可视为超参数,为了提升性能,你可以任意”折腾“,经过测试,32×32性能较好)。之所以填充,是因为VGG16有5层池化(汇聚)层,如果不加以扩充,可能多层池化后图片变成了1*1大小。
x_train = tf.pad(x_train, [[0, 0], [2, 2], [2, 2]]) / 255 # 填充,除以255表示归一化
x_test = tf.pad(x_test, [[0, 0], [2, 2], [2, 2]]) / 255
(4) 升级数据维度,参考如何用VGG16训练MNIST数据集?
由于VGG16是适配3通道图片的,而MNIST是单通道的图片,所以需要将其”升级“为3单通道。最简单的升级就是对单通道的图片连续复制3次。
x_train = tf.stack((x_train, x_train, x_train), axis=-1)
x_test = tf.stack((x_test, x_test, x_test), axis=-1)
(5) 模型实例化
model = tf.keras.applications.VGG16(
include_top=False,
weights= 'imagenet',
input_tensor=None,
input_shape=(32, 32, 3),
pooling=None,
classes=1000,
classifier_activation="softmax",
)
(6)冻结其他层
由于使用了预训练模型,VGG16的基础部分(卷积、池化等)的权值都不用训练。所以逐层设定layer.trainable = False将其冻结。
for layer in model.layers:
layer.trainable = False
)
(7)由于没有使用模型自带的全连接层,因此我们需要自己重写全连接层
x = tf.keras.layers.Flatten()(model.output) # 展平
x = tf.keras.layers.Dense(4096, activation='relu')(x) # 定义全连接
x = tf.keras.layers.Dropout(0.5)(x) # Dropout
x = tf.keras.layers.Dense(4096, activation='relu')(x)
x = tf.keras.layers.Dropout(0.5)(x)
predictions = tf.keras.layers.Dense(10, activation='softmax')(x) # softmax回归,10分类
head_model = tf.keras.Model(inputs=model.input, outputs=predictions)
(8)定义优化器,损失函数,训练的batch,epoch,并将训练集和测试集喂给网络
head_model.compile(optimizer='adam',
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=['accuracy'])
history = head_model.fit(x_train, y_train,
batch_size=64,
epochs=10,
validation_data=(x_test, y_test))
(9) 全部代码如下
import tensorflow as tf
if __name__ == '__main__':
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = tf.pad(x_train, [[0, 0], [2, 2], [2, 2]]) / 255 # 填充,除以255表示归一化
x_test = tf.pad(x_test, [[0, 0], [2, 2], [2, 2]]) / 255
x_train = tf.stack((x_train, x_train, x_train), axis=-1)
x_test = tf.stack((x_test, x_test, x_test), axis=-1)
model = tf.keras.applications.VGG16(
include_top=False,
weights= 'imagenet',
input_tensor=None,
input_shape=(32, 32, 3),
pooling=None,
classes=1000,
classifier_activation="softmax",
)
for layer in model.layers:
layer.trainable = False
model.summary()
x = tf.keras.layers.Flatten()(model.output) # 展平
x = tf.keras.layers.Dense(4096, activation='relu')(x) # 定义全连接
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(4096, activation='relu')(x)
x = tf.keras.layers.Dropout(0.5)(x)
predictions = tf.keras.layers.Dense(10, activation='softmax')(x) # softmax回归,10分类
head_model = tf.keras.Model(inputs=model.input, outputs=predictions)
# 搭配训练参数
head_model.compile(optimizer='adam',
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=['accuracy'])
history = head_model.fit(x_train, y_train,
batch_size=64,
epochs=10,
validation_data=(x_test, y_test))