主要内容

训练生成对抗网络(GAN)

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

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

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

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

  2. Discriminator—给定包含来自训练数据和从生成器生成的数据的几批数据,该网络试图将这些观察结果分类为“真正的”“生成”

要训练一个GAN,需要同时训练两个网络以使两个网络的性能最大化:

  • 训练生成器生成能愚弄识别器的数据。

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

为了优化生成器的性能,在给定生成数据时最大限度地减少鉴别器的损耗。也就是说,生成器的目标是生成识别器分类的数据“真正的”

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

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

负荷训练数据

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

url =“http://download.tensorflow.org/example_images/flower_photos.tgz”;downloadFolder = tempdir;文件名= fullfile (downloadFolder,“flower_dataset.tgz”);imageFolder = fullfile (downloadFolder,“flower_photos”);如果~存在(imageFolder“dir”) disp (下载Flowers数据集(218mb)…) websave(文件名,url);解压(文件名,downloadFolder)结束

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

datasetFolder = fullfile (imageFolder);imd = imageDatastore (datasetFolder IncludeSubfolders = true);

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

增量= imageDataAugmenter (RandXReflection = true);augimds = augmentedImageDatastore([64 64],imds,DataAugmentation=augmenter);

定义发电机网络

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

这个网络:

  • 将大小为100的随机向量转换为7 × 7 × 128的数组,使用一个完全连接的层,然后执行重塑操作。

  • 使用一系列带批处理规范化和ReLU层的转置卷积层,将结果数组升级为64 × 64 × 3的数组。

将这个网络架构定义为一个层图,并指定以下网络属性。

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

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

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

为了投射和重塑噪声输入,使用一个全连接层,然后使用一个重塑操作,该重塑操作指定为具有函数的函数层feature2image函数,作为支持文件附加到本示例中。万博1manbetx要访问这个函数,请将这个示例作为一个活动脚本打开。

filterSize = 5;numFilters = 64;numLatentInputs = 100;projectionSize = [4 4 512];layersGenerator = [featureInputLayer (numLatentInputs) fullyConnectedLayer (prod (projectionSize)) functionLayer (@ (X) feature2image (X, projectionSize) Formattable = true) transposedConv2dLayer (filterSize 4 * numFilters) batchNormalizationLayer reluLayer transposedConv2dLayer (2 * numFilters filterSize,跨步= 2,裁剪=“相同”) batchNormalizationLayer reluLayer转座conv2dlayer (filterSize,numFilters,Stride=2,裁剪=“相同”) batchNormalizationLayer reluLayer转座conv2dlayer (filterSize,3,Stride=2,裁剪=“相同”) tanhLayer);lgraphGenerator = layerGraph (layersGenerator);

为了使用自定义训练循环训练网络并实现自动微分,将层图转换为dlnetwork对象。

dlnetGenerator = dlnetwork (lgraphGenerator);

定义鉴别器网络

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

创建一个网络,该网络获取64 × 64 × 3图像,并使用一系列具有批处理规范化和泄漏ReLU层的卷积层返回标量预测得分。使用dropout添加噪声到输入图像。

  • 对于dropout层,指定dropout概率为0.5。

  • 对于卷积层,指定5 × 5的过滤器,并为每一层增加过滤器的数量。还要指定步长为2并填充输出。

  • 对于有泄漏的ReLU层,指定0.2的刻度。

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

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

dropoutProb = 0.5;numFilters = 64;规模= 0.2;inputSize = [64 64 3];filterSize = 5;layersDiscriminator = [imageInputLayer(inputSize,归一化=“没有”) dropoutLayer (dropoutProb) convolution2dLayer (filterSize numFilters,跨步= 2,填充=“相同”) leakyReluLayer(规模)convolution2dLayer (2 * numFilters filterSize,跨步= 2,填充=“相同”) batchNormalizationLayer leakyReluLayer(缩放)卷积2dlayer (filterSize,4*numFilters,Stride=2,填充=“相同”) batchNormalizationLayer leakyReluLayer(缩放)卷积2dlayer (filterSize,8*numFilters,Stride=2,填充=“相同”) batchNormalizationLayer leakyReluLayer(scale)卷积2dlayer (4,1)];lgraphDiscriminator = layerGraph (layersDiscriminator);

为了使用自定义训练循环训练网络并实现自动微分,将层图转换为dlnetwork对象。

dlnetDiscriminator = dlnetwork (lgraphDiscriminator);

定义模型梯度和损失函数

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

指定培训选项

用128个小批量训练500个时代。对于更大的数据集,您可能不需要训练那么多的时代。

