主要内容

训练生成对抗网络(GAN)

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

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

trainNetwork函数不支持训练GANs,因此必须实现自定义训练循环。要使用自定义训练循环训练GAN,可以使用dlarray而且dlnetwork对象自动区分。

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

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

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

这张图说明了GAN的生成网络,它从随机输入的向量生成图像。

这张图说明了GAN的结构。

为了训练GAN,同时训练两个网络以最大化两者的性能:

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

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

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

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

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

方法来训练GAN生成图像数据集[1],包含花的图像。

负荷训练数据

下载并撷取数据集[1]。

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

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

imd = imageDatastore (imageFolder IncludeSubfolders = true);

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

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

定义生成对抗网络

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

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

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

这张图说明了GAN的结构。

定义发电机网络

定义下面的网络体系结构,它从随机向量生成图像。

这个网络:

  • 使用投影和重塑操作将大小为100的随机向量转换为4 × 4 × 512的数组。

  • 使用一系列带批处理归一化和ReLU层的转置卷积层将生成的数组扩展到64 × 64 × 3数组。

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

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

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

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

要投射和重塑噪声输入,使用自定义层projectAndReshapeLayer,作为支持文件附加到本示例中。要访问此层,请将示例作为实时脚本打开。

filterSize = 5;numFilters = 64;numLatentInputs = 100;projectionSize = [4 4 512];layersGenerator = [featureInputLayer(numLatentInputs) projectAndReshapeLayer(projectionSize) transposedConv2dLayer(filterSize,4*numFilters) batchNormalizationLayer reluLayer transposedConv2dLayer(filterSize,2*numFilters,Stride=2,剪裁= .“相同”(filterSize,numFilters,Stride=2,裁剪= .“相同”conver2dlayer (filterSize,3,Stride=2,裁剪=“相同”) tanhLayer);

要用自定义训练循环训练网络并启用自动区分,请将层图转换为dlnetwork对象。

netG = dlnetwork (layersGenerator);

定义鉴别器网络

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

创建一个接受64 × 64 × 3图像的网络,并使用一系列具有批处理归一化和泄漏ReLU层的卷积层返回标量预测评分。使用dropout为输入图像添加噪声。

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

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

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

  • 要输出[0,1]范围内的概率,指定一个带有一个4 × 4过滤器的卷积层,后面是一个sigmoid层。

dropoutProb = 0.5;numFilters = 64;规模= 0.2;inputSize = [64 64 3];filterSize = 5;layersDiscriminator = [imageInputLayer(inputSize, normalized = .“没有”) dropoutLayer (dropoutProb) convolution2dLayer (filterSize numFilters,跨步= 2,填充=“相同”) leakyReluLayer(规模)convolution2dLayer (2 * numFilters filterSize,跨步= 2,填充=“相同”) batchNormalizationLayer leakyReluLayer(scale) convolution2dLayer(filterSize,4*numFilters,Stride=2,Padding=“相同”) batchNormalizationLayer leakyReluLayer(scale) convolution2dLayer(filterSize,8*numFilters,Stride=2,Padding=“相同”) batchNormalizationLayer leakyReluLayer(scale) convolution2dLayer(4,1) sigmoidLayer];

要用自定义训练循环训练网络并启用自动区分,请将层图转换为dlnetwork对象。

= dlnetwork经济技术开发区(layersDiscriminator);

定义模型损失函数

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

指定培训选项

训练小批次大小为128,500课时。对于较大的数据集,您可能不需要训练那么多的epoch。

numEpochs = 500;miniBatchSize = 128;

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

  • 学习率为0.0002

  • 梯度衰减系数为0.5

  • 平方梯度衰减系数为0.999

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

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

指定以0.35的概率翻转真实标签。注意,这不会损害生成器,因为所有生成的图像仍然被正确标记。

flipProb = 0.35;

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

validationFrequency = 100;

火车模型

为了训练GAN,同时训练两个网络以最大化两者的性能:

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

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

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

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

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

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

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

  • 丢弃任何观察量少于指定小批大小的部分小批。

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

  • 如果有GPU,请使用GPU进行训练。默认情况下,minibatchqueue对象将每个输出转换为gpuArray如果有可用的GPU。使用GPU需要并行计算工具箱™和支持的GPU设备。有关支持的设备的信息,请参见GPU计算的需求(并行计算工具箱)

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

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

初始化Adam优化的参数。

trailingAvgG = [];trailingAvgSqG = [];trailingAvg = [];trailingAvgSqD = [];

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

创建一个持有随机值的数组。

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

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

ZValidation = dlarray (ZValidation,“CB”);

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

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

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

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

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

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

初始化分数图的动画行。

C = colororder;lineScoreG = animatedline (scoreAxes颜色= C (1:));lineScoreD = animatedline (scoreAxes颜色= C (2:));传奇(“发电机”“鉴频器”);ylim([0 1])包含(“迭代”) ylabel (“分数”网格)

训练甘。对于每个epoch,洗牌数据存储并遍历小批数据。

为每个mini-batch:

  • 评估损失的梯度与可学习参数,发电机状态,和网络评分使用dlfevalmodelLoss函数。

  • 更新网络参数adamupdate函数。

  • 画出两个网络的得分。

  • 在每一个validationFrequency迭代,为固定的搁置生成器输入显示一批生成的图像。

跑步训练需要一些时间。

迭代= 0;开始=抽搐;循环遍历各个时代。时代= 1:numEpochs重置和洗牌数据存储。洗牌(兆贝可);在小批量上循环。Hasdata (mbq)迭代=迭代+ 1;读取小批数据。X =下一个(兆贝可);为发电机网络生成潜在输入。转换为% dlarray并指定格式“CB”(通道,批处理)。如果GPU是%可用,然后将潜在输入转换为gpuArray。Z = randn (numLatentInputs miniBatchSize,“单身”);Z = dlarray (Z,“CB”);如果canUseGPU Z = gpuArray(Z);结束评估损失相对于可学习内容的梯度。%参数、生成器状态和使用的网络评分% dlfeval和modelLoss函数。[~, ~, gradientsG、gradientsD stateG, scoreG,得分)=...dlfeval (@modelLoss netG,经济技术开发区X, Z, flipProb);netG。状态= stateG;更新鉴别器网络参数。[netD,trailingAvg,trailingAvgSqD] = adamupdate(netD, gradientsD,...trailingAvg trailingAvgSqD,迭代,...learnRate、gradientDecayFactor squaredGradientDecayFactor);更新发电机网络参数。[netG,trailingAvgG,trailingAvgSqG] = adamupdate(netG, gradientsG,...trailingAvgG trailingAvgSqG,迭代,...learnRate、gradientDecayFactor squaredGradientDecayFactor);%每个validationFrequency迭代,显示批量生成%的图像使用hold out生成器输入。如果mod(迭代,validationFrequency) == 0 ||迭代== 1使用hold out生成器输入生成图像。XGeneratedValidation =预测(netG ZValidation);%平铺并缩放范围为[0 1]的图像。我= imtile (extractdata (XGeneratedValidation));I =重新调节(我);显示图片。次要情节(1、2、1);图像(imageAxes,我)xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结束更新分数图。subplot(1,2,2) scoreG = double(extractdata(scoreG));addpoints (lineScoreG迭代,scoreG);得分=双(extractdata(得分));addpoints (lineScoreD迭代,得分);用培训进度信息更新标题。。D =持续时间(0,0,toc(开始),格式=“hh: mm: ss”);标题(...”时代:“+时代+”、“+...“迭代:“+迭代+”、“+...”经过:“+ drawnow字符串(D))结束结束

在这里,鉴别器学习了一种强特征表示,可以在生成的图像中识别真实图像。反过来,生成器学习了类似的强特征表示,使其能够生成与训练数据相似的图像。

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

生成新的图片

要生成新图像,请使用预测函数在生成器上用dlarray对象,该对象包含一批随机向量。要将图像显示在一起,请使用imtile函数并对图像进行缩放重新调节函数。

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

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

如果GPU可用,那么将潜在向量转换为gpuArray

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

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

XGeneratedNew =预测(netG ZNew);

显示图像。

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

损失函数模型

这个函数modelLoss以生成器和鉴别器为输入dlnetwork对象netG而且netD,一个小批量的输入数据X,一个随机值的数组Z,和翻转真实标签的概率flipProb,并返回损失值、损失值相对于网络中可学习参数的梯度、生成器状态和两个网络的分数。

函数[lossG, lossD gradientsG、gradientsD stateG, scoreG,得分)=...modelLoss (netG,经济技术开发区X, Z, flipProb)用鉴别器网络对真实数据进行预测。。YReal =前进,经济技术开发区(X);用鉴别器计算生成数据的预测。%网络。向前(XGenerated stateG] = (netG, Z);YGenerated =前进(,经济技术开发区XGenerated);计算鉴别器的得分。。scores =(均值(YReal) +均值(1-YGenerated)) / 2;计算生成器的分数。scoreG =意味着(YGenerated);随机翻转真实图片的标签。numObservations =大小(YReal 4);idx = rand(1,numObservations) < flipProb;YReal(:,:,:,idx) = 1 - YReal(:,:,:,idx);%计算GAN损耗。[lossG, lossD] = ganLoss(YReal,YGenerated);对于每个网络,计算有关损失的梯度。。gradientsG = dlgradient (lossG、netG.Learnables RetainData = true);gradientsD = dlgradient (lossD netD.Learnables);结束

GAN损失函数和评分

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

考虑到输出 Y 鉴频器:

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

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

发电机的损耗函数为

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 生成的

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

函数[lossG, lossD] = ganLoss (YReal YGenerated)计算鉴别器网络的损失。lossD = -mean(log(YReal)) -mean(log(1-YGenerated));计算发电机网络的损耗。lossG =意味着(日志(YGenerated));结束

Mini-Batch预处理功能

preprocessMiniBatch函数使用以下步骤对数据进行预处理:

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

  2. 缩放图像到范围内[1]

函数X = preprocessMiniBatch(数据)%连接mini-batchX =猫(4、数据{:});%重新缩放范围[-1]内的图像。X =重新调节(X, 1, 1, InputMin = 0, InputMax = 255);结束

参考文献

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

  2. 雷德福,亚历克,卢克·梅茨,还有索史密斯·钦塔拉。用深度卷积生成对抗网络进行无监督表示学习。预印本,2015年11月19日提交。http://arxiv.org/abs/1511.06434。

另请参阅

|||||||

相关的话题

Baidu
map