TensorFlow 1.x 加载 VGG19 预训练模型详解
本文介绍如何在 TensorFlow 1.x 环境下加载 VGG19 预训练模型。通过解析 .mat 文件提取卷积核与偏置,构建 VGG19 网络类,并实现前向传播以获取各层特征图。文章包含环境配置、代码实现及测试流程,适用于风格迁移、目标检测等计算机视觉任务。
环境准备与模型文件解析
在开始加载模型之前,需要确保实验环境满足以下要求:Windows 10 操作系统、GTX 1050 Ti 显卡、CUDA 9.0 以及 TensorFlow 1.12 版本。VGG19 预训练模型通常以 .mat 格式存储,其中包含了网络各层的权重和偏置数据。
首先,使用 scipy.io.loadmat 读取模型文件。加载后的数据是一个字典对象,包含 '__header__'、'__version__'、'__globals__'、'layers' 和 'meta' 等键。我们需要从 data['layers'][0] 中提取卷积层的权重矩阵。
import tensorflow as tf
import numpy as np
import scipy.io
data_path = 'model/vgg19.mat' # 模型文件路径
data = scipy.io.loadmat(data_path)
print("type: ", type(data))
print("data.keys: ", data.keys())
# 提取权重数据
weights = data['layers'][0]VGG19 网络由多个卷积层(conv)、ReLU 激活层和池化层(pool)组成。通过遍历 layers 元组,可以打印出每个卷积层的维度信息,例如 conv1_1 的权重形状为 (3, 3, 3, 64),表示卷积核大小为 3x3,输入通道为 3,输出通道为 64。

构建 VGG19 网络类
为了在 TensorFlow 中复用 VGG19 结构,我们定义一个 VGG19 类。该类负责初始化权重,并实现前向传播逻辑。网络层名称定义如下:
class VGG19:
layers = (
'conv1_1', 'relu1_1', 'conv1_2', 'relu1_2', 'pool1',
'conv2_1', 'relu2_1', 'conv2_2', 'relu2_2', 'pool2',
'conv3_1', 'relu3_1', 'conv3_2', 'relu3_2', 'conv3_3',
'relu3_3', 'conv3_4', 'relu3_4', 'pool3',
'conv4_1', 'relu4_1', 'conv4_2', 'relu4_2', 'conv4_3',
'relu4_3', 'conv4_4', 'relu4_4', 'pool4',
'conv5_1', 'relu5_1', 'conv5_2', 'relu5_2', 'conv5_3',
'relu5_3', 'conv5_4', 'relu5_4'
)
def __init__(self, data_path):
data = scipy.io.loadmat(data_path)
self.weights = data['layers'][0]在 feed_forward 方法中,我们遍历每一层,根据层类型执行相应的操作:
- 卷积层(conv):提取权重和偏置,调整权重维度以符合 TensorFlow 的
conv2d输入要求(通过np.transpose交换前两个维度),并添加偏置。 - ReLU 层:应用
tf.nn.relu激活函数。 - 池化层(pool):应用最大池化
tf.nn.max_pool,步长和核大小均为 2。
每一步的输出特征图都会保存到 net 字典中,以便后续使用。
def _conv_layer(input, weights, bias):
conv = tf.nn.conv2d(input, tf.constant(weights), strides=(1, 1, 1, 1),
padding='SAME')
return tf.nn.bias_add(conv, bias)
def _pool_layer(input):
return tf.nn.max_pool(input, ksize=(1, 2, 2, 1), strides=(1, 2, 2, 1),
padding='SAME')
class VGG19:
# ... 初始化代码 ...
def feed_forward(self, input_image, scope=None):
net = {}
current = input_image
with tf.variable_scope(scope):
for i, name in enumerate(self.layers):
kind = name[:4]
if kind == 'conv':
kernels = self.weights[i][0][0][2][0][0]
bias = self.weights[i][0][0][2][0][1]
kernels = np.transpose(kernels, (1, 0, 2, 3))
bias = bias.reshape(-1)
current = _conv_layer(current, kernels, bias)
elif kind == 'relu':
current = tf.nn.relu(current)
elif kind == 'pool':
current = _pool_layer(current)
net[name] = current
return net加载图片与测试流程
测试时,需要读取本地图片并进行预处理。注意以下几点:
- 使用
tf.gfile.GFile以二进制模式读取图片。 - 将图片转换为
tf.float类型,否则可能报错。 - 使用
tf.expand_dims将三维图片扩展为四维,以符合 VGG19 的输入接口(批次大小、高度、宽度、通道数)。
image_path = "data/test.jpg" # 本地测试图片路径
image_raw = tf.gfile.GFile(image_path, 'rb').read()
image_decoded = tf.to_float(tf.image.decode_jpeg(image_raw))
image_expand_dim = tf.expand_dims(image_decoded, 0)
# 实例化 VGG19 并执行前向传播
vgg19 = VGG19(data_path)
net = vgg19.feed_forward(image_expand_dim, 'vgg19')
print(net)执行上述代码后,net 字典将包含每一层的张量信息。例如,conv1_1 的输出形状为 (1, ?, ?, 64),其中 ? 表示图片的高度和宽度。随着网络层数的加深,通道数逐渐增加(如 conv5_4 为 512),而空间维度逐渐减小。
以上就是 TensorFlow 加载 VGG19 预训练模型的详细内容,更多关于模型训练、深度学习及计算机视觉的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









