火车快风格传输网络
这个例子展示了如何训练一个网络的风格一个图像转移到另一个图像。它是基于[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网络。网络由三部分组成:
网络的第一部分将作为输入的RGB图像大小[256 x256x3], downsamples特征地图大小[64 x64x128]。
的第二部分网络包括五个相同的残块中定义的支持功能万博1manbetx
residualBlock。
网络的第三部分,也是最后一部分upsamples特性映射到原始图像并返回转换后的图像的大小。最后一个部分使用
upsampleLayer
,这是一个自定义层附加到这个例子作为支持文件。万博1manbetx
层= [%第一部分。imageInputLayer([256 256 3],标准化=“没有”32岁的)convolution2dLayer(9[9]填充=“相同”)groupNormalizationLayer (“channel-wise”)reluLayer convolution2dLayer(3[3], 64年,跨步= 2,填充=“相同”)groupNormalizationLayer (“channel-wise”)reluLayer convolution2dLayer(3[3], 128年,跨步= 2,填充=“相同”)groupNormalizationLayer (“channel-wise”)reluLayer (Name =“relu_3”)%第二部分。residualBlock (“1”)residualBlock (“2”)residualBlock (“3”)residualBlock (“4”)residualBlock (“5”)%第三部分。64年upsampleLayer convolution2dLayer(3[3],填充=“相同”)groupNormalizationLayer (“channel-wise”)reluLayer upsampleLayer convolution2dLayer(3[3]、32、填充=“相同”)groupNormalizationLayer (“channel-wise”3)reluLayer convolution2dLayer(9日,填充=“相同”));lgraph = layerGraph(层);
添加缺失的连接残块。
lgraph = connectLayers (lgraph,“relu_3”,“add_1 / in2”);lgraph = connectLayers (lgraph,“add_1”,“add_2 / in2”);lgraph = connectLayers (lgraph,“add_2”,“add_3 / in2”);lgraph = connectLayers (lgraph,“add_3”,“add_4 / in2”);lgraph = connectLayers (lgraph,“add_4”,“add_5 / in2”);
可视化图像变压器网络在一个阴谋。
图绘制(lgraph)标题(“变换网络”)
创建一个dlnetwork
对象的层图。
netTransform = dlnetwork (lgraph);
风格失去网络
这个示例使用pretrained VGG-16深层神经网络提取图像内容和风格的特性在不同的层。这些多层功能用于计算各自的内容和风格的损失。
得到一个pretrained VGG-16网络,使用vgg16
函数。如果你没有安装所需的支持包,然后软件提供一个下载链接。万博1manbetx
netLoss = vgg16;
提取计算所需的功能损失只需要第一个24层。提取和转换为一层图。
lossLayers = netLoss.Layers(桥);lgraph = layerGraph (lossLayers);
转换为一个dlnetwork
。
netLoss = dlnetwork (lgraph);
定义模型损失函数
创建函数modelLoss
中列出,损失函数模型部分的例子。这个函数作为输入失去网络,网络变压器的图片,mini-batch输入图像,数组包含克矩阵的风格形象,与内容相关的重量损失和重量与风格相关的损失。函数返回的总损失,与内容相关的损失和损失与风格,全损的梯度对图像的可学的参数变压器、形象变压器的状态网络,转换后的图像。
指定培训选项
火车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;
指定体重的风格和内容给出的一个损失计算的总损失。
注意,为了找到一个好的平衡内容和风格,你可能需要尝试不同的组合权重。
weightContent = 1的军医;weightStyle = 3 e-8;
选择的情节频率训练进展。这将指定每个情节之间有多少的迭代更新。
plotFrequency = 10;
火车模型
为了能够计算出损失在训练,计算矩阵克风格的图像。
转换图像风格dlarray
。
S = dlarray(单(styleImage),“SSC”);
为了计算格拉姆矩阵、饲料的风格形象VGG-16网络的激活和提取四个不同的层次。
[SActivations1, SActivations2 SActivations3 SActivations4] =前进(netLoss,年代,…输出= [“relu1_2”“relu2_2”“relu3_3”“relu4_3”]);
计算每组的格拉姆矩阵激活使用支持功能万博1manbetxcreateGramMatrix
。
SGram {1} = createGramMatrix (SActivations1);SGram {2} = createGramMatrix (SActivations2);SGram {3} = createGramMatrix (SActivations3);SGram {4} = createGramMatrix (SActivations4);
培训情节包含两个数据:
图显示一个阴谋培训期间的损失
图包含一个输入和一个输出图像的图像变压器网络
初始化培训的阴谋。你可以检查支持函数中初始化的细节万博1manbetxinitializeFigures。
这个函数返回:轴ax₁
你把损失,轴在哪里ax2
你图验证图片,动画行吗lineLossContent
它包含内容,动画lineLossStyle
其中包含样式损失和动画行吗lineLossTotal
它包含的总损失。
(ax₁, ax2 lineLossContent、lineLossStyle lineLossTotal] = initializeStyleTransferPlots;
初始化的平均梯度和平均平方梯度hyperparameters亚当优化器。
averageGrad = [];averageSqGrad = [];
计算训练迭代的总数。
numIterations =地板(augimds.NumObservations * numEpochs / miniBatchSize);
初始化迭代数量和计时器前培训。
迭代= 0;开始=抽搐;
火车模型。火车在GPU如果一个是可用的。使用GPU需要并行计算工具箱™和支持GPU设备。万博1manbetx支持设备的信息,请参阅万博1manbetxGPU计算的需求(并行计算工具箱)。这可能需要很长时间才能运行。
%循环时期。为我= 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”(空间、空间、通道、批)。X = dlarray (X,“SSCB”);%如果训练在GPU,然后将数据转换成gpuArray。如果canUseGPU X = gpuArray (X);结束%损失评估模型,使用渐变和网络状态% dlfeval modelLoss函数结束时上市%的例子。(损失、lossContent lossStyle、渐变状态,Y] = dlfeval (@modelLoss,…netLoss netTransform X, SGram、weightContent weightStyle);netTransform。年代tate = state;%更新网络参数。[netTransform, averageGrad averageSqGrad] =…adamupdate (netTransform、渐变averageGrad averageSqGrad,迭代,…learnRate、gradientDecayFactor squaredGradientDecayFactor);%每个plotFequency迭代,情节的培训进度。如果国防部(迭代,plotFrequency) = = 0 addpoints (lineLossTotal、迭代、双(损失))addpoints (lineLossContent、迭代、双(lossContent)) addpoints (lineLossStyle、迭代、双(lossStyle))%使用的第一形象mini-batch作为验证的形象。十五= X (:,:,: 1);%使用转换后的图像验证计算。青年志愿= Y (:,:,: 1);%使用函数imshow uint8转换。validationImage = uint8(收集(extractdata(十五)));transformedValidationImage = uint8(收集(extractdata(青年志愿)));%画出输入图像和输出图像,增加大小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。
X = dlarray(单(im),“SSCB”);
使用GPU皈依gpuArray
如果一个人是可用的。
如果canUseGPU X = gpuArray (X);结束
应用样式的图片,把它转发给图像变压器使用函数预测。
Y =预测(netTransform X);
重新调节图像的范围(0 255)。首先,使用函数双曲正切
要重新调节Y
(1)范围。然后,和规模输出转移到重新进入255年[0]范围内。
Y = 255 *(双曲正切(Y) + 1) / 2;
准备Y
策划。使用的函数extractdata
提取的数据dlarray。
使用聚集函数Y的GPU转移到本地工作区。
Y = uint8(收集(extractdata (Y)));
显示输入图像(左)旁边的程式化形象(右)。
图m = imtile ({im, Y});imshow (m)
损失函数模型
这个函数modelLoss
作为输入失去网络netLoss
,图像变压器网络netTransform
mini-batch的输入图像X
数组,包含克矩阵的风格形象SGram
,与内容相关的重量损失contentWeight
和重量与风格相关的损失styleWeight
。函数返回的总损失,与内容相关的损失lossContent
和与风格相关的损失lossStyle
的梯度全损对图像的可学的参数变压器梯度
,图像变压器状态的网络状态
,转换后的图像Y
。
函数(损失、lossContent lossStyle、渐变状态,Y] =…modelLoss (netLoss netTransform X、SGram contentWeight, styleWeight) [Y,状态]=前进(netTransform X);Y = 255 *(双曲正切(Y) + 1) / 2;[损失,lossContent, lossStyle] = styleTransferLoss (netLoss Y X, SGram contentWeight, styleWeight);梯度= dlgradient(损失、netTransform.Learnables);结束
风格传递损失
这个函数styleTransferLoss
作为输入失去网络netLoss
mini-batch的输入图像X,
mini-batch转换图像Y
数组,包含克矩阵的风格形象SGram
,与内容相关的权重和风格contentWeight
和styleWeight,
分别。它返回的总损失损失
和个人部分:内容丢失lossContent
和风格损失lossStyle。
损失是多少的测量内容输入图像之间的空间结构有差异X
和输出图像Y
。
另一方面,风格告诉你损失之间有多少不同风格外观风格的形象年代
和输出图像Y
。
下面的图表说明了算法styleTransferLoss
实现计算的总损失。
首先,函数将输入图像X
,转换后的图像Y
和风格的形象年代
VGG-16 pretrained网络。这pretrained网络从这些图像中提取一些特性。然后算法计算损失的内容使用的空间特性输出图像的输入图像X和Y .此外,计算风格损失通过输出图像Y的文体特征和风格的形象s .最后,它获得的总损失增加的内容和风格的损失。
内容丢失
mini-batch中的每个图像的内容损失函数比较原始图像的特性和转换后的图像输出的层relu3_3
。特别是,它计算激活并返回之间的均方误差的平均损失mini-batch:
在哪里
包含输入图像,
包含了转换后的图像,
是mini-batch大小,
代表了激活提取层relu3_3。
风格的损失
计算风格损失,为每个mini-batch单张图片:
提取层的激活
relu1_2
,relu2_2
,relu3_3
和relu4_3
。为每个四个激活 计算格拉姆矩阵 。
计算平方矩阵对应的克之间的区别。
每层加起来四个输出 从上一步。
获取整个mini-batch风格损失,计算每个图像风格的平均损失 mini-batch:
在哪里 层的索引, 格拉姆矩阵。
全部损失
函数[损失,lossContent, lossStyle] = styleTransferLoss (netLoss, Y, X,…SGram、weightContent weightStyle)%提取激活。YActivations =细胞(1、4);YActivations [YActivations {1}, {2}, YActivations {3}, YActivations {4}] =…转发(netLoss Y“输出”,(“relu1_2”“relu2_2”“relu3_3”“relu4_3”]);XActivations =前进(netLoss X,“输出”,“relu3_3”);%计算激活之间的均方误差。lossContent =意味着((YActivations {3} - XActivations)。^ 2,“所有”);%增加损失的所有四个激活。lossStyle = 0;为j = 1:4 G = createGramMatrix (YActivations {j});lossStyle = lossStyle +总和((G - SGram {j}) ^ 2,。“所有”);结束% mini-batch平均损失。miniBatchSize =大小(X, 4);lossStyle = lossStyle / miniBatchSize;%应用权重。lossContent = weightContent * lossContent;lossStyle = weightStyle * lossStyle;%计算全损。损失= lossContent + lossStyle;结束
剩余块
的residualBlock
函数返回一个数组的六层。归一化层,它由卷积层,实例ReLu层和附加层。请注意,groupNormalizationLayer (“channel-wise”)
只是一个实例归一化层。
函数层= residualBlock(名字)层= [convolution2dLayer(128年3[3],填充=“相同”、名称=“convRes_”+名称+“_1”)groupNormalizationLayer (“channel-wise”、名称=“normRes_”+名称+“_1”)reluLayer (Name =“reluRes_”+名称+“_1”3)convolution2dLayer([3], 128年,填充=“相同”、名称=“convRes_”+名称+“_2”)groupNormalizationLayer (“channel-wise”、名称=“normRes_”+名称+“_2”)additionLayer (Name =“加”+名字)];结束
格拉姆矩阵
这个函数createGramMatrix
需要作为输入单一层的激活,并返回一个风格表示mini-batch每个图像。
大小的输入特性映射[W H, C, N],其中H是高度,W是宽度,C是通道的数量,N是mini-batch大小。函数输出数组G
的大小(C, C, N)。每个子数组G (:,:, k)
相对应的格拉姆矩阵吗
mini-batch形象。每个条目
的格拉姆矩阵表示通道之间的相关性
和
,因为每个条目在通道
繁殖在通道入口在相应的位置
:
在哪里 的激活吗 mini-batch形象。
格拉姆矩阵包含哪些特性信息激活在一起但没有信息出现在图像的特性。这是因为高度和宽度的总和失去了空间结构的信息。损失函数使用这个矩阵作为一个风格的代表形象。
函数G = createGramMatrix(激活)[h, w, numChannels] =大小(激活,1:3);特点=重塑(激活,h * w, numChannels, []);特点=排列(功能,(2 1 3));G = dlmtimes(功能、特点)/ w (h * * numChannels);结束
引用
约翰逊,贾斯汀,亚历山大Alahi,李菲菲。“知觉损失实时传输和超分辨率风格。”欧洲计算机视觉。施普林格,可汗,2016。
另请参阅
dlnetwork
|向前
|预测
|dlarray
|dlgradient
|dlfeval
|adamupdate