主要内容

基于深度学习的神经风格迁移

这个例子展示了如何使用预先训练的vgg19网络将一个图像的风格外观应用到另一个图像的场景内容[1]

数据加载

加载样式图像和内容图像。本例以梵高的代表作《星夜》为风格图,以灯塔的照片为内容图。

styleImage = im2double(imread(“starryNight.jpg”));contentImage = imread (“lighthouse.png”);

以蒙太奇的方式显示样式图像和内容图像。

imshow (imtile ({styleImage, contentImage},'背景颜色''W'));

负荷特征提取网络

在此示例中,您使用修改后的预磨损的VGG-19深神经网络,以在各个层中提取内容和样式图像的特征。这些多层特征用于计算各自的内容和样式损耗。网络使用组合损耗生成风格化传输图像。

获取佩带的VGG-19网络,安装vgg19(深度学习工具箱).如果您没有安装所需的支持包,那么该软件将提供下载链接。金宝app

净= vgg19;

为了使VGG-19网络适于特征提取,从网络中删除所有的完全连接层。

lastFeatureLayerIdx = 38;层= net.Layers;层=层(1:lastFeatureLayerIdx);

VGG-19网络的最大池化层会导致衰落效应。为了减少褪色效果和增加梯度流,将所有最大池化层替换为平均池化层[1]

为了l = 1:lastFeatureLayerIdx如果isa(层,'nnet.cnn.layer.MaxPooling2DLayer') layers(l) = averagePooling2dLayer(layer.)PoolSize,“跨越论”,layer.Stride,'姓名', layer.Name);结尾结尾

创建与改性层的层图。

lgraph = layerGraph(层);

将特征提取网络可视化。

