VGG in TensorFlow

本文介绍了VGG16模型的实现及从Caffe到TensorFlow的权重转换。VGG16是由牛津大学提出的卷积神经网络模型,在ImageNet数据集上取得了92.7%的top-5测试精度。
摘要由CSDN通过智能技术生成

原文链接:https://www.cs.toronto.edu/~frossard/post/vgg16/

VGG:Visual Graphics Generator 视觉图形生成器

Files
文件:

•   Model weights - vgg16_weights.npz
•   TensorFlow model - vgg16.py
•   Class names - imagenet_classes.py
•   Example input - laska.png

上述四个文件下载链接如下:
https://www.cs.toronto.edu/~frossard/vgg16/vgg16_weights.npz

https://www.cs.toronto.edu/~frossard/vgg16/vgg16.py

https://www.cs.toronto.edu/~frossard/vgg16/imagenet_classes.py

https://www.cs.toronto.edu/~frossard/vgg16/laska.png

To test run it, download all files to the same folder and run python vgg16.py
若要测试运行它,请将所有文件下载到同一文件夹并运行命令。

Introduction
介绍

Very Deep Convolutional Networks for Large-Scale Image Recognition
https://arxiv.org/abs/1409.1556

ImageNet
http://image-net.org/

Caffe to TensorFlow
https://github.com/ethereon/caffe-tensorflow

VGG是牛津大学K. Simonyan和A. Zisserman提出的一种卷积神经网络模型,用于“大规模图像识别的深度卷积网络”。该模型在ImageNet中达到92.7%的top-5测试精度,ImageNet是属于1000个类的1400万个图像的数据集。

在这个简短的帖子中,我们提供了VGG16的实现和从原来的Caffe模型转换为TensorFlow的权重。

weasel

Architecture
结构

VGG16结构图如下

VGG16结构图

我们在TensorFlow文件中的vgg16.py进行编码。注意,我们包括一个预处理层,该层采用具有0~255范围内的像素值的RGB图像,并减去平均图像值(在整个ImageNet训练集上计算)。

Weights
权重

我们使用作者的GitHub配置文件使用专门的工具来转换CAFE权重。进行了一些后处理,以确保模型符合TensorFlow标准。最后,我们在vgg16_weights.npz中得到了可用的权重。

Class Names
类名

为了将模型的输出与类名相关联,我们可以在 imagenet_classes.py 中使用映射。

Future Content
未来内容

我们鼓励您熟悉这个模型,因为它被广泛使用,并且将是未来知识转移的基础,卷积神经网络的反向传播和其他有趣的话题。

### 如何使用TensorFlowVGG19实现图像风格迁移 #### 导入必要的库 为了构建一个能够执行风格迁移的任务,首先需要导入一些基本的库。 ```python import tensorflow as tf from tensorflow.keras.applications.vgg19 import VGG19, preprocess_input from tensorflow.keras.models import Model import numpy as np import matplotlib.pyplot as plt from PIL import Image ``` #### 定义辅助函数来处理图像 定义几个帮助函数用于加载并预处理输入图片以及显示最终的结果图。 ```python def load_image(image_path, max_dim=512): img = Image.open(image_path) img.thumbnail((max_dim, max_dim)) img = np.array(img) # Add batch dimension and apply preprocessing required by VGG19. img = preprocess_input(np.expand_dims(img, axis=0)) return img def imshow(image, title=None): if len(image.shape) > 3: image = tf.squeeze(image, axis=0).numpy() plt.imshow(image) if title is not None: plt.title(title) plt.axis('off') ``` #### 构建VGG19模型实例化对象 创建一个特定配置下的VGG19模型实例,该模型仅保留卷积基部分而不包含顶部全连接分类器,并设置`trainable=False`以冻结参数防止更新。 ```python content_layers = ['block5_conv2'] style_layers = [ 'block1_conv1', 'block2_conv1', 'block3_conv1', 'block4_conv1', 'block5_conv1' ] num_content_layers = len(content_layers) num_style_layers = len(style_layers) def get_model(): """Creates our model with access to intermediate layers.""" # Load pre-trained VGG19 without classifier on top. vgg = VGG19(include_top=False, weights='imagenet') outputs = [vgg.get_layer(name).output for name in (style_layers + content_layers)] # Build the custom model that exposes these outputs. model = Model(inputs=[vgg.input], outputs=outputs) # Set trainable flag off since we don't want to train this network further. model.trainable = False return model ``` #### 计算内容损失(Content Loss) 通过比较目标图像与原始内容图像之间指定层激活值之间的均方误差(MSE),可以量化两者间的相似度差异。 ```python def get_content_loss(base_content, target): return tf.reduce_mean(tf.square(target - base_content)) ``` #### 计算样式损失(Style Loss) 对于每一层而言,先计算Gram矩阵再求解两幅画作间对应位置处元素差平方之和除以其总数目得到平均欧式距离;最后累加各层次得分即得总分。 ```python def gram_matrix(input_tensor): result = tf.linalg.einsum('bijc,bijd->bcd', input_tensor, input_tensor) shape = tf.shape(input_tensor) num_locations = tf.cast(shape[1]*shape[2], tf.float32) scaled_result = result / num_locations return scaled_result def get_style_loss(base_style, generated_style): height, width, channels = generated_style.get_shape().as_list() size = height * width * channels loss = tf.reduce_sum(tf.square(generated_style - base_style)) / (4.0 * (channels ** 2) * ((height * width) ** 2)) return loss ``` #### 组合内容损失和样式损失 将上述两种类型的损失按照一定比例组合起来形成总的优化目标。 ```python def compute_loss(combination_image, content_features, style_features, model): combination_outputs = model(combination_image) style_weight = 1e-2 content_weight = 1e4 total_variation_weight = 30. style_score = 0 content_score = 0 # Accumulate style losses from all layers weight_per_style_layer = 1.0 / float(num_style_layers) for i in range(len(style_features)): style_score += weight_per_style_layer * \ get_style_loss(style_features[i], combination_outputs[num_content_layers+i]) # Accumulate content losses from all layers weight_per_content_layer = 1.0 / float(num_content_layers) for j in range(len(content_features)): content_score += weight_per_content_layer * \ get_content_loss( content_features[j], combination_outputs[j] ) variation_loss = tf.image.total_variation(combination_image)[0] loss = style_weight*style_score + content_weight*content_score + total_variation_weight*variation_loss return loss ``` #### 执行梯度下降算法最小化损失函数 初始化随机噪声作为初始猜测值并通过AdamOptimizer迭代调整直至收敛至局部最优解。 ```python @tf.function() def train_step(image, extractor, optimizer, content_targets, style_targets): with tf.GradientTape() as tape: outputs = extractor(image) loss = compute_loss(image, content_targets, style_targets, extractor.model) grad = tape.gradient(loss, image) optimizer.apply_gradients([(grad, image)]) image.assign(tf.clip_by_value(image, clip_value_min=-1., clip_value_max=1.)) ``` #### 创建提取器类封装前面提到的功能模块 简化调用接口方便后续操作流程设计。 ```python class StyleContentModel(Model): def __init__(self, style_layers, content_layers): super().__init__() self.vgg = get_model() self.style_layers = style_layers self.content_layers = content_layers self.num_style_layers = len(style_layers) self.vgg.trainable = False @property def model(self): return self.vgg def call(self, inputs): "Expects float input in [-1,1]" inputs = inputs*127.5+127.5 preprocessed_input = preprocess_input(inputs) outputs = self.vgg(preprocessed_input) style_outputs, content_outputs = ( outputs[:self.num_style_layers], outputs[self.num_style_layers
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值