TensorFlow 1.x 加载 VGG19 预训练模型详解

半杯拿铁
半杯拿铁
发布时间:2026-10-11| 4人浏览过
原创

本文介绍如何在 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

加载图片与测试流程

测试时,需要读取本地图片并进行预处理。注意以下几点:

  1. 使用 tf.gfile.GFile 以二进制模式读取图片。
  2. 将图片转换为 tf.float 类型,否则可能报错。
  3. 使用 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 预训练模型的详细内容,更多关于模型训练、深度学习及计算机视觉的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。