情节(LGROPH)标题(“特征提取网络”

用一个定制的训练循环训练网络并启用自动分化,该层图形转换成dlnetwork对象。

dlnet = dlnetwork(lgraph);

数据进行预处理

调整的风格形象和内容,图像尺寸更小更快的处理。

图象尺寸= [384512];styleImg = imresize (styleImage、图象尺寸);contentImg = imresize (contentImage、图象尺寸);

通道方向的平均减影图像上的预训练VGG-19网络进行分类。获得从图像输入层,这是在网络中的第一层中的信道逐平均值。

imgInputLayer = lgraph.Layers (1);meanVggNet = imgInputLayer.Mean (1 1:);

通道均值的值适用于像素值范围为[0,255]的浮点数据类型的图像。将样式图像和内容图像转换为数据类型范围[0,255]。然后,从样式图像和内容图像中减去频道均值。

styleImg = rescale(single(styleImg),0,255) - meanVggNet;contentImg = rescale(single(contentImg),0,255) - meanVggNet;

初始化传输图像

转换图像是样式转换的结果。您可以使用样式图像、内容图像或任何随机图像初始化传输图像。初始化样式图像或内容图像会使样式转换过程产生偏差,从而生成更类似于输入图像的转换图像。相比之下,初始化白噪声消除了偏差,但需要更长的时间在程式化的图像上收敛。为了更好的样式化和更快的收敛,本例将输出传输图像初始化为内容图像和白噪声图像的加权组合。

noiseRatio = 0.7;randImage =兰迪([ -  20,20],[3 IMAGESIZE]);transferImage = noiseRatio * randImage +(1-noiseRatio)* contentImg。;

定义损耗函数和样式传递参数

内容丢失

内容丢失的目的是使传输图像的特征与内容图像的特征匹配。计算内容丢失作为每个内容特征层的内容图像特征和传输图像特征之间的平均平方差[1] y ˆ 是用于传送图像的预测特征地图和 y 是内容图像的预测特征映射。 W. C L. 内容层权重为 L. T. H 层。 H W. C 是特征图的高度,宽度和频道。

L. C O. N. T. E. N. T. = L. W. C L. × 1 H W. C 一世 j y ˆ 一世 j L. - y 一世 j L. 2

指定内容特征提取层的名称。从这些层中提取的特征被用于计算所述内容的损失。在VGG-19网络,训练使用从更深的层,而不是从浅层特征特征是更有效的。因此,指定内容的特征提取层作为第四层卷积。

styleTransferOptions。CO.N.T.E.N.T.FeatureLayerNames = {'conv4_2'};

指定内容特征提取层的权重。

styleTransferOptions.contentFeatureLayerWeights = 1;

风格损失

风格损失的目的是使传输图像的纹理匹配风格图像的纹理。的图像的样式表示被表示为革兰氏矩阵。因此,风格损耗被计算为风格图像的革兰氏矩阵和转印图像的革兰氏矩阵之间的平均平方差[1] Z. Z. ˆ 都为风格和转印图像的预测特征图,分别。 G Z. G Z. ˆ 分别为风格特征和转移特征的Gram矩阵。 W. S. L. 款式层重量是否适合 L. T. H 风格层。

G Z. ˆ = 一世 j Z. ˆ 一世 j × Z. ˆ j 一世

G Z. = 一世 j Z. 一世 j × Z. j 一世

L. S. T. y L. E. = L. W. S. L. × 1 2 H W. C 2 G Z. ˆ L. - G Z. L. 2

指定的风格特征提取图层的名称。从这些层中提取的特征被用来计算式损失。

styleTransferOptions。S.T.yL.E.FeatureLayerNames = {“conv1_1”“conv2_1”“conv3_1”'conv4_1''conv5_1'};

指定的风格特征提取层的权重。指定简约风格的图像小的权重,并增加复杂风格的图像的权重。

standetransferoptions.StyleFeaturelayerwights = [0.5,1.0,1.5,3.0,4.0];

全部损失

总损失量损失和风格损失的加权组合。 α. β 分别为内容损失和风格损失的权重因素。

L. T. O. T. 一种 L. = α. × L. C O. N. T. E. N. T. + β × L. S. T. y L. E.

指定权重因素αβ内容丢失和风格丢失。的比例αβ应该在1e-3还是1e-4附近[1]

styleTransferOptions。α= 1;styleTransferOptions。β= 1 e3;

指定培训选项

火车2500次迭代。

numiterations = 2500;

为Adam优化指定选项。设置学习率为2,收敛速度更快。您可以通过观察输出图像和损失来实验学习速率。初始化尾随平均梯度和尾随平均梯度平方衰减率[]

learningRate = 2;trailingAvg = [];trailingAvgSq = [];

训练网络

转换样式图像、内容图像和传输图像dlarray(深度学习工具箱)具有底层类型的对象和尺寸的标签SSC的

dlStyle = dlarray(styleImg,SSC的);dlContent = dlarray (contentImg,SSC的);dlTransfer = dlarray (transferImage,SSC的);

在可用的GPU上进行训练。使用GPU需要并行计算工具箱™和支持CUDA®的NVIDIA®GPU。有关更多信息,请参见GPU支金宝app持情况(并行计算工具箱).对于GPU训练,将数据转换为gpuArray

如果canUseGPU dlContent = gpuArray(dlContent);dlStyle = gpuArray (dlStyle);dlTransfer = gpuArray (dlTransfer);结尾

从内容图像提取内容特征。

numContentFeatureLayers = numel(styleTransferOptions.contentFeatureLayerNames);contentFeatures =细胞(1,numContentFeatureLayers);[contentFeatures {:}] =正向(dlnet,dlContent,“输出”, styleTransferOptions.contentFeatureLayerNames);

摘自风格图像的风格特点。

numStyleFeatureLayers =元素个数(styleTransferOptions.styleFeatureLayerNames);styleFeatures =细胞(1、numStyleFeatureLayers);[styleFeatures{}): =前进(dlnet dlStyle,“输出”, styleTransferOptions.styleFeatureLayerNames);

使用自定义训练循环训练模型。每一次迭代:

  • 利用内容图像、样式图像和传输图像的特征计算内容损失和样式损失。要计算损失和梯度,请使用helper函数imageGradients(定义在金宝app支持功能这个例子的一部分)。

  • 使用。更新传输图像adamupdate.(深度学习工具箱)功能。

  • 选择最佳样式传输图像作为最终输出图像。

数字最终= inf;为了迭代= 1:numIterations使用dlfeval和% imageGradients函数列在例子的最后。[毕业,损失] = dlfeval(@ imageGradients,dlnet,dlTransfer,contentFeatures,styleFeatures,styleTransferOptions);[dlTransfer,trailingAvg,trailingAvgSq] = adamupdate(dlTransfer,毕业,trailingAvg,trailingAvgSq,迭代,learningRate);如果的损失。来T.一种L.L.O.S.S.< minimumLoss minimumLoss = losses.totalLoss; dlOutput = dlTransfer;结尾%显示器上的第一迭代和每50后的转印图像%的迭代。后处理步骤在“Postprocess”中描述%转移图像,用于显示”该实施例中的部分。如果mod(iteration,50) == 0 || (iteration == 1) transferImage = gather(extractdata(dlTransfer));transferImage = transferImage + meanVggNet;transferImage = uint8 (transferImage);transferImage = imresize(transferImage,size(contentImage,[1 2]));图像(transferImage)标题([“转印图像后迭代”num2str(迭代)])轴图片drawnow结尾结尾

后处理转移图像,用于显示

获取更新的传输图像。

transferImage =聚集(ExtractData由(dlOutput));

将网络训练的平均值添加到传输图像中。

transferImage = transferImage + meanVggNet;

一些像素值可能超过内容和样式图像的原始范围[0,255]。您可以通过将数据类型转换为uint8

transferImage = uint8 (transferImage);

传输图像尺寸调整到内容图像的原始大小。

transferImage = imresize(transferImage,size(contentImage,[1 2]));

在蒙太奇中显示内容图像,传输图像和样式图像。

imshow (imtile ({contentImage、transferImage styleImage},...“GridSize”,[1 3],'背景颜色''W'));

金宝app支持功能

计算图像损失和梯度

imageGradients辅助函数使用内容图像、样式图像和传输图像的特性返回损失和渐变。

函数(渐变,亏损)= imageGradients (dlnet、dlTransfer contentFeatures, styleFeatures, params)%初始化传输图像特征容器。numContentFeatureLayers =元素个数(params.contentFeatureLayerNames);numStyleFeatureLayers =元素个数(params.styleFeatureLayerNames);transferContentFeatures =细胞(1、numContentFeatureLayers);transferStyleFeatures =细胞(1、numStyleFeatureLayers);%提取传输图像的内容特征。[transferContentFeatures{}): =前进(dlnet dlTransfer,“输出”,params.contentFeatureLayerNames);%提取传输图像的风格特征。[transferStyleFeatures{}): =前进(dlnet dlTransfer,“输出”,params.styleFeatureLayerNames);%计算内容损失。closs = contentloss(transctcontentfeatures,contentfeatures,params.contentFeaturelayersers);%计算样式丢失。SLOSS = styleLoss(transferStyleFeatures,styleFeatures,params.styleFeatureLayerWeights);%计算最终损失的内容和风格损失加权组合。= (params损失。α* cLoss) + (params.beta * sLoss);计算关于转移图像的梯度。梯度= dlgradient(损失,dlTransfer);提取各种损失。的损失。来T.一种L.L.O.S.S.=gather(extractdata(loss)); losses.contentLoss = gather(extractdata(cLoss)); losses.styleLoss = gather(extractdata(sLoss));结尾

计算丢失内容

contentloss.辅助函数计算所述内容的图像特征和所述转印图像特征之间的加权平均平方差。

函数损耗= contentLoss(transferContentFeatures,contentFeatures,contentWeights)损失= 0;为了if (transferContentFeatures{1,i} - contentFeatures{1,i}).^2, if (transferContentFeatures{1,i} - contentFeatures{1,i}).^2,“所有”);损失=损失+ (contentWeights(i)*temp);结尾结尾

计算风格损失

styledelos.helper函数计算风格图像特征的Gram矩阵与传输图像特征的Gram矩阵的加权均方根差。

函数损失= styledeloss(转移术,风格,风格款)损失= 0;为了i=1:numel(styleFeatures) tsf = transferStyleFeatures{1,i};科幻小说= styleFeatures {1,};[w h, c] =大小(sf);gramStyle = computeGramMatrix (sf);gramTransfer = computeGramMatrix (tsf);sLoss = mean((gramTransfer - gramStyle).^2,“所有”)/((H * W * C)^ 2);损耗=损耗+(styleWeights(I)* SLOSS);结尾结尾

计算格莱姆矩阵

computeGramMatrix辅助函数使用由所述styledelos.辅助函数来计算特征图的Gram矩阵。

函数[H,W,C] = size(featureMap);reshapedFeatures =重塑(featureMap H * W C);repedfeatures ' * repedfeatures;结尾

参考

Leon A. Gatys, Alexander S. Ecker和Matthias Bethge。《艺术风格的神经算法》预印本,2015年9月2日提交。https://arxiv.org/abs/1508.06576

也可以看看

(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)

相关的话题