numEpochs = 500;miniBatchSize = 128;

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

  • 学习速率为0.0002

  • 梯度衰减因子为0.5

  • 梯度衰减系数的平方为0.999

learnRate = 0.0002;gradientDecayFactor = 0.5;squaredGradientDecayFactor = 0.999;

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

指定一个flipFactor值为0.3,翻转30%的真实标签(15%的总标签)。注意,这不会损害生成器,因为所有生成的图像仍然被正确标记。

flipFactor = 0.3;

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

validationFrequency = 100;

火车模型

使用minibatchqueue处理和管理小批量映像。为每个mini-batch:

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

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

  • 使用尺寸标签格式化图像数据“SSCB”(空间,空间,通道,批处理)。默认情况下,minibatchqueue对象将数据转换为dlarray具有基础类型的对象

  • 如果有可用的GPU,训练。当OutputEnvironment选择minibatchqueue“汽车”minibatchqueue将每个输出转换为gpuArray如果有GPU可用。使用GPU需要并行计算工具箱™和支持CUDA®的NVIDIA®GPU,计算能力为3.0或更高。

augimds。MiniBatchSize = MiniBatchSize;executionEnvironment =“汽车”;兆贝可= minibatchqueue (augimds,...MiniBatchSize = MiniBatchSize,...PartialMiniBatch =“丢弃”...MiniBatchFcn = @preprocessMiniBatch,...MiniBatchFormat =“SSCB”...OutputEnvironment = executionEnvironment);

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

为Adam初始化参数。

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

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

创建一个随机值数组。

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

将数据转换为dlarray对象,并指定维度标签“CB”(频道,批处理)。

dlZValidation = dlarray (ZValidation,“CB”);

对于GPU训练,将数据转换为gpuArray对象。

如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”dlZValidation = gpuArray (dlZValidation);结束

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

f =图;f.Position (3) = 2 * f.Position (3);

为生成的图像和网络分数创建一个子图。

imageAxes =情节(1、2、1);scoreAxes =情节(1、2、2);

初始化分数图的动画线。

lineScoreGenerator = animatedline(scoreAxes,Color=[0 0.447 0.741]);lineScoreDiscriminator = animatedline(scoreAxes,Color=[0.85 0.325 0.098]);传奇(“发电机”“鉴频器”);ylim([0 1])包含(“迭代”) ylabel (“分数”网格)

训练甘。对于每个时期,在小批数据上移动数据存储并循环。

为每个mini-batch:

  • 使用评估模型梯度dlfevalmodelGradients函数。

  • 更新网络参数adamupdate函数。

  • 标出这两个网络的得分。

  • 在每一个validationFrequency迭代,显示一批生成的图像为一个固定的helout发电机输入。

训练需要一些时间来跑步。

迭代= 0;开始=抽搐;%循环纪元。时代= 1:numEpochs%重置和shuffle数据存储。洗牌(兆贝可);在小批量上循环。Hasdata (mbq)迭代=迭代+ 1;%读取小批数据。dlX =下一个(兆贝可);%为发电机网络产生潜在输入。转换为% dlarray,并指定尺寸标签“CB”(通道,批)。%如果在GPU上进行训练,那么将潜在输入转换为gpuArray。Z = randn (numLatentInputs miniBatchSize,“单身”);dlZ = dlarray (Z,“CB”);如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”dlZ = gpuArray (dlZ);结束使用评估模型梯度和生成器状态控件末尾列出的modelGradients函数%的例子。[gradientsGenerator, gradientsDiscriminator, stateGenerator, scoreGenerator, scoreDiscriminator] =...dlfeval(@modelGradients, dlnetGenerator, dlnetDiscriminator, dlX, dlZ, flipFactor);dlnetGenerator。状态= stateGenerator;%更新鉴别器网络参数。[dlnetDiscriminator, trailingAvgDiscriminator trailingAvgSqDiscriminator] =...adamupdate (dlnetDiscriminator gradientsDiscriminator,...trailingAvgDiscriminator trailingAvgSqDiscriminator,迭代,...learnRate、gradientDecayFactor squaredGradientDecayFactor);%更新生成器网络参数。[dlnetGenerator, trailingAvgGenerator trailingAvgSqGenerator] =...adamupdate (dlnetGenerator gradientsGenerator,...trailingAvgGenerator trailingAvgSqGenerator,迭代,...learnRate、gradientDecayFactor squaredGradientDecayFactor);每次验证频率迭代,显示批量生成的图像使用%输出发电机输入。如果mod(iteration,validationFrequency) == 0 || iteration == 1%使用helout generator输入生成图像。dlXGeneratedValidation =预测(dlnetGenerator dlZValidation);%平铺并缩放范围[0 1]内的图像。我= imtile (extractdata (dlXGeneratedValidation));I =重新调节(我);%显示图像。次要情节(1、2、1);图像(imageAxes,我)xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结束%更新分数图。次要情节(1、2、2)addpoints (lineScoreGenerator,迭代,...双(收集(extractdata (scoreGenerator))));addpoints (lineScoreDiscriminator迭代,...双(收集(extractdata (scoreDiscriminator))));%更新标题与培训进度信息。D =持续时间(0,0,toc(开始),格式=“hh: mm: ss”);标题(...”时代:“+时代+”、“+...“迭代:“+迭代+”、“+...”经过:“+ drawnow字符串(D))结束结束

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

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

