主要内容

训练生成对抗网络(GAN)

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

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

trainNetwork函数不支持训练GANs,因此必须实现金宝app自定义训练循环。要使用自定义训练循环训练GAN,可以使用dlarraydlnetwork对象用于自动区分。

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

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

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

该图说明了GAN的生成器网络从随机输入的向量生成图像。

该图说明了GAN的结构。

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

  • 训练生成器生成“欺骗”鉴别器的数据。

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

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

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

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

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

负荷训练数据

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

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

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

imds = imageDatastore(imageFolder, inclesubfolders =true);

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

augmenter = 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,作为支持文件附在本例中。金宝app要访问此层,请将示例作为活动脚本打开。

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,裁剪=“相同”) batchNormalizationLayer reluLayer转置conv2dlayer (filterSize,numFilters,Stride=2,裁剪=“相同”) batchNormalizationLayer relullayer转置conv2dlayer (filterSize,3,Stride=2,裁剪=“相同”) tanhLayer);

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

netG = dlnetwork(layersGenerator);

定义鉴别器网络

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

创建一个接受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,归一化=“没有”) dropoutLayer(dropoutProb) convolution2dLayer(filterSize,numFilters,Stride=2,Padding=“相同”) leakyReluLayer(scale) convolution2dLayer(filterSize,2*numFilters,Stride=2,Padding=“相同”) 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];

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

netD = dlnetwork(layersDiscriminator);

定义模型损失函数

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

指定培训项目

使用500个epoch的128个小批量进行训练。对于较大的数据集,您可能不需要训练那么多的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处理和管理小批量的图像。对于每个小批量:

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

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

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

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

augimds。MiniBatchSize = MiniBatchSize;MBQ = minibatchqueue(增加,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);结束

要跟踪生成器和鉴别器的分数,请使用trainingProgressMonitor对象。计算监视器的总迭代次数。

numObservationsTrain = numel(imds.Files);numIterationsPerEpoch = floor(numObservationsTrain/miniBatchSize);numIterations = nummepochs *numIterationsPerEpoch;

初始化TrainingProgressMonitor对象。因为计时器在创建监视器对象时开始,所以请确保创建的对象接近训练循环。

monitor = trainingProgressMonitor(指标= [“GeneratorScore”“DiscriminatorScore”],信息= [“时代”“迭代”],包含=“迭代”);groupSubPlot(监视、得分= (“GeneratorScore”“DiscriminatorScore”])

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

对于每个小批量:

  • 停止,如果停止的属性TrainingProgressMonitor对象是真正的.的停止属性更改为真正的当你点击停止按钮。

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

  • 方法更新网络参数adamupdate函数。

  • 绘制两家电视台的得分图。

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

跑步训练需要一些时间。

Epoch = 0;迭代= 0;%遍历epoch。epoch < numEpochs && ~monitor。停止epoch = epoch + 1;重置和洗牌数据存储。洗牌(兆贝可);在小批上循环。Hasdata (mbq) && ~monitor。停止iteration = iteration + 1;读取小批数据。X = next(mbq);为发电机网络生成潜在输入。转换为% darray,并指定格式“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。State = stateG;更新鉴别器网络参数。[netD,trailingAvg,trailingAvgSqD] = adamupdate(netD, gradientsD,trailingAvg trailingAvgSqD迭代learnRate, gradientDecayFactor, squaredGradientDecayFactor);更新发电机网络参数。[netG,trailingAvgG,trailingAvgSqG] = adamupdate(netG, gradientsG,trailingAvgG, trailingAvgSqG,迭代,learnRate, gradientDecayFactor, squaredGradientDecayFactor);%每个validationFrequency迭代,显示批生成%图像使用保留的生成器输入。如果mod(迭代,validationFrequency) == 0 ||迭代== 1使用保留的生成器输入生成图像。XGeneratedValidation = predict(netG,ZValidation);平铺和重新缩放范围[0 1]的图像。I = imtile(extractdata(XGeneratedValidation));I = rescale(I);显示图片。图像(I) xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结束更新培训进度监视器。recordMetrics(监控、迭代GeneratorScore = scoreG,DiscriminatorScore =得分);updateInfo(监控、时代=时代迭代=迭代);班长。进度= 100*iteration/numIterations;结束结束

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

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

生成新图像

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

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

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

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

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

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

XGeneratedNew = predict(netG,ZNew);

显示图像。

I = imtile(extractdata(XGeneratedNew));I = rescale(I);图像(I)轴标题(“生成的图像”

模型损失函数

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

函数[lossG, lossD gradientsG、gradientsD stateG, scoreG,得分)=modelLoss (netG,经济技术开发区X, Z, flipProb)用鉴别器网络计算真实数据的预测。。YReal = forward(netD,X);用鉴别器计算生成数据的预测%网络。[XGenerated,stateG] = forward(netG,Z);YGenerated = forward(netD,XGenerated);计算鉴别器的分数。得分= (mean(YReal) + mean(1-YGenerated)) / 2;计算发电机的得分。scoreG = mean(YGenerated);随机翻转真实图像的标签。numObservations = size(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,net . 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 = -mean(log(YGenerated));结束

小批量预处理功能

preprocessMiniBatch函数按照以下步骤对数据进行预处理:

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

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

函数X = preprocessMiniBatch(数据)连接迷你批X = cat(4,data{:});重新缩放范围为[-1 1]的图像。(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。

另请参阅

|||||||

相关的话题