主要内容

训练条件生成对抗网络(CGAN)

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

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

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

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

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

一个有条件的生成对抗网络(CGAN)是一种同样在训练过程中利用标签的GAN。

  1. 生成器——给定一个标签和一个随机数组作为输入,该网络生成的数据结构与对应于同一标签的训练数据观察结果相同。

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

为了训练一个条件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数据集(218 MB)…”) websave(文件名,url);解压(文件名,downloadFolder)结束

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

datasetFolder = fullfile (imageFolder);imd = imageDatastore (datasetFolder IncludeSubfolders = true, LabelSource =“foldernames”);

查看类的数量。

类=类别(imds.Labels);numClasses =元素个数(类)
numClasses = 5

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

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

定义发电机网络

定义下面的双输入网络,它生成给定大小为100的随机向量和相应标签的图像。

这个网络:

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

  • 将类别标签转换为嵌入向量并将它们重新形状为4 × 4数组。

  • 沿着通道维度连接两个输入的结果图像。输出是一个4乘4乘1025的数组。

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

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

  • 对于分类输入,使用嵌入维数50。

  • 对于转置卷积层,指定5 × 5滤波器,每层滤波器的数量递减,步幅为2,和“相同”裁剪输出。

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

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

要投射和重塑噪声输入,请使用完全连接层,然后使用指定为函数层的重塑操作,函数由feature2image函数,作为支持文件附加到本示例中。要嵌入分类标签,请使用自定义层embeddingLayer作为支持文件附加到这个示例中。要访问这些支持文件,请将示例作为实时脚本打开。

numLatentInputs = 100;embeddingDimension = 50;numFilters = 64;filterSize = 5;projectionSize = [4 4 1024];layersGenerator = [featureInputLayer(numLatentInputs) fulllyconnectedlayer (prod(projectionSize)) functionLayer(@(X) feature2image(X,projectionSize),Formattable=true) concatenationLayer(3,2,Name=“猫”);transsedconv2dlayer (filterSize,2*numFilters,Stride=2,裁剪=“相同”(filterSize,numFilters,Stride=2,裁剪= .“相同”conver2dlayer (filterSize,3,Stride=2,裁剪=“相同”) tanhLayer);lgraphGenerator = layerGraph (layersGenerator);layers = [featureInputLayer(embeddingLayer(embeddingDimension,numClasses) fulllyconnectedlayer (prod(projectionSize(1:2))) functionLayer(@(X) feature2image(X,[projectionSize(1:2) 1]),Formattable=true,Name=“emb_reshape”));lgraphGenerator = addLayers (lgraphGenerator层);lgraphGenerator = connectLayers (lgraphGenerator,“emb_reshape”“猫/ in2”);

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

netG = dlnetwork (lgraphGenerator)
dlnetGenerator = dlnetwork with properties: Layers: [19×1 nnet. cn.layer .layer] Connections: [18×2 table] Learnables: [19×3 table] State: [6×3 table] InputNames: {'input' 'input_1'} OutputNames: {'layer_2'} Initialized: 1

定义鉴别器网络

定义下面的双输入网络,它在给定一组图像和相应的标签的情况下对真实的和生成的64 × 64图像进行分类。

创建一个网络,将64 × 64 × 1的图像和相应的标签作为输入,并使用一系列具有批处理归一化和泄漏ReLU层的卷积层输出标量预测评分。使用dropout为输入图像添加噪声。

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

  • 对于卷积层,指定5 × 5过滤器,每个层的过滤器数量不断增加。还要指定stride为2,并在每条边缘上指定输出的填充。

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

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

dropoutProb = 0.75;numFilters = 64;规模= 0.2;inputSize = [64 64 3];filterSize = 5;layersDiscriminator = [imageInputLayer(inputSize, normalized = .“没有”) dropoutLayer (dropoutProb) concatenationLayer(3 2名=“猫”) 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)];lgraphDiscriminator = layerGraph (layersDiscriminator);layers = [featureInputLayer(embeddingDimension,numClasses) fulllyconnectedlayer (prod(inputSize(1:2))) functionLayer(@(X) feature2image(X,[inputSize(1:2) 1]),Formattable=true,Name= . @(X) feature2image(X,[inputSize(1:2) 1]),Formattable=true,Name=“emb_reshape”));lgraphDiscriminator = addLayers (lgraphDiscriminator层);lgraphDiscriminator = connectLayers (lgraphDiscriminator,“emb_reshape”“猫/ in2”);

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

= dlnetwork经济技术开发区(lgraphDiscriminator)
dlnetDiscriminator = dlnetwork with properties: Layers: [19×1 nnet.cnn.layer.Layer] Connections: [18×2 table] Learnables: [19×3 table] State: [6×3 table] InputNames: {'imageinput' 'input'} OutputNames: {'conv_5'} Initialized: 1

定义模型损失函数

创建函数modelLoss,列于损失函数模型部分,它将生成器和鉴别器网络、一小批输入数据和随机值数组作为输入,并返回相对于网络中的可学习参数和生成的图像数组的损失梯度。

指定培训选项

训练小批次大小为128,500课时。

numEpochs = 500;miniBatchSize = 128;

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

  • 学习率为0.0002

  • 梯度衰减系数为0.5

  • 平方梯度衰减系数为0.999

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

每100次迭代更新训练进度图。

validationFrequency = 100;

如果鉴别器学习区分真实图像和生成图像的速度太快,那么生成器可能无法训练。为了更好地平衡鉴别器和生成器的学习,可以随机翻转一定比例的真实图像的标签。指定翻转因子为0.5。

flipFactor = 0.5;

火车模型

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

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

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

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

  • 用尺寸标签格式化图像数据“SSCB”(空间,空间,渠道,批处理)。

  • 用尺寸标签格式化标签数据“公元前”(批处理、通道)。

  • 如果有GPU,请使用GPU进行训练。当OutputEnvironment选择minibatchqueue“汽车”minibatchqueue将每个输出转换为gpuArray如果有可用的GPU。使用GPU需要并行计算工具箱™和支持的GPU设备。有关支持的设备的信息,请参见GPU计算的需求(并行计算工具箱)

minibatchqueue对象,默认情况下将数据转换为dlarray具有基础类型的对象

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

初始化Adam优化器的参数。

velocityD = [];trailingAvgG = [];trailingAvgSqG = [];trailingAvgD = [];trailingAvgSqD = [];

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

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 (“分数”网格)

为了监视训练进度,创建一个包含25个随机向量的保留批次和一组重复5次的标签1到5(对应于类)。

numValidationImagesPerClass = 5;ZValidation = randn (numLatentInputs numValidationImagesPerClass * numClasses,“单身”);TValidation = single(repmat(1:numClasses,[1 numValidationImagesPerClass]));

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

ZValidation = dlarray (ZValidation,“CB”);TValidation = dlarray (TValidation,“CB”);

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

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

训练条件GAN。对于每个历元,洗牌数据并遍历小批数据。

为每个mini-batch:

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

  • 更新网络参数adamupdate函数。

  • 画出两个网络的得分。

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

跑步训练需要一些时间。

迭代= 0;开始=抽搐;循环遍历各个时代。时代= 1:numEpochs重置和洗牌数据。洗牌(兆贝可);在小批量上循环。Hasdata (mbq)迭代=迭代+ 1;读取小批数据。[X, T] =下一个(兆贝可);为发电机网络生成潜在输入。转换为% dlarray并指定尺寸标签“CB”(通道,批次)。%如果在GPU上训练,那么转换潜在的输入到GPU array。Z = randn (numLatentInputs miniBatchSize,“单身”);Z = dlarray (Z,“CB”);如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”Z = gpuArray (Z);结束评估损失相对于可学习内容的梯度。%参数、生成器状态和使用的网络评分% dlfeval和modelLoss函数。[~, ~, gradientsG、gradientsD stateG, scoreG,得分)=...dlfeval (@modelLoss netG,经济技术开发区X, T, Z, flipFactor);netG。状态= stateG;更新鉴别器网络参数。[netD,trailingAvgD,trailingAvgSqD] = adamupdate(netD, gradientsD,...trailingAvgD 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 TValidation);%平铺并缩放范围为[0 1]的图像。我= imtile (extractdata (XGeneratedValidation),...GridSize = [numValidationImagesPerClass numClasses]);I =重新调节(我);显示图片。次要情节(1、2、1);图像(imageAxes,我)xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结束更新分数图。次要情节(1、2、2)addpoints (lineScoreGenerator、迭代、双(scoreG));addpoints (lineScoreDiscriminator、迭代、双(得分));用培训进度信息更新标题。。D =持续时间(0,0,toc(开始),格式=“hh: mm: ss”);标题(...”时代:“+时代+”、“+...“迭代:“+迭代+”、“+...”经过:“+ drawnow字符串(D))结束结束

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

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

生成新的图片

要生成特定类的新图像,请使用预测函数在生成器上用dlarray对象,该对象包含一批随机向量和与所需类对应的标签数组。将数据转换为dlarray对象,并指定尺寸标签“CB”(频道,批处理)。对于GPU预测,需要将数据转换为gpuArray对象。要将图像显示在一起,请使用imtile函数并对图像进行缩放重新调节函数。

创建一个包含36个随机值向量的数组,该数组对应于第一个类。

numObservationsNew = 36;idxClass = 1;ZNew = randn (numLatentInputs numObservationsNew,“单身”);TNew = repmat(single(idxClass),[1 numObservationsNew]);

将数据转换为dlarray具有维度标签的对象“SSCB”(空间,空间,渠道,批处理)。

ZNew = dlarray (ZNew,“CB”);TNew = dlarray (TNew,“CB”);

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

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

使用预测与发电机网络功能。

XGeneratedNew =预测(netG ZNew TNew);

在图中显示生成的图像。

图I = imtile(extractdata(XGeneratedNew));I =重新调节(我);imshow (I)标题(”类:“+类(idxClass))

在这里,生成器网络生成符合指定类条件的图像。

损失函数模型

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

如果鉴别器学习区分真实图像和生成图像的速度太快,那么生成器可能无法训练。为了更好地平衡鉴别器和生成器的学习,可以随机翻转一定比例的真实图像的标签。

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

氮化镓损失函数

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

考虑到输出 Y 鉴频器:

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

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

注意sigmoid运算 σ 发生在modelLoss函数。发电机的损耗函数为

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

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

鉴别器的目标是不被生成器“愚弄”。为了使鉴别器成功鉴别真实图像和生成图像的概率最大化,将相应的负对数似然函数的和最小化。鉴别器的损失函数为

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

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

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

Mini-Batch预处理功能

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

  1. 从输入单元格数组中提取图像和标签数据,并将它们连接到数值数组中。

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

函数[X, T] = preprocessData(伊势亚TCell)从单元格中提取图像数据并连接猫(X = 4,伊势亚{:});从单元格中提取标签数据并连接猫(T = 1, TCell {:});%重新缩放范围[-1]内的图像。X =重新调节(X, 1, 1, InputMin = 0, InputMax = 255);结束

参考文献

另请参阅

||||||

相关的话题

Baidu
map