生成新的图片

要生成新图像,请使用预测函数在发生器上dlarray包含一批随机向量的对象。要同时显示这些图像,请使用imtile函数并缩放图像重新调节函数。

创建一个dlarray对象包含一批25个随机矢量输入到发电机网络。

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

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

如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”dlZNew = gpuArray (dlZNew);结束

生成新图像预测函数与生成器和输入数据。

dlXGeneratedNew =预测(dlnetGenerator dlZNew);

显示图像。

我= imtile (extractdata (dlXGeneratedNew));I =重新调节(我);数字图像(I)轴标题(“生成的图像”

模型梯度函数

这个函数modelGradients将生成器和鉴别器作为输入dlnetwork对象dlnetGeneratordlnetDiscriminator,输入数据的小批处理dlX,一个随机值数组dlZ,以及实际标签翻转的百分比flipFactor,并返回损失相对于网络中可学习参数的梯度、生成器状态和两个网络的分数。由于鉴别器输出不在[0,1]范围内,因此modelGradients函数应用sigmoid函数将其转换为概率。

函数[gradientsGenerator, gradientsDiscriminator, stateGenerator, scoreGenerator, scoreDiscriminator] =...modelGradients(dlnetGenerator, dlnetDiscriminator, dlX, dlZ, flipFactor)%利用判别器网络对真实数据进行预测。dlYPred = forward(dlnetDiscriminator, dlX);%利用判别器网络对生成数据进行预测。向前(dlXGenerated stateGenerator] = (dlnetGenerator, dlZ);dlYPredGenerated = forward(dlnetDiscriminator, dlXGenerated);%将识别器输出转换为概率。probGenerated =乙状结肠(dlYPredGenerated);probReal =乙状结肠(dlYPred);%计算判别器的分数。scoreDiscriminator =(平均值(probReal) +平均值(1-probGenerated)) / 2;%计算生成器的得分。scoreGenerator =意味着(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.Learnables,RetainData=true);gradientsDiscriminator = dlgradient(lossDiscriminator, dlnetDiscriminator.Learnables);结束

GAN损失函数和得分

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

考虑到输出 Y 鉴频器:

  • Y ˆ σ Y 输入图像属于该类的概率是多少“真正的”

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

注意这个s形操作 σ 发生在modelGradients函数。发电机的损耗函数由

lossGenerator - 的意思是 日志 Y ˆ 生成的

在哪里 Y ˆ G e n e r 一个 t e d 包含生成图像的识别器输出概率。

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

鉴频器的损耗函数由

lossDiscriminator - 的意思是 日志 Y ˆ 真正的 - 的意思是 日志 1 - Y ˆ 生成的

在哪里 Y ˆ R e 一个 l 包含真实图像的鉴别器输出概率。

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

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

scoreGenerator 的意思是 Y ˆ 生成的

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

scoreDiscriminator 1 2 的意思是 Y ˆ 真正的 + 1 2 的意思是 1 - Y ˆ 生成的

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

函数[lossGenerator, lossDiscriminator] = ganLoss(probReal,probGenerated)%计算鉴别器网络的损耗。lossDiscriminator = -mean(log(probReal)) -mean(log(1-probGenerated));%计算发电机网络的损耗。lossGenerator =意味着(日志(probGenerated));结束

Mini-Batch预处理功能

preprocessMiniBatchFunction对数据进行预处理,步骤如下:

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

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

函数X = preprocessMiniBatch(数据)%连接mini-batchX =猫(4、数据{:});%缩放[-1 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,和soumitchintala。深度卷积生成对抗网络的无监督表示学习预印本,2015年11月19日提交。http://arxiv.org/abs/1511.06434。

另请参阅

|||||||

相关的话题