主要内容

列车生成对抗网络(GAN)

这个例子展示了如何训练生成性对抗网络来生成图像。

生成性对抗网络(GAN)是一种深度学习网络,能够生成与输入真实数据具有相似特征的数据。

GAN由两个一起训练的网络组成:

  1. 生成器-给定一个随机值向量(潜在输入)作为输入,该网络生成与训练数据具有相同结构的数据。

  2. 鉴别器-给定包含训练数据和生成器生成数据的观察值的数据批次,该网络尝试将观察值分类为“真实的”“生成”.

要训练一个GAN,同时训练两个网络,以最大限度地提高这两个网络的性能:

  • 训练生成器生成“愚弄”鉴别器的数据。

  • 训练鉴别器区分真实数据和生成的数据。

为了优化生成器的性能,在给定生成的数据时,使鉴别器的损失最大化。也就是说,生成器的目标是生成鉴别器分类为的数据“真实的”.

为了优化鉴别器的性能,在给定批次的真实数据和生成的数据时,将鉴别器的损失降至最低。也就是说,鉴别器的目标是不被生成器“愚弄”。

理想情况下,这些策略产生一个生成令人信服的真实数据的生成器和一个学习了训练数据特征的强特征表示的鉴别器。

负荷训练数据

下载并解压缩数据集[1]。

网址="http://download.tensorflow.org/example_images/flower_photos.tgz";downloadFolder=tempdir;filename=fullfile(downloadFolder,“flower_dataset.tgz”); imageFolder=fullfile(下载文件夹,“花卉照片”);如果~exist(imageFolder,“目录”)disp(“正在下载花卉数据集(218MB))websave(文件名、url);untar(文件名,下载文件夹)终止

创建包含花的照片的图像数据存储。

datasetFolder=fullfile(imageFolder);imds=imageDatastore(datasetFolder,IncludeSubfolders=true);

增加数据以包括随机水平翻转,并调整图像大小,使其大小为64×64。

augmenter=imageDataAugmenter(randxrelection=true);augimds=augmentedImageDatastore([64],imds,DataAugmentation=augmenter);

定义发电机网络

定义以下网络架构,它从大小为100的随机向量生成图像。

该网络:

  • 使用完全连接的层,然后执行整形操作,将大小为100的随机向量转换为7×7×128阵列。

  • 使用一系列转置卷积层(带有批处理规范化和ReLU层),将生成的数组放大到64×64×3数组。

将此网络体系结构定义为图层图,并指定以下网络属性。

  • 对于转置卷积层,指定5乘5个过滤器,每个层的过滤器数量减少,跨步为2,并在每条边上裁剪输出。

  • 对于最终的转置卷积层,指定与生成图像的三个RGB通道对应的三个5×5滤波器,以及前一层的输出大小。

  • 在网络的末尾,包括一个tanh层。

若要投影和重塑噪波输入,请使用完全连接的层,然后使用重塑操作,该操作指定为功能层,其功能由特征2图像函数,作为支持文件附加到此示例。若要访问此函数,请将此示例作为实时脚本打开。万博1manbetx

filterSize=5;numFilters=64;numLatentInputs=100;projectionSize=[4 512];layersGenerator=[featureInputLayer(numLatentInputs)fullyConnectedLayer(prod(projectionSize))functionLayer(@(X)feature2image(X,projectionSize),Formattable=true)TransposeConv2Layer(filterSize,4*numFilters)批次规格化Layer reluLayer TransposcedConv2Layer(filterSize,2*numFilters,Strip=2,裁剪=“相同”)batchNormalizationLayer reluLayer TransposeSedConv2dLayer(filterSize,NumFilter,步长=2,裁剪=“相同”)batchNormalizationLayer reluLayer TransposeSedConv2dLayer(filterSize,3,步长=2,裁剪=“相同”)tanhLayer];lgraphGenerator=layerGraph(LayerGenerator);

要使用自定义训练循环训练网络并启用自动微分,请将层图转换为数据链路网络对象

dlnetGenerator=dlnetwork(lgraphGenerator);

定义鉴别器网络

定义以下网络,该网络对真实图像和生成的64×64图像进行分类。

创建一个网络,该网络获取64×64×3图像,并使用一系列卷积层返回标量预测分数,这些卷积层具有批标准化和泄漏ReLU层。使用dropout向输入图像添加噪声。

  • 对于退出层,指定0.5的退出概率。

  • 对于卷积层,指定5乘5的过滤器,每个层的过滤器数量增加。还指定2的跨距和输出的填充。

  • 对于泄漏的ReLU层,请指定0.2的比例。

  • 对于最后一层,指定一个带有一个4×4滤波器的卷积层。

