先贴上效果图,让前面两张图片具有梵高的星空之夜风格。
其中原始的图片为下面两张图片。
上面所展示的图片中,直观的理解是把梵高中的图片的这种风格揉到前面两张图片当中。但是,这种图片风格生成的并不是简单得让图片C尽量同时和图片A、B相似。(假设A是原始的想要变化的图片,B是风格图片(比如星空之夜),C是将要生成的图片,所以,这里可以叫A为内容图片,B为风格图片,C为生成图片),而是让C和A的“内容”尽量相似,同时让C的“风格”跟B的“风格”尽量相似。换句话说便是保留图片A的内容,但是要改变它的风格。这一点的具体实现将体现再损失函数的定义上面。如何定义C的内容以及它的风格呢?不用担心,下面会讲到的。
总体思路
在卷积神经网络中,如果下面是输入上面是输出,那么,从下到上卷积层所获取的图片特征将越来越全面。在风格转换卷积层中,选取中间某一个卷积层作为作为内容图片A,将A于生成图片C比较它们的相似度,越相似越好,两个矩阵(图片)对应像素之差的平方之和便是相似度,下面会给出具体的公式。同时,选取相关的卷积层作为风格图片B,然后和C比较风格相似度。选取风格图片有一点不一样,其中一种选取方法是,如果卷积层有5层,那么分别选取这5层,然后都分别乘以0.2的权重,然后相加之后得到风格图片。这里的权重可以改为其他的值,这只是其中的一种选择方法。只是不同的权重值将影响生成图片C最后的效果。(这一点暂时无法理解也没关系)
要进行风格的比较,首先需要使用数学公式表示出图片的风格。
两张图片可以理解为两个矩阵,格拉姆矩阵/Gram matrix可以表示矩阵中不同行和列之间的关联程度。而行和列的关联程度在图片上体现的是图片风格。所以,最终我们要比较的是两个图片的格拉姆矩阵的相似程度。
对于图片B,它的格拉姆矩阵为 ,对于C,它的格拉姆矩阵为 ,然后这两个格拉姆矩阵对应位置元素相减平方再求和,便可以得到两个格拉姆矩阵的相似度,也就是两个图片的风格的相似度了。
我们的目的是使得两个相似度都很高,分别是图片A和C的内容相似度,图片B和C的风格相似度。这样的图片C正是我们所想要的。由此便可以得出我们的损失函数,然后使用反向传播来训练模型,得到最后的结果。
这便是模型的总体思路。
损失函数
内容损失函数
其中。
和
分别表示的是图片A和图片C某一卷积层激活函数的输出值。nH和nW以及nC分别表示图片的高、宽和通道个数。
风格损失函数
其中G表示的是格拉姆矩阵/Gram matrix。
最终的损失函数为:
其中系数a和β是全局系数,用它们来调节图片风格的严重程度。比如,如果a比β大很多,那么原始图片只有稍微一点点变化。
前向传播函数
使用VGG16作为我们的网络模型,同时使用别人已经训练好的VGG16模型参数来加快我们的模型的训练速度。
我们知道,神经网络模型最重要的是把模型的损失函数表达出来,这里,我们从上面的模型中可以获得内容图片和风格图片,然后成功表达出了损失函数。
所以,上面VGG16模型的全连接层是没有作用的。
优化问题
这里使用别人已经训练好的VGG16模型参数来加快我们的模型的训练速度。所以,在代码中将会看到如何提取预训练好的模型的参数。
预训练VGG16模型下载地址:https://pan.baidu.com/s/1o9qEW3K
源代码下载地址:https://github.com/liangyihuai/my_tensorflow/tree/master/com/huai/converlution/project/style_tranfer
总结:本文的思路使用了tensorflow框架实现。生成一张风格图片需要较长的时间,大概半个小时。现在已经有更快的方法。可以阅读这篇论文:
快速风格转移算法https://arxiv.org/pdf/1603.08155.pdf
本文中的思路由这篇论文得来:Leon A. Gatys, Alexander S. Ecker, Matthias Bethge, (2015). A Neural Algorithm of Artistic Style (https://arxiv.org/abs/1508.06576)