深度学习实践:使用Tensorflow实现快速风格迁移

简介: 一、风格迁移简介风格迁移(Style Transfer)是深度学习众多应用中非常有趣的一种,如图,我们可以使用这种方法把一张图片的风格“迁移”到另一张图片上:然而,原始的风格迁移(论文地址:[https://arxiv.org/pdf/1508.06576v2.pdf )的速度是非常慢的。

一、风格迁移简介
风格迁移(Style Transfer)是深度学习众多应用中非常有趣的一种,如图,我们可以使用这种方法把一张图片的风格“迁移”到另一张图片上:

然而,原始的风格迁移(论文地址:[ https://arxiv.org/pdf/1508.06576v2.pdf )的速度是非常慢的。在GPU上,生成一张图片都需要10分钟左右,而如果只使用CPU而不使用GPU运行程序,甚至需要几个小时。这个时间还会随着图片尺寸的增大而迅速增大。
这其中的原因在于,在原始的风格迁移过程中, 把生成图片的过程当做一个“训练”的过程。每生成一张图片,都相当于要训练一次模型,这中间可能会迭代几百几千次。如果你了解过一点机器学习的知识,就会知道,从头训练一个模型要比执行一个已经训练好的模型要费时太多。而这也正是原始的风格迁移速度缓慢的原因。
二、快速风格迁移简介
那有没有一种方法,可以不把生成图片当做一个“训练”的过程,而当成一个“执行”的过程呢?答案是肯定的。这就这篇快速风格迁移(fast neural style transfer): Perceptual Losses for Real-Time Style Transfer and Super-Resolution
快速风格迁移的网络结构包含两个部分。一个是“生成网络”(原文中为Transformation Network),一个是“损失网络”(Loss Network)。生成网络接收一个图片当做输入,然后输出也是一张图片(即风格迁移后的结果)。如下图,左侧是生成网络,右侧为损失网络:
训练阶段:首先选定一张风格图片。训练的目标是让生成网络可以有效生成图片。目标由损失网络定义。
执行阶段:给定一张图片,将其输入生成网络,输出这张图片风格迁移后的结果。
我们可以发现, 在模型的“执行”阶段我们就可以完成风格图片的生成。因此生成一张图片的速度非常块,在GPU上一般小于1秒,在CPU上运行也只需要几秒的时间。
三、快速风格迁移的Tensorflow实现
话不多说,直接上我的代码的Github地址: hzy46/fast-neural-style-tensorflow
还有变换效果如下。
原始图片:
风格迁移后的图片:
以上图片在GPU(Titan Black)下生成约需要0.8s,CPU(i7-6850K)下生成用时约2.9s。
关于快速风格迁移,其实之前在Github上已经有了Tensorflow的两个实现:
junrushao1994/fast-neural-style.tf
OlavHN/fast-neural-style

但是第一个项目只提供了几个训练好的模型,没有提供训练的代码,也没有提供具体的网络结构。所以实际用处不大。
而第二个模型做了完整的实现,可以进行模型的训练,但是训练出来的效果不是很好,在作者自己的博客 中,给出了一个范例,可以看到生成的图片有很多噪声点:

我的项目就是在 OlavHN/fast-neural-style 的基础上做了很多修改和调整。
四、一些实现细节
1、与Tensorflow Slim结合在原来的实现中,作者使用了VGG19模型当做损失网络。而在原始的论文中,使用的是VGG16。为了保持一致性,我使用了Tensorflow Slim(地址: tensorflow/models)对损失网络重新进行了包装。
Slim是Tensorflow的一个扩展库,提供了很多与图像分类有关的函数,已经很多已经训练好的模型(如VGG、Inception系列以及ResNet系列)。
下图是Slim支持的模型:
使用Slim替换掉原先的网络之后, 在损失函数中,我们不仅可以使用VGG16,也可以方便地使用VGG19、ResNet等其他网络结构。具体的实现请参考源码。
2、改进转置卷积的两个Trick
原先我们需要使用网络生成图像的时候,一般都是采用转置卷积直接对图像进行上采样。
这篇文章指出了转置卷积的一些问题,认为转置卷积由于不合理的重合,使得生成的图片总是有“棋盘状的噪声点”,它提出使用先将图片放大,再做卷积的方式来代替转置卷积做上采样,可以提高生成图片的质量,下图为两种方法的对比:
对应的Tensorflow的实现:
def resize_conv2d(x, input_filters, output_filters, kernel, strides, training): with tf.variable_scope('conv_transpose') as scope: height = x.get_shape()[1].value if training else tf.shape(x)[1] width = x.get_shape()[2].value if training else tf.shape(x)[2] new_height = height * strides * 2 new_width = width * strides * 2 x_resized = tf.image.resize_images(x, [new_height, new_width], tf.image.ResizeMethod.NEAREST_NEIGHBOR) shape = [kernel, kernel, input_filters, output_filters] weight = tf.Variable(tf.truncated_normal(shape, stddev=0.1), name='weight') return conv2d(x_resized, input_filters, output_filters, kernel, strides)

以上为第一个Trick。
第二个Trick是文章 Instance Normalization: The Missing Ingredient for Fast Stylization 中提到的,用 Instance Normalization来代替通常的Batch Normalization,可以改善风格迁移的质量。
3、注意使用Optimizer和Saver
这是关于Tensorflow实现的一个小细节。
在Tensorflow中,Optimizer和Saver是默认去训练、保存模型中的所有变量的。但在这个项目中,整个网络分为生成网络和损失网络两部分。我们的目标是训练好生成网络,因此只需要去训练、保存生成网络中的变量。在构造Optimizer和Saver的时候,要注意只传入生成网络中的变量。
找出需要训练的变量,传递给Optimizer:
variable_to_train = []for variable in tf.trainable_variables(): if not(variable.name.startswith(FLAGS.loss_model)): variable_to_train.append(variable)train_op = tf.train.AdamOptimizer(1e-3).minimize(loss, global_step=global_step, var_list=variable_to_train)

五、总结
总之是做了一个还算挺有趣的项目。代码不是特别多,如果只是用训练好的模型生成图片的话,使用CPU也可以在几秒内运行出结果,不需要去搭建GPU环境。建议有兴趣的同学可以自己玩一下。(再贴下地址吧:hzy46/fast-neural-style-tensorflow
关于训练,其实也有一段比较坎(dan)坷(teng)的调参经历,下次有时间再分享一下,今天就先写到这儿。谢谢大家!

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
14天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN): 从理论到实践
本文将深入浅出地介绍卷积神经网络(CNN)的工作原理,并带领读者通过一个简单的图像分类项目,实现从理论到代码的转变。我们将探索CNN如何识别和处理图像数据,并通过实例展示如何训练一个有效的CNN模型。无论你是深度学习领域的新手还是希望扩展你的技术栈,这篇文章都将为你提供宝贵的知识和技能。
26 7
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络:从理论到实践
【10月更文挑战第35天】在人工智能的浪潮中,深度学习技术以其强大的数据处理能力成为科技界的宠儿。其中,卷积神经网络(CNN)作为深度学习的一个重要分支,在图像识别和视频分析等领域展现出了惊人的潜力。本文将深入浅出地介绍CNN的工作原理,并结合实际代码示例,带领读者从零开始构建一个简单的CNN模型,探索其在图像分类任务中的应用。通过本文,读者不仅能够理解CNN背后的数学原理,还能学会如何利用现代深度学习框架实现自己的CNN模型。
|
15天前
|
机器学习/深度学习 数据采集 自然语言处理
深入浅出深度学习:从理论到实践
【10月更文挑战第38天】本文旨在通过浅显易懂的语言和直观的代码示例,带领读者探索深度学习的奥秘。我们将从深度学习的基本概念出发,逐步深入到模型构建、训练以及应用实例,让初学者也能轻松入门。文章不仅介绍了深度学习的原理,还提供了实战操作指南,帮助读者在实践中加深理解。无论你是编程新手还是有一定基础的学习者,都能在这篇文章中找到有价值的内容。让我们一起开启深度学习之旅吧!
|
15天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
57 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
15天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
50 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
15天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
58 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
17天前
|
机器学习/深度学习 自然语言处理 语音技术
深度学习的奇妙之旅:从理论到实践
【10月更文挑战第36天】在本文中,我们将一起探索深度学习的神秘世界。我们将首先了解深度学习的基本概念和原理,然后通过一个简单的Python代码示例,学习如何使用深度学习库Keras进行图像分类。无论你是深度学习的初学者,还是有一定基础的学习者,都可以从这篇文章中获得新的知识和启示。
|
22天前
|
机器学习/深度学习 监控 PyTorch
深度学习工程实践:PyTorch Lightning与Ignite框架的技术特性对比分析
在深度学习框架的选择上,PyTorch Lightning和Ignite代表了两种不同的技术路线。本文将从技术实现的角度,深入分析这两个框架在实际应用中的差异,为开发者提供客观的技术参考。
37 7
|
1月前
|
机器学习/深度学习 数据采集 人工智能
深度学习的魔法:从理论到实践的探索####
【10月更文挑战第22天】 本文深入探讨了深度学习这一现代人工智能领域的璀璨明珠,通过生动实例与通俗语言,揭示了其背后的原理、发展历程及在多个行业的应用潜力。文章首先概述了深度学习的基本概念,随后详细解析了神经网络的核心构成,并探讨了当前面临的挑战与未来趋势。最终,通过实际案例展示了深度学习如何改变世界,为读者呈现一幅技术革新引领未来的画卷。 ####
26 3