要输出[0,1]范围内的概率,请使用乙状结肠功能模型梯度函数,列在模型梯度函数示例的第三部分。

dropoutProb=0.5;numFilters=64;scale=0.2;inputSize=[64 3];filterSize=5;LayerDiscriminator=[imageInputLayer(inputSize,归一化=“没有”)dropoutLayer(dropoutProb)卷积2dLayer(filterSize,NumFilter,步长=2,填充=“相同”)leakyReluLayer(比例)卷积2Dlayer(过滤器尺寸,2*numFilters,步长=2,填充=“相同”)batchNormalizationLayer leakyReluLayer(缩放)卷积2dLayer(filterSize,4*numFilter,步长=2,填充=“相同”)batchNormalizationLayer leakyReluLayer(缩放)卷积2dLayer(filterSize,8*numFilter,步长=2,填充=“相同”)batchNormalizationLayer泄漏层(刻度)卷积层(4,1)];lgraphDiscriminator=层图(层鉴别器);

要使用自定义训练循环训练网络并启用自动微分,请将层图转换为数据链路网络对象

dlnetDiscriminator=dlnetwork(lgraphDiscriminator);

定义模型梯度和损失函数

创建函数模型梯度,列於模型梯度函数示例的一部分,将生成器和鉴别器网络、一小批输入数据、一组随机值和翻转因子作为输入,并返回与网络中可学习参数和两个网络分数相关的损失梯度。

指定培训选项

对于500个历元,使用128个小批量进行训练。对于较大的数据集,可能不需要训练那么多历元。

numEpochs=500;miniBatchSize=128;

指定Adam优化的选项。对于两个网络,指定:

  • 学习率为0.0002

  • 梯度衰减因子为0.5

  • 平方梯度衰减因子为0.999

learnRate=0.0002;梯度衰减因子=0.5;平方半径衰减因子=0.999;

如果鉴别器学习辨别真实图像和生成图像的速度过快,则生成器可能无法训练。为了更好地平衡鉴别器和生成器的学习,通过随机翻转标签向真实数据添加噪声。

指定一个翻转因子值0.3以翻转30%的真实标签(总标签的15%)。请注意,这不会影响生成器,因为所有生成的图像仍正确标记。

翻转系数=0.3;

每100次迭代显示生成的验证图像。

验证频率=100;

列车模型

使用小型批处理队列处理和管理图像的小批量。对于每个小批量:

  • 使用自定义小批量预处理功能预处理小批量(在本例末尾定义)以重新缩放范围内的图像[-1,1].

  • 丢弃观察值少于128的任何部分小批次。

  • 使用标注标签格式化图像数据“SSCB”(空间、空间、通道、批次)。默认情况下小型批处理队列对象将数据转换为dlarray具有基础类型的对象仅有一个的.

  • 如果GPU可用,则在GPU上进行培训。当户外环境选择小型批处理队列“自动”,小型批处理队列将每个输出转换为gpuArray如果GPU可用。使用GPU需要并行计算工具箱™ 以及支持CUDA®的NVIDIA®GPU,具有3.0或更高的计算能力。

augimds.MiniBatchSize=MiniBatchSize;executionEnvironment=“自动”;mbq=小批量队列(augimds,...MiniBatchSize=MiniBatchSize,...部分小批量=“丢弃”,...MiniBatchFcn=@prepreprocessminibatch,...迷你批处理格式=“SSCB”,...OutputEnvironment=executionEnvironment);

使用自定义训练循环对模型进行训练。循环训练数据并在每次迭代时更新网络参数。要监控训练进度,请显示一批生成的图像,使用随机值数组输入生成器,以及分数图。

初始化Adam的参数。

trailingAvgGenerator=[];trailingAvgSqGenerator=[];trailingAvgDiscriminator=[];trailingAvgSqDiscriminator=[];

为了监控训练进度,使用一批固定随机向量显示一批生成的图像,并绘制网络分数。

创建一个随机值数组。

numValidationImages=25;ZValidation=randn(numLatentInputs、numValidationImages、,“单身”);

将数据转换为dlarray对象并指定标注标签“CB”(通道、批次)。

dlZValidation=dlarray(ZValidation,“CB”);

对于GPU培训,将数据转换为gpuArray物体。

如果(b)执行环境==“自动”&&canUseGPU)| |执行环境==“gpu”dlZValidation=gpuArray(dlZValidation);终止

初始化训练进度图。创建一个图形,并将其调整为两倍宽度。

f=图形;f位置(3)=2*f位置(3);

为生成的图像和网络分数创建子地块。

ImageAxis=子批次(1,2,1);得分轴=子批次(1,2,2);

初始化分数绘图的动画线。

