主要内容

火车快风格传输网络

这个例子展示了如何训练一个网络的风格一个图像转移到另一个图像。它是基于[1]中定义的架构。

这个例子是类似的使用深度学习神经风格转移,但它工作速度一旦训练网络风格形象s .这是因为,获得的程式化形象Y你只需要做一个传球前进的输入图像X的网络。

找一个高级图下面的训练算法。它使用三个图像计算损失:输入图像X, Y和风格形象S转换后的图像。

请注意,损失函数使用pretrained网络VGG-16从图像中提取特征。你可以找到它的实现和数学定义风格传递损失这个例子。

负荷训练数据

下载并提取可可2014训练图像和字幕https://cocodataset.org/下载通过单击“2014训练图像”。数据保存在指定的文件夹imageFolder。图像提取到imageFolder。可可2014年收集的可可财团

创建目录来存储可可数据集。

imageFolder = fullfile (tempdir,“可可”);如果~存在(imageFolder“dir”mkdir (imageFolder);结束

创建一个包含可可图像的图像数据存储。

imd = imageDatastore (imageFolder,“IncludeSubfolders”,真正的);

培训需要花很长时间运行。如果你想减少训练时间为代价的准确性产生的网络,然后选择一个子集的图像数据存储设置分数一个较小的值。

分数= 1;numObservations =元素个数(imds.Files);imd =子集(imd, 1:地板(numObservations *分数);

调整图像和它们都转换为RGB,创建一个增强图像数据存储。

augimds = augmentedImageDatastore (imd (256 256),“ColorPreprocessing”,“gray2rgb”);

阅读风格形象。

styleImage = imread (“starryNight.jpg”);styleImage = imresize (styleImage (256 256));

显示所选的风格形象。

图imshow (styleImage)标题(“风格形象”)

定义图像网络变压器

定义图像变压器网络。这是一个image-to-image网络。网络由三部分组成:

  1. 网络的第一部分将作为输入的RGB图像大小[256 x256x3], downsamples特征地图大小[64 x64x128]。

  2. 的第二部分网络包括五个相同的残块中定义的支持功能金宝appresidualBlock。

  3. 网络的第三部分,也是最后一部分upsamples特性映射到原始图像并返回转换后的图像的大小。最后一个部分使用upsampleLayer,这是一个自定义层附加到这个例子作为支持文件。金宝app

层= [%第一部分。imageInputLayer ([256 256 3),“名字”,“输入”,“归一化”,“没有”32岁的)convolution2dLayer (9 [9]“填充”,“相同”,“名字”,“conv1”)groupNormalizationLayer (“channel-wise”,“名字”,“norm1”)reluLayer (“名字”,“relu1”3)convolution2dLayer([3], 64年,“步”2,“填充”,“相同”,“名字”,“conv2”)groupNormalizationLayer (“channel-wise”,“名字”,“norm2”)reluLayer (“名字”,“relu2”3)convolution2dLayer([3], 128年,“步”2,“填充”,“相同”,“名字”,“conv3”)groupNormalizationLayer (“channel-wise”,“名字”,“norm3”)reluLayer (“名字”,“relu3”)%第二部分。residualBlock (“1”)residualBlock (“2”)residualBlock (“3”)residualBlock (“4”)residualBlock (“5”)%第三部分。upsampleLayer (“up1”3)convolution2dLayer([3], 64年,“步”,1“填充”,“相同”,“名字”,“upconv1”)groupNormalizationLayer (“channel-wise”,“名字”,“norm6”)reluLayer (“名字”,“relu5”)upsampleLayer (“呼吁”3)convolution2dLayer([3], 32岁“步”,1“填充”,“相同”,“名字”,“upconv2”)groupNormalizationLayer (“channel-wise”,“名字”,“norm7”)reluLayer (“名字”,“relu6”3)convolution2dLayer(9日,“填充”,“相同”,“名字”,“conv_out”));lgraph = layerGraph(层);

添加缺失的连接残块。

lgraph = connectLayers (lgraph,“relu3”,“add1 / in2”);lgraph = connectLayers (lgraph,“add1”,“add2 / in2”);lgraph = connectLayers (lgraph,“add2”,“add3 / in2”);lgraph = connectLayers (lgraph,“add3”,“add4 / in2”);lgraph = connectLayers (lgraph,“add4”,“折扣/ in2”);

可视化图像变压器网络在一个阴谋。

图绘制(lgraph)标题(“变换网络”)

创建一个dlnetwork对象的层图。

dlnetTransform = dlnetwork (lgraph);

风格失去网络

这个示例使用pretrained VGG-16深层神经网络提取图像内容和风格的特性在不同的层。这些多层功能用于计算各自的内容和风格的损失。

得到一个pretrained VGG-16网络,使用vgg16函数。如果你没有安装所需的支持包,然后软件提供一个下载链接。金宝app

netLoss = vgg16;

提取计算所需的功能损失只需要第一个24层。提取和转换为一层图。

lossLayers = netLoss.Layers(桥);lgraph = layerGraph (lossLayers);

转换为一个dlnetwork

dlnetLoss = dlnetwork (lgraph);

定义了损失函数和格拉姆矩阵

创建styleTransferLoss函数中定义风格传递损失这个例子。

这个函数styleTransferLoss作为输入失去网络dlnetLoss,mini-batch输入图像转换dlX,mini-batch转换图像海底数组,包含克矩阵的风格形象dlSGram,与内容相关的重量损失contentWeight和重量与风格相关的损失styleWeight。函数返回的总损失损失和个人部分:内容丢失lossContent和风格损失lossStyle。

styleTransferLoss函数使用支持功能金宝appcreateGramMatrix在风格的计算损失。

createGramMatrix函数作为输入的特性提取损失网络并返回一个风格为每个图像在mini-batch表示。你可以找到格拉姆矩阵的实现和数学定义的部分格拉姆矩阵

定义模型梯度函数

创建函数modelGradients中列出,模型梯度函数部分的例子。这个函数作为输入失去网络dlnetLoss,图像变压器网络dlnetTransformmini-batch的输入图像dlX数组,包含克矩阵的风格形象dlSGram,与内容相关的重量损失contentWeight和重量与风格相关的损失styleWeight。该函数返回梯度失去对图像的可学的参数变压器,变压器图像网络的状态,转换后的图像海底,总损失损失,与内容相关的损失lossContent和与风格相关的损失lossStyle。

指定培训选项

火车mini-batch大小为4 2时代[1]。

numEpochs = 2;miniBatchSize = 4;

设置读取大小mini-batch增强图像数据存储的大小。

augimds。MiniBatchSize = MiniBatchSize;

指定的选项为亚当的优化。指定一个学习的速度梯度衰减系数为0.01,0.001和0.999平方梯度衰减系数。

learnRate = 0.001;gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;

火车在GPU如果一个是可用的。使用GPU需要并行计算工具箱™和支持GPU设备。金宝app支持设备的信息,请参阅金宝appGPU的金宝app支持版本(并行计算工具箱)

executionEnvironment =“汽车”;

指定体重的风格和内容给出的一个损失计算的总损失。

注意,为了找到一个好的平衡内容和风格,你可能需要尝试不同的组合权重。

weightContent = 1的军医;weightStyle = 3 e-8;

选择的情节频率训练进展。这将指定每个情节之间有多少的迭代更新。

plotFrequency = 10;

火车模型

为了能够计算出损失在训练,计算矩阵克风格的图像。

转换图像风格dlarray

dlS = dlarray(单(styleImage),SSC的);

为了计算格拉姆矩阵、饲料的风格形象VGG-16网络的激活和提取四个不同的层次。

[dlSActivations1, dlSActivations2 dlSActivations3 dlSActivations4] =前进(dlnetLoss dlS,“输出”,(“relu1_2”“relu2_2”“relu3_3”“relu4_3”]);

计算每组的格拉姆矩阵激活使用支持功能金宝appcreateGramMatrix

dlSGram {1} = createGramMatrix (dlSActivations1);dlSGram {2} = createGramMatrix (dlSActivations2);dlSGram {3} = createGramMatrix (dlSActivations3);dlSGram {4} = createGramMatrix (dlSActivations4);

培训情节包含两个数据:

  1. 图显示一个阴谋培训期间的损失

  2. 图包含一个输入和一个输出图像的图像变压器网络

初始化培训的阴谋。你可以检查支持函数中初始化的细节金宝appinitializeFigures。这个函数返回:轴ax₁你把损失,轴在哪里ax2你图验证图片,动画行吗lineLossContent它包含内容,动画lineLossStyle其中包含样式损失和动画行吗lineLossTotal它包含的总损失。

(ax₁, ax2 lineLossContent、lineLossStyle lineLossTotal] = initializeStyleTransferPlots ();

初始化的平均梯度和平均平方梯度hyperparameters亚当优化器。

averageGrad = [];averageSqGrad = [];

计算训练迭代的总数。

numIterations =地板(augimds.NumObservations * numEpochs / miniBatchSize);

初始化迭代数量和计时器前培训。

迭代= 0;开始=抽搐;

火车模型。这可能需要很长时间才能运行。

%循环时期。我= 1:numEpochs%重置和洗牌数据存储。重置(augimds);augimds = shuffle (augimds);%在mini-batches循环。hasdata (augimds)迭代=迭代+ 1;% mini-batch读取的数据。data =阅读(augimds);%忽略时代的最后部分mini-batch。如果(数据,1)< miniBatchSize大小继续结束%提取图像数据存储单元阵列。数据图像= {:1};%连接图像在第四维度。X =猫(4、图像{:});X =单(X);%转换mini-batch dlarray和指定的数据维度标签%的SSCB(空间、空间、通道、批)。dlX = dlarray (X,“SSCB”);%如果训练在GPU,然后将数据转换成gpuArray。如果(executionEnvironment = =“汽车”& & canUseGPU) | | executionEnvironment = =“图形”dlX = gpuArray (dlX);结束%评估模型梯度和网络状态使用% dlfeval modelGradients函数结束时上市%的例子。(梯度、州、海底、失去、lossContent lossStyle] = dlfeval (@modelGradients,dlnetLoss、dlnetTransform dlX, dlSGram、weightContent weightStyle);dlnetTransform。=状态;%更新网络参数。[dlnetTransform, averageGrad averageSqGrad] =adamupdate (dlnetTransform、渐变averageGrad averageSqGrad,迭代,learnRate、gradientDecayFactor squaredGradientDecayFactor);%每个plotFequency迭代,情节的培训进度。如果国防部(迭代,plotFrequency) = = 0 addpoints (lineLossTotal、迭代、双(收集(extractdata(损失))))addpoints (lineLossContent、迭代、双(收集(extractdata (lossContent)))) addpoints (lineLossStyle、迭代、双(收集(extractdata (lossStyle))))%使用的第一形象mini-batch作为验证的形象。dlV = dlX (:,:,: 1);%使用转换后的图像验证计算。dlVY =海底(:,:,:1);%使用函数imshow uint8转换。validationImage = uint8(收集(extractdata (dlV)));transformedValidationImage = uint8(收集(extractdata (dlVY)));%画出输入图像和输出图像,增加大小imshow (imtile ({validationImage, transformedValidationImage}),“父”,ax2);结束%显示多长时间开始培训,培训完成百分比。D =持续时间(0,0,toc(开始),“格式”,“hh: mm: ss”);completionPercentage =圆(迭代/ numIterations * 100, 2);标题(ax₁,”时代:“+我+”,迭代:“+迭代+“的”+ numIterations +”(“+ completionPercentage +“%)”+”,过去:“+ drawnow字符串(D))结束结束

使风格化图像

一旦训练完成之后,您可以使用您所选择的图像变压器在任何图像。

加载图片你想变换。

imFilename =“peppers.png”;我= imread (imFilename);

调整图像的输入图像输入维度变压器。

[256256]im = imresize (im);

把它转换成dlarray。

dlX = dlarray(单(im),“SSCB”);

使用GPU皈依gpuArray如果一个人是可用的。

如果canUseGPU dlX = gpuArray (dlX);结束

应用样式的图片,把它转发给图像变压器使用函数预测。

海底=预测(dlnetTransform dlX);

重新调节图像的范围(0 255)。首先,使用函数双曲正切要重新调节海底(1)范围。然后,和规模输出转移到重新进入255年[0]范围内。

Y = 255 *(双曲正切(海底)+ 1)/ 2;

准备Y策划。使用的函数extractdata提取的数据dlarray。使用聚集函数Y的GPU转移到本地工作区。

Y = uint8(收集(extractdata (Y)));

显示输入图像(左)旁边的程式化形象(右)。

图m = imtile ({im, Y});imshow (m)

模型梯度函数

这个函数modelGradients作为输入失去网络dlnetLoss,图像变压器网络dlnetTransformmini-batch的输入图像dlX数组,包含克矩阵的风格形象dlSGram,与内容相关的重量损失contentWeight和重量与风格相关的损失styleWeight。它将返回梯度失去对图像的可学的参数变压器,变压器图像网络的状态,转换后的图像海底,总损失损失,与内容相关的损失lossContent和与风格相关的损失lossStyle。

函数(梯度、州、海底、失去、lossContent lossStyle] =modelGradients (dlnetLoss、dlnetTransform dlX、dlSGram contentWeight, styleWeight)[海底、州]=前进(dlnetTransform dlX);海底= 255 *(双曲正切(海底)+ 1)/ 2;[损失,lossContent, lossStyle] = styleTransferLoss (dlnetLoss,海底,dlX dlSGram, contentWeight, styleWeight);梯度= dlgradient(损失、dlnetTransform.Learnables);结束

风格传递损失

这个函数styleTransferLoss作为输入失去网络dlnetLossmini-batch的输入图像dlX,mini-batch转换图像海底数组,包含克矩阵的风格形象dlSGram,与内容相关的权重和风格contentWeightstyleWeight,分别。它返回的总损失损失和个人部分:内容丢失lossContent和风格损失lossStyle。

损失是多少的测量内容输入图像之间的空间结构有差异X和输出图像Y

另一方面,风格告诉你损失之间有多少不同风格外观风格的形象年代和输出图像Y

下面的图表说明了算法styleTransferLoss实现计算的总损失。

首先,函数将输入图像X,转换后的图像Y和风格的形象年代VGG-16 pretrained网络。这pretrained网络从这些图像中提取一些特性。然后算法计算损失的内容使用的空间特性输出图像的输入图像X和Y .此外,计算风格损失通过输出图像Y的文体特征和风格的形象s .最后,它获得的总损失增加的内容和风格的损失。

内容丢失

mini-batch中的每个图像的内容损失函数比较原始图像的特性和转换后的图像输出的层relu_3_3。特别是,它计算激活并返回之间的均方误差的平均损失mini-batch:

lossContent = 1 N n = 1 N 的意思是 ( ( ϕ ( X n ) - - - - - - ϕ ( Y n ) ] 2 ) ,

在哪里 X 包含输入图像, Y 包含了转换后的图像, N 是mini-batch大小, ϕ ( ) 代表了激活提取层relu_3_3。

风格的损失

计算风格损失,为每个mini-batch单张图片:

  1. 提取层的激活relu1_2,relu2_2,relu3_3relu4_3

  2. 为每个四个激活 ϕ j 计算格拉姆矩阵 G ( ϕ j )

  3. 计算平方矩阵对应的克之间的区别。

  4. 每层加起来四个输出 j 从上一步。

获取整个mini-batch风格损失,计算每个图像风格的平均损失 n mini-batch:

lossStyle = 1 N n = 1 N j = 1 4 ( G ( ϕ j ( X n ) ) - - - - - - G ( ϕ j ( 年代 ) ) ] 2 ,

在哪里 j 层的索引, G ( ) 格拉姆矩阵。

全部损失

函数[损失,lossContent, lossStyle] = styleTransferLoss (dlX dlnetLoss,海底,dlSGram、weightContent weightStyle)%提取激活。dlYActivations =细胞(1、4);dlYActivations [dlYActivations {1}, {2}, dlYActivations {3}, dlYActivations {4}] =转发(dlnetLoss,海底,“输出”,(“relu1_2”“relu2_2”“relu3_3”“relu4_3”]);dlX dlXActivations =前进(dlnetLoss,“输出”,“relu3_3”);%计算激活之间的均方误差。lossContent =意味着((dlYActivations {3} - dlXActivations)。^ 2,“所有”);%增加损失的所有四个激活。lossStyle = 0;j = 1:4 G = createGramMatrix (dlYActivations {j});lossStyle = lossStyle +总和((G - dlSGram {j}) ^ 2,。“所有”);结束% mini-batch平均损失。miniBatchSize =大小(dlX 4);lossStyle = lossStyle / miniBatchSize;%应用权重。lossContent = weightContent * lossContent;lossStyle = weightStyle * lossStyle;%计算全损。损失= lossContent + lossStyle;结束

剩余块

residualBlock函数返回一个数组的六层。归一化层,它由卷积层,实例ReLu层和附加层。请注意,groupNormalizationLayer (“channel-wise”)只是一个实例归一化层。

函数层= residualBlock(名字)层= [convolution2dLayer (3 [3], 128,“步”,1“填充”,“相同”,“名字”,“convRes”+名称+“_1”)groupNormalizationLayer (“channel-wise”,“名字”,“normRes”+名称+“_1”)reluLayer (“名字”,“reluRes”+名称+“_1”3)convolution2dLayer([3], 128年,“步”,1“填充”,“相同”,“名字”,“convRes”+名称+“_2”)groupNormalizationLayer (“channel-wise”,“名字”,“normRes”+名称+“_2”)additionLayer (2“名字”,“添加”+名字)];结束

格拉姆矩阵

这个函数createGramMatrix需要作为输入单一层的激活,并返回一个风格表示mini-batch每个图像大小的输入特性映射[W H, C, N],其中H是高度,W是宽度,C是通道的数量,N是mini-batch大小。函数输出数组G的大小(C, C, N)。每个子数组G (:,:, k)相对应的格拉姆矩阵吗 k t h mini-batch形象。每个条目 G ( , j , k ) 的格拉姆矩阵表示通道之间的相关性 c c j ,因为每个条目在通道 c 繁殖在通道入口在相应的位置 c j :

G ( , j , k ) = 1 C × H × W h = 1 H w = 1 W ϕ k ( h , w , c ) ϕ k ( h , w , c j ) ,

在哪里 ϕ k 的激活吗 k t h mini-batch形象。

格拉姆矩阵包含哪些特性信息激活在一起但没有信息出现在图像的特性。这是因为高度和宽度的总和失去了空间结构的信息。损失函数使用这个矩阵作为一个风格的代表形象。

函数G = createGramMatrix(激活)[h, w, numChannels] =大小(激活,1:3);特点=重塑(激活,h * w, numChannels, []);特点=排列(功能,(2 1 3));G = dlmtimes(功能、特点)/ w (h * * numChannels);结束

引用

  1. 约翰逊,贾斯汀,亚历山大Alahi,李菲菲。“知觉损失实时传输和超分辨率风格。”欧洲计算机视觉。施普林格,可汗,2016。

另请参阅

||||||

相关的话题