这个例子展示了如何训练生成式对抗网络来生成图像。
生成的对抗性网络(GaN)是一种深度学习网络,可以生成具有与输入实际数据相似特征的数据。
GAN由两个一起训练的网络组成:
发电机 - 给定随机值的向量(潜在输入)作为输入,该网络生成具有与训练数据相同结构的数据。
鉴别者 - 给定批次包含训练数据的观察的数据,并从发电机生成数据,这个网络试图将观察分类为“真实的”
或“生成”
.
为了训练一个GAN,需要同时训练两个网络,使两个网络的性能最大化:
训练生成器生成“骗过”鉴别器的数据。
培训鉴别器以区分实际和生成的数据。
为了优化发生器的性能,当给定生成的数据时,最大限度地减少鉴别器的损失。也就是说,生成器的目标是生成鉴别器分类的数据“真实的”
.
为了优化鉴别器的性能,在给定批次的真实和生成数据时,最小化判别符的丢失。也就是说,鉴别者的目标是由发电机“被愚弄”。
理想情况下,这些策略会产生一个生成令人信服的真实数据的生成器,以及一个学习了训练数据特征的强特征表示的鉴别器。
下载并提取花数据集[1]。
URL =.'http://download.tensorflow.org/example_images/flower_photos.tgz';downloadfolder = tempdir;filename = fullfile(downloadFolder,'flower_dataset.tgz');imagefolder = fullfile(downloadFolder,'flower_photos');如果~存在(imageFolder'dir')disp('下载鲜花数据集(218 MB)......')Websave(Filename,URL);Untar(文件名,DownloadFolder)结尾
创建一个包含鲜花照片的图像数据存储。
datasetFolder = fullfile (imageFolder);imd = imageDatastore (datasetFolder,...'insertumbfolders',真正的);
增强数据以包括随机水平翻转,并调整图像大小以具有64乘值64。
增量= imageDataAugmenter ('randxreflection',真正的);Augimds = AugmentedimageDataStore([64 64],IMDS,“DataAugmentation”,增强者);
定义以下网络架构,从大小100的随机向量生成图像。
这个网络:
使用a将大小100到7-ob-7-by-128阵列的随机向量转换为项目和重塑层。
使用具有批量归一化和Relu层的一系列转换卷积层将产生的数组升高到64×64×3阵列。
将此网络架构定义为一个层图,并指定以下网络属性。
对于转置卷积层,指定5 × 5滤波器,每个层的滤波器数量减少,步幅为2,裁剪每个边缘的输出。
对于最终转置卷积层,指定与生成图像的三个RGB通道对应的三个5-5-5滤波器,以及前一层的输出大小。
在网络的末端,包括一个tanh层。
要投影并重塑噪声输入,请使用自定义层ProjectAndreshapelayer.
,附加到该示例作为支持文件。金宝app的ProjectAndreshapelayer.
Object使用完全连接的操作Upscales输入,并将输出重新插入指定大小。
filtersize = 5;numfilters = 64;numlattentinputs = 100;ProjectionSize = [4 4 512];tallersgenerator = [featureinputlayer(numlatentinputs,“名字”,“在”) projectAndReshapeLayer (projectionSize numLatentInputs,“名字”,“项目”);transposedConv2dLayer (filterSize 4 * numFilters,“名字”,'tconv1'batchnormalizationlayer(“名字”,'bnorm1') reluLayer (“名字”,'relu1')TransposedConv2dlayer(过滤,2 * NumFilters,“步”2,'裁剪',“相同”,“名字”,'tconv2'batchnormalizationlayer(“名字”,'bnorm2') reluLayer (“名字”,“relu2”) transposedConv2dLayer (filterSize numFilters,“步”2,'裁剪',“相同”,“名字”,'tconv3'batchnormalizationlayer(“名字”,“bnorm3”) reluLayer (“名字”,“relu3”) transposedConv2dLayer (filterSize 3“步”2,'裁剪',“相同”,“名字”,'tconv4')Tanhlayer(“名字”,'tanh')];Lgroggenerator = LayerGraph(层Generator);
为了使用自定义的训练循环来训练网络并使其能够自动区分,将层图转换为dlnetwork.
对象。
dlnetgenerator = dlnetwork(lgropgenerator);
定义以下网络,该网络分类真实和生成的64×64图像。
创建一个网络,它接收64 × 64 × 3的图像,并使用一系列带有批处理归一化和泄漏ReLU层的卷积层返回标量预测评分。使用dropout为输入图像添加噪声。
对于退出层,指定退出概率为0.5。
对于卷积层,指定5 × 5滤波器,并为每个层增加滤波器的数量。还要指定步幅为2和输出的填充。
对于泄漏的Relu层,指定0.2的等级。
对于最终图层,用一个4×4滤波器指定卷积层。
要输出范围[0,1]的概率,使用sigmoid.
功能MapicalGRADENTERS.
功能,列出模型梯度函数该示例的部分。
dropoutprob = 0.5;numfilters = 64;Scale = 0.2;InputSize = [64 64 3];filtersize = 5;LayersDiscriminator = [ImageInputLayer(输入,'正常化','没有任何',“名字”,“在”)DropoutLayer(DropoutProb,“名字”,'退出')卷积2dlayer(过滤,numfilters,“步”2,'填充',“相同”,“名字”,'conv1') leakyReluLayer(规模、“名字”,'lrelu1')卷积2dlayer(过滤,2 * numfilters,“步”2,'填充',“相同”,“名字”,'conv2'batchnormalizationlayer(“名字”,“bn2”) leakyReluLayer(规模、“名字”,'lrelu2')卷积2dlayer(过滤,4 * numfilters,“步”2,'填充',“相同”,“名字”,'conv3'batchnormalizationlayer(“名字”,“bn3”) leakyReluLayer(规模、“名字”,'lrelu3')卷积2dlayer(过滤,8 * numfilters,“步”2,'填充',“相同”,“名字”,“conv4”batchnormalizationlayer(“名字”,“bn4”) leakyReluLayer(规模、“名字”,'lrelu4'1) convolution2dLayer(4日,“名字”,“conv5”)];Lgraphdiscriminator = DaterGraph(LayersDiscriminator);
为了使用自定义的训练循环来训练网络并使其能够自动区分,将层图转换为dlnetwork.
对象。
dlnetDiscriminator = dlnetwork (lgraphDiscriminator);
创建函数MapicalGRADENTERS.
,列于模型梯度函数示例的一部分,它以发电机和鉴别器网络为输入,一个迷你输入数据,随机值阵列和翻转因子,并返回到网络中的学习参数的损失梯度和两个网络的分数。
500个纪元的128个小批量列车。对于更大的数据集,您可能不需要为那么多的纪元进行训练。
numEpochs = 500;miniBatchSize = 128;
指定Adam优化的选项。对于两个网络,指定:
学习率为0.0002
梯度衰减因子0.5
平方梯度衰减因子为0.999
学习= 0.0002;梯度Dayfactor = 0.5;squaredgradientdecayfactor = 0.999;
如果鉴别者学会过快地区分真实和生成的图像,则发电机可以无法训练。为了更好地平衡鉴别器和发电机的学习,通过随机翻转标签将噪声添加到真实数据。
指定A.Flipfactor.
值为0.3,以翻转30%的真实标签(占总标签的15%)。请注意,由于所有生成的图像仍然正确标记,这不会损害发电机。
flipFactor = 0.3;
每100次迭代显示生成的验证图像。
验证频率= 100;
采用minibatchqueue
处理和管理迷你批次的图像。对于每个迷你批处理:
使用自定义小批量预处理功能preprocessMiniBatch
(在此示例结束时定义)以重新缩放范围内的图像[1]
.
丢弃任何小于128个观测值的部分小批。
使用尺寸标签格式化图像数据'SSCB'
(spatial, spatial, channel, batch)。默认情况下,minibatchqueue
对象将数据转换为dlarray.
底层类型的对象单
.
在GPU上培训如果有一个可用的。当。。。的时候'outputenvironment'
选择minibatchqueue
是“汽车”
,minibatchqueue
将每个输出转换为GPUArray.
如果有可用的GPU。使用GPU需要并行计算工具箱™和支持CUDA®的NVIDIA®GPU,其计算能力为3.0或更高。
Augimds.minibatchsize =小匹匹匹匹配;executionenvironment =“汽车”;兆贝可= minibatchqueue (augimds,...'minibatchsize',小匹马,...'partialminibatch','丢弃',...“MiniBatchFcn”,@preprocessminibatch,...“MiniBatchFormat”,'SSCB',...'outputenvironment',刽子毒环境;
使用自定义训练循环训练模型。在训练数据上循环并在每次迭代时更新网络参数。要监视培训进度,请使用已停用的随机值阵列显示一批生成的图像,以输入到发电机以及分数的曲线图。
初始化Adam的参数。
trailingAvgGenerator = [];trailingAvgSqGenerator = [];trailingAvgDiscriminator = [];trailingAvgSqDiscriminator = [];
为了监视培训进度,使用进入发电机的固定随机向量显示一批生成的图像并绘制网络分数。
创建一个保留的随机值数组。
numvalidationimages = 25;zvalidation = Randn(NumlatentInputs,NumValidationImages,'单身的');
将数据转换为dlarray.
对象并指定维度标签“CB”
(频道,批处理)。
dlZValidation = dlarray (ZValidation,“CB”);
对于GPU培训,将数据转换为GPUArray.
对象。
如果(execultenvironment ==.“汽车”&& canUseGPU) || executionEnvironment ==“图形”dlZValidation = gpuArray (dlZValidation);结尾
初始化训练进度图。创建一个图形,并将其大小调整为两倍的宽度。
f =图;f.Position (3) = 2 * f.Position (3);
为生成的图像和网络分数创建子图。
imageaxes =子图(1,2,1);scoreaxes =子图(1,2,2);
初始化Scores Plot的动画行。
lineScoreGenerator = animatedline (scoreAxes,'颜色',[0 0.447 0.741]);LineScoredIscriminator = AnimatedLine(Scoreaxes,'颜色', [0.85 0.325 0.098]);传奇('发电机','鉴别者');ylim([01])xlabel(“迭代”) ylabel (“分数”) 网格在
训练甘。对于每个时代,将数据存储和循环播放和循环在迷你批量数据上。
对于每个迷你批处理:
使用模型梯度评估使用dlfeval
和MapicalGRADENTERS.
函数。
使用使用的网络参数更新网络参数adamupdate.
函数。
绘制两个网络的分数。
在每一个validationFrequency
迭代,显示一批生成的图像,用于固定的保持发生器输入。
培训可能需要一些时间来运行。
迭代= 0;start = tic;%循环epochs。为时代= 1:numEpochs重置和洗牌数据存储。洗牌(MBQ);%循环在迷你批次。尽管Hasdata(MBQ)迭代=迭代+ 1;%读取迷你批次数据。dlX =下一个(兆贝可);%为发电机网络生成潜在输入。转换成% dlarray,并指定尺寸标签'CB'(通道,批次)。%如果在GPU上训练,则将潜在输入转换为gpuArray。Z = randn (numLatentInputs miniBatchSize,'单身的');dlz = dlarray(z,“CB”);如果(execultenvironment ==.“汽车”&& canUseGPU) || executionEnvironment ==“图形”DLZ = GPUARRAY(DLZ);结尾%评估模型梯度和生成器状态使用%dlfeval和easturedients函数在结束时列出% 例子。[梯度总是,梯度分子剂,术语或级别,刻痕试验器,划分脉状物] =...dlfeval(@modelgradients,dlnetgenerator,dlnetdiscriminator,dlx,dlz,flipfactor);dlnetgenerator.state = stategenerator;%更新鉴别器网络参数。[DlnetDiscriminator,trailingavgdiscriminator,trailingavgsqdiscriminator] =...adamupdate (dlnetDiscriminator gradientsDiscriminator,...trailingAvgDiscriminator trailingAvgSqDiscriminator,迭代,...学习,梯度dayfactor,squaredgradientdecayfactor);%更新生成器网络参数。[DlnetGenerator,TrailingAvggenerator,TrailingAvgsqgenerator] =...adamupdate (dlnetGenerator gradientsGenerator,...trailingAvgGenerator trailingAvgSqGenerator,迭代,...学习,梯度dayfactor,squaredgradientdecayfactor);%每次validationFrequency迭代,使用%保持发电机输入。如果mod(迭代,验证频率)== 0 ||迭代== 1%使用保持的发电机输入生成图像。dlxgeneratedValidation =预测(DlnetGenerator,DLZValidation);%瓷砖并重新归类范围的图像[0 1]。i = Imtile(提取数据(DLXGeneratedValidation));我= Rescale(i);%显示图像。次要情节(1、2、1);图像(imageAxes,我)xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结尾%更新分数绘图。次要情节(1、2、2)addpoints (lineScoreGenerator,迭代,...双(收集(摘录(刻度))))));addpoints(LineScoredIscriminator,迭代,...双(收集(提取物)));%用培训进度信息更新标题。d =持续时间(0,0,toc(start),'格式','hh:mm:ss');标题(...”时代:“+时代+”、“+...“迭代:”+迭代+”、“+...”经过:“+字符串(d))绘制结尾结尾
这里,鉴别器学习了一种强大的特征表示,可以在生成的图像中识别出真实的图像。反过来,生成器学习了一个类似的强特征表示,允许它生成与训练数据相似的图像。
训练图显示了生成器和鉴别器网络的得分。要了解更多关于如何解释网络分数,请看监控GAN培训进度,识别常见故障模式.
要生成新的图像,请使用预测
函数在生成器上使用dlarray.
包含一批随机载体的对象。要将图像显示在一起,请使用imtile
使用函数并使用图像重新扫描图像rescale.
函数。
创建一个dlarray.
对象包含一批25个随机矢量输入到生成器网络。
numObservations = 25;ZNew = randn (numLatentInputs numObservations,'单身的');dlZNew = dlarray (ZNew,“CB”);
要使用GPU生成图像,还需要将数据转换为GPUArray.
对象。
如果(execultenvironment ==.“汽车”&& canUseGPU) || executionEnvironment ==“图形”dlZNew = gpuArray (dlZNew);结尾
生成新的图像使用预测
使用发电机和输入数据。
dlxgeneratednew =预测(Dlnetgenerator,dlznew);
显示图像。
i = Imtile(提取数据(DLXGeneratedNew));我= Rescale(i);图图像(i)轴离开标题(“生成的图像”)
这个函数MapicalGRADENTERS.
将生成器和鉴别器作为输入dlnetwork.
对象dlnetGenerator
和dlnetdiscriminator
,迷你批次输入数据dlX
,一个随机值数组DLZ.
,以及实际标签翻转的百分比Flipfactor.
,并返回关于网络中的学习参数,发电机状态和两个网络的分数的丢失渐变。因为鉴别器输出不在范围内[0,1],所以MapicalGRADENTERS.
函数应用s型函数将其转换为概率。
功能[梯度总是,梯度分子剂,术语或级别,刻痕试验器,划分脉状物] =...ModelGRADENTERS(DLNETGENERATOR,DLNETDISCRIMINATOR,DLX,DLZ,FLIPFORTOR)%计算使用鉴别器网络的实际数据的预测。dlYPred = forward(dlnetDiscriminator, dlX);%计算具有鉴别器网络的生成数据的预测。向前(dlXGenerated stateGenerator] = (dlnetGenerator, dlZ);dlYPredGenerated = forward(dlnetDiscriminator, dlXGenerated);%将鉴别器输出转换为概率。probGenerated =乙状结肠(dlYPredGenerated);probReal =乙状结肠(dlYPred);%计算鉴别器的得分。scoreDiscriminator = (mean(probReal) + mean(1-probGenerated)) / 2;%计算生成器的得分。刻录物=平均值(probgenerated);%随机翻转真实图像的标签的一部分。numObservations =大小(probReal 4);idx = randperm(numObservations,floor(flipFactor * numObservations));%翻转标签。probreal(::::,idx)= 1 - probreal(::::,IDX);%计算GaN丢失。[lossGenerator, lossDiscriminator] = ganLoss(probReal,probGenerated);%对于每个网络,计算相对于损失的梯度。gradientsGenerator = dlgradient(lossGenerator, dlnetGenerator。可学的,'etaindata',真正的);gradientsDiscriminator = dlgradient(lossDiscriminator, dlnetDiscriminator.Learnables);结尾
发电机的目的是生成鉴别器分类为的数据“真实的”
.为了最大限度地提高来自发生器的图像被鉴别器分类为真实图像的概率,最小化负对数似然函数。
鉴于输出 判别者:
输入图像属于类的概率是概率“真实的”
.
输入图像属于类的概率是概率“生成”
.
请注意,SIGMOID操作
发生在MapicalGRADENTERS.
函数。发电机的损耗函数为
在哪里 包含生成的图像的鉴别器输出概率。
鉴别器的目的是不被生成器“愚弄”。为了最大限度地提高鉴别器在真实图像和生成图像之间成功鉴别的概率,最小化相应的负对数似然函数的和。
给出了该鉴别器的损失函数
在哪里 包含真实图像的鉴别器输出概率。
要在0到1的范围内衡量生成器和鉴别器实现各自目标的程度,可以使用分数的概念。
发电机分数是与生成的图像的鉴别器输出对应的概率的平均值:
鉴别器分数是与真实和生成的图像的鉴别器输出对应的概率的平均值:
分数与损失成反比,但实际上包含相同的信息。
功能[损失Generator,损失Discriminator] = Ganloss(Probreal,Probenerated)%计算鉴别器网络的损耗。lossDiscriminator = -mean(log(probReal)) -mean(log(1-probGenerated));%计算发电机网络的损耗。损失generator = -mean(log(probgenerated));结尾
的preprocessMiniBatch
函数使用以下步骤预处理数据:
从传入单元格数组中提取图像数据并将其连接到数字阵列中。
重新调整图像的范围[1]
.
功能x = preprocessminibatch(数据)%contenate mini-batchX =猫(4、数据{:});%重新归类范围[-1 1]中的图像。x = Rescale(x,-1,1,'Inputmin',0,'inputmax',255);结尾
TensorFlow团队。花http://download.tensorflow.org/example_images/flower_photos.tgz
雷德福,亚历克,卢克·梅茨,和苏史密斯·钦塔拉。基于深度卷积生成对抗网络的无监督表示学习。预印本,2015年11月19日提交。http://arxiv.org/abs/1511.06434。
adamupdate.
|dlarray.
|dlfeval
|Dlgradient.
|dlnetwork.
|向前
|minibatchqueue
|预测