lineScoreGenerator=动画线条(scoreAxes,颜色=[0.447 0.741]);lineScoreDiscriminator=动画线条(scoreAxes,颜色=[0.85 0.325 0.098]);图例(“发电机”,“鉴别器”);ylim([01])xlabel(“迭代”)伊拉贝尔(“得分”)网格在…上

训练GAN。对于每个历元,洗牌数据存储并循环小批量数据。

对于每个小批量:

  • 使用德尔费瓦尔模型梯度作用

  • 使用以下命令更新网络参数:阿达木酯作用

  • 绘制两个网络的分数。

  • 以后验证频率在迭代中,显示一批生成的图像,用于固定的保留生成器输入。

训练可能需要一些时间来运行。

迭代=0;开始=tic;%环游各个时代。对于历元=1:numEpochs%重置和洗牌数据存储。洗牌(mbq);%在小批量上循环。虽然hasdata(mbq)迭代=迭代+1;%读取小批量数据。dlX=下一个(mbq);%为发电机网络生成潜在输入。转换为%dlarray并指定标注标签“CB”(通道,批次)。%如果在GPU上进行训练,则将潜在输入转换为gpuArray。Z=randn(numLatentInputs,miniBatchSize,“单身”);dlZ=dlZ阵列(Z,“CB”);如果(b)执行环境==“自动”&&canUseGPU)| |执行环境==“gpu”dlZ=gpuArray(dlZ);终止%使用评估模型梯度和生成器状态%dlfeval和列在末尾的modelGradients函数%例如。[gradientsGenerator,gradientsDiscriminator,stateGenerator,scoreGenerator,scoreDiscriminator]=...dlfeval(@modelGradients,dlnetGenerator,dlnetDiscriminator,dlX,dlZ,flipFactor);dlnetGenerator.State=stateGenerator;%更新鉴别器网络参数。[dlnetDiscriminator,trailingAvgDiscriminator,trailingAvgSqDiscriminator]=...adamupdate(dlnetDiscriminator、Gradients Discriminator、,...trailingAvgDiscriminator,trailingAvgSqDiscriminator,迭代,...learnRate、gradientDecayFactor、squaredGradientDecayFactor);%更新发电机网络参数。[dlnetGenerator、trailingAvgGenerator、trailingAvgSqGenerator]=...数据更新(dlnetGenerator、梯度生成器、,...trailingAvgGenerator,trailingAvgSqGenerator,迭代,...learnRate、gradientDecayFactor、squaredGradientDecayFactor);%每次validationFrequency迭代,使用%保持发电机输入。如果mod(迭代,验证频率)==0 | |迭代==1%使用保留的生成器输入生成图像。dlXGeneratedValidation=预测(dlnetGenerator、dlZValidation);%平铺并重新缩放[0 1]范围内的图像。I=imtile(提取数据(dlXGeneratedValidation));I=重新缩放(I);%显示图像。子批次(1,2,1);图像(imageAxes,I)xticklabels([]);yticklabels([]);标题(“生成的图像”);终止%更新分数图。子批次(1,2,2)添加点(lineScoreGenerator、迭代、,...double(收集(提取数据(scoreGenerator));addpoints(lineScoreDiscriminator,迭代,...双(收集(提取数据(记分鉴别器));%使用培训进度信息更新标题。D=持续时间(0,0,toc(开始),格式=“hh:mm:ss”); 头衔(...“时代:”+纪元+", "+...“迭代:”+迭代+", "+...“已过:”+字符串(D)现在开始终止终止

在这里,鉴别器学习了一个强特征表示法,它在生成的图像中识别真实图像。反过来,生成器学习了一个类似的强特征表示法,它可以生成类似于训练数据的图像。

训练图显示生成器和鉴别器网络的分数。要了解有关如何解释网络分数的更多信息,请参阅监控GAN培训进度并识别常见故障模式.

生成新图像

要生成新图像,请使用预测函数在带有dlarray包含一批随机向量的对象。若要同时显示图像,请使用imtile函数并使用重新缩放作用

创建一个dlarray对象,该对象包含一批25个随机向量以输入到生成器网络。

numObservations=25;ZNew=randn(numLatentInputs,numObservations,“单身”);dlZNew=dlarray(ZNew,“CB”);

要使用GPU生成图像,还需要将数据转换为gpuArray物体。

如果(b)执行环境==“自动”&&canUseGPU)| |执行环境==“gpu”dlZNew=gpuArray(dlZNew);终止

使用预测与发电机和输入数据一起工作。

dlXGeneratedNew=预测(dlnetGenerator,dlZNew);

显示图像。

I=imtile(提取数据(dlXGeneratedNew));I=重新缩放(I);图形图像(I)轴头衔(“生成的图像”)

模型梯度函数

功能模型梯度将生成器和鉴别器作为输入数据链路网络物体dlnetGeneratordlnetDiscriminator,一小批输入数据dlX,一个随机值数组dlZ,以及要翻转的实际标签的百分比翻转因子,并返回与网络中的可学习参数、生成器状态和两个网络的分数相关的损失梯度。由于鉴别器输出不在范围[0,1]内,因此模型梯度函数应用sigmoid函数将其转换为概率。

作用[gradientsGenerator,gradientsDiscriminator,stateGenerator,scoreGenerator,scoreDiscriminator]=...模型渐变(dlnetGenerator、dlnetDiscriminator、dlX、dlZ、flipFactor)%使用鉴别器网络计算实际数据的预测。dlYPred=转发(dlnetDiscriminator,dlX);%使用鉴别器网络计算生成数据的预测。[dlXGenerated,stateGenerator]=转发(dlnetGenerator,dlZ);dlYPredGenerated=转发(dlnetDiscriminator,dlXGenerated);%将鉴别器输出转换为概率。probGenerated=sigmoid(dlYPredGenerated);probReal=sigmoid(dlYPred);%计算鉴别器的分数。记分鉴别器=(平均值(probReal)+平均值(1-probGenerated))/2;%计算生成器的分数。scoreGenerator=平均值(生成的概率);%随机翻转真实图像的一小部分标签。numObservations=size(probReal,4);idx=randperm(numObservations,floor(flipFactor*numObservations));%翻转标签。probReal(:,:,:,idx)=1-probReal(:,:,,:,idx);%计算GAN损耗。[lossGenerator,lossDiscriminator]=ganLoss(probReal,probGenerated);%对于每个网络,计算与损耗相关的梯度。gradientsGenerator=dlgradient(lossGenerator,dlnetGenerator.Learnables,RetainData=true);gradientsDiscriminator=dlgradient(lossDiscriminator,dlnetDiscriminator.Learnables);终止

GAN损失函数与分数

生成器的目标是生成鉴别器分类为的数据“真实的”。为了最大化来自发生器的图像被鉴别器分类为真实图像的概率,最小化负对数似然函数。

给定输出 Y 鉴别器的功能:

  • Y ˆ = σ ( Y ) 是输入图像属于该类的概率“真实的”.

  • 1. - Y ˆ 是输入图像属于该类的概率“生成”.

请注意,sigmoid操作 σ 发生在模型梯度函数。发电机的损耗函数由下式给出

损耗发生器 = - 意思是 ( 日志 ( Y ˆ 生成 ) ) ,

哪里 Y ˆ G E N E R A. T E D 包含生成图像的鉴别器输出概率。

鉴别器的目标是不被生成器“愚弄”。为了最大限度地提高鉴别器成功鉴别真实图像和生成图像的概率,最小化相应的负对数似然函数之和。

鉴别器的损失函数由下式给出

损失辨别器 = - 意思是 ( 日志 ( Y ˆ 真实的 ) ) - 意思是 ( 日志 ( 1. - Y ˆ 生成 ) ) ,

哪里 Y ˆ R E A. L 包含真实图像的鉴别器输出概率。

要在0到1的范围内衡量生成器和鉴别器实现各自目标的程度,可以使用分数的概念。

生成器分数是与所生成图像的鉴别器输出相对应的概率的平均值:

记分发生器 = 意思是 ( Y ˆ 生成 ) .

鉴别器得分是与真实图像和生成图像的鉴别器输出相对应的概率的平均值:

记分器 = 1. 2. 意思是 ( Y ˆ 真实的 ) + 1. 2. 意思是 ( 1. - Y ˆ 生成 ) .

分数与损失成反比,但实际上包含相同的信息。

作用[lossGenerator,lossDiscriminator]=ganLoss(probReal,probGenerated)%计算鉴别器网络的损耗。lossDiscriminator=-mean(log(probReal))-mean(log(1-probGenerated));%计算发电机网络的损耗。lossGenerator=-平均值(log(probGenerated));终止

小批量预处理函数

这个预处理小批量函数使用以下步骤预处理数据:

  1. 从传入的单元格数组中提取图像数据并连接到数字数组中。

  2. 将图像重新缩放到范围内[-1,1].

作用X=预处理小批量(数据)%串联小批量X=cat(4,数据{:});%在[-1]范围内重新缩放图像。X=重新缩放(X,-1,1,InputMin=0,InputMax=255);终止

工具书类

  1. TensorFlow团队。http://download.tensorflow.org/example_images/flower_photos.tgz

  2. Radford、Alec、Luke Metz和Soumith Chintala.《深层卷积生成对抗网络的无监督表征学习》,预印本,2015年11月19日提交。http://arxiv.org/abs/1511.06434.

另见

|||||||